import colorsys
from rowers.models import Workout, User, Rower, WorkoutForm,RowerForm,GraphImage
from rowingdata import rower as rrower
from rowingdata import main as rmain
from rowingdata import cumcpdata,histodata

from rowingdata import rowingdata as rrdata
from math import pi
from django.utils import timezone

from bokeh.palettes import Dark2_8 as palette
import itertools
from bokeh.plotting import figure, ColumnDataSource, Figure,curdoc
from bokeh.models import CustomJS,Slider, TextInput,BoxAnnotation
from bokeh.charts import Histogram,HeatMap,Area,BoxPlot,Bar
from bokeh.resources import CDN,INLINE
from bokeh.embed import components
from bokeh.layouts import layout,widgetbox
from bokeh.layouts import row as layoutrow
from bokeh.layouts import column as layoutcolumn
from bokeh.models import LinearAxis,LogAxis,Range1d,DatetimeTickFormatter,HoverTool
from bokeh.io import output_file, show, vplot
from bokeh.models import (
    GMapPlot, GMapOptions, ColumnDataSource, Circle,
    DataRange1d, PanTool, WheelZoomTool, BoxSelectTool,
    SaveTool,	ResizeTool, ResetTool, TapTool,CrosshairTool,BoxZoomTool,
    Span, Label
)
from bokeh.models.glyphs import ImageURL

#from bokeh.models.widgets import Slider, Select, TextInput
from bokeh.core.properties import value

from collections import OrderedDict
from django.conf import settings

import datetime
import math
import numpy as np
import pandas as pd
from pytz import timezone as tz,utc
from django.utils.timezone import get_current_timezone
from django.utils.timezone import activate
activate(settings.TIME_ZONE)
thetimezone = get_current_timezone()

from scipy.stats import linregress
from scipy import optimize
from scipy.signal import savgol_filter

import stravastuff

from rowers.dataprep import rdata
import rowers.dataprep as dataprep

from rowers.metrics import axes,axlabels,yaxminima,yaxmaxima

from utils import lbstoN
import datautils

watermarkurl = "/static/img/logo7.png"
watermarksource = ColumnDataSource(dict(
    url = [watermarkurl],))

watermarkrange = Range1d(start=0,end=1)
watermarkalpha = 0.6
watermarkx = 0.99
watermarky = 0.01
watermarkw = 184
watermarkh = 35
watermarkanchor = 'bottom_right'

def errorbar(fig, x, y, source=ColumnDataSource(),
             xerr=False, yerr=False, color='black', 
             point_kwargs={}, error_kwargs={}):


    xvalues = source.data[x]
    yvalues = source.data[y]

    xerrvalues = source.data['xerror']
    yerrvalues = source.data['yerror']
    try:
        colorvalues = source.data['color']
    except KeyError:
        colorvalues = ["#%02x%02x%02x" % (255,0,0) for x in xvalues]

        
    try:
        a = xvalues[0]+1
        if xerr:
            x_err_x = []
            x_err_y = []
            err_color = []
            for px, py, err, color in zip(xvalues, yvalues, xerrvalues, colorvalues):
                x_err_x.append((px - err, px + err))
                x_err_y.append((py, py))
                (r, g, b) = tuple(int(color[i:i+2],16) for i in (1, 3, 5))
                h,s,v = colorsys.rgb_to_hsv(r/255., g/255., b/255.)
                v = v*0.8
                r, g, b = colorsys.hsv_to_rgb(h, s, v)
                color2 = "#%02x%02x%02x" % (int(255.*r), int(255.*g), int(255*b))
                err_color.append(color2)

            fig.multi_line(x_err_x, x_err_y, color=err_color,
                           name='xerr',
                           **error_kwargs)
    except TypeError:
        pass

    try:
        a = yvalues[0]+1
        if yerr:
            y_err_x = []
            y_err_y = []
            err_color = []
            for px, py, err, color in zip(xvalues, yvalues, yerrvalues, colorvalues):
                y_err_x.append((px, px))
                y_err_y.append((py - err, py + err))
                (r, g, b) = tuple(int(color[i:i+2],16) for i in (1, 3, 5))
                h,s,v = colorsys.rgb_to_hsv(r/255., g/255., b/255.)
                v = v*0.8
                r, g, b = colorsys.hsv_to_rgb(h, s, v)
                color2 = "#%02x%02x%02x" % (int(255.*r), int(255.*g), int(255*b))
                err_color.append(color2)
                
            fig.multi_line(y_err_x, y_err_y, color=err_color,
                           name='yerr',**error_kwargs)
    except TypeError:
        pass

    fig.circle(x, y, source=source, name='data',color=color,
               **point_kwargs)

    
def tailwind(bearing,vwind,winddir):
    """ Calculates head-on head/tailwind in direction of rowing

    positive numbers are tail wind

    """

    b = np.radians(bearing)
    w = np.radians(winddir)

    vtail = -vwind*np.cos(w-b)
    
    return vtail


from rowers.dataprep import nicepaceformat,niceformat
from rowers.dataprep import timedeltaconv    

def interactive_boxchart(datadf,fieldname,extratitle=''):

    if datadf.empty:
        return '','It looks like there are no data matching your filter'
    
    TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,resize,hover'

    plot = BoxPlot(datadf, values=fieldname, label='date',
                   legend=False,
                   title=axlabels[fieldname]+' '+extratitle,
                   outliers=False,
                   tools=TOOLS,
		   toolbar_location="above",
                   toolbar_sticky=False,
                   x_mapper_type='datetime')

    yrange1 = Range1d(start=yaxminima[fieldname],end=yaxmaxima[fieldname])
    plot.y_range = yrange1

    plot.xaxis.axis_label = 'Date'
    plot.yaxis.axis_label = axlabels[fieldname]


    # add watermark
    plot.extra_y_ranges = {"watermark": watermarkrange}
    plot.extra_x_ranges = {"watermark": watermarkrange}

    plot.image_url([watermarkurl],watermarkx,watermarky,
                   watermarkw,watermarkh,
                   global_alpha=watermarkalpha,
                   w_units='screen',
                   h_units='screen',
                   anchor=watermarkanchor,
                   dilate=True,
                   x_range_name = "watermark",
                   y_range_name = "watermark",
                   )

    
    plot.xaxis.formatter = DatetimeTickFormatter(
        days=["%d %B %Y"],
        months=["%d %B %Y"],
        years=["%d %B %Y"],
        )

    if fieldname == 'pace':
	plot.yaxis[0].formatter = DatetimeTickFormatter(
		seconds = ["%S"],
		minutes = ["%M"]
	    )


    plot.xaxis.major_label_orientation = pi/4

    hover = plot.select(dict(type=HoverTool))

    hover.tooltips = OrderedDict([
	('Value','@y'),
        ('Date','@x'),
	])

    hover.mode = 'mouse'

    script, div = components(plot)

    return script,div


def interactive_activitychart(workouts,startdate,enddate):
    if len(workouts) == 0:
        return "",""
    
    dates = []
    types = []
    durations = []

    for w in workouts:
        if w.privacy == 'visible':
            dd = w.date.strftime('%m/%d')
            du = w.duration.hour*60+w.duration.minute
            dates.append(dd)
            durations.append(du)
            types.append(w.workouttype)

    try:
        d = utc.localize(startdate)
    except ValueError:
        d = startdate

    try:
        enddate = utc.localize(enddate)
    except ValueError:
        pass

        
    while d<=enddate:
        dates.append(d.strftime('%m/%d'))
        durations.append(0)
        types.append('rower')
        d += datetime.timedelta(days=1)
                     

    df = pd.DataFrame({
        'date':dates,
        'duration':durations,
        'type':types,
        })
                      
    p = Bar(df,'date',values='duration',title='Activity',
            stack='type',
    	    plot_width=350,
	    plot_height=250,
            toolbar_location = None, 
    )

    for legend in p.legend:
        new_items = []
        for legend_item in legend.items:
            it = legend_item.label['value']
            tot = df[df['type']==it].duration.sum()
            if tot != 0:
                new_items.append(legend_item)
        legend.items = new_items

    
    p.legend.location = "top_left"
    p.legend.background_fill_alpha = 0.7

    p.yaxis.axis_label = 'Minutes'
    
    script, div = components(p)

    return script,div

