Create Timeline Plot of Platforms in a STOQS Database

Walk through activities of the database and summarize platform time in water

Executing this Notebook requires a personal STOQS server. Follow the steps to build your own development system — this will take a few hours and depends on a good connection to the Internet. Once your server is up log into it (after a cd ~/Vagrants/stoqsvm) and activate your virtual environment with the usual commands:

vagrant ssh -- -X
cd /vagrant/dev/stoqsgit
source venv-stoqs/bin/activate

Connect to your Institution's STOQS database server using read-only credentials. (Note: firewalls typically limit unprivileged access to such resources.)

cd stoqs
ln -s mbari_campaigns.py campaigns.py
export DATABASE_URL=postgis://everyone:guest@kraken.shore.mbari.org:5433/stoqs

Launch Jupyter Notebook on your system with:

cd contrib/notebooks
../../manage.py shell_plus --notebook

navigate to this file and open it. You will then be able to execute the cells and experiment with this notebook.


For the KISS April 2017 campaign add up the hours and collect in a dictionary all the platform start and end times using Matplotlib mdate format:


In [1]:
from collections import defaultdict
from datetime import timedelta
import matplotlib.dates as mdates
import operator

db = 'stoqs_canon_april2017'

plat_start_ends = defaultdict(list)
plat_depl_dur = {}
print('Platform Name     # Deployments   Hours')
print('-------------     -------------   -----')
for plat in Platform.objects.using(db).all():
    time_diff_sum = timedelta(0)
    for act in Activity.objects.using(db).filter(platform=plat):
        time_diff = act.enddate - act.startdate
        time_diff_sum += time_diff
        plat_start_ends[plat].append((mdates.date2num(act.startdate), 
                                      mdates.date2num(act.enddate)))

    plat_depl_dur[plat] = (len(plat_start_ends[plat]), 
                           time_diff_sum.total_seconds() / 3600)
    print(f'{plat.name:20s} {plat_depl_dur[plat][0]:10d} {plat_depl_dur[plat][1]:7.1f}')


Platform Name     # Deployments   Hours
-------------     -------------   -----
tethys                       35   341.9
NPS_Glider_34                 1   910.0
SG_Glider_621               335   703.6
dorado                        3    65.3
Slocum_nemesis              127   173.5
SG_Glider_539               322   686.5
opah                        306   282.4
WesternFlyer_PCTD            37    10.1
OA1_Mooring                   1   912.0
OA2_Mooring                   1   912.0
M1_Mooring                    1   912.0
wg_Tiny_Glider                1   912.0
SPRAY_L66a_Glider             1   912.0
daphne                       41   291.3
aku                          45   254.1
ahi                           2     1.6
WesternFlyer_UCTD            26    90.1

Activity start and end date values may be incorrect in legacy databases. To correct them this script can be run by the database admininstrator to update them based on the actual InstantPoint timevalues:

db = 'stoqs_canon_april2017'
for act in Activity.objects.using(db):
    ip_qs = (InstantPoint.objects.using(db)
                .filter(activity=act)
                .aggregate(Max('timevalue'), Min('timevalue')))
    if ip_qs['timevalue__min'] and ip_qs['timevalue__max']:
        act.startdate = ip_qs['timevalue__min']
        act.enddate = ip_qs['timevalue__max']
        act.save(using=db)
    else:
        act.delete(using=db)

In [2]:
%matplotlib inline

import matplotlib.pyplot as plt
import matplotlib.dates as mdates
from matplotlib import pylab
from numpy import arange

pylab.rcParams['figure.figsize'] = (15, 9);
fig, ax = plt.subplots()
plat_labels = []

# Annotate at max x value and plot in order by platformtype name 
xpos = max([dr[1] for dr in list(plat_start_ends.values())[0]])
for ypos, plat in enumerate(
                    sorted(plat_start_ends.keys(),
                           key=operator.attrgetter('platformtype.name'))):
    plat_labels.append(f'{plat.name} ({plat.platformtype.name})')    
    for bdate, edate in plat_start_ends[plat]:
        ax.barh(ypos+0.5, edate - bdate, left=bdate, height=0.8, 
                align='center', color='#' + plat.color, alpha=0.5)
    if plat_depl_dur[plat][0] == 1:
        fmt = '{:10d} deployment {:7.1f} hours'
    else:
        fmt = '{:10d} deployments {:7.1f} hours'
    ax.annotate(fmt.format(plat_depl_dur[plat][0], plat_depl_dur[plat][1]),
                verticalalignment='center', horizontalalignment='right', 
                xy=(xpos, ypos+0.5), fontsize=13, )    

ax.set_title(Campaign.objects.using(db).get(id=1).description)
ax.set_ylim(-0.5, len(plat_labels) + 0.5)
ax.set_yticks(arange(len(plat_labels)) + 0.5)
ax.set_yticklabels(plat_labels)
ax.grid(True)
plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%m/%d/%Y'))
plt.gca().xaxis.set_major_locator(mdates.WeekdayLocator(byweekday=mdates.MO))
plt.gca().xaxis.set_minor_locator(mdates.DayLocator())
plt.gcf().autofmt_xdate()
plt.show()



In [ ]: