<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-258056851683254325</id><updated>2011-12-06T13:43:03.816-05:00</updated><category term='Global RTOFS python ocean salinity temperature model'/><category term='ARGO RTOFS python bash wget'/><title type='text'>2bitBrain</title><subtitle type='html'>This is where I come to dump the contents of my brain.  As I only have a 2-bit memory, I need to do this very often.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://2bitbrain.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/258056851683254325/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://2bitbrain.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Jonnyb</name><uri>http://www.blogger.com/profile/17969795764233636985</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_Pc5sciCQfw4/S7veI9tzJWI/AAAAAAAAAAM/VmEgIF3mpHk/S220/Photo+on+2010-04-06+at+21.19.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>9</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-258056851683254325.post-3463814931792847669</id><published>2011-12-06T13:40:00.001-05:00</published><updated>2011-12-06T13:43:03.823-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ARGO RTOFS python bash wget'/><title type='text'>ARGO data</title><content type='html'>I've been playing with &lt;a href="http://www.argo.net/" target="_blank"&gt;ARGO&lt;/a&gt; data to get a sense of how well the &lt;a href="http://polar.ncep.noaa.gov/global/" target="_blank"&gt;RTOFS Global&lt;/a&gt; model is doing in predicting vertical temperature and salinity structure.&amp;nbsp; I eventually got a script running that would do a daily download of the current day's real-time data for use in my comparison analysis with the RTOFS Global model.  Keep in mind that I plan on using this script while at sea over a limited bandwidth connection to the internet so I chose to run wget for each file instead of passing it a list of files with the -i and -base options.&lt;br /&gt;&lt;br /&gt;The script starts by downloading the "directory file" listing all available files, it looks like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;# Title : Profile directory file of the Argo Global Data Assembly Center&lt;br /&gt;# Description : The directory file describes all individual profile files of the argo GDAC ftp site.&lt;br /&gt;# Project : ARGO&lt;br /&gt;# Format version : 2.0&lt;br /&gt;# Date of update : 20111206174544&lt;br /&gt;# FTP root number 1 : ftp://ftp.ifremer.fr/ifremer/argo/dac&lt;br /&gt;# FTP root number 2 : ftp://usgodae.usgodae.org/pub/outgoing/argo/dac&lt;br /&gt;# GDAC node : FNMOC&lt;br /&gt;file,date,latitude,longitude,ocean,profiler_type,institution,date_update&lt;br /&gt;aoml/13857/profiles/R13857_001.nc,19970729200300,0.267,-16.032,A,845,AO,20080918131927&lt;br /&gt;aoml/13857/profiles/R13857_002.nc,19970809192112,0.072,-17.659,A,845,AO,20080918131929&lt;br /&gt;aoml/13857/profiles/R13857_003.nc,19970820184544,0.543,-19.622,A,845,AO,20080918131931&lt;br /&gt;aoml/13857/profiles/R13857_004.nc,19970831193905,1.256,-20.521,A,845,AO,20080918131933&lt;br /&gt;aoml/13857/profiles/R13857_005.nc,19970911185807,0.720,-20.768,A,845,AO,20080918131934&lt;br /&gt;aoml/13857/profiles/R13857_006.nc,19970922195701,1.756,-21.566,A,845,AO,20080918131936&lt;br /&gt;aoml/13857/profiles/R13857_007.nc,19971003191549,2.595,-21.564,A,845,AO,20080918131938&lt;br /&gt;aoml/13857/profiles/R13857_008.nc,19971014183934,1.761,-21.587,A,845,AO,20080918131940&lt;br /&gt;aoml/13857/profiles/R13857_009.nc,19971025193234,1.804,-21.774,A,845,AO,20080918131941&lt;br /&gt;aoml/13857/profiles/R13857_010.nc,19971105185142,1.642,-21.362,A,845,AO,20080918131943&lt;br /&gt;aoml/13857/profiles/R13857_011.nc,19971116194909,1.708,-20.758,A,845,AO,20080918131945&lt;br /&gt;aoml/13857/profiles/R13857_012.nc,19971127190705,2.048,-20.224,A,845,AO,20080918131947&lt;br /&gt;aoml/13857/profiles/R13857_013.nc,19971208183912,2.087,-19.769,A,845,AO,20080918131948&lt;br /&gt;aoml/13857/profiles/R13857_014.nc,19971219192355,2.674,-20.144,A,845,AO,20080918131950&lt;br /&gt;aoml/13857/profiles/R13857_015.nc,19971230184421,2.890,-20.433,A,845,AO,20080918131952&lt;br /&gt;aoml/13857/profiles/R13857_016.nc,19980110194140,2.818,-20.699,A,845,AO,20080918131954&lt;br /&gt;aoml/13857/profiles/R13857_017.nc,19980121190033,2.940,-20.789,A,845,AO,20080918131956&lt;br /&gt;aoml/13857/profiles/R13857_018.nc,19980201195831,3.224,-20.757,A,845,AO,20080918131957&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;I parse the directory file looking for a date match in the date/time field (2nd field).  You could easily modify this to limit it to a specific lat/lon bounding box or any other criteria.&lt;br /&gt;&lt;br /&gt;Here's the script:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;#!/bin/bash&lt;br /&gt;&lt;br /&gt;base_argo_url=ftp://usgodae.org/pub/outgoing/argo&lt;br /&gt;&lt;br /&gt;# Download the profile index&lt;br /&gt;time1=`stat -f "%m" ar_index_global_prof.txt.gz`&lt;br /&gt;wget --timestamping $base_argo_url/ar_index_global_prof.txt.gz&lt;br /&gt;time2=`stat -f "%m" ar_index_global_prof.txt.gz`&lt;br /&gt;&lt;br /&gt;if [ $time1 -eq $time2 ]&lt;br /&gt;then&lt;br /&gt;        echo "Nothing to do...no changes since last run"&lt;br /&gt;        exit&lt;br /&gt;fi&lt;br /&gt;&lt;br /&gt;# Get today's date&lt;br /&gt;today=`date -u '+%Y%m%d'`&lt;br /&gt;echo "today is" $today&lt;br /&gt;&lt;br /&gt;mkdir $today&lt;br /&gt;&lt;br /&gt;zcat ar_index_global_prof.txt.gz | awk -F, '{if (NR &amp;gt; 9 &amp;amp;&amp;amp; substr($2,1,8) == '$today') print $1 }' &amp;gt; $today/todays_casts.txt&lt;br /&gt;&lt;br /&gt;cd $today&lt;br /&gt;&lt;br /&gt;num_files=`cat todays_casts.txt | wc -l`&lt;br /&gt;&lt;br /&gt;if [ $num_files -eq 0 ]&lt;br /&gt;then&lt;br /&gt;        echo "Nothing to do...no files to download yet for" $today&lt;br /&gt;    exit&lt;br /&gt;fi&lt;br /&gt;&lt;br /&gt;echo "Going to check" $num_files "files"&lt;br /&gt;&lt;br /&gt;for f in `cat todays_casts.txt`; do&lt;br /&gt;        echo "Doing file" $f&lt;br /&gt;&lt;br /&gt;        if [ -e `basename $f` ]&lt;br /&gt;        then&lt;br /&gt;                # Skip files that have already been downloaded&lt;br /&gt;                continue&lt;br /&gt;        fi&lt;br /&gt;&lt;br /&gt;        # Don't need time stamping here, we check locally for existence of the&lt;br /&gt;        # .nc file so don't need to waste time requesting a listing from the FTP server&lt;br /&gt;        wget $base_argo_url/dac/$f&lt;br /&gt;done&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;What comes out of this is a directory for the current day (named yyyymmdd) with a set of netCDF files in it (.nc file extension).  Each file represents a cast from a given instrument, for example 20111206/R1900847_089.nc.&lt;br /&gt;&lt;br /&gt;I then use a python script to read the .nc files and turn them into OMG/UNB format so that I can run comparisons against casts from RTOFS Global.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;#!/usr/bin/env python2.6&lt;br /&gt;&lt;br /&gt;import glob&lt;br /&gt;import netCDF4&lt;br /&gt;import numpy as np&lt;br /&gt;import math&lt;br /&gt;import datetime as dt&lt;br /&gt;import matplotlib.pyplot as plt&lt;br /&gt;import os&lt;br /&gt;&lt;br /&gt;do_plot = True&lt;br /&gt;&lt;br /&gt;if do_plot:&lt;br /&gt;    plt.figure()&lt;br /&gt;    plt.subplot(1,2,1)&lt;br /&gt;    plt.xlabel("Temperature, deg C")&lt;br /&gt;    plt.ylabel("Pressure, dbar")&lt;br /&gt;    plt.hold&lt;br /&gt;    plt.subplot(1,2,2)&lt;br /&gt;    plt.xlabel("Salinity, psu")&lt;br /&gt;    plt.ylabel("Pressure, dbar")&lt;br /&gt;    plt.hold&lt;br /&gt;&lt;br /&gt;for name in glob.glob('*.nc'):&lt;br /&gt;    file = netCDF4.Dataset(name)&lt;br /&gt;&lt;br /&gt;    latitude = file.variables['LATITUDE'][0]&lt;br /&gt;    longitude = file.variables['LONGITUDE'][0]&lt;br /&gt;&lt;br /&gt;    if math.isnan(latitude) or math.isnan(longitude):&lt;br /&gt;        print "    skipping NAN lat/lon"&lt;br /&gt;        continue&lt;br /&gt;&lt;br /&gt;    juld = file.variables['JULD'][0]&lt;br /&gt;&lt;br /&gt;    # TODO: the reference date is stored in 'REFERENCE_DATE_TIME'&lt;br /&gt;    refdate = dt.datetime(1950,1,1,0,0,0,0,tzinfo=None)&lt;br /&gt;    castdate = refdate + dt.timedelta(days=juld)&lt;br /&gt;&lt;br /&gt;    print name + " " + str(latitude) + " " + str(longitude) + " " + str(castdate)&lt;br /&gt;&lt;br /&gt;    try:&lt;br /&gt;        # Only deal with casts that have ALL the data we need&lt;br /&gt;        p = file.variables['PRES'][0][:]&lt;br /&gt;        t = file.variables['TEMP'][0][:]&lt;br /&gt;        t_fill_value = file.variables['TEMP']._FillValue&lt;br /&gt;        t_qc = file.variables['TEMP_QC'][0][:]&lt;br /&gt;        s = file.variables['PSAL'][0][:]&lt;br /&gt;        s_fill_value = file.variables['PSAL']._FillValue&lt;br /&gt;        s_qc = file.variables['PSAL_QC'][0][:]&lt;br /&gt;    except:&lt;br /&gt;        continue&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    # Replace masked data with NAN&lt;br /&gt;    # This will fail if there is no masked data since netCDF4 returns&lt;br /&gt;    # a regular numpy array if no masked data but returns a masked numpy array&lt;br /&gt;    # if there is.&lt;br /&gt;    try:&lt;br /&gt;        t_mask = t.mask&lt;br /&gt;        t[t_mask] = np.NAN&lt;br /&gt;    except:&lt;br /&gt;        pass&lt;br /&gt;&lt;br /&gt;    try:&lt;br /&gt;        s_mask = s.mask&lt;br /&gt;        s[s_mask] = np.NAN&lt;br /&gt;    except:&lt;br /&gt;        pass&lt;br /&gt;&lt;br /&gt;    try:&lt;br /&gt;        p_mask = p.mask&lt;br /&gt;        p[p_mask] = np.NAN&lt;br /&gt;    except:&lt;br /&gt;        pass&lt;br /&gt;&lt;br /&gt;    # Now filter based on quality control flags (we want 1, 2 or 5)&lt;br /&gt;    t_ind = (t_qc == '1') | (t_qc == '2') | (t_qc == '5')&lt;br /&gt;    s_ind = (s_qc == '1') | (s_qc == '2') | (s_qc == '5')&lt;br /&gt;&lt;br /&gt;    # We only want to consider valid concurrent observations of T and S&lt;br /&gt;    pair_ind = t_ind &amp;amp; s_ind&lt;br /&gt;&lt;br /&gt;    if do_plot:&lt;br /&gt;        plt.subplot(1,2,1)&lt;br /&gt;        plt.plot(t[pair_ind],-p[pair_ind]);&lt;br /&gt;        plt.subplot(1,2,2)&lt;br /&gt;        plt.plot(s[pair_ind],-p[pair_ind]);&lt;br /&gt;&lt;br /&gt;    t_filt = t[pair_ind]&lt;br /&gt;    s_filt = s[pair_ind]&lt;br /&gt;    p_filt = p[pair_ind]&lt;br /&gt;    num_samples = t_filt.size&lt;br /&gt;&lt;br /&gt;    file.close&lt;br /&gt;&lt;br /&gt;    if num_samples == 0:&lt;br /&gt;        print "    Skipping " + name + " due to lack of data!"&lt;br /&gt;        continue&lt;br /&gt;&lt;br /&gt;if do_plot:&lt;br /&gt;    plt.show()&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Here's a plot of data from 2011-12-06 at 1:30PM, EST.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-LWPysmejj8I/Tt5fjawAvVI/AAAAAAAAACg/NMlGYAATYGU/s1600/Screen+shot+2011-12-06+at+1.30.26+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="272" src="http://4.bp.blogspot.com/-LWPysmejj8I/Tt5fjawAvVI/AAAAAAAAACg/NMlGYAATYGU/s320/Screen+shot+2011-12-06+at+1.30.26+PM.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Here's a map showing the geographic distribution of the casts for this particular run (2011-12-06).&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-gQBx6Pbe0lY/Tt5f81uKRVI/AAAAAAAAACo/JPr8ADNxpv0/s1600/Screen+shot+2011-12-06+at+1.32.19+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="275" src="http://1.bp.blogspot.com/-gQBx6Pbe0lY/Tt5f81uKRVI/AAAAAAAAACo/JPr8ADNxpv0/s320/Screen+shot+2011-12-06+at+1.32.19+PM.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Still to do?&amp;nbsp; Read up more about the various QC procedures applied to ARGO data and try to automate detection of casts that will mess up my comparison analysis (large chunks of missing data, etc).&amp;nbsp; Here's a bit of &lt;a href="http://journals.ametsoc.org/doi/abs/10.1175/2008JTECHO552.1" target="_blank"&gt;light reading&lt;/a&gt; to get me started.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;A la prochaine...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/258056851683254325-3463814931792847669?l=2bitbrain.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://2bitbrain.blogspot.com/feeds/3463814931792847669/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://2bitbrain.blogspot.com/2011/12/argo-data.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/258056851683254325/posts/default/3463814931792847669'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/258056851683254325/posts/default/3463814931792847669'/><link rel='alternate' type='text/html' href='http://2bitbrain.blogspot.com/2011/12/argo-data.html' title='ARGO data'/><author><name>Jonnyb</name><uri>http://www.blogger.com/profile/17969795764233636985</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_Pc5sciCQfw4/S7veI9tzJWI/AAAAAAAAAAM/VmEgIF3mpHk/S220/Photo+on+2010-04-06+at+21.19.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-LWPysmejj8I/Tt5fjawAvVI/AAAAAAAAACg/NMlGYAATYGU/s72-c/Screen+shot+2011-12-06+at+1.30.26+PM.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-258056851683254325.post-671842958758809424</id><published>2011-11-02T16:18:00.000-04:00</published><updated>2011-11-02T16:18:50.300-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Global RTOFS python ocean salinity temperature model'/><title type='text'>Global RTOFS continued: vertical T/S profiles</title><content type='html'>I'm primarily interested in extracing depth profiles of temperature/salinity from the model, here's an example of how to do it.&lt;br /&gt;&lt;br /&gt;import matplotlib.pyplot as plt&lt;br /&gt;import netCDF4&lt;br /&gt;&lt;br /&gt;mydate='20111101'&lt;br /&gt;url_temp='http://nomads.ncep.noaa.gov:9090/dods/rtofs/rtofs_global'+mydate+'/rtofs_glo_3dz_forecast_daily_temp'&lt;br /&gt;file = netCDF4.Dataset(url_temp)&lt;br /&gt;lat&amp;nbsp; = file.variables['lat'][:]&lt;br /&gt;lon&amp;nbsp; = file.variables['lon'][:]&lt;br /&gt;data_temp = file.variables['temperature'][1,:,1000,2000]&lt;br /&gt;depths=file.variables['lev'][:]&lt;br /&gt;file.close&lt;br /&gt;url_salt='http://nomads.ncep.noaa.gov:9090/dods/rtofs/rtofs_global'+mydate+'/rtofs_glo_3dz_forecast_daily_salt'&lt;br /&gt;file = netCDF4.Dataset(url_salt)&lt;br /&gt;data_salt = file.variables['salinity'][1,:,1000,2000]&lt;br /&gt;plt.figure()&lt;br /&gt;plt.plot(data_temp,-depths)&lt;br /&gt;plt.xlabel("Potential Temperature (re 2000m)")plt.ylabel("Depth (m)")&lt;br /&gt;plt.figure()&lt;br /&gt;plt.plot(data_salt,-depths)&lt;br /&gt;plt.xlabel("Salinity (psu)")&lt;br /&gt;plt.ylabel("Depth (m)")&lt;br /&gt;&lt;br /&gt;And that's it!&amp;nbsp; A few figures below to show the plots. &lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-L2Bjhl3dErg/TrGlc_X3k5I/AAAAAAAAACI/yNExaSlbnlg/s1600/Screen+shot+2011-11-02+at+4.16.34+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="272" src="http://3.bp.blogspot.com/-L2Bjhl3dErg/TrGlc_X3k5I/AAAAAAAAACI/yNExaSlbnlg/s320/Screen+shot+2011-11-02+at+4.16.34+PM.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-hGF4wzNlm3I/TrGldbdlobI/AAAAAAAAACQ/argrDN4J6vA/s1600/Screen+shot+2011-11-02+at+4.15.36+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="272" src="http://2.bp.blogspot.com/-hGF4wzNlm3I/TrGldbdlobI/AAAAAAAAACQ/argrDN4J6vA/s320/Screen+shot+2011-11-02+at+4.15.36+PM.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/258056851683254325-671842958758809424?l=2bitbrain.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://2bitbrain.blogspot.com/feeds/671842958758809424/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://2bitbrain.blogspot.com/2011/11/global-rtofs-continued-vertical-ts.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/258056851683254325/posts/default/671842958758809424'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/258056851683254325/posts/default/671842958758809424'/><link rel='alternate' type='text/html' href='http://2bitbrain.blogspot.com/2011/11/global-rtofs-continued-vertical-ts.html' title='Global RTOFS continued: vertical T/S profiles'/><author><name>Jonnyb</name><uri>http://www.blogger.com/profile/17969795764233636985</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_Pc5sciCQfw4/S7veI9tzJWI/AAAAAAAAAAM/VmEgIF3mpHk/S220/Photo+on+2010-04-06+at+21.19.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-L2Bjhl3dErg/TrGlc_X3k5I/AAAAAAAAACI/yNExaSlbnlg/s72-c/Screen+shot+2011-11-02+at+4.16.34+PM.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-258056851683254325.post-2618577027582452304</id><published>2011-10-28T10:34:00.000-04:00</published><updated>2011-10-28T10:34:48.820-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Global RTOFS python ocean salinity temperature model'/><title type='text'>Global RTOFS</title><content type='html'>&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-X5eAiXNsgKg/Tqq0km1w5qI/AAAAAAAAABw/OOfAhFc2KbA/s1600/Screen+shot+2011-10-28+at+9.56.14+AM.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="272" src="http://2.bp.blogspot.com/-X5eAiXNsgKg/Tqq0km1w5qI/AAAAAAAAABw/OOfAhFc2KbA/s320/Screen+shot+2011-10-28+at+9.56.14+AM.png" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Sea surface temperature, 2011-10-27&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;Thanks to John Kelley for pointing this out to me.&amp;nbsp; There's a Global RTOFS ocean model running now with pretty easy access via python.&amp;nbsp; I spent last night trying to get it up and running on my MacBook Pro, here are a few notes.&amp;nbsp; Before diving into it, check out the website for Global RTOFS &lt;a href="http://polar.ncep.noaa.gov/global/?"&gt;here&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size: large;"&gt;Step 1: get some python modules&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;# unpack the tarball&lt;br /&gt;cd ~/installs_Mac/python_modules/ &lt;br /&gt;tar -zxvf netCDF4-0.9.7.tar.gz &lt;br /&gt;cd netCDF4-0.9.7&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;# install some hdf5 libs&lt;br /&gt;fink install hdf5-18&lt;br /&gt;&lt;br /&gt;# install some netcdf4 libs, this installs hdf5 stuff also so I'm not sure the above step was needed?&lt;br /&gt;fink install netcdf7&lt;br /&gt;&lt;br /&gt;# I had to figure out where fink installed the shared libraries for netcdf4 (they're in /sw/opt/netcdf7/)&lt;br /&gt;&lt;br /&gt;otool -L /sw/bin/ncdump&lt;br /&gt;/sw/bin/ncdump:&lt;br /&gt;/sw/opt/netcdf7/lib/libnetcdf.7.dylib (compatibility version 9.0.0,  current version 9.1.0)&lt;br /&gt;/sw/lib/libsz.2.dylib (compatibility version  3.0.0, current version 3.0.0)&lt;br /&gt;/sw/lib/libhdf5_hl.7.dylib  (compatibility version 8.0.0, current version 8.1.0)&lt;br /&gt;/sw/lib/libhdf5.7.dylib (compatibility version 8.0.0, current version  8.1.0)&lt;br /&gt;/usr/lib/libSystem.B.dylib (compatibility version 1.0.0,  current version 125.2.11)&lt;br /&gt;/usr/lib/libz.1.dylib (compatibility  version 1.0.0, current version 1.2.3)&lt;br /&gt;/sw/lib/libcurl.4.dylib  (compatibility version 7.0.0, current version 7.0.0)&lt;br /&gt;&lt;br /&gt;# set the NETCDF4_DIR based on output from otool above&lt;br /&gt;export NETCDF4_DIR=/sw/opt/netcdf7/&lt;br /&gt;&lt;br /&gt;# okay, now ready tot build the netCDF4 for python bits&lt;br /&gt;# Set some enviroenment variablesexport CFLAGS=-m32&lt;br /&gt;python2.6 setup.py install --home=~ &lt;br /&gt;&lt;br /&gt;# Now do the same for the basemap module&lt;br /&gt;cd ~/installs_Mac/python_modules/ &lt;br /&gt;tar -zxvf basemap-1.0.1.tar.gz&lt;br /&gt;cd basemap-1.0.1&lt;br /&gt;&lt;br /&gt;# Need to use the default 'python' instead of the version installed through fink...wish I knew why&lt;br /&gt;PATH="/Library/Frameworks/Python.framework/Versions/2.6/bin:${PATH}"&lt;br /&gt;export PATH&lt;br /&gt;&lt;br /&gt;# can't do the usual CFLAGS=-m32 (which is usually required for building against python as installed&lt;br /&gt;# by fink?&lt;br /&gt;unset CFLAGS&lt;br /&gt;export GEOS_DIR=/sw/opt/libgeos3.2.2/&lt;br /&gt;python2.6 setup.py install --home=~&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size: large;"&gt;Step 2.&amp;nbsp; Plot some data&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Now that all goodies are installed, I tried out the script from &lt;a href="http://polar.ncep.noaa.gov/global/examples/usingpython.shtml"&gt;here&lt;/a&gt; (note that I had to change the date to 20111027, the date provided in the example didn't work for me).&lt;br /&gt;&lt;br /&gt;Here's my version of the script, mine does a salinity plot as well.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;#!/usr/bin/env python2.6&lt;br /&gt;&lt;br /&gt;from mpl_toolkits.basemap import Basemap&lt;br /&gt;import numpy as np&lt;br /&gt;import matplotlib.pyplot as plt&lt;br /&gt;from pylab import *&lt;br /&gt;import netCDF4&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;mydate='20111027'&lt;br /&gt;&lt;br /&gt;url_temp='http://nomads.ncep.noaa.gov:9090/dods/rtofs/rtofs_global'+mydate+'/rtofs_glo_3dz_forecast_daily_temp'&lt;br /&gt;file = netCDF4.Dataset(url_temp)&lt;br /&gt;lat&amp;nbsp; = file.variables['lat'][:]&lt;br /&gt;lon&amp;nbsp; = file.variables['lon'][:]&lt;br /&gt;data_temp&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = file.variables['temperature'][1,1,:,:]&lt;br /&gt;file.close()&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;m=Basemap(projection='mill',lat_ts=10, llcrnrlon=lon.min(),urcrnrlon=lon.max(), llcrnrlat=lat.min(),urcrnrlat=lat.max(), resolution='c')&lt;br /&gt;Lon, Lat = meshgrid(lon,lat)&lt;br /&gt;x, y = m(Lon,Lat)&lt;br /&gt;&lt;br /&gt;plt.figure()&lt;br /&gt;cs = m.pcolormesh(x,y,data_temp,shading='flat', cmap=plt.cm.jet)&lt;br /&gt;&lt;br /&gt;m.drawcoastlines()&lt;br /&gt;m.fillcontinents()&lt;br /&gt;m.drawmapboundary()&lt;br /&gt;m.drawparallels(np.arange(-90.,120.,30.), labels=[1,0,0,0])&lt;br /&gt;m.drawmeridians(np.arange(-180.,180.,60.), labels=[0,0,0,1])&lt;br /&gt;&lt;br /&gt;colorbar(cs)&lt;br /&gt;plt.title('Example 1: RTOFS Global Temperature')&lt;br /&gt;plt.show()&lt;br /&gt;&lt;br /&gt;# Now do the salinity&lt;br /&gt;url_salt='http://nomads.ncep.noaa.gov:9090/dods/rtofs/rtofs_global'+mydate+'/rtofs_glo_3dz_forecast_daily_salt'&lt;br /&gt;file = netCDF4.Dataset(url_salt)&lt;br /&gt;lat&amp;nbsp; = file.variables['lat'][:]&lt;br /&gt;lon&amp;nbsp; = file.variables['lon'][:]&lt;br /&gt;data_salt&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = file.variables['salinity'][1,1,:,:]&lt;br /&gt;file.close()&lt;br /&gt;&lt;br /&gt;m=Basemap(projection='mill',lat_ts=10, llcrnrlon=lon.min(),urcrnrlon=lon.max(), llcrnrlat=lat.min(),urcrnrlat=lat.max(), resolution='c')&lt;br /&gt;Lon, Lat = meshgrid(lon,lat)&lt;br /&gt;x, y = m(Lon,Lat)&lt;br /&gt;&lt;br /&gt;plt.figure()&lt;br /&gt;cs = m.pcolormesh(x,y,data_salt,shading='flat', cmap=plt.cm.jet)&lt;br /&gt;&lt;br /&gt;m.drawcoastlines()&lt;br /&gt;m.fillcontinents()&lt;br /&gt;m.drawmapboundary()&lt;br /&gt;m.drawparallels(np.arange(-90.,120.,30.), labels=[1,0,0,0])&lt;br /&gt;m.drawmeridians(np.arange(-180.,180.,60.), labels=[0,0,0,1])&lt;br /&gt;&lt;br /&gt;colorbar(cs)&lt;br /&gt;plt.title('Example 1: RTOFS Global Salinity')&lt;br /&gt;plt.show()&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size: large;"&gt;Results?&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Here's a few screen shots of the plots I managed to generate using my script.&amp;nbsp; Next up?&amp;nbsp; Extracting vertical profiles of temperature and salinity.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-UG5EMmeOuhc/Tqq8PRCppwI/AAAAAAAAAB4/kCMjal6-IWA/s1600/Screen+shot+2011-10-28+at+10.28.30+AM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="272" src="http://2.bp.blogspot.com/-UG5EMmeOuhc/Tqq8PRCppwI/AAAAAAAAAB4/kCMjal6-IWA/s320/Screen+shot+2011-10-28+at+10.28.30+AM.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-3Aga1MMUqk0/Tqq8lUWsjYI/AAAAAAAAACA/cPDfgNP-uxE/s1600/Screen+shot+2011-10-28+at+10.30.38+AM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="272" src="http://1.bp.blogspot.com/-3Aga1MMUqk0/Tqq8lUWsjYI/AAAAAAAAACA/cPDfgNP-uxE/s320/Screen+shot+2011-10-28+at+10.30.38+AM.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/258056851683254325-2618577027582452304?l=2bitbrain.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://2bitbrain.blogspot.com/feeds/2618577027582452304/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://2bitbrain.blogspot.com/2011/10/global-rtofs.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/258056851683254325/posts/default/2618577027582452304'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/258056851683254325/posts/default/2618577027582452304'/><link rel='alternate' type='text/html' href='http://2bitbrain.blogspot.com/2011/10/global-rtofs.html' title='Global RTOFS'/><author><name>Jonnyb</name><uri>http://www.blogger.com/profile/17969795764233636985</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_Pc5sciCQfw4/S7veI9tzJWI/AAAAAAAAAAM/VmEgIF3mpHk/S220/Photo+on+2010-04-06+at+21.19.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-X5eAiXNsgKg/Tqq0km1w5qI/AAAAAAAAABw/OOfAhFc2KbA/s72-c/Screen+shot+2011-10-28+at+9.56.14+AM.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-258056851683254325.post-6224366036413746594</id><published>2010-08-10T09:37:00.000-04:00</published><updated>2010-08-10T09:37:09.510-04:00</updated><title type='text'>svp_tool WOD query tool</title><content type='html'>I spent some time coding on the weekend (which would be considered sad by many, but not by me) and built a simple push button GUI interface that allows the user to refine WOD queries by instrument and month.&amp;nbsp; If I wasn't limited by the X interface, I'd add more SQL type functionality and allow for queries on any field (year, cruise ID, etc).&amp;nbsp; More work in the future I guess.&amp;nbsp; Here's a screen shot of the button bar that allows the user to choose instrument type and month of observation, the top row is for the month, the bottom row is for instrument type.&amp;nbsp; The labels on the buttons switch to UPPERCASE when selected and back to lowercase when deselected.&amp;nbsp; The query is only done after a geographic selection in the map window.&amp;nbsp; I've shown an example of several hundred CTD casts collected in the months of July, August and September in the Northwest Passage in northern Canada, one of my favourite areas that I've ever worked in.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_Pc5sciCQfw4/TGFTzdurJpI/AAAAAAAAABA/ee1A8avexQ8/s1600/Screen+shot+2010-08-10+at+9.26.14+AM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_Pc5sciCQfw4/TGFTzdurJpI/AAAAAAAAABA/ee1A8avexQ8/s320/Screen+shot+2010-08-10+at+9.26.14+AM.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_Pc5sciCQfw4/TGFT6CpJU2I/AAAAAAAAABI/NYuxRWl9728/s1600/Screen+shot+2010-08-10+at+9.26.28+AM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_Pc5sciCQfw4/TGFT6CpJU2I/AAAAAAAAABI/NYuxRWl9728/s320/Screen+shot+2010-08-10+at+9.26.28+AM.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_Pc5sciCQfw4/TGFUAKyuZMI/AAAAAAAAABQ/mFaJBbfen-I/s1600/Screen+shot+2010-08-10+at+9.26.48+AM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_Pc5sciCQfw4/TGFUAKyuZMI/AAAAAAAAABQ/mFaJBbfen-I/s320/Screen+shot+2010-08-10+at+9.26.48+AM.png" /&gt;&lt;/a&gt;&lt;/div&gt;The CTD data is plotted in the main SVP Tool window above, with sound speed, temperature and salinity plotted versus depth (left to right, respectively).&lt;br /&gt;&lt;br /&gt;More work?&amp;nbsp; Of course.&amp;nbsp; If I turn on the debug mode of the WOD query engine, I can see that it spends an awful lot of its time unzipping the raw source data for each WMO square that it visits during the query extraction.&amp;nbsp; I'm still looking to speed this up if i can, right now the code fires off a system('gunzip -c file &amp;gt; tempfile'); whenever it hits a zipped WOD file.&amp;nbsp; I'm curious if it would be faster to run through zlib instead?&amp;nbsp; Kurt had also suggested converting the WOD files to a binary format so that's another option that would guarantee to bear some fruit but I really do like the elegance of sticking with the raw WOD files (easy to update, no need to reconvert with each update).&amp;nbsp; More thinking needs to be done, obviously...&amp;nbsp; Suggestions are welcome.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/258056851683254325-6224366036413746594?l=2bitbrain.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://2bitbrain.blogspot.com/feeds/6224366036413746594/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://2bitbrain.blogspot.com/2010/08/svptool-wod-query-tool.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/258056851683254325/posts/default/6224366036413746594'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/258056851683254325/posts/default/6224366036413746594'/><link rel='alternate' type='text/html' href='http://2bitbrain.blogspot.com/2010/08/svptool-wod-query-tool.html' title='svp_tool WOD query tool'/><author><name>Jonnyb</name><uri>http://www.blogger.com/profile/17969795764233636985</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_Pc5sciCQfw4/S7veI9tzJWI/AAAAAAAAAAM/VmEgIF3mpHk/S220/Photo+on+2010-04-06+at+21.19.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_Pc5sciCQfw4/TGFTzdurJpI/AAAAAAAAABA/ee1A8avexQ8/s72-c/Screen+shot+2010-08-10+at+9.26.14+AM.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-258056851683254325.post-5936732865569661189</id><published>2010-08-04T09:32:00.000-04:00</published><updated>2010-08-04T09:32:24.796-04:00</updated><title type='text'>Downloading WOD</title><content type='html'>&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: x-small;"&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-family: inherit;"&gt;You can download the WOD files from the NODC website through an online query (http://www.nodc.noaa.gov/OC5/SELECT/dbsearch/dbsearch.html), you can also download the entire database if you look hard enough for the links (http://www.nodc.noaa.gov/OC5/WOD09/data09geo.html).&amp;nbsp; I didn't feel like pointing and clicking myself to death so I wrote this script to download the entire thing.&amp;nbsp; I also added a line in the script to compile a summary database of the CTD and XBT data for use in svp_tool.&lt;/span&gt;&lt;/span&gt; &lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: x-small;"&gt;#!/bin/bash&lt;br /&gt;&lt;br /&gt;count=0&lt;br /&gt;&lt;br /&gt;mkdir -p {OSD,MBT,CTD,XBT,PFL,MRB,DRB,APB,UOR,GLD}/OBS&lt;br /&gt;mkdir -p {OSD,MBT,CTD,XBT,PFL,MRB,DRB,APB,UOR,GLD}/STD&lt;br /&gt;&lt;br /&gt;echo "Downloading the WOD database"&lt;br /&gt;&lt;br /&gt;for quadrant in 1 3 5 7 &lt;br /&gt;do&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for latitude in 0 1 2 3 4 5 6 7 8 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; do&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for longitude in 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; do&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; let count++&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for type in OSD MBT CTD XBT PFL MRB DRB APB UOR GLD &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; do&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # Get the "observed" data&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; file=$type\O$quadrant$latitude$longitude.gz&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; wget http://data.nodc.noaa.gov/woa/WOD09/GEOGRAPHIC/$type/OBS/$file&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; mv $file $type/OBS&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # Get the "standard level" data (observed is filtered and then&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # interpolated to standard depth levels)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; file=$type\S$quadrant$latitude$longitude.gz&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; wget http://data.nodc.noaa.gov/woa/WOD09/GEOGRAPHIC/$type/STD/$file&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; mv $file $type/STD&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; done&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; done&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; done&lt;br /&gt;done&lt;br /&gt;&lt;br /&gt;echo got total $count&lt;br /&gt;&lt;br /&gt;# Now add a tmp directory for use by the WOD library for unzipping database files&lt;br /&gt;# during extraction&lt;br /&gt;mkdir tmp &lt;br /&gt;&lt;br /&gt;# Now build database of CTD and XBT data&lt;br /&gt;echo "Building a CTD/XBT summary database"&lt;br /&gt;wod2db3 -out wod.db3 CTD/OBS/CTDO*gz XBT/OBS/XBTO*gz&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: x-small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;echo&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;echo&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;echo "Add WOD_PATH="`pwd` "as an environment variable"&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;echo "Add WOD_DATABASE_NAME="`pwd`"/"wod.db3 "as an environment variable"&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;exit&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/258056851683254325-5936732865569661189?l=2bitbrain.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://2bitbrain.blogspot.com/feeds/5936732865569661189/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://2bitbrain.blogspot.com/2010/08/downloading-wod.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/258056851683254325/posts/default/5936732865569661189'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/258056851683254325/posts/default/5936732865569661189'/><link rel='alternate' type='text/html' href='http://2bitbrain.blogspot.com/2010/08/downloading-wod.html' title='Downloading WOD'/><author><name>Jonnyb</name><uri>http://www.blogger.com/profile/17969795764233636985</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_Pc5sciCQfw4/S7veI9tzJWI/AAAAAAAAAAM/VmEgIF3mpHk/S220/Photo+on+2010-04-06+at+21.19.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-258056851683254325.post-1872559433938287554</id><published>2010-08-03T21:50:00.000-04:00</published><updated>2010-08-03T21:50:28.746-04:00</updated><title type='text'>sqlite3 and the World Ocean Database, continued</title><content type='html'>I got things sped up quite a bit by directly querying the database file I had created (see my last post) and by returning the query results as an array of watercolumn structures instead of writing them to disk and then reading them in again in my svp_tool.&lt;br /&gt;&lt;br /&gt;Here's the bit of code that deals with building the query:&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: x-small;"&gt;int wod_extract_profiles (WOD_Reader * wod_reader)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int rc;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; char *zErrMsg = 0;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int i;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int offset;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; char month_list[50];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; char instrument_list[50];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; char sql_string[500];&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; memset(month_list,0,50);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; memset(instrument_list,0,50);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; memset(sql_string,0,500);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // There must be easier ways to do this than the way I'm doing it&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; month_list[0]='(';&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; offset = 1;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for (i=1;i&amp;lt;=12;i++)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (!wod_reader-&amp;gt;query_bounds.month[i]) continue;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; sprintf(&amp;amp;month_list[offset],"%d,",i);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; offset = strlen(month_list);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; month_list[offset-1]=')';&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // There must be easier ways to do this than the way I'm doing it&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; instrument_list[0]='(';&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; offset = 1;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for (i=1;i&amp;lt;=WOD_NUM_TYPES;i++)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (!wod_reader-&amp;gt;query_bounds.instrument[i]) continue;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; sprintf(&amp;amp;instrument_list[offset],"%d,",i);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; offset = strlen(instrument_list);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; instrument_list[offset-1]=')';&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Check some of the query bounds before we start&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (wod_reader-&amp;gt;query_bounds.longitude_west &amp;gt; 180) wod_reader-&amp;gt;query_bounds.longitude_west -= 360;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (wod_reader-&amp;gt;query_bounds.longitude_east &amp;gt; 180) wod_reader-&amp;gt;query_bounds.longitude_east -= 360;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: x-small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Form the query: select records based on geo/time bounds and then sort in such a way that&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // the hits return in WOD filename order to minimize jumping around between files&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; sprintf(sql_string,"SELECT * FROM tbl1 WHERE latitude &amp;gt; %.3f AND latitude &amp;lt; %.3f AND longitude &amp;gt; %.3f AND longitude &amp;lt; %.3f AND month in %s AND instrument in %s ORDER BY instrument, observed, quadrant, wmo_lat, wmo_lon, year, month, day;",&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; wod_reader-&amp;gt;query_bounds.latitude_south, wod_reader-&amp;gt;query_bounds.latitude_north,&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; wod_reader-&amp;gt;query_bounds.longitude_west, wod_reader-&amp;gt;query_bounds.longitude_east,month_list,instrument_list);&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (wod_reader-&amp;gt;debug) printf("Doing SQL string %s\n",sql_string);&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; printf("Doing WOD query...patience\n");&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Do the query and deal with the results&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; rc = sqlite3_exec(wod_reader-&amp;gt;db, sql_string, wod_query_callback, wod_reader, &amp;amp;zErrMsg);&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (rc) error("SQL error: %s",zErrMsg);&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return(0);&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The callback function (wod_query_callback) in the sqlite3_exec call deals with the query results one at a time.&amp;nbsp; Here'swhat's going on in there:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;static int wod_query_callback(void * reader_in, int argc, char **argv, char **azColName)&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;{&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int i;&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int iend;&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int got_new_file;&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WOD_Reader *wod_reader;&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; char * inname = NULL;&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int file_offset, num_bytes;&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int instrument, observed, quadrant, wmo_lat, wmo_lon;&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; char type_lowercase[4];&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; char type_uppercase[4];&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; memset(type_uppercase,0,4);&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; memset(type_lowercase,0,4);&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; wod_reader = (WOD_Reader *) reader_in;&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; got_new_file = 0;&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Parse the output record from the query&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for(i=0; i&lt;argc; i++)=""&gt;&lt;/argc;&gt;&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (wod_reader-&amp;gt;debug) printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (!strcmp(azColName[i],"instrument"))&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; instrument = atoi(argv[i]);&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (instrument != wod_reader-&amp;gt;instrument) got_new_file++;&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else if (!strcmp(azColName[i],"observed"))&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; observed = atoi(argv[i]);&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (observed != wod_reader-&amp;gt;observed) got_new_file++;&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else if (!strcmp(azColName[i],"quadrant"))&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; quadrant = atoi(argv[i]);&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (quadrant != wod_reader-&amp;gt;quadrant) got_new_file++;&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else if (!strcmp(azColName[i],"wmo_lat"))&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; wmo_lat = atoi(argv[i]);&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (wmo_lat != wod_reader-&amp;gt;wmo_lat) got_new_file++;&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else if (!strcmp(azColName[i],"wmo_lon"))&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; wmo_lon = atoi(argv[i]);&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (wmo_lon != wod_reader-&amp;gt;wmo_lon) got_new_file++;&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else if (!strcmp(azColName[i],"file_offset"))&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; file_offset = atoi(argv[i]);&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else if (!strcmp(azColName[i],"num_bytes"))&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; num_bytes = atoi(argv[i]);&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (got_new_file)&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (wod_reader-&amp;gt;debug) printf("Need to load a new WOD file!!\n");&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Got a new file, so close the old one...&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; wod_close_file(wod_reader);&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; memcpy(type_uppercase,wod_data_types[instrument],3);&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; type_lowercase[0] = tolower(type_uppercase[0]);&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; type_lowercase[1] = tolower(type_uppercase[1]);&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; type_lowercase[2] = tolower(type_uppercase[2]);&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Build up the filename&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; inname = calloc(strlen(wod_reader-&amp;gt;wod_path)+50,1);&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; memset(inname,0,strlen(wod_reader-&amp;gt;wod_path)+50);&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // this the type of path that we're trying to construct: ctd/OBS/CTDO7807.gz&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; sprintf(inname,"%s/%s/OBS/%sO%d%d%0.2d.gz",&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; wod_reader-&amp;gt;wod_path,type_lowercase,type_uppercase,quadrant,wmo_lat,wmo_lon);&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (wod_open_file(wod_reader,inname))&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; sprintf(inname,"%s/%s/OBS/%sO%d%d%0.2d",wod_reader-&amp;gt;wod_path,type_lowercase,type_uppercase,&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; quadrant,wmo_lat,wmo_lon);&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (wod_open_file(wod_reader,inname))&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; printf("Can't open file %s ... non-existant??\n",inname);&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; free(inname);&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; inname = NULL;&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return(1);&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (inname) free(inname);&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; inname = NULL;&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (wod_reader-&amp;gt;debug) printf("%s: fseeking to %d for %d bytes\n",wod_reader-&amp;gt;fname, file_offset,num_bytes);&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Seek to the right spot in the file&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; fseek(wod_reader-&amp;gt;fp,file_offset,SEEK_SET);&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Now read the profile at that location&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ((iend = oclread (wod_reader)) == -1)&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; wod_close_file(wod_reader);&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return(1);&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Convert the cast to OMG SVP format, this updates the extracted_watercolumns array&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; wod2svp(wod_reader);&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return 0;&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Now I've just got to build a query building utility in the graphical end that lets the user select instrument, month and/or other fields.&amp;nbsp; Geographic bounds are currently selected by lasso in the map viewer and the month defaults to the current month.&lt;br /&gt;&lt;br /&gt;I'm also planning on speeding up the oclread function (was delivered with the free NODC code that came with the WOD), right now it's reading things a single field at a time and I think it can be sped up a bit by reading the entire cast into memory and then parsing it from there.&lt;br /&gt;&lt;br /&gt;jb&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/258056851683254325-1872559433938287554?l=2bitbrain.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://2bitbrain.blogspot.com/feeds/1872559433938287554/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://2bitbrain.blogspot.com/2010/08/sqlite3-and-world-ocean-database.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/258056851683254325/posts/default/1872559433938287554'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/258056851683254325/posts/default/1872559433938287554'/><link rel='alternate' type='text/html' href='http://2bitbrain.blogspot.com/2010/08/sqlite3-and-world-ocean-database.html' title='sqlite3 and the World Ocean Database, continued'/><author><name>Jonnyb</name><uri>http://www.blogger.com/profile/17969795764233636985</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_Pc5sciCQfw4/S7veI9tzJWI/AAAAAAAAAAM/VmEgIF3mpHk/S220/Photo+on+2010-04-06+at+21.19.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-258056851683254325.post-9197685418542613672</id><published>2010-07-30T11:58:00.001-04:00</published><updated>2010-07-30T12:02:39.471-04:00</updated><title type='text'>sqlite3 and the World Ocean Database</title><content type='html'>I'm working on getting the World Ocean Database (WOD) to be directly accessible by my svp_tool (sound velocity processing toolkit) and wanted to document some of the procedure I took.&amp;nbsp; Here's a map view of a query area near the Mariana Trench, the green squares show the locations of the 125 CTD casts in the WOD (for the month of August).&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_Pc5sciCQfw4/TFL1Tr3tecI/AAAAAAAAAAw/z2yDI1ljTZk/s1600/Screen+shot+2010-07-30+at+11.52.16+AM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_Pc5sciCQfw4/TFL1Tr3tecI/AAAAAAAAAAw/z2yDI1ljTZk/s320/Screen+shot+2010-07-30+at+11.52.16+AM.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;The resulting sound speed, temperature and salinity vertical profiles are shown below (left to right, all plotted versus depth on the vertical axis). &lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_Pc5sciCQfw4/TFL1WdSqF_I/AAAAAAAAAA4/b6BPyidARLQ/s1600/Screen+shot+2010-07-30+at+11.52.19+AM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_Pc5sciCQfw4/TFL1WdSqF_I/AAAAAAAAAA4/b6BPyidARLQ/s320/Screen+shot+2010-07-30+at+11.52.19+AM.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;The WOD is a database of oceanographic data that records physical/biological/chemical oceanographic measurements, currently the 2009 database holds ~10 million sets of measurements.  The data are organized spatially by WMO squares and by instrument type resulting in 12,960 files.  I'm mainly interested in XBT and CTD measurements; the files that I need to tuck into and extract temperature and/or salinity profiles based on a user selected geographic region and range of months.  The unzipped files are in an awkward ASCII format that take up about 6GB on the disk in gzip format.  I'd like to make the lookup options as quick as possible so:&lt;br /&gt;&lt;br /&gt;0) Wrap up the sample I/O C program as a C library (wod.{c,h}).  The sample program that comes with the database has lots of global variables so I just wrapped it all up in a structure and then wrote some functions to initialize, open/close files, read data that neatly hide away the details and keep the programmer (me) from stepping on my own toes with all those globals and obscure function calls that need to be done just to read a single cast.&lt;br /&gt;&lt;br /&gt;1) Build a database.  The raw files contain header information (position, date, cruise number, etc) and then the measurements themselves.  Having to unzip files just to search through to find casts that intersect the area of interest is slow and painful.  I took the sample C program to read the WOD from their website and my new C library (wod.{c,h}) and morphed it into a program that writes out a sqlite3 database that contains only a small subset of the info in the header so that I can quickly query and find casts.  The database also contains enough info to determine which of the 12,960 files an individual cast falls within and its file offset.  Based on some advice from Kurt, I went with sqlite3 and googled my way through the problem.  Here are a few juicy bits from the code, it was pretty simple in the end.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-small;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;#include &lt;/span&gt;&lt;/span&gt;&lt;sqlite3.h&gt;&lt;span style="font-size: x-small;"&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt; int main()&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt; {&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt; ....&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt; // declaration&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt; sqlite3 *db;&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt; ....&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt; // open a database with (char * outname)&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt; sqlite3_open(outname, &amp;amp;db);&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt; ....&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt; // Create a table, will puke if the table has been added already&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt; sqlite3_exec(db, "create table tbl1 (instrument integer, observed integer, quadrant integer, wmo_lat integer, wmo_lon integer, latitude real, longitude real, year integer, month integer, day integer, file_offset integer)", callback, 0, &amp;amp;zErrMsg);&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt; .....&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt; // Now insert some records&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt; sprintf(sql_string,"INSERT INTO tbl1 (instrument, observed, quadrant, wmo_lat, wmo_lon, \&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;                 latitude, longitude, year, month, day, file_offset) VALUES (%d,%d,%d,%d,%d,%.3f,%.3f,%4d,%d,%d,%d)",&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;                 wod_reader.instrument,wod_reader.observed,wod_reader.quadrant,&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;                 wod_reader.wod_lat,wod_reader.wod_lon,&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;                 wod_reader.latitude,wod_reader.longitude,&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;                 wod_reader.year,wod_reader.month,wod_reader.day,file_offset);&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;             rc = sqlite3_exec(db, sql_string, callback, 0, &amp;amp;zErrMsg); &lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt; // Build indices based on latitude and longitude as I expect to be querying against&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt; // these most often&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt; sqlite3_exec(db, "CREATE INDEX tbl1_idx_longitude ON tbl1(longitude)", callback, 0, &amp;amp;zErrMsg);&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt; sqlite3_exec(db, "CREATE INDEX tbl1_idx_latitude ON tbl1(latitude)", callback, 0, &amp;amp;zErrMsg);&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt; // Now close the database.&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt; sqlite3_close(db);&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt; ...&lt;/span&gt;&lt;br style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt; }&lt;/span&gt;&lt;/span&gt;   &lt;br /&gt;&lt;br /&gt;Kurt had suggested using the SQLite Manager extension in Firefox to have a peek at what's in the database.  I did so, and everything seemed okay.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Next steps?&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;- add sqlite3 querying ability into svp_tool&lt;br /&gt;- add functionality to wod.{c,h} to read casts based on query results, right now it searches the entire WOD namespace and quickly rejects files that can't possibly intersect the spatial query bounds.&amp;nbsp; Those that do intersect are then unzipped and search sequentially to find the observations that fall within a specified area (and month).&amp;nbsp; ALL records are read through in their entirety even though MOST aren't desired.&lt;br /&gt;- modify wod.{c,h} to deal with reading the .gz files directly through zlib instead of gunzipping and then gzipping the files for each extraction.&lt;br /&gt;&lt;/sqlite3.h&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/258056851683254325-9197685418542613672?l=2bitbrain.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://2bitbrain.blogspot.com/feeds/9197685418542613672/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://2bitbrain.blogspot.com/2010/07/sqlite3-and-world-ocean-database.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/258056851683254325/posts/default/9197685418542613672'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/258056851683254325/posts/default/9197685418542613672'/><link rel='alternate' type='text/html' href='http://2bitbrain.blogspot.com/2010/07/sqlite3-and-world-ocean-database.html' title='sqlite3 and the World Ocean Database'/><author><name>Jonnyb</name><uri>http://www.blogger.com/profile/17969795764233636985</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_Pc5sciCQfw4/S7veI9tzJWI/AAAAAAAAAAM/VmEgIF3mpHk/S220/Photo+on+2010-04-06+at+21.19.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_Pc5sciCQfw4/TFL1Tr3tecI/AAAAAAAAAAw/z2yDI1ljTZk/s72-c/Screen+shot+2010-07-30+at+11.52.16+AM.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-258056851683254325.post-6878673269843219494</id><published>2010-04-07T09:07:00.002-04:00</published><updated>2010-04-07T09:09:26.770-04:00</updated><title type='text'>Follow up on compiling OMG code</title><content type='html'>So, I mentioned yesterday that I was gearing up to compile a bunch of C-code that I use but then never really described how to get through the compilation step of the code.&amp;nbsp; The code I'm referring to is a bundle of programs put together by the Ocean Mapping Group at the University of New Brunswick in Fredericton, Canada.&amp;nbsp; The group maintains a code repository, to check out a version you'll need to contact someone from the group to get access.  This assumes that you've installed Xcode and the extra packages outlined in my post from yesterday.  Here it is again, just in case (don't forget to download and install Xcode first):&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;$ fink install lesstif&lt;br /&gt;$ fink install gsl&lt;br /&gt;$ fink install imagemagick&lt;br /&gt;$ fink install gmt&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Step 1 is to get the code repository.  You'll need to change "user" to your username given to you by the OMG sys admin folks and machine to the machine they tell you that the repository is stored on.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;$ svn checkout svn+ssh://user@machine.omg.unb.ca/drives/machine/disk1/code&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;That'll checkout the repository (name "code") into the directory you're currently sitting in.  You can move it anywhere on your file system after you've checked it out.&lt;br /&gt;&lt;br /&gt;Step 2 is to set up some environment variables in your shell's configuration files; these direct the code compiling script on where to install things and also update your path with the appropriate directory.  I had decided to switch from &lt;code&gt;tcsh&lt;/code&gt; to &lt;code&gt;bash&lt;/code&gt; since I was already making a transition from PC to Mac, so I had to put together some config files for &lt;code&gt;bash&lt;/code&gt; in my home directory.  Here's a dump from the &lt;code&gt;.bash_profile&lt;/code&gt; file that I cobbled together.  You'll need to change &lt;code&gt;username&lt;/code&gt; to your username.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;PATH=$PATH:/Users/username/local/bin&lt;br /&gt;export PATH&lt;br /&gt;&lt;br /&gt;# For OMG software development&lt;br /&gt;export DEVELOPMENT_HOME=/Users/username&lt;br /&gt;# Sneaky way to shoehorn 32 bit architecture into the makefiles&lt;br /&gt;export CCOMPILER="gcc -m32"&lt;br /&gt;export LOCALLIB=/Users/username/local/lib&lt;br /&gt;export LOCALBIN=/Users/username/local/bin&lt;br /&gt;export LOCALOBJ=/Users/username/local/obj&lt;br /&gt;&lt;br /&gt;# For subversion, but only if you're doing commits&lt;br /&gt;export SVN_EDITOR=/usr/bin/vi&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Step 3.  After that's done, it's time to compile.  This uses a mildly flaky script that compiles everything in the appropriate order and then places all the goodies in the locations specified by the environment variables defined earlier.  The script is written in &lt;code&gt;tcsh&lt;/code&gt;, so you might want to make sure you have that installed (it was on my Mac, but you have to install it on Ubuntu).  The script will dump everything in &lt;code&gt;~/local&lt;/code&gt;, again, based on the environment variables set earlier.  It will also create an error.log file with a listing of everything it had trouble with.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;$ cd ~/code&lt;br /&gt;$ ./compile_every_gd_thing&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;That should do it!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/258056851683254325-6878673269843219494?l=2bitbrain.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://2bitbrain.blogspot.com/feeds/6878673269843219494/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://2bitbrain.blogspot.com/2010/04/so-i-mentioned-yesterday-that-i-was.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/258056851683254325/posts/default/6878673269843219494'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/258056851683254325/posts/default/6878673269843219494'/><link rel='alternate' type='text/html' href='http://2bitbrain.blogspot.com/2010/04/so-i-mentioned-yesterday-that-i-was.html' title='Follow up on compiling OMG code'/><author><name>Jonnyb</name><uri>http://www.blogger.com/profile/17969795764233636985</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_Pc5sciCQfw4/S7veI9tzJWI/AAAAAAAAAAM/VmEgIF3mpHk/S220/Photo+on+2010-04-06+at+21.19.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-258056851683254325.post-4191379017705278023</id><published>2010-04-06T21:48:00.000-04:00</published><updated>2010-04-06T21:48:41.680-04:00</updated><title type='text'>Getting my Mac on</title><content type='html'>I started my new job on Friday and I had come face to face with what seemed like a good idea one month earlier:&amp;nbsp; I was going to switch my digital life from a PC to a Mac.&amp;nbsp; Backstory: I've been living off of a 5 year old Dell Latitude that was dual-booting Windows XP (used only for MS Office) and Xubuntu (9.10) and was sick and tired of rebooting into windows just to have a clean look at Powerpoint and Word files.&amp;nbsp; I'm a command line kind of guy so I figured I could do all of that on a Mac without the Windows hassle.&amp;nbsp; That was the logic behind the move, only time will tell whether it was the right decision.&amp;nbsp; I'm using this blog to document everything I've done during the transition so that I might someday remember all of this if I have to move to another Mac.&amp;nbsp; Maybe it might even be useful to another Mac newbie.&lt;br /&gt;&lt;br /&gt;As a few days have passed already, I'm just jotting down stuff from memory.&amp;nbsp; First order of business was to make sure I could compile all the C-code I've been working with over the years.&amp;nbsp; After talking to some co-workers, I found out I need to install this stuff:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Xcode: this puts all sorts of development goodies at my fingertips, e.g. gcc, X headers for Linuxy graphics programs I use.&amp;nbsp; After signing up to be an official Apple Developer (Mom would be so proud), I downloaded an archived .dmg file which installed simply by dragging it onto my Application folder.&lt;/li&gt;&lt;li&gt;fink: this lets me get lots of open source code that I use for some of my software development and scripts that I use in my research.&amp;nbsp; Stuff I really needed to get going was the GNU Scientific Libraries, GMT, ImageMagick, lesstif and a few others I can't remember off the top of my head.&amp;nbsp; Fink downloaded as a tarball and was pretty painless to install.&amp;nbsp; It asked an awful lot of questions and I just went with the defaults but found out afterwards that I should have probably chosen the "unstable" branch but it's worked well for me so far.&lt;/li&gt;&lt;/ul&gt;I googled my way through importing my email from Thunderbird on my PC to the Mac.&amp;nbsp; Most folks suggested just copying over your "profile" folder and updating profile.ini with your old profile name.&amp;nbsp; It worked for me without any difficulties.&amp;nbsp; Probably should have made sure I had the same version of Thunderbird running on the PC and the Mac but didn't think of this until I was halfway through.&lt;br /&gt;&lt;br /&gt;That's it for now...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/258056851683254325-4191379017705278023?l=2bitbrain.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://2bitbrain.blogspot.com/feeds/4191379017705278023/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://2bitbrain.blogspot.com/2010/04/getting-my-mac-on.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/258056851683254325/posts/default/4191379017705278023'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/258056851683254325/posts/default/4191379017705278023'/><link rel='alternate' type='text/html' href='http://2bitbrain.blogspot.com/2010/04/getting-my-mac-on.html' title='Getting my Mac on'/><author><name>Jonnyb</name><uri>http://www.blogger.com/profile/17969795764233636985</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_Pc5sciCQfw4/S7veI9tzJWI/AAAAAAAAAAM/VmEgIF3mpHk/S220/Photo+on+2010-04-06+at+21.19.jpg'/></author><thr:total>0</thr:total></entry></feed>