def interactive_forcecurve(theworkouts,workstrokesonly=False):
    TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,hover,resize,crosshair'

    ids = [int(w.id) for w in theworkouts]

    boattype = theworkouts[0].boattype
    
    columns = ['catch','slip','wash','finish','averageforce',
               'peakforceangle','peakforce','spm','distance',
               'workoutstate','driveenergy']
    
    rowdata = dataprep.getsmallrowdata_db(columns,ids=ids)
    
    rowdata.dropna(axis=1,how='all',inplace=True)
    rowdata.dropna(axis=0,how='any',inplace=True)

    workoutstateswork = [1,4,5,8,9,6,7]
    workoutstatesrest = [3]
    workoutstatetransition = [0,2,10,11,12,13]

    if workstrokesonly:
	try:
	    rowdata = rowdata[~rowdata['workoutstate'].isin(workoutstatesrest)]
	except KeyError:
	    pass

    if rowdata.empty:
	return "","No Valid Data Available","",""

    try:
        catchav = rowdata['catch'].mean()
    except KeyError:
        catchav = 0

    try:
        finishav = rowdata['finish'].mean()
    except KeyError:
        finishav = 0
    try:
        washav = rowdata['wash'].mean()
    except KeyError:
        washav = 0

    try:
        slipav = rowdata['slip'].mean()
    except KeyError:
        slipav = 0

    try:
        peakforceav = rowdata['peakforce'].mean()
    except KeyError:
        peakforceav = 0

    try:
        averageforceav = rowdata['averageforce'].mean()
    except KeyError:
        averageforceav = 0

    try:
        peakforceangleav = rowdata['peakforceangle'].mean()
    except KeyError:
        peakforceangleav = 0

    x = [catchav,
         catchav+slipav,
         peakforceangleav,
         finishav-washav,
         finishav]

    thresholdforce = 100 if 'x' in boattype else 200
    #thresholdforce /= 4.45 # N to lbs
    y = [0,thresholdforce,
         peakforceav,
         thresholdforce,0]

    source = ColumnDataSource(
        data = dict(
            x = x,
            y = y,
        ))

    
    source2 = ColumnDataSource(
        rowdata
        )

    plot = Figure(tools=TOOLS,
		  toolbar_sticky=False)

    # add watermark
    plot.extra_y_ranges = {"watermark": watermarkrange}
    plot.extra_x_ranges = {"watermark": watermarkrange}

    plot.image_url([watermarkurl],watermarkx,watermarky,
                   watermarkw,watermarkh,
                   global_alpha=watermarkalpha,
                   w_units='screen',
                   h_units='screen',
                   anchor=watermarkanchor,
                   dilate=True,
                   x_range_name = "watermark",
                   y_range_name = "watermark",
                   )

    avf = Span(location=averageforceav,dimension='width',line_color='blue',
               line_dash=[6,6],line_width=2)
    
    plot.line('x','y',source=source,color="red")

    plot.add_layout(avf)
    
    peakflabel = Label(x=455,y=530,x_units='screen',y_units='screen',
                       text="Fpeak: {peakforceav:6.2f}".format(peakforceav=peakforceav),
                       background_fill_alpha=.7,
                       background_fill_color='white',
                       text_color='blue',
    )

    avflabel = Label(x=465,y=500,x_units='screen',y_units='screen',
                     text="Favg: {averageforceav:6.2f}".format(averageforceav=averageforceav),
                     background_fill_alpha=.7,
                     background_fill_color='white',
                     text_color='blue',
    )

    catchlabel = Label(x=460,y=470,x_units='screen',y_units='screen',
                       text="Catch: {catchav:6.2f}".format(catchav=catchav),
                       background_fill_alpha=0.7,
                       background_fill_color='white',
                       text_color='red',
                       )

    peakforceanglelabel = Label(x=420,y=440,x_units='screen',y_units='screen',
                                text="Peak angle: {peakforceangleav:6.2f}".format(peakforceangleav=peakforceangleav),
                                background_fill_alpha=0.7,
                                background_fill_color='white',
                                text_color='red',
                       )

    finishlabel = Label(x=455,y=410,x_units='screen',y_units='screen',
                        text="Finish: {finishav:6.2f}".format(finishav=finishav),
                        background_fill_alpha=0.7,
                        background_fill_color='white',
                        text_color='red',
                       )

    sliplabel = Label(x=470,y=380,x_units='screen',y_units='screen',
                      text="Slip: {slipav:6.2f}".format(slipav=slipav),
                      background_fill_alpha=0.7,
                      background_fill_color='white',
                      text_color='red',
                       )

    washlabel = Label(x=460,y=350,x_units='screen',y_units='screen',
                      text="Wash: {washav:6.2f}".format(washav=washav),
                      background_fill_alpha=0.7,
                      background_fill_color='white',
                      text_color='red',
    )

    plot.add_layout(peakflabel)
    plot.add_layout(peakforceanglelabel)
    plot.add_layout(avflabel)
    plot.add_layout(catchlabel)
    plot.add_layout(sliplabel)
    plot.add_layout(washlabel)
    plot.add_layout(finishlabel)

    plot.xaxis.axis_label = "Angle"
    plot.yaxis.axis_label = "Force (N)"
    plot.title.text = theworkouts[0].name
    plot.title.text_font_size=value("1.0em")

    yrange1 = Range1d(start=0,end=900)
    plot.y_range = yrange1

    xrange1 = Range1d(start=yaxmaxima['catch'],end=yaxmaxima['finish'])
    plot.x_range = xrange1

    callback = CustomJS(args = dict(
        source=source,
        source2=source2,
        avf=avf,
        avflabel=avflabel,
        catchlabel=catchlabel,
        finishlabel=finishlabel,
        sliplabel=sliplabel,
        washlabel=washlabel,
        peakflabel=peakflabel,
        peakforceanglelabel=peakforceanglelabel,
    ), code="""
       var data = source.data
       var data2 = source2.data
                               
       var x = data['x']
       var y = data['y']
       var spm1 = data2['spm']
       var distance1 = data2['distance']
       var driveenergy1 = data2['driveenergy']

       var thresholdforce = y[1]
       
       var c = source2.data['catch']
       var finish = data2['finish']
       var slip = data2['slip']
       var wash = data2['wash']
       var peakforceangle = data2['peakforceangle']
       var peakforce = data2['peakforce']
       var averageforce = data2['averageforce']

       var minspm = minspm.value
       var maxspm = maxspm.value
       var mindist = mindist.value
       var maxdist = maxdist.value
       var minwork = minwork.value
       var maxwork = maxwork.value

       var catchav = 0
       var finishav = 0
       var slipav = 0
       var washav = 0
       var peakforceangleav = 0
       var averageforceav = 0
       var peakforceav = 0
       var count = 0


      for (i=0; i<c.length; i++) {
	  if (spm1[i]>=minspm && spm1[i]<=maxspm) {
	     if (distance1[i]>=mindist && distance1[i]<=maxdist) {
                if (driveenergy1[i]>=minwork && driveenergy1[i]<=maxwork) {
		   catchav += c[i]
		   finishav += finish[i]
		   slipav += slip[i]
		   washav += wash[i]
		   peakforceangleav += peakforceangle[i]
		   averageforceav += averageforce[i]
                   peakforceav += peakforce[i]
                   count += 1
                   }
		}
	     }
       }

       catchav /= count
       finishav /= count
       slipav /= count
       washav /= count
       peakforceangleav /= count
       peakforceav /= count
       averageforceav /= count

       data['x'] = [catchav,catchav+slipav,peakforceangleav,finishav-washav,finishav]
       data['y'] = [0,thresholdforce,peakforceav,thresholdforce,0]

       avf.location = averageforceav
       avflabel.text = 'Favg: '+averageforceav.toFixed(2)
       catchlabel.text = 'Catch: '+catchav.toFixed(2)
       finishlabel.text = 'Finish: '+finishav.toFixed(2)
       sliplabel.text = 'Slip: '+slipav.toFixed(2)
       washlabel.text = 'Wash: '+washav.toFixed(2)
       peakflabel.text = 'Fpeak: '+peakforceav.toFixed(2)
       peakforceanglelabel.text = 'Peak angle: '+peakforceangleav.toFixed(2)
 
       source.trigger('change');
       """)

    slider_spm_min = Slider(start=15.0, end=55,value=15.0, step=.1,
		title="Min SPM",callback=callback)
    callback.args["minspm"] = slider_spm_min
    

    slider_spm_max = Slider(start=15.0, end=55,value=55.0, step=.1,
		title="Max SPM",callback=callback)
    callback.args["maxspm"] = slider_spm_max

    slider_work_min = Slider(start=0, end=1500,value=0, step=10,
		title="Min Work per Stroke",callback=callback)
    callback.args["minwork"] = slider_work_min
    

    slider_work_max = Slider(start=0, end=1500,value=1500, step=10,
		title="Max Work per Stroke",callback=callback)
    callback.args["maxwork"] = slider_work_max

    distmax = 100+100*int(rowdata['distance'].max()/100.)
    
    slider_dist_min = Slider(start=0,end=distmax,value=0,step=1,
			     title="Min Distance",callback=callback)
    callback.args["mindist"] = slider_dist_min
    
    slider_dist_max = Slider(start=0,end=distmax,value=distmax,
			     step=1,
			     title="Max Distance",callback=callback)
    callback.args["maxdist"] = slider_dist_max

    layout = layoutrow([layoutcolumn([slider_spm_min,
			              slider_spm_max,
			              slider_dist_min,
			              slider_dist_max,
                                      slider_work_min,
                                      slider_work_max,
			       ],
				     ),
			plot])

    script, div = components(layout)
    js_resources = INLINE.render_js()
    css_resources = INLINE.render_css()

 

    return [script,div,js_resources,css_resources]

                       
    
def interactive_histoall(theworkouts):
    TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,hover,resize,crosshair'

    ids = [int(w.id) for w in theworkouts]

    rowdata = dataprep.getsmallrowdata_db(['power'],ids=ids,doclean=True)

    
    rowdata.dropna(axis=0,how='any',inplace=True)

    if rowdata.empty:
	return "","No Valid Data Available","",""

    histopwr = rowdata['power'].values
    if len(histopwr) == 0:
        return "","No valid data available","",""
        
    # throw out nans
    histopwr = histopwr[~np.isinf(histopwr)]
    histopwr = histopwr[histopwr > 25]
    histopwr = histopwr[histopwr < 1000]

    plot = Figure(tools=TOOLS,plot_width=900,
		  toolbar_sticky=False,
		  toolbar_location="above"
		  )

    # add watermark
    plot.extra_y_ranges = {"watermark": watermarkrange}
    plot.extra_x_ranges = {"watermark": watermarkrange}

    plot.image_url([watermarkurl],watermarkx,watermarky,
                   watermarkw,watermarkh,
                   global_alpha=watermarkalpha,
                   w_units='screen',
                   h_units='screen',
                   anchor=watermarkanchor,
                   dilate=True,
                   x_range_name = "watermark",
                   y_range_name = "watermark",
                   )

    hist,edges = np.histogram(histopwr,bins=150)

    histsum = np.cumsum(hist)
    histsum = 100.*histsum/max(histsum)

    hist_norm = 100.*hist/float(hist.sum())

    source = ColumnDataSource(
	data = dict(
	    left = edges[:-1],
	    right = edges[1:],
	    histsum = histsum,
	    hist_norm = hist_norm,
	    )
	)


#    plot.quad(top='hist_norm',bottom=0,left=edges[:-1],right=edges[1:])
    plot.quad(top='hist_norm',bottom=0,left='left',right='right',source=source)
    
    plot.xaxis.axis_label = "Power (W)"
    plot.yaxis.axis_label = "% of strokes"
    plot.y_range = Range1d(0,1.05*max(hist_norm))

    hover = plot.select(dict(type=HoverTool))

    hover.tooltips = OrderedDict([
	('Power(W)','@left{int}'),
	('% of strokes','@hist_norm'),
	('Cumulative %','@histsum{int}'),
	])

    hover.mode = 'mouse'

    plot.extra_y_ranges["fraction"] = Range1d(start=0,end=105)
    plot.line('right','histsum',source=source,color="red",
	      y_range_name="fraction")
    plot.add_layout(LinearAxis(y_range_name="fraction",
			       axis_label="Cumulative % of strokes"),'right')

    script, div = components(plot)
    return [script,div]

def leaflet_chart(lat,lon,name=""):
    if lat.empty or lon.empty:
        return [0,"invalid coordinate data"]

    latmean = lat.mean()
    lonmean = lon.mean()
    latbegin = lat[lat.index[0]]
    longbegin = lon[lon.index[0]]
    latend = lat[lat.index[-1]]
    longend = lon[lon.index[-1]]

    coordinates = zip(lat,lon)

    scoordinates = "["

    for x,y in coordinates:
        scoordinates += """[{x},{y}],
        """.format(
            x=x,
            y=y
            )

    scoordinates += "]"
    
    script = """
    <script>
      
      
    var streets = L.tileLayer('https://api.tiles.mapbox.com/v4/{{id}}/{{z}}/{{x}}/{{y}}.png?access_token=pk.eyJ1Ijoic2FuZGVycm9vc2VuZGFhbCIsImEiOiJjajY3aTRkeWQwNmx6MzJvMTN3andlcnBlIn0.MFG8Xt0kDeSA9j7puZQ9hA', {{
		maxZoom: 18,
		id: 'mapbox.streets'
    }}),

    satellite = L.tileLayer('https://api.tiles.mapbox.com/v4/{{id}}/{{z}}/{{x}}/{{y}}.png?access_token=pk.eyJ1Ijoic2FuZGVycm9vc2VuZGFhbCIsImEiOiJjajY3aTRkeWQwNmx6MzJvMTN3andlcnBlIn0.MFG8Xt0kDeSA9j7puZQ9hA', {{
		maxZoom: 18,
		id: 'mapbox.satellite'
    }}),

    outdoors = L.tileLayer('https://api.tiles.mapbox.com/v4/{{id}}/{{z}}/{{x}}/{{y}}.png?access_token=pk.eyJ1Ijoic2FuZGVycm9vc2VuZGFhbCIsImEiOiJjajY3aTRkeWQwNmx6MzJvMTN3andlcnBlIn0.MFG8Xt0kDeSA9j7puZQ9hA', {{
		maxZoom: 18,
		id: 'mapbox.outdoors'
    }});

    var mymap = L.map('map_canvas', {{
              center: [{latmean}, {lonmean}],
              zoom: 13, 
              layers: [streets, satellite]
              }}).setView([{latmean},{lonmean}], 13);

   var osmUrl2='http://tiles.openseamap.org/seamark/{{z}}/{{x}}/{{y}}.png';
   var osmUrl='http://{{s}}.tile.openstreetmap.org/{{z}}/{{x}}/{{y}}.png';


    //create two TileLayer
    var nautical=new L.TileLayer(osmUrl,{{
             maxZoom:18}});


    L.control.layers({{
        "Streets": streets,
        "Satellite": satellite,
        "Outdoors": outdoors,
        "Nautical": nautical,
    }}).addTo(mymap);
 
    var marker = L.marker([{latbegin}, {longbegin}]).addTo(mymap);
    marker.bindPopup("<b>Start</b>");
    var emarker = new L.marker([{latend}, {longend}]).addTo(mymap);
    emarker.bindPopup("<b>End</b>");
      
    var latlongs = {scoordinates}
    var polyline = L.polyline(latlongs, {{color:'red'}}).addTo(mymap)
    mymap.fitBounds(polyline.getBounds())

    </script>
      """.format(
          latmean=latmean,
          lonmean=lonmean,
          latbegin = latbegin,
          latend=latend,
          longbegin=longbegin,
          longend=longend,
          scoordinates=scoordinates,
          )

    div = """
    <div id="map_canvas" style="width: 100%; height: 400px;"><p>&nbsp;</p></div>
    """



    return script,div

def googlemap_chart(lat,lon,name=""):
    if lat.empty or lon.empty:
        return [0,"invalid coordinate data"]
    # plot tools
    TOOLS =     'save,pan,box_zoom,wheel_zoom,reset,tap,resize'

    map_options = GMapOptions(lat = lat.mean(),lng=lon.mean(),
			      map_type="roadmap",zoom=13)

    plot = GMapPlot(
    x_range=DataRange1d(), y_range=DataRange1d(),
	map_options=map_options,
	api_key = "AIzaSyAgu1w9QSthaGPMLp8y9JedPoMc9sfEgJ8",
	plot_width=400,plot_height=400,
	toolbar_sticky=False,

	)


    source = ColumnDataSource(
	data = dict(
	    lat=lat,
	    lon=lon,
	    )
	)

    circle = Circle(x="lon",y="lat",size=5,fill_color="blue",
		    fill_alpha=0.2,line_color=None)
    plot.add_glyph(source,circle)
    plot.add_tools(PanTool(), WheelZoomTool(), 
		   SaveTool(),	ResizeTool(), ResetTool(),
		   TapTool(),CrosshairTool(),
		   )
    plot.title.text = name
    plot.title.text_font="1.0em"
    script, div = components(plot)

    return [script,div]
			    

def interactive_otwcpchart(powerdf,promember=0):
    powerdf = powerdf[~(powerdf == 0).any(axis=1)]
    # plot tools
    if (promember==1):
	TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,hover,resize,crosshair'
    else:
	TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,hover,crosshair'


    x_axis_type = 'log'
    y_axis_type = 'linear'

    deltas = powerdf['Delta'].apply(lambda x: timedeltaconv(x))
    powerdf['ftime'] = niceformat(deltas)
    
    
    source = ColumnDataSource(
        data = powerdf
        )

    # there is no Paul's law for OTW

    thesecs = powerdf['Delta']
    theavpower = powerdf['CP']

    p1,fitt,fitpower,ratio = datautils.cpfit(powerdf)
    
    message = ""
    #if len(fitpower[fitpower<0]) > 0:
	# message = "CP model fit didn't give correct results"


    deltas = fitt.apply(lambda x: timedeltaconv(x))
    ftime = niceformat(deltas)
        
    sourcecomplex = ColumnDataSource(
        data = dict(
            CP = fitpower,
            CPmax = ratio*fitpower,
            duration = fitt,
            ftime = ftime
            )
        )

        # making the plot
    plot = Figure(tools=TOOLS,x_axis_type=x_axis_type,
		  plot_width=900,
		  toolbar_location="above",
		  toolbar_sticky=False)

    # add watermark
    plot.extra_y_ranges = {"watermark": watermarkrange}

    plot.image_url([watermarkurl],1.8*max(thesecs),watermarky,
                   watermarkw,watermarkh,
                   global_alpha=watermarkalpha,
                   w_units='screen',
                   h_units='screen',
                   anchor=watermarkanchor,
                   dilate=True,
                   y_range_name = "watermark",
                   )

    plot.circle('Delta','CP',source=source,fill_color='red',size=15,
		legend='Power Data')
    plot.xaxis.axis_label = "Duration (seconds)"
    plot.yaxis.axis_label = "Power (W)"

    plot.y_range = Range1d(0,1.5*max(theavpower))
    plot.x_range = Range1d(1,2*max(thesecs))
    plot.legend.orientation = "vertical"

    hover = plot.select(dict(type=HoverTool))

    hover.tooltips = OrderedDict([
	('Duration ','@ftime'),
	('Power (W)','@CP{int}'),
	('Power (W) upper','@CPmax{int}'),
	])
 
    hover.mode = 'mouse'

    plot.line('duration','CP',source=sourcecomplex,legend="CP Model",
	      color='green')
    
    plot.line('duration','CPmax',source=sourcecomplex,legend="CP Model",
	      color='red')
    
    script, div = components(plot)

    return [script,div,p1,ratio,message]

def interactive_cpchart(thedistances,thesecs,theavpower,
			theworkouts,promember=0):

    
    message = 0
    # plot tools
    if (promember==1):
	TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,hover,resize,crosshair'
    else:
	TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,hover,crosshair'


    x_axis_type = 'log'
    y_axis_type = 'linear'

    thesecs = pd.Series(thesecs)

    velo = thedistances/thesecs
    p = pd.Series(500./velo)

    p2 = p.fillna(method='ffill').apply(lambda x: timedeltaconv(x))

    source = ColumnDataSource(
	data = dict(
	    dist = thedistances,
	    duration = thesecs,
	    spm = 0*theavpower,
	    tim = niceformat(
		thesecs.fillna(method='ffill').apply(lambda x: timedeltaconv(x))	      
		),
	    
	    power = theavpower,
	    fpace = nicepaceformat(p2),
	    )
	)

    # fitting the data to Paul
    if len(thedistances)>=2:
	paulslope, paulintercept,r,p,stderr = linregress(np.log10(thedistances),p)
    else:
	paulslope = 5.0/np.log10(2.0)
	paulintercept = p[0]-paulslope*np.log10(thedistances[0])

    fitx = pd.Series(np.arange(100)*2*max(np.log10(thedistances))/100.)

    fitp = paulslope*fitx+paulintercept

    fitvelo = 500./fitp
    fitpower = 2.8*(fitvelo**3)
    fitt = 10**fitx/fitvelo
    fitp2 = fitp.fillna(method='ffill').apply(lambda x: timedeltaconv(x))


    sourcepaul = ColumnDataSource(
	data = dict(
	    dist = 10**fitx,
	    duration = fitt,
	    power = fitpower,
	    spm = 0*fitpower,
	    tim = niceformat(
		fitt.fillna(method='ffill').apply(lambda x: timedeltaconv(x))
		),
	    fpace = nicepaceformat(fitp2),
	    )
	)


    # fitting the data to three parameter CP model
    fitfunc = lambda pars,x: pars[0]/(1+(x/pars[2])) + pars[1]/(1+(x/pars[3]))
    errfunc = lambda pars,x,y: fitfunc(pars,x)-y
    
    p0 = [500,350,10,8000]

    p1 = p0
    if len(thesecs)>=4:
	p1, success = optimize.leastsq(errfunc, p0[:], args = (thesecs,theavpower))
    else:
	factor = fitfunc(p0,thesecs.mean())/theavpower.mean()
	p1 = [p0[0]/factor,p0[1]/factor,p0[2],p0[3]]


    fitt = pd.Series(10**(4*np.arange(100)/100.))

    fitpower = fitfunc(p1,fitt)

    message = ""
    if len(fitpower[fitpower<0]) > 0:
	message = "CP model fit didn't give correct results"

    fitvelo = (fitpower/2.8)**(1./3.)
    fitdist = fitt*fitvelo
    fitp = 500./fitvelo
    fitp2 = fitp.fillna(method='ffill').apply(lambda x: timedeltaconv(x))

    sourcecomplex = ColumnDataSource(
	data = dict(
	    dist = fitdist,
	    duration = fitt,
	    tim = niceformat(
		fitt.fillna(method='ffill').apply(lambda x: timedeltaconv(x))
		),
	    spm = 0*fitpower,
	    power = fitpower,
	    fpace = nicepaceformat(fitp2),
	    )
	)

    

    # making the plot
    plot = Figure(tools=TOOLS,x_axis_type=x_axis_type,
		  plot_width=900,
		  toolbar_location="above",
		  toolbar_sticky=False)

    # add watermark
    plot.extra_y_ranges = {"watermark": watermarkrange}

    plot.image_url([watermarkurl],1.8*max(thesecs),watermarky,
                   watermarkw,watermarkh,
                   global_alpha=watermarkalpha,
                   w_units='screen',
                   h_units='screen',
                   anchor=watermarkanchor,
                   dilate=True,
                   y_range_name = "watermark",
                   )

    plot.circle('duration','power',source=source,fill_color='red',size=15,
		legend='Power')
    plot.xaxis.axis_label = "Duration (seconds)"
    plot.yaxis.axis_label = "Power (W)"

    therows = []
    for workout in theworkouts:
	f1 = workout.csvfilename
	rowdata = rdata(f1)
	if rowdata != 0:
	    therows.append(rowdata)

    cpdata = cumcpdata(therows)

    velo = cpdata['Distance']/cpdata['Delta']

    p = 500./velo

    p2 = p.fillna(method='ffill').apply(lambda x: timedeltaconv(x))

    source2 = ColumnDataSource(
	data = dict(
	    duration = cpdata['Delta'],
	    power = cpdata['CP'],
	    tim = niceformat(
		cpdata['Delta'].fillna(method='ffill').apply(lambda x: timedeltaconv(x))
		),
	    dist = cpdata['Distance'],
	    pace = nicepaceformat(p2),
	    )
	)
    
    plot.circle('duration','power',source=source2,
		fill_color='blue',size=3,
		legend = 'Power from segments')
    
    hover = plot.select(dict(type=HoverTool))

    hover.tooltips = OrderedDict([
	('Duration ','@tim'),
	('Power (W)','@power{int}'),
	('Distance (m)','@dist{int}'),
	('Pace (/500m)','@fpace'),
	])
 
    hover.mode = 'mouse'

    plot.y_range = Range1d(0,1.5*max(theavpower))
    plot.x_range = Range1d(1,2*max(thesecs))
    plot.legend.orientation = "vertical"


    plot.line('duration','power',source=sourcepaul,legend="Paul's Law")
    plot.line('duration','power',source=sourcecomplex,legend="CP Model",
	      color='green')

 
    script, div = components(plot)

    return [script,div,paulslope,paulintercept,p1,message]

def interactive_windchart(id=0,promember=0):
    # check if valid ID exists (workout exists)
    row = Workout.objects.get(id=id)
    # g = GraphImage.objects.filter(workout=row).order_by("-creationdatetime")

    f1 = row.csvfilename
	
    # create interactive plot
    plot = Figure(plot_width=400,plot_height=300)
    
    # get user
    # u = User.objects.get(id=row.user.id)
    r = row.user
    u = r.user



    rr = rrower(hrmax=r.max,hrut2=r.ut2,
		hrut1=r.ut1,hrat=r.at,
		hrtr=r.tr,hran=r.an,ftp=r.ftp)

    rowdata = rdata(f1,rower=rr)
    if rowdata == 0:
	return 0

    dist = rowdata.df.ix[:,'cum_dist']

    try:
	vwind = rowdata.df.ix[:,'vwind']
	winddirection = rowdata.df.ix[:,'winddirection']
	bearing = rowdata.df.ix[:,'bearing']
    except KeyError:
	rowdata.add_wind(0,0)
	rowdata.add_bearing()
	vwind = rowdata.df.ix[:,'vwind']
	winddirection = rowdata.df.ix[:,'winddirection']
	bearing = rowdata.df.ix[:,'winddirection']
	rowdata.write_csv(f1,gzip=True)
        dataprep.update_strokedata(id,rowdata.df)

    winddirection = winddirection % 360
    winddirection = (winddirection + 360) % 360

    tw = tailwind(bearing,vwind,1.0*winddirection)


    source = ColumnDataSource(
	data = dict(
	    dist=dist,
	    vwind=vwind,
	    tw=tw,
	    winddirection=winddirection,
	    )
	)

    # plot tools
    if (promember==1):
	TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,resize,crosshair'
    else:
	TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,crosshair'


 
    # making the plot
    plot = Figure(tools=TOOLS,plot_width=400,height=500,
#		  toolbar_location="below",
		  toolbar_sticky=False,
		  )
    plot.line('dist','vwind',source=source,legend="Wind Speed (m/s)")
    plot.line('dist','tw',source=source,legend="Tail (+)/Head (-) Wind (m/s)",color='black')
    plot.title.text = row.name
    #    plot.title.text_font_size=value("1.0em")
    plot.title.text_font="1.0em"
    plot.xaxis.axis_label = "Distance (m)"
    plot.yaxis.axis_label = "Wind Speed (m/s)"
    plot.y_range = Range1d(-7,7)


    plot.extra_y_ranges = {"winddirection": Range1d(start=0,end=360)}
    plot.line('dist','winddirection',source=source,
	      legend='Wind Direction',color="red",
	      y_range_name="winddirection")
    plot.add_layout(LinearAxis(y_range_name="winddirection",axis_label="Wind Direction (degree)"),'right')

 
    script, div = components(plot)

    return [script,div]

def interactive_streamchart(id=0,promember=0):
    # check if valid ID exists (workout exists)
    row = Workout.objects.get(id=id)
    # g = GraphImage.objects.filter(workout=row).order_by("-creationdatetime")

    f1 = row.csvfilename
	
    # create interactive plot
    plot = Figure(plot_width=400,
		  )
    # get user
    # u = User.objects.get(id=row.user.id)
    r = row.user
    u = r.user



    rr = rrower(hrmax=r.max,hrut2=r.ut2,
		hrut1=r.ut1,hrat=r.at,
		hrtr=r.tr,hran=r.an,ftp=r.ftp)

    rowdata = rdata(f1,rower=rr)
    if rowdata == 0:
	return "","No Valid Data Available"
    
    dist = rowdata.df.ix[:,'cum_dist']

    try:
	vstream = rowdata.df.ix[:,'vstream']
    except KeyError:
	rowdata.add_stream(0)
	vstream = rowdata.df.ix[:,'vstream']
	rowdata.write_csv(f1,gzip=True)
        dataprep.update_strokedata(id,rowdata.df)

    # plot tools
    if (promember==1):
	TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,resize,crosshair'
    else:
	TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,crosshair'


 
    # making the plot
    plot = Figure(tools=TOOLS,plot_width=400,height=500,
#		  toolbar_location="below",
		  toolbar_sticky=False,
		  )
    plot.line(dist,vstream,legend="River Stream Velocity (m/s)")
    plot.title.text = row.name
    plot.title.text_font_size=value("1.0em")
    plot.xaxis.axis_label = "Distance (m)"
    plot.yaxis.axis_label = "River Current (m/s)"
    plot.y_range = Range1d(-2,2)

 
    script, div = components(plot)

    return [script,div]

def interactive_chart(id=0,promember=0):
    # Add hover to this comma-separated string and see what changes
    if (promember==1):
	TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,hover,resize,crosshair'
    else:
	TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,hover,crosshair'

        
    columns = ['time','pace','hr','fpace','ftime']
    datadf = dataprep.getsmallrowdata_db(columns,ids=[id])
    
    datadf.dropna(axis=0,how='any',inplace=True)
    row = Workout.objects.get(id=id)
    if datadf.empty:
	return "","No Valid Data Available"
    else:
        datadf.sort_values(by='time',ascending=True,inplace=True)

    #datadf,row = dataprep.getrowdata_db(id=id)
    #if datadf.empty:
	#return "","No Valid Data Available"

    source = ColumnDataSource(
	datadf
	)

    plot = Figure(x_axis_type="datetime",y_axis_type="datetime",
		  plot_width=400,
		  plot_height=400,
		  toolbar_sticky=False,
		  tools=TOOLS)

    # add watermark
    plot.extra_y_ranges = {"watermark": watermarkrange}
    plot.extra_x_ranges = {"watermark": watermarkrange}

    plot.image_url([watermarkurl],0.01,0.99,
                   0.5*watermarkw,0.5*watermarkh,
                   global_alpha=watermarkalpha,
                   w_units='screen',
                   h_units='screen',
                   anchor='top_left',
                   dilate=True,
                   x_range_name = "watermark",
                   y_range_name = "watermark",
                   )

    plot.line('time','pace',source=source,legend="Pace")
    plot.title.text = row.name
    plot.title.text_font_size=value("1.0em")
    plot.xaxis.axis_label = "Time"
    plot.yaxis.axis_label = "Pace (/500m)"
    plot.xaxis[0].formatter = DatetimeTickFormatter(
	    hours = ["%H"],
	    minutes = ["%M"],
	    seconds = ["%S"],
	    days = ["0"],
	    months = [""],
	    years = [""]
	)
    plot.yaxis[0].formatter = DatetimeTickFormatter(
	    seconds = ["%S"],
	    minutes = ["%M"]
	)
    ymax = 90.
    ymin = 150.

    if row.workouttype == 'water':
	ymax = 90.
	ymin = 210.
    
    plot.y_range = Range1d(1.e3*ymin,1.e3*ymax)


    hover = plot.select(dict(type=HoverTool))


    hover.tooltips = OrderedDict([
	('Time','@ftime'),
	('Pace','@fpace'),
	('HR','@hr{int}'),
	('SPM','@spm{1.1}'),
	])
 
    hover.mode = 'mouse'

    plot.extra_y_ranges["hrax"] = Range1d(start=100,end=200)
    plot.line('time','hr',source=source,color="red",
	      y_range_name="hrax", legend="Heart Rate")
    plot.add_layout(LinearAxis(y_range_name="hrax",axis_label="HR"),'right')

    plot.legend.location = "bottom_right"
 
    script, div = components(plot)

    return [script,div]

def interactive_multiflex(datadf,xparam,yparam,groupby,extratitle='',
                          ploterrorbars=False,
                          title=None,binsize=1,colorlegend=[]):

    if datadf.empty:
        return ['','<p>No non-zero data in selection</p>']

    if xparam == 'workoutid':
        xparamname = 'Workout'
    else:
        xparamname = axlabels[xparam]

    if yparam == 'workoutid':
        yparamname = 'Workout'
    else:
        yparamname = axlabels[yparam]
        
    if groupby == 'workoutid':
        groupname = 'Workout'
    elif groupby == 'date':
        groupname = 'Date'
    else:
        groupname = axlabels[groupby]
        

    if title==None:
        title = '{y} vs {x} grouped by {gr}'.format(
            x = xparamname,
            y = yparamname,
            gr = groupname,
            )


    if xparam=='distance':
	xaxmax = datadf[xparam].max()
	xaxmin = datadf[xparam].min()
    elif xparam=='time':
        tseconds = datadf.ix[:,'time']
        xaxmax = tseconds.max()
        xaxmin = 0
    elif xparam == 'workoutid':
        xaxmax = datadf[xparam].max()-5
        xaxmin = datadf[xparam].min()+5
    else:
	xaxmax = yaxmaxima[xparam]
	xaxmin = yaxminima[xparam]

    if yparam=='distance':
	yaxmax = datadf[yparam].max()
	yaxmin = datadf[yparam].min()
    elif yparam=='time':
        tseconds = datadf.ix[:,'time']
        yaxmax = tseconds.max()
        yaxmin = 0
    elif yparam == 'workoutid':
        yaxmax = datadf[yparam].max()-5
        yaxmin = datadf[yparam].min()+5
    else:
	yaxmax = yaxmaxima[yparam]
	yaxmin = yaxminima[yparam]

    x_axis_type = 'linear'
    y_axis_type = 'linear'
    if xparam == 'time':
        x_axis_type = 'datetime'
    if yparam == 'pace':
        y_axis_type = 'datetime'

    source = ColumnDataSource(
        datadf,
        )

    TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,resize'

    if groupby != 'date':
        hover = HoverTool(names=['data'],
                          tooltips = [
                              (groupby,'@groupval{1.1}'),
                              (xparamname,'@x{1.1}'),
                              (yparamname,'@y')
                          ])
    else:
        hover = HoverTool(names=['data'],
                          tooltips = [
                              (groupby,'@groupval'),
                              (xparamname,'@x{1.1}'),
                              (yparamname,'@y')
                              ,
                          ])

    hover.mode = 'mouse'
    TOOLS = [SaveTool(),PanTool(),BoxZoomTool(),WheelZoomTool(),
             ResetTool(),TapTool(),ResizeTool(),hover]
    

    plot = Figure(x_axis_type=x_axis_type,y_axis_type=y_axis_type,
		  tools=TOOLS,
		  toolbar_location="above",
		  toolbar_sticky=False) #,plot_width=500,plot_height=500)

    # add watermark
    plot.extra_y_ranges = {"watermark": watermarkrange}
    plot.extra_x_ranges = {"watermark": watermarkrange}

    plot.title.text = title
    plot.title.text_font_size=value("1.0em")

    plot.image_url([watermarkurl],watermarkx,watermarky,
                   watermarkw,watermarkh,
                   global_alpha=watermarkalpha,
                   w_units='screen',
                   h_units='screen',
                   anchor=watermarkanchor,
                   dilate=True,
                   x_range_name = "watermark",
                   y_range_name = "watermark",
                   )
    
    errorbar(plot,xparam,yparam,source=source,
             xerr=ploterrorbars,
             yerr=ploterrorbars,
             point_kwargs={
                 'line_color':"#969696",
                 'size':"groupsize",
                 'fill_color':"color",
                 'fill_alpha':1.0,
             },
    )



    for nr, gvalue, color in colorlegend:
        box = BoxAnnotation(bottom=400+20*nr,left=550,top=420+20*nr,
                            right=570,
                            bottom_units='screen',
                            top_units='screen',
                            left_units='screen',
                            right_units='screen',
                            fill_color=color,
                            fill_alpha=1.0,
                            line_color=color)
        legendlabel = Label(x=571,y=403+20*nr,x_units='screen',
                            y_units='screen',
                            text = "{gvalue:3.0f}".format(gvalue=gvalue),
                            background_fill_alpha=1.0,
                            text_color='black',
                            text_font_size=value("0.7em"))
        plot.add_layout(box)
        plot.add_layout(legendlabel)

    if colorlegend:
        legendlabel = Label(x=372,y=300,x_units='screen',
                            y_units='screen',
                            text = 'group legend',
                            text_color='black',
                            text_font_size=value("0.7em"),
                            angle=90,
                            angle_units='deg')
    
    if xparam == 'workoutid':
        plot.xaxis.axis_label = 'Workout'
    else:
        plot.xaxis.axis_label = axlabels[xparam]

    if yparam == 'workoutid':
        plot.xaxis.axis_label = 'Workout'
    else:
        plot.yaxis.axis_label = axlabels[yparam]

    binlabel = Label(x=100,y=100,x_units='screen',
                     y_units='screen',
                     text="Bin size {binsize:3.1f}".format(binsize=binsize),
                     background_fill_alpha=0.7,
                     background_fill_color='white',
                     text_color='black',
                     )

    plot.add_layout(binlabel)

    yrange1 = Range1d(start=yaxmin,end=yaxmax)
    plot.y_range = yrange1

    xrange1 = Range1d(start=xaxmin,end=xaxmax)
    plot.x_range = xrange1

    if yparam == 'pace':
	plot.yaxis[0].formatter = DatetimeTickFormatter(
		seconds = ["%S"],
		minutes = ["%M"]
	    )


    script,div = components(plot)


    return [script,div]
        
def interactive_cum_flex_chart2(theworkouts,promember=0,
                                xparam='spm',
                                yparam1='power',
                                yparam2='spm',
                                workstrokesonly=False):

    # datadf = dataprep.smalldataprep(theworkouts,xparam,yparam1,yparam2)
    ids = [int(w.id) for w in theworkouts]
    columns = [xparam,yparam1,yparam2,'spm','driveenergy','distance']
    datadf = dataprep.getsmallrowdata_db(columns,ids=ids,doclean=True,
                                         workstrokesonly=workstrokesonly)

    try:
        tests = datadf[yparam2]
    except KeyError:
        yparam2 = 'None'

    try:
        tests = datadf[yparam1]
    except KeyError:
        yparam1 = 'None'

    datadf.dropna(axis=1,how='all',inplace=True)
    datadf.dropna(axis=0,how='any',inplace=True)

    # test if we have drive energy
    nowork = 1
    try:
        test = datadf['driveenergy'].mean()
        nowork = 0
    except KeyError:
        datadf['driveenergy'] = 500.

    # test if we have power
    nopower = 1
    try:
        test = datadf['power'].mean()
        nopower = 0
    except KeyError:
        datadf['power'] = 50.

    
    yparamname1 = axlabels[yparam1]
    if yparam2 != 'None':
        yparamname2 = axlabels[yparam2]


    # check if dataframe not empty
    if datadf.empty:
	return ['','<p>No non-zero data in selection</p>','','']


    try:
        datadf['x1'] = datadf.ix[:,xparam]
    except KeyError:
        datadf['x1'] = datadf['distance']
    try:
        datadf['y1'] = datadf.ix[:,yparam1]
    except KeyError:
        try:
            datadf['y1'] = datadf['pace']
        except KeyError:
            return ['','<p>No non-zero data in selection</p>','','']
    if yparam2 != 'None':
        try:
	    datadf['y2'] = datadf.ix[:,yparam2]
        except KeyError:
            datadf['y2'] = datadf['y1']
    else:
	datadf['y2'] = datadf['y1']


    if xparam=='distance':
	xaxmax = datadf['x1'].max()
	xaxmin = datadf['x1'].min()
    else:
	xaxmax = yaxmaxima[xparam]
	xaxmin = yaxminima[xparam]

    # average values
    x1mean = datadf['x1'].mean()
	
    y1mean = datadf['y1'].mean()
    y2mean = datadf['y2'].mean()


    xvals = pd.Series(xaxmin+np.arange(100)*(xaxmax-xaxmin)/100.)
	
    x_axis_type = 'linear'
    y_axis_type = 'linear'
    if xparam == 'time':
	x_axis_type = 'datetime'

    if yparam1 == 'pace':
	y_axis_type = 'datetime'
	y1mean = datadf.ix[:,'pace'].mean()

    datadf['xname'] = axlabels[xparam]
    datadf['yname1'] = axlabels[yparam1]
    if yparam2 != 'None':
        datadf['yname2'] = axlabels[yparam2]
    else:
        datadf['yname2'] = axlabels[yparam1]


    source = ColumnDataSource(
	datadf
	)

    source2 = ColumnDataSource(
	datadf.copy()
	)

    # Add hover to this comma-separated string and see what changes
    if (promember==1):
	TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,resize,crosshair'
    else:
	TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,crosshair'

    plot = Figure(x_axis_type=x_axis_type,y_axis_type=y_axis_type,
		  tools=TOOLS,
		  toolbar_location="above",
		  toolbar_sticky=False)

    # add watermark
    plot.extra_y_ranges = {"watermark": watermarkrange}
    plot.extra_x_ranges = {"watermark": watermarkrange}

    plot.image_url([watermarkurl],watermarkx,watermarky,
                   watermarkw,watermarkh,
                   global_alpha=watermarkalpha,
                   w_units='screen',
                   h_units='screen',
                   anchor=watermarkanchor,
                   dilate=True,
                   x_range_name = "watermark",
                   y_range_name = "watermark",
                   )

    x1means = Span(location=x1mean,dimension='height',line_color='green',
		   line_dash=[6,6], line_width=2)

    y1means = Span(location=y1mean,dimension='width',line_color='blue',
		   line_dash=[6,6],line_width=2)
    y2means = y1means

    xlabel = Label(x=100,y=130,x_units='screen',y_units='screen',
                   text=axlabels[xparam]+": {x1mean:6.2f}".format(x1mean=x1mean),
                   background_fill_alpha=.7,
                   background_fill_color='white',
                   text_color='green',
    )
    

    plot.add_layout(x1means)
    plot.add_layout(xlabel)

    plot.add_layout(y1means)

    y1label = Label(x=100,y=100,x_units='screen',y_units='screen',
                    text=axlabels[yparam1]+": {y1mean:6.2f}".format(y1mean=y1mean),
                    background_fill_alpha=.7,
                    background_fill_color='white',
                    text_color='blue',
    )

    if yparam1 != 'time' and yparam1 != 'pace':
        plot.add_layout(y1label)

    y2label = y1label
    plot.circle('x1','y1',source=source2,fill_alpha=0.3,line_color=None,
		 legend=yparamname1,
		 )
	
    plot.xaxis.axis_label = axlabels[xparam]
    plot.yaxis.axis_label = axlabels[yparam1]


    yrange1 = Range1d(start=yaxminima[yparam1],end=yaxmaxima[yparam1])
    plot.y_range = yrange1

    xrange1 = Range1d(start=yaxminima[xparam],end=yaxmaxima[xparam])
    plot.x_range = xrange1

    if yparam1 == 'pace':
	plot.yaxis[0].formatter = DatetimeTickFormatter(
		seconds = ["%S"],
		minutes = ["%M"]
	    )

    if yparam2 != 'None':
	yrange2 = Range1d(start=yaxminima[yparam2],end=yaxmaxima[yparam2])
	plot.extra_y_ranges["yax2"] = yrange2

	plot.circle('x1','y2',color="red",y_range_name="yax2",
		    legend=yparamname2,
		    source=source2,fill_alpha=0.3,line_color=None)
	
	plot.add_layout(LinearAxis(y_range_name="yax2",
				   axis_label=axlabels[yparam2]),'right')

	y2means = Span(location=y2mean,dimension='width',line_color='red',
		       line_dash=[6,6],line_width=2,y_range_name="yax2")


	plot.add_layout(y2means)
        y2label = Label(x=100,y=70,x_units='screen',y_units='screen',
                        text=axlabels[yparam2]+": {y2mean:6.2f}".format(y2mean=y2mean),
                        background_fill_alpha=.7,
                        background_fill_color='white',
                        text_color='red',
        )
        if yparam2 != 'pace' and yparam2 != 'time':
            plot.add_layout(y2label)


    callback = CustomJS(args = dict(source=source,source2=source2,
				    x1means=x1means,
				    y1means=y1means,
                                    y1label=y1label,
                                    y2label=y2label,
                                    xlabel=xlabel,
				    y2means=y2means), code="""
       var data = source.data
       var data2 = source2.data
       var x1 = data['x1']
       var y1 = data['y1']
       var y2 = data['y2']
       var spm1 = data['spm']
       var distance1 = data['distance']
       var driveenergy1 = data['driveenergy']
       var xname = data['xname'][0]
       var yname1 = data['yname1'][0]
       var yname2 = data['yname2'][0]
       
       var minspm = minspm.value
       var maxspm = maxspm.value
       var mindist = mindist.value
       var maxdist = maxdist.value
       var minwork = minwork.value
       var maxwork = maxwork.value
       var xm = 0
       var ym1 = 0
       var ym2 = 0

       data2['x1'] = []
       data2['y1'] = []
       data2['y2'] = []
       data2['spm'] = []
       data2['distance'] = []
       data2['x1mean'] = []
       data2['y1mean'] = []
       data2['y2mean'] = []
       data2['xvals'] = []
       data2['y1vals'] = []
       data2['y2vals'] = []

       for (i=0; i<x1.length; i++) {
	  if (spm1[i]>=minspm && spm1[i]<=maxspm) {
	     if (distance1[i]>=mindist && distance1[i]<=maxdist) {
                if (driveenergy1[i]>=minwork && driveenergy1[i]<=maxwork) {
  	           data2['x1'].push(x1[i])
		   data2['y1'].push(y1[i])
		   data2['y2'].push(y2[i])
		   data2['spm'].push(spm1[i])
		   data2['distance'].push(distance1[i])

		   xm += x1[i]
		   ym1 += y1[i]
		   ym2 += y2[i]
                   }
		}
	     }
       }

       xm /= data2['x1'].length
       ym1 /= data2['x1'].length
       ym2 /= data2['x1'].length

       data2['x1mean'] = [xm,xm]
       data2['y1mean'] = [ym1,ym1]
       data2['y2mean'] = [ym2,ym2]
       x1means.location = xm
       y1means.location = ym1
       y2means.location = ym2
       y1label.text = yname1+': '+(ym1).toFixed(2)
       y2label.text = yname2+': '+(ym2).toFixed(2)
       xlabel.text = xname+': '+(xm).toFixed(2)

       source2.trigger('change');
       """)

    slider_spm_min = Slider(start=15.0, end=55,value=15.0, step=.1,
		title="Min SPM",callback=callback)
    callback.args["minspm"] = slider_spm_min
    

    slider_spm_max = Slider(start=15.0, end=55,value=55.0, step=.1,
		title="Max SPM",callback=callback)
    callback.args["maxspm"] = slider_spm_max
    
    slider_work_min = Slider(start=0.0, end=1500,value=0.0, step=10,
		title="Min Work per Stroke",callback=callback)
    callback.args["minwork"] = slider_work_min
    

    slider_work_max = Slider(start=0.0, end=1500,value=1500.0, step=10,
		title="Max Work per Stroke",callback=callback)
    callback.args["maxwork"] = slider_work_max

    distmax = 100+100*int(datadf['distance'].max()/100.)
    
    slider_dist_min = Slider(start=0,end=distmax,value=0,step=1,
			     title="Min Distance",callback=callback)
    callback.args["mindist"] = slider_dist_min
    
    slider_dist_max = Slider(start=0,end=distmax,value=distmax,
			     step=1,
			     title="Max Distance",callback=callback)
    callback.args["maxdist"] = slider_dist_max

    layout = layoutrow([layoutcolumn([slider_spm_min,
			              slider_spm_max,
			              slider_dist_min,
			              slider_dist_max,
                                      slider_work_min,
                                      slider_work_max,
			       ],
				     ),
			plot])

    script, div = components(layout)
    js_resources = INLINE.render_js()
    css_resources = INLINE.render_css()

 

    return [script,div,js_resources,css_resources]




def interactive_flex_chart2(id=0,promember=0,
			   xparam='time',
			   yparam1='pace',
			   yparam2='hr',
			   plottype='line',
			   workstrokesonly=False):


    #rowdata,row = dataprep.getrowdata_db(id=id)
    columns = [xparam,yparam1,yparam2,
               'ftime','distance','fpace',
               'power','hr','spm','driveenergy',
               'time','pace','workoutstate','time']

    rowdata = dataprep.getsmallrowdata_db(columns,ids=[id],doclean=True,
                                          workstrokesonly=workstrokesonly)

    if rowdata.empty:
        rowdata = dataprep.getsmallrowdata_db(columns,ids=[id],doclean=True,
                                              workstrokesonly=False)
        workstrokesonly=False
        
    try:
        tests = rowdata[yparam2]
    except KeyError:
        yparam2 = 'None'

    try:
        tests = rowdata[yparam1]
    except KeyError:
        yparam1 = 'None'
        
    rowdata.dropna(axis=1,how='all',inplace=True)
    rowdata.dropna(axis=0,how='any',inplace=True)

    # test if we have drive energy
    nowork = 1
    try:
        test = rowdata['driveenergy'].mean()
        nowork = 0
    except KeyError:
        rowdata['driveenergy'] = 500.

    # test if we have power
    nopower = 1
    try:
        test = rowdata['power'].mean()
        nopower = 0
    except KeyError:
        rowdata['power'] = 50.
        
    row = Workout.objects.get(id=id)
    if rowdata.empty:
	return "","No valid data"
    else:
        try:
            rowdata.sort_values(by='time',ascending=True,inplace=True)
        except KeyError:
            pass

    workoutstateswork = [1,4,5,8,9,6,7]
    workoutstatesrest = [3]
    workoutstatetransition = [0,2,10,11,12,13]

    if workstrokesonly:
	try:
	    rowdata = rowdata[~rowdata['workoutstate'].isin(workoutstatesrest)]
	except KeyError:
	    pass

    try:
        tseconds = rowdata.ix[:,'time']
    except KeyError:
        return '','No time data - cannot make flex plot','',''

    
    try:
        rowdata['x1'] = rowdata.ix[:,xparam]
    except KeyError:
        rowdata['x1'] = 0*rowdata.ix[:,'time']

    try:
        rowdata['y1'] = rowdata.ix[:,yparam1]
    except KeyError:
        rowdata['y1'] = 0*rowdata.ix[:,'time']

    if yparam2 != 'None':
        try:
	    rowdata['y2'] = rowdata.ix[:,yparam2]
        except KeyError:
            rowdata['y2'] = 0*rowdata.ix[:,'time']
    else:
	rowdata['y2'] = rowdata['y1']

    if xparam=='time':
	xaxmax = tseconds.max()
	xaxmin = tseconds.min()
    elif xparam=='distance' or xparam=='cumdist':
	xaxmax = rowdata['x1'].max()
	xaxmin = rowdata['x1'].min()
    else:
	xaxmax = yaxmaxima[xparam]
	xaxmin = yaxminima[xparam]

    # average values
    if xparam != 'time':
        try:
	    x1mean = rowdata['x1'].mean()
        except TypeError:
            x1mean = 0
    else:
	x1mean = 0
	
    y1mean = rowdata['y1'].mean()
    y2mean = rowdata['y2'].mean()

    if xparam != 'time':
	xvals = xaxmin+np.arange(100)*(xaxmax-xaxmin)/100.
    else:
	xvals = np.arange(100)

    # constant power plot
    if yparam1 == 'driveenergy':
	if xparam == 'spm':
	    yconstantpower = rowdata['y1'].mean()*rowdata['x1'].mean()/xvals
	
    x_axis_type = 'linear'
    y_axis_type = 'linear'
    if xparam == 'time':
	x_axis_type = 'datetime'

    if yparam1 == 'pace':
	y_axis_type = 'datetime'
	y1mean = rowdata.ix[:,'pace'].mean()


    rowdata['xname'] = axlabels[xparam]
    rowdata['yname1'] = axlabels[yparam1]
    if yparam2 != 'None':
        rowdata['yname2'] = axlabels[yparam2]
    else:
        rowdata['yname2'] = axlabels[yparam1]

        
    # prepare data
    source = ColumnDataSource(
	rowdata
	)

    # second source for filtering
    source2 = ColumnDataSource(
	rowdata.copy()
	)
    
    # Add hover to this comma-separated string and see what changes
    if (promember==1):
	TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,hover,resize,crosshair'
    else:
	TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,hover,crosshair'



    sizing_mode = 'fixed'  # 'scale_width' also looks nice with this example

    plot = Figure(x_axis_type=x_axis_type,y_axis_type=y_axis_type,
		  tools=TOOLS,
		  toolbar_sticky=False
		  )
                                   


    # add watermark
    plot.extra_y_ranges = {"watermark": watermarkrange}
    plot.extra_x_ranges = {"watermark": watermarkrange}

    plot.image_url([watermarkurl],watermarkx,watermarky,
                   watermarkw,watermarkh,
                   global_alpha=watermarkalpha,
                   w_units='screen',
                   h_units='screen',
                   anchor=watermarkanchor,
                   dilate=True,
                   x_range_name = "watermark",
                   y_range_name = "watermark",
                   )
    
    x1means = Span(location=x1mean,dimension='height',line_color='green',
		   line_dash=[6,6], line_width=2)

    y1means = Span(location=y1mean,dimension='width',line_color='blue',
		   line_dash=[6,6],line_width=2)
    y2means = y1means

    xlabel = Label(x=100,y=130,x_units='screen',y_units='screen',
                   text=axlabels[xparam]+": {x1mean:6.2f}".format(x1mean=x1mean),
                   background_fill_alpha=.7,
                   background_fill_color='white',
                   text_color='green',
    )

    annolabel = Label(x=100,y=500,x_units='screen',y_units='screen',
                      text='',
                      background_fill_alpha=0.7,
                      background_fill_color='white',
                      text_color='black',
    )
    

    if (xparam != 'time') and (xparam != 'distance') and (xparam != 'cumdist'):
	plot.add_layout(x1means)
        plot.add_layout(xlabel)


    plot.add_layout(y1means)
    plot.add_layout(annolabel)

    y1label = Label(x=100,y=100,x_units='screen',y_units='screen',
                    text=axlabels[yparam1]+": {y1mean:6.2f}".format(y1mean=y1mean),
                    background_fill_alpha=.7,
                    background_fill_color='white',
                    text_color='blue',
    )
    if yparam1 != 'time' and yparam1 != 'pace':
        plot.add_layout(y1label)
    y2label = y1label
    
    # average values
    if yparam1 == 'driveenergy':
	if xparam == 'spm':
	    plot.line(xvals,yconstantpower,color="green",legend="Constant Power")

    if plottype=='line':
	plot.line('x1','y1',source=source2,legend=axlabels[yparam1])
    elif plottype=='scatter':
	plot.scatter('x1','y1',source=source2,legend=axlabels[yparam1],fill_alpha=0.4,
		     line_color=None)

    plot.title.text = row.name
    plot.title.text_font_size=value("1.0em")

    plot.xaxis.axis_label = axlabels[xparam]
    plot.yaxis.axis_label = axlabels[yparam1]



    yrange1 = Range1d(start=yaxminima[yparam1],end=yaxmaxima[yparam1])
    plot.y_range = yrange1

    if (xparam != 'time') and (xparam != 'distance') and (xparam != 'cumdist'):
	xrange1 = Range1d(start=yaxminima[xparam],end=yaxmaxima[xparam])
	plot.x_range = xrange1

    if xparam == 'time':
	xrange1 = Range1d(start=xaxmin,end=xaxmax)
	plot.x_range = xrange1
	plot.xaxis[0].formatter = DatetimeTickFormatter(
		hours = ["%H"],
		minutes = ["%M"],
		seconds = ["%S"],
		days = ["0"],
		months = [""],
		years = [""]
	    )


    if yparam1 == 'pace':
	plot.yaxis[0].formatter = DatetimeTickFormatter(
		seconds = ["%S"],
		minutes = ["%M"]
	    )

        
    if yparam2 != 'None':
	yrange2 = Range1d(start=yaxminima[yparam2],end=yaxmaxima[yparam2])
	plot.extra_y_ranges["yax2"] = yrange2
        #= {"yax2": yrange2}

	if plottype=='line':
	    plot.line('x1','y2',color="red",y_range_name="yax2",
		      legend=axlabels[yparam2],
		      source=source2)

	elif plottype=='scatter':
	    plot.scatter('x1','y2',source=source2,legend=axlabels[yparam2]
			 ,fill_alpha=0.4,
			 line_color=None,color="red",y_range_name="yax2")
	
	plot.add_layout(LinearAxis(y_range_name="yax2",
				   axis_label=axlabels[yparam2]),'right')

	y2means = Span(location=y2mean,dimension='width',line_color='red',
		       line_dash=[6,6],line_width=2,y_range_name="yax2")


	plot.add_layout(y2means)
        y2label = Label(x=100,y=70,x_units='screen',y_units='screen',
                        text=axlabels[yparam2]+": {y2mean:6.2f}".format(y2mean=y2mean),
                        background_fill_alpha=.7,
                        background_fill_color='white',
                        text_color='red',
        )
        if yparam2 != 'pace' and yparam2 != 'time':
            plot.add_layout(y2label)

    hover = plot.select(dict(type=HoverTool))


    hover.tooltips = OrderedDict([
	('Time','@ftime'),
	('Distance','@distance{int}'),
	('Pace','@fpace'),
	('HR','@hr{int}'),
	('SPM','@spm{1.1}'),
	('Power','@power{int}'),
	])
 
    hover.mode = 'mouse'

    
    callback = CustomJS(args = dict(source=source,source2=source2,
				    x1means=x1means,
				    y1means=y1means,
                                    y1label=y1label,
                                    y2label=y2label,
                                    xlabel=xlabel,
                                    annolabel=annolabel,
				    y2means=y2means,
    ), code="""
       var data = source.data
       var data2 = source2.data
       var x1 = data['x1']
       var y1 = data['y1']
       var y2 = data['y2']
       var spm1 = data['spm']
       var time1 = data['time']
       var pace1 = data['pace']
       var hr1 = data['hr']
       var fpace1 = data['fpace']
       var distance1 = data['distance']
       var power1 = data['power']
       var driveenergy1 = data['driveenergy']
       var xname = data['xname'][0]
       var yname1 = data['yname1'][0]
       var yname2 = data['yname2'][0]
       
       var annotation = annotation.value
       var minspm = minspm.value
       var maxspm = maxspm.value
       var mindist = mindist.value
       var maxdist = maxdist.value
       var minwork = minwork.value
       var maxwork = maxwork.value
       var xm = 0
       var ym1 = 0
       var ym2 = 0

       data2['x1'] = []
       data2['y1'] = []
       data2['y2'] = []
       data2['spm'] = []
       data2['time'] = []
       data2['pace'] = []
       data2['hr'] = []
       data2['fpace'] = []
       data2['distance'] = []
       data2['power'] = []
       data2['x1mean'] = []
       data2['y1mean'] = []
       data2['y2mean'] = []
       data2['xvals'] = []
       data2['y1vals'] = []
       data2['y2vals'] = []

       for (i=0; i<x1.length; i++) {
	  if (spm1[i]>=minspm && spm1[i]<=maxspm) {
	     if (distance1[i]>=mindist && distance1[i]<=maxdist) {
                if (driveenergy1[i]>=minwork && driveenergy1[i]<=maxwork) {
	           data2['x1'].push(x1[i])
		   data2['y1'].push(y1[i])
		   data2['y2'].push(y2[i])
		   data2['spm'].push(spm1[i])
		   data2['time'].push(time1[i])
                   data2['fpace'].push(fpace1[i])
		   data2['pace'].push(pace1[i])
		   data2['hr'].push(hr1[i])
		   data2['distance'].push(distance1[i])
		   data2['power'].push(power1[i])

		   xm += x1[i]
		   ym1 += y1[i]
		   ym2 += y2[i]
                 }
		}
	     }
       }

       xm /= data2['x1'].length
       ym1 /= data2['x1'].length
       ym2 /= data2['x1'].length

       data2['x1mean'] = [xm,xm]
       data2['y1mean'] = [ym1,ym1]
       data2['y2mean'] = [ym2,ym2]
       x1means.location = xm
       y1means.location = ym1
       y2means.location = ym2
       y1label.text = yname1+': '+ym1.toFixed(2)
       y2label.text = yname2+': '+ym2.toFixed(2)
       xlabel.text = xname+': '+xm.toFixed(2)
       annolabel.text = annotation

       source2.trigger('change');
       """)

    annotation = TextInput(title="Type your plot notes here", value="",
                           callback=callback)
    callback.args["annotation"] = annotation
    
    slider_spm_min = Slider(start=15.0, end=55,value=15.0, step=.1,
		title="Min SPM",callback=callback)
    callback.args["minspm"] = slider_spm_min
    

    slider_spm_max = Slider(start=15.0, end=55,value=55.0, step=.1,
		title="Max SPM",callback=callback)
    callback.args["maxspm"] = slider_spm_max
    
    slider_work_min = Slider(start=0.0, end=1500,value=0.0, step=10,
		title="Min Work per Stroke",callback=callback)
    callback.args["minwork"] = slider_work_min
    

    slider_work_max = Slider(start=0.0, end=1500,value=1500.0, step=10,
		title="Max Work per Stroke",callback=callback)
    callback.args["maxwork"] = slider_work_max
    
    distmax = 100+100*int(rowdata['distance'].max()/100.)
    
    slider_dist_min = Slider(start=0,end=distmax,value=0,step=1,
			     title="Min Distance",callback=callback)
    callback.args["mindist"] = slider_dist_min

    slider_dist_max = Slider(start=0,end=distmax,value=distmax,
			     step=1,
			     title="Max Distance",callback=callback)
    callback.args["maxdist"] = slider_dist_max

    layout = layoutrow([layoutcolumn([slider_spm_min,
			              slider_spm_max,
			              slider_dist_min,
			              slider_dist_max,
                                      slider_work_min,
                                      slider_work_max,
                                      annotation,
			       ],
				     ),
			plot])

    script, div = components(layout)
    js_resources = INLINE.render_js()
    css_resources = INLINE.render_css()

    return [script,div,js_resources,css_resources,workstrokesonly]


def interactive_bar_chart(id=0,promember=0):
    # check if valid ID exists (workout exists)
    rowdata,row = dataprep.getrowdata_db(id=id)
    rowdata.dropna(axis=1,how='all',inplace=True)
    rowdata.dropna(axis=0,how='any',inplace=True)

    if rowdata.empty:
	return "","No Valid Data Available"

    # Add hover to this comma-separated string and see what changes
    if (promember==1):
	TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,hover,resize,crosshair'
    else:
	TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,hover,crosshair'
    
    source = ColumnDataSource(
	rowdata
	)

    plot = Figure(x_axis_type="datetime",y_axis_type="datetime",
		  toolbar_sticky=False,
		  plot_width=920,
		  tools=TOOLS)

    # add watermark
    plot.extra_y_ranges = {"watermark": watermarkrange}
    plot.extra_x_ranges = {"watermark": watermarkrange}

    plot.image_url([watermarkurl],0.01,0.99,
                   watermarkw,watermarkh,
                   global_alpha=watermarkalpha,
                   w_units='screen',
                   h_units='screen',
                   anchor='top_left',
                   dilate=True,
                   x_range_name = "watermark",
                   y_range_name = "watermark",
                   )

    plot.title.text = row.name
    plot.title.text_font_size=value("1.0em")
    plot.xaxis.axis_label = "Time"
    plot.yaxis.axis_label = "Pace (/500m)"
    plot.xaxis[0].formatter = DatetimeTickFormatter(
	hours ="",
	minutes = ["%M"],
	seconds = ["%S"],
	days = ["0"],
	months = [""],
	years = [""]
	)

    plot.yaxis[0].formatter = DatetimeTickFormatter(
	hours = "",
	seconds = ["%S"],
	minutes = ["%M"],
	)
    ymax = 1.0e3*90
    ymin = 1.0e3*180

    if row.workouttype == 'water':
	ymax = 1.0e3*90
	ymin = 1.0e3*210
    
    plot.y_range = Range1d(ymin,ymax)


    hover = plot.select(dict(type=HoverTool))


    hover.tooltips = OrderedDict([
	('Time','@ftime'),
	('Pace','@fpace'),
	('HR','@hr{int}'),
	('SPM','@spm{1.1}'),
	])
 
    hover.mode = 'mouse'

    plot.extra_y_ranges["hr"] = Range1d(start=100,end=200)
    plot.quad(left='time',top='hr_ut2',bottom='hr_bottom',
	      right='x_right',source=source,color="gray",
	      y_range_name="hr", legend="<UT2")
    plot.quad(left='time',top='hr_ut1',bottom='hr_bottom',
	      right='x_right',source=source,color="tan",
	      y_range_name="hr", legend="UT2")
    plot.quad(left='time',top='hr_at',bottom='hr_bottom',
	      right='x_right',source=source,color="green",
	      y_range_name="hr", legend="UT1")
    plot.quad(left='time',top='hr_tr',bottom='hr_bottom',
	      right='x_right',source=source,color="blue",
	      y_range_name="hr", legend="AT")
    plot.quad(left='time',top='hr_an',bottom='hr_bottom',
	      right='x_right',source=source,color="violet",
	      y_range_name="hr", legend="TR")
    plot.quad(left='time',top='hr_max',bottom='hr_bottom',
	      right='x_right',source=source,color="red",
	      y_range_name="hr", legend="AN")


    plot.add_layout(LinearAxis(y_range_name="hr",axis_label="HR"),'right')

    plot.line('time','pace',source=source,legend="Pace",color="black")

 
    script, div = components(plot)

    return [script,div]

def interactive_multiple_compare_chart(ids,xparam,yparam,plottype='line',
                                       promember=0,
                                       labeldict=None):
    columns = [xparam,yparam,
               'ftime','distance','fpace',
               'power','hr','spm',
               'time','pace','workoutstate',
               'workoutid']
    
    datadf = dataprep.getsmallrowdata_db(columns,ids=ids)
    datadf.dropna(axis=1,how='all',inplace=True)
    datadf.dropna(axis=0,how='any',inplace=True)

    nrworkouts = len(ids)
    
    tseconds = datadf.ix[:,'time']

    yparamname = axlabels[yparam]

    #datadf = datadf[datadf[yparam] > 0]
	
    #datadf = datadf[datadf[xparam] > 0]
	
    # check if dataframe not empty
    if datadf.empty:
	return ['','<p>No non-zero data in selection</p>','','']

    if xparam != 'distance' and xparam != 'time' and xparam !=  'cumdist':
	xaxmax = yaxmaxima[xparam]
	xaxmin = yaxminima[xparam]
    elif xparam == 'time':
	xaxmax = tseconds.max()
	xaxmin = tseconds.min()
    else:
        xaxmax = datadf['distance'].max()
	xaxmin = datadf['distance'].min()

    if yparam == 'distance':
        yaxmin = datadf['distance'].min()
        yaxmax = datadf['distance'].max()
    elif yparam == 'cumdist':
        yaxmin = datadf['cumdist'].min()
        yaxmax = datadf['cumdist'].max()
    else:
        yaxmin = yaxminima[yparam]
        yaxmax = yaxmaxima[yparam]
        
    x_axis_type = 'linear'
    y_axis_type = 'linear'

    # Add hover to this comma-separated string and see what changes
    if (promember==1):
	TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,resize,crosshair'
    else:
	TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,crosshair'

    if yparam == 'pace':
	y_axis_type = 'datetime'
        yaxmax = 90.*1e3
        yaxmin = 150.*1e3
        
    if xparam == 'time':
	x_axis_type = 'datetime'

    if xparam != 'time':
	xvals = xaxmin+np.arange(100)*(xaxmax-xaxmin)/100.
    else:
	xvals = np.arange(100)

    plot = Figure(x_axis_type=x_axis_type,y_axis_type=y_axis_type,
		  tools=TOOLS,
		  toolbar_location="above",
                  plot_width=920,
		  toolbar_sticky=False)

    # add watermark
    plot.extra_y_ranges = {"watermark": watermarkrange}
    plot.extra_x_ranges = {"watermark": watermarkrange}

    plot.image_url([watermarkurl],0.05,0.9,
                   watermarkw,watermarkh,
                   global_alpha=watermarkalpha,
                   w_units='screen',
                   h_units='screen',
                   anchor='top_left',
                   dilate=True,
                   x_range_name = "watermark",
                   y_range_name = "watermark",
                   )

    colors = itertools.cycle(palette)

    cntr = 0
    
    for id,color in itertools.izip(ids,colors):
        group = datadf[datadf['workoutid']==int(id)].copy()
        group.sort_values(by='time',ascending=True,inplace=True)
        group['x'] = group[xparam]
        try:
            group['y'] = group[yparam]
        except KeyError:
            group['y'] = 0.0*group['x']

        ymean = group['y'].mean()
        ylabel = Label(x=100,y=60+nrworkouts*20-20*cntr,
                       x_units='screen',y_units='screen',
                       text=axlabels[yparam]+": {ymean:6.2f}".format(ymean=ymean),
                       background_fill_alpha=.7,
                       background_fill_color='white',
                       text_color=color,
        )
        if yparam != 'time' and yparam != 'pace':
            plot.add_layout(ylabel)

        source = ColumnDataSource(
            group
            )

        TIPS = OrderedDict([
	    ('time','@ftime'),
            ('pace','@fpace'),
	    ('hr','@hr'),
	    ('spm','@spm{1.1}'),
	    ('distance','@distance{5}'),
	])

        hover = plot.select(type=HoverTool)
        hover.tooltips = TIPS

        if labeldict:
            legend=labeldict[id]
        else:
            legend=str(id)
            
        if plottype=='line':
            l1 = plot.line('x','y',source=source,color=color,legend=legend)
        else:
            l1 = plot.scatter('x','y',source=source,color=color,legend=legend,
                         fill_alpha=0.4,line_color=None)

        plot.add_tools(HoverTool(renderers=[l1],tooltips=TIPS))
        cntr += 1

    plot.legend.location='bottom_right'
    plot.xaxis.axis_label = axlabels[xparam]
    plot.yaxis.axis_label = axlabels[yparam]

    if (xparam != 'time') and (xparam != 'distance') and (xparam != 'cumdist'):
	xrange1 = Range1d(start=yaxminima[xparam],end=yaxmaxima[xparam])
	plot.x_range = xrange1

    yrange1 = Range1d(start=yaxmin,end=yaxmax)
    plot.y_range = yrange1
        
    if xparam == 'time':
	xrange1 = Range1d(start=xaxmin,end=xaxmax)
	plot.x_range = xrange1
	plot.xaxis[0].formatter = DatetimeTickFormatter(
		hours = ["%H"],
		minutes = ["%M"],
		seconds = ["%S"],
		days = ["0"],
		months = [""],
		years = [""]
	    )


    if yparam == 'pace':
	plot.yaxis[0].formatter = DatetimeTickFormatter(
		seconds = ["%S"],
		minutes = ["%M"]
	    )
        
    script, div = components(plot)

 

    return [script,div]



def interactive_comparison_chart(id1=0,id2=0,xparam='distance',yparam='spm',
			         promember=0,plottype='line'):




    columns = [xparam,yparam,
               'ftime','distance','fpace',
               'power','hr','spm',
               'time','pace','workoutstate']
    
    # check if valid ID exists (workout exists)
    #rowdata1,row1 = dataprep.getrowdata_db(id=id1)
    #rowdata2,row2 = dataprep.getrowdata_db(id=id2)

    rowdata1 = dataprep.getsmallrowdata_db(columns,ids=[id1])
    rowdata2 = dataprep.getsmallrowdata_db(columns,ids=[id2])
    for n in ['distance','power','hr','spm','time','pace','workoutstate']:
        rowdata1[n].fillna(value=0,inplace=True)
        rowdata2[n].fillna(value=0,inplace=True)

    rowdata1.dropna(axis=1,how='all',inplace=True)
    rowdata1.dropna(axis=0,how='any',inplace=True)
    rowdata2.dropna(axis=1,how='all',inplace=True)
    rowdata2.dropna(axis=0,how='any',inplace=True)

    row1 = Workout.objects.get(id=id1)
    row2 = Workout.objects.get(id=id2)

    if rowdata1.empty:
	return "","No Valid Data Available"
    else:
        rowdata1.sort_values(by='time',ascending=True,inplace=True)
    
    if rowdata2.empty:
	return "","No Valid Data Available"
    else:
        rowdata2.sort_values(by='time',ascending=True,inplace=True)

    try:
        x1 = rowdata1.ix[:,xparam]
        x2 = rowdata2.ix[:,xparam]

        y1 = rowdata1.ix[:,yparam]
        y2 = rowdata2.ix[:,yparam]
    except KeyError:
        return "","No valid Data Available"

    x_axis_type = 'linear'
    y_axis_type = 'linear'
    if xparam == 'time':
	x_axis_type = 'datetime'

    if yparam == 'pace':
	y_axis_type = 'datetime'
	ymax = 1.0e3*90
	ymin = 1.0e3*180

	if row1.workouttype == 'water':
	    ymax = 1.0e3*90
	    ymin = 1.0e3*210

    ftime1 = rowdata1.ix[:,'ftime']
    ftime2 = rowdata2.ix[:,'ftime']

    hr1 = rowdata1.ix[:,'hr']
    hr2 = rowdata2.ix[:,'hr']


    fpace1 = rowdata1.ix[:,'fpace']
    fpace2 = rowdata2.ix[:,'fpace']

    distance1 = rowdata1.ix[:,'distance']
    distance2 = rowdata2.ix[:,'distance']

    spm1 = rowdata1.ix[:,'spm']
    spm2 = rowdata2.ix[:,'spm']

    if (promember==1):
	TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,hover,resize,crosshair'
    else:
	TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,hover,crosshair'


    data1 = pd.DataFrame(
	dict(
	    x1=x1,
	    y1=y1,
	    ftime1=ftime1,
	    fpace1=fpace1,
	    hr1 = hr1,
	    spm1 = spm1,
	    distance1=distance1,
	    )
	).dropna()

    data2 = pd.DataFrame(
	dict(
	    x2=x2,
	    y2=y2,
	    ftime2=ftime2,
	    fpace2=fpace2,
	    hr2 = hr2,
	    spm2 = spm2,
	    distance2=distance2,
	    )
	).dropna()


    
    source1 = ColumnDataSource(
	data1 
	)

    source2 = ColumnDataSource(
	data2 
	)

    ymean1 = data1['y1'].mean()
    ymean2 = data2['y2'].mean()
    
    # create interactive plot
    plot = Figure(x_axis_type=x_axis_type,y_axis_type=y_axis_type,
		  tools=TOOLS,
		  plot_width=920,
		  toolbar_sticky=False)

    # add watermark
    plot.extra_y_ranges = {"watermark": watermarkrange}
    plot.extra_x_ranges = {"watermark": watermarkrange}

    plot.image_url([watermarkurl],0.05,watermarky,
                   watermarkw,watermarkh,
                   global_alpha=watermarkalpha,
                   w_units='screen',
                   h_units='screen',
                   anchor='bottom_left',
                   dilate=True,
                   x_range_name = "watermark",
                   y_range_name = "watermark",
                   )
    
    TIPS = OrderedDict([
	('time','@ftime1'),
        ('pace','@fpace1'),
	('hr','@hr1'),
	('spm','@spm1{1.1}'),
	('distance','@distance1{5}'),
	]) 
    TIPS2 = OrderedDict([
	('time','@ftime2'),
        ('pace','@fpace2'),
	('hr','@hr2'),
	('spm','@spm2{1.1}'),
	('distance','@distance2{5}'),
	]) 



    hover1 = plot.select(type=HoverTool)
    hover1.tooltips = TIPS
    hover2 = plot.select(type=HoverTool)
    hover2.tooltips = TIPS2
    
 
    if plottype=='line':
	l1 = plot.line('x1','y1',source=source1,
                       color="blue",legend=row1.name,
                       )
	l2 = plot.line('x2','y2',source=source2,
                       color="red",legend=row2.name,
                       )
    elif plottype=='scatter':
	l1 = plot.scatter('x1','y1',source=source1,legend=row1.name,
                          fill_alpha=0.4,
		          line_color=None)
	l2 = plot.scatter('x2','y2',source=source2,legend=row2.name,
                          fill_alpha=0.4,
		          line_color=None,color="red")

    plot.add_tools(HoverTool(renderers=[l1],tooltips=TIPS))
    plot.add_tools(HoverTool(renderers=[l2],tooltips=TIPS2))
    plot.legend.location = "bottom_right"

    plot.title.text = row1.name+' vs '+row2.name
    plot.title.text_font_size=value("1.2em")
    plot.xaxis.axis_label = axlabels[xparam]
    plot.yaxis.axis_label = axlabels[yparam]

    ylabel1 = Label(x=100,y=90,x_units='screen',y_units='screen',
                   text=axlabels[yparam]+": {ymean1:6.2f}".format(
                       ymean1=ymean1
                       ),
                   background_fill_alpha=.7,
                   background_fill_color='white',
                   text_color='blue'
                   )
    ylabel2 = Label(x=100,y=110,x_units='screen',y_units='screen',
                   text=axlabels[yparam]+": {ymean2:6.2f}".format(
                       ymean2=ymean2
                       ),
                   background_fill_alpha=.7,
                   background_fill_color='white',
                   text_color='red'
                   )
    plot.add_layout(ylabel1)
    plot.add_layout(ylabel2)

    if xparam == 'time':
	plot.xaxis[0].formatter = DatetimeTickFormatter(
		hours = ["%H"],
		minutes = ["%M"],
		seconds = ["%S"],
		days = ["0"],
		months = [""],
		years = [""]
	    )


    if yparam == 'pace':
	plot.yaxis[0].formatter = DatetimeTickFormatter(
		seconds = ["%S"],
		minutes = ["%M"]
	    )

        plot.y_range = Range1d(ymin,ymax)

        
    script, div = components(plot)

    return [script,div]

def interactive_otw_advanced_pace_chart(id=0,promember=0):
    # check if valid ID exists (workout exists)
    rowdata,row = dataprep.getrowdata_db(id=id)
    rowdata.dropna(axis=1,how='all',inplace=True)
    rowdata.dropna(axis=0,how='any',inplace=True)

    if rowdata.empty:
	return "","No Valid Data Available"

    # Add hover to this comma-separated string and see what changes
    if (promember==1):
	TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,hover,resize,crosshair'
    else:
	TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,hover,crosshair'

    source = ColumnDataSource(
	rowdata
	)


    plot = Figure(x_axis_type="datetime",y_axis_type="datetime",
		  tools=TOOLS,
		  plot_width=920,
		  toolbar_sticky=False)

    # add watermark
    plot.extra_y_ranges = {"watermark": watermarkrange}
    plot.extra_x_ranges = {"watermark": watermarkrange}

    plot.image_url([watermarkurl],watermarkx,watermarky,
                   watermarkw,watermarkh,
                   global_alpha=watermarkalpha,
                   w_units='screen',
                   h_units='screen',
                   anchor=watermarkanchor,
                   dilate=True,
                   x_range_name = "watermark",
                   y_range_name = "watermark",
                   )

    plot.title.text = row.name
    plot.title.text_font_size=value("1.2em")
    plot.xaxis.axis_label = "Time"
    plot.yaxis.axis_label = "Pace (/500m)"
    plot.xaxis[0].formatter = DatetimeTickFormatter(
	    hours = ["%H"],
	    minutes = ["%M"],
	    seconds = ["%S"],
	    days = ["0"],
	    months = [""],
	    years = [""]
	)
    plot.yaxis[0].formatter = DatetimeTickFormatter(
	    seconds = ["%S"],
	    minutes = ["%M"]
	)

    ymax = 1.0e3*90
    ymin = 1.0e3*210
    
    plot.y_range = Range1d(ymin,ymax)


    hover = plot.select(dict(type=HoverTool))

    plot.line('time','pace',source=source,legend="Pace",color="black")
    plot.line('time','nowindpace',source=source,legend="Corrected Pace",color="red")

    hover.tooltips = OrderedDict([
	('Time','@ftime'),
	('Pace','@fpace'),
	('Corrected Pace','@fnowindpace'),
	('HR','@hr{int}'),
	('SPM','@spm{1.1}'),
	])
 
    hover.mode = 'mouse'

    script, div = components(plot)

    return [script,div]

