""" Background tasks done by Celery (develop) or QR (production) """ import os import time import gc import gzip import shutil import numpy as np import re from scipy import optimize import rowingdata from rowingdata import rowingdata as rdata from datetime import timedelta from sqlalchemy import create_engine from celery import app import datetime import pytz import iso8601 from matplotlib.backends.backend_agg import FigureCanvas #from matplotlib.backends.backend_cairo import FigureCanvasCairo as FigureCanvas import matplotlib.pyplot as plt from matplotlib import path from rowsandall_app.settings import SITE_URL from rowsandall_app.settings_dev import SITE_URL as SITE_URL_DEV from rowsandall_app.settings import PROGRESS_CACHE_SECRET from rowsandall_app.settings import SETTINGS_NAME import pandas as pd from django_rq import job from django.utils import timezone from django.utils.html import strip_tags from utils import deserialize_list from rowers.dataprepnodjango import ( update_strokedata, new_workout_from_file, getsmallrowdata_db, updatecpdata_sql, update_agegroup_db,fitnessmetric_to_sql, add_c2_stroke_data_db,totaltime_sec_to_string, create_c2_stroke_data_db,update_empower, database_url_debug,database_url, ) from django.core.mail import ( send_mail, EmailMessage,EmailMultiAlternatives, ) from django.template import Context from django.db.utils import OperationalError from jinja2 import Template,Environment,FileSystemLoader env = Environment(loader = FileSystemLoader(["rowers/templates"])) import datautils import utils import requests import longtask import arrow siteurl = SITE_URL # testing task from rowers.emails import send_template_email from rowers.courseutils import coursetime_paths, coursetime_first @app.task def add(x, y): return x + y @app.task def handle_c2_import_stroke_data(c2token, c2id,workoutid, starttimeunix, csvfilename,debug=True,**kwargs): authorizationstring = str('Bearer ' + c2token) headers = {'Authorization': authorizationstring, 'user-agent': 'sanderroosendaal', 'Content-Type': 'application/json'} url = "https://log.concept2.com/api/users/me/results/"+str(c2id)+"/strokes" s = requests.get(url,headers=headers) if s.status_code == 200: strokedata = pd.DataFrame.from_dict(s.json()['data']) result = add_c2_stroke_data_db( strokedata,workoutid,starttimeunix, csvfilename,debug=debug, ) return 1 else: url = "https://log.concept2.com/api/users/me/results/"+str(c2id) s = requests.get(url,headers=headers) if s.status_code == 200: workoutdata = s.json()['data'] distance = workoutdata['distance'] c2id = workoutdata['id'] workouttype = workoutdata['type'] verified = workoutdata['verified'] startdatetime = iso8601.parse_date(workoutdata['date']) weightclass = workoutdata['weight_class'] weightcategory = 'hwt' if weightclass == "L": weightcategory = 'lwt' totaltime = workoutdata['time']/10. duration = totaltime_sec_to_string(totaltime) duration = datetime.datetime.strptime(duration,'%H:%M:%S.%f').time() try: timezone_str = tz(workoutdata['timezone']) except: timezone_str = 'UTC' workoutdate = startdatetime.astimezone( pytz.timezone(timezone_str) ).strftime('%Y-%m-%d') starttime = startdatetime.astimezone( pytz.timezone(timezone_str) ).strftime('%H:%M:%S') result = create_c2_stroke_data_db( distance,duration,workouttype, workoutid,starttimeunix, csvfilename,debug=debug, ) return 1 return 0 return 0 def getagegrouprecord(age,sex='male',weightcategory='hwt', distance=2000,duration=None,indf=pd.DataFrame()): if not duration: df = indf[indf['distance'] == distance] else: duration = 60*int(duration) df = indf[indf['duration'] == duration] if not df.empty: ages = df['age'] powers = df['power'] #poly_coefficients = np.polyfit(ages,powers,6) fitfunc = lambda pars, x: np.abs(pars[0])*(1-x/max(120,pars[1]))-np.abs(pars[2])*np.exp(-x/np.abs(pars[3]))+np.abs(pars[4])*(np.sin(np.pi*x/max(50,pars[5]))) errfunc = lambda pars, x,y: fitfunc(pars,x)-y p0 = [700,120,700,10,100,100] p1, success = optimize.leastsq(errfunc,p0[:], args = (ages,powers)) if success: power = fitfunc(p1, float(age)) #power = np.polyval(poly_coefficients,age) power = 0.5*(np.abs(power)+power) else: power = 0 else: power = 0 return power def polygon_to_path(polygon,debug=True): pid = polygon[0] query = "SELECT id, latitude, longitude FROM rowers_geopoint WHERE polygon_id = {pid} ORDER BY order_in_poly ASC".format( pid=pid ) if debug: engine = create_engine(database_url_debug, echo=False) else: engine = create_engine(database_url, echo=False) with engine.connect() as conn, conn.begin(): result = conn.execute(query) points = result.fetchall() conn.close() engine.dispose() s = [] for point in points: s.append([point[1],point[2]]) p = path.Path(s[:-1]) return p @app.task(bind=True) def handle_check_race_course(self, f1,workoutid,courseid, recordid,**kwargs): if 'debug' in kwargs: debug = kwargs['debug'] else: debug = False mode = 'race' if 'mode' in kwargs: mode = kwargs['mode'] columns = ['time',' latitude',' longitude','cum_dist'] try: row = rdata(csvfile=f1) except IOError: try: row = rdata(f1 + '.csv') except IOError: try: row = rdata(f1 + '.gz') except IOError: return 0 rowdata = row.df rowdata.rename(columns = { ' latitude':'latitude', ' longitude':'longitude', ' ElapsedTime (sec)': 'time', }, inplace=True) rowdata.fillna(method='backfill',inplace=True) rowdata['time'] = rowdata['time']-rowdata.ix[0,'time'] # we may want to expand the time (interpolate) rowdata['dt'] = rowdata['time'].apply( lambda x: timedelta(seconds=x) ) rowdata = rowdata.resample('100ms',on='dt').mean() rowdata = rowdata.interpolate() # initiate database engine if debug: engine = create_engine(database_url_debug, echo=False) else: engine = create_engine(database_url, echo=False) # get polygons query = "SELECT id FROM rowers_geopolygon WHERE course_id = {courseid} ORDER BY order_in_course ASC".format( courseid=courseid ) with engine.connect() as conn, conn.begin(): result = conn.execute(query) polygons = result.fetchall() conn.close() engine.dispose() paths = [] for polygon in polygons: path = polygon_to_path(polygon,debug=debug) paths.append(path) ( coursetimeseconds, coursemeters, coursecompleted, ) = coursetime_paths(rowdata,paths) ( coursetimefirst, coursemetersfirst, firstcompleted ) = coursetime_first( rowdata,paths) coursetimeseconds = coursetimeseconds-coursetimefirst coursemeters = coursemeters-coursemetersfirst if coursecompleted: query = 'UPDATE rowers_virtualraceresult SET coursecompleted = 1, duration = "{duration}", distance = {distance}, workoutid = {workoutid} WHERE id={recordid}'.format( recordid=recordid, duration=totaltime_sec_to_string(coursetimeseconds), distance=int(coursemeters), workoutid=workoutid, ) if mode == 'coursetest': query = 'UPDATE rowers_coursetestresult SET coursecompleted = 1, duration = "{duration}", distance = {distance}, workoutid = {workoutid} WHERE id={recordid}'.format( recordid=recordid, duration=totaltime_sec_to_string(coursetimeseconds), distance=int(coursemeters), workoutid=workoutid, ) with engine.connect() as conn, conn.begin(): result = conn.execute(query) conn.close() engine.dispose() return 1 else: return 2 return 0 @app.task(bind=True) def handle_getagegrouprecords(self, df, distances,durations, age,sex,weightcategory, **kwargs): wcdurations = [] wcpower = [] if 'debug' in kwargs: debug = kwargs['debug'] else: debug = False df = pd.read_json(df) if sex == 'not specified': return 0 for distance in distances: worldclasspower = getagegrouprecord( age, sex=sex, distance=distance, weightcategory=weightcategory,indf=df, ) velo = (worldclasspower/2.8)**(1./3.) try: duration = distance/velo wcdurations.append(duration) wcpower.append(worldclasspower) except ZeroDivisionError: pass for duration in durations: worldclasspower = getagegrouprecord( age, sex=sex, duration=duration, weightcategory=weightcategory,indf=df ) try: velo = (worldclasspower/2.8)**(1./3.) distance = int(60*duration*velo) wcdurations.append(60.*duration) wcpower.append(worldclasspower) except ValueError: pass update_agegroup_db(age,sex,weightcategory,wcdurations,wcpower, debug=debug) return 1 @app.task(bind=True) def long_test_task(self,aantal,debug=False,job=None,session_key=None): job = self.request return longtask.longtask(aantal,jobid=job.id,debug=debug, session_key=session_key) @app.task(bind=True) def long_test_task2(self,aantal,**kwargs): #debug=False,job=None,jobid='aap'): job = self.request job_id = job.id if 'jobkey' in kwargs: job_id = kwargs.pop('jobkey') kwargs['jobid'] = job_id return longtask.longtask2(aantal,**kwargs) # create workout @app.task def handle_new_workout_from_file(r, f2, workouttype='rower', title='Workout', makeprivate=False, notes='',debug=False): return new_workout_from_file(r, f2, workouttype, title, makeprivate, notes) # process and update workouts @app.task(bind=True) def handle_update_empower(self, useremail, workoutdicts, debug=False, **kwargs): job = self.request job_id = job.id if 'jobkey' in kwargs: job_id = kwargs.pop('jobkey') aantal = len(workoutdicts) counter = 0 for workoutdict in workoutdicts: wid = workoutdict['id'] inboard = workoutdict['inboard'] oarlength = workoutdict['oarlength'] boattype = workoutdict['boattype'] f1 = workoutdict['filename'] # oarlength consistency checks will be done in view havedata = 1 try: rowdata = rdata(f1) except IOError: try: rowdata = rdata(f1 + '.csv') except IOError: try: rowdata = rdata(f1 + '.gz') except IOError: havedata = 0 progressurl = SITE_URL siteurl = SITE_URL if debug: progressurl = SITE_URL_DEV siteurl = SITE_URL_DEV secret = PROGRESS_CACHE_SECRET kwargs['job_id'] = job_id progressurl += "/rowers/record-progress/" progressurl += job_id if havedata: success = update_empower(wid, inboard, oarlength, boattype, rowdata.df, f1, debug=debug) counter += 1 progress = 100.*float(counter)/float(aantal) post_data = { "secret":secret, "value":progress, } s = requests.post(progressurl, data=post_data) status_code = s.status_code subject = "Rowsandall.com Your Old Empower Oarlock data have been corrected" message = """ We have updated Power and Work per Stroke data according to the instructions by Nielsen-Kellerman. """ email = EmailMessage(subject, message, 'Rowsandall ', [useremail]) if 'emailbounced' in kwargs: emailbounced = kwargs['emailbounced'] else: emailbounced = False if not emailbounced: res = email.send() return 1 @app.task def handle_updatedps(useremail, workoutids, debug=False,**kwargs): for wid, f1 in workoutids: havedata = 1 try: rowdata = rdata(f1) except IOError: try: rowdata = rdata(f1 + '.csv') except IOError: try: rowdata = rdata(f1 + '.gz') except IOError: havedata = 0 if havedata: update_strokedata(wid, rowdata.df, debug=debug) subject = "Rowsandall.com Your Distance per Stroke metric has been updated" message = "All your workouts now have Distance per Stroke" email = EmailMessage(subject, message, 'Rowsandall ', [useremail]) if 'emailbounced' in kwargs: emailbounced = kwargs['emailbounced'] else: emailbounced = False if not emailbounced: res = email.send() return 1 # send email when a breakthrough workout is uploaded @app.task def handle_sendemail_breakthrough(workoutid, useremail, userfirstname, userlastname, btvalues=pd.DataFrame().to_json(), **kwargs): if 'debug' in kwargs: debug = kwargs['debug'] else: debug = False btvalues = pd.read_json(btvalues) btvalues.sort_values('delta', axis=0, inplace=True) tablevalues = [ {'delta': t.delta, 'cpvalue': t.cpvalues, 'pwr': t.pwr } for t in btvalues.itertuples() ] # send email with attachment subject = "A breakthrough workout on rowsandall.com" from_email = 'Rowsandall ' d = { 'first_name':userfirstname, 'siteurl':siteurl, 'workoutid':workoutid, 'btvalues':tablevalues, } res = send_template_email(from_email,[useremail], subject,'breakthroughemail.html', d,**kwargs) return 1 # send email when a breakthrough workout is uploaded @app.task def handle_sendemail_hard(workoutid, useremail, userfirstname, userlastname, btvalues=pd.DataFrame().to_json(), debug=False,**kwargs): if 'debug' in kwargs: debug = kwargs['debug'] else: debug = False btvalues = pd.read_json(btvalues) btvalues.sort_values('delta', axis=0, inplace=True) tablevalues = [ {'delta': t.delta, 'cpvalue': t.cpvalues, 'pwr': t.pwr } for t in btvalues.itertuples() ] # send email with attachment subject = "That was a pretty hard workout on rowsandall.com" from_email = 'Rowsandall ' d = { 'first_name':userfirstname, 'siteurl':siteurl, 'workoutid':workoutid, 'btvalues':tablevalues, } res = send_template_email(from_email,[useremail], subject,'hardemail.html',d,**kwargs) return 1 # send email when user deletes account @app.task def handle_sendemail_userdeleted(name, email, debug=False, **kwargs): fullemail = 'roosendaalsander@gmail.com' subject = 'User account deleted' message = 'Sander,\n\n' message += 'The user {name} ({email}) has just deleted his account'.format( name=name, email=email ) email = EmailMessage(subject,message, 'Rowsandall ', [fullemail]) if 'emailbounced' in kwargs: emailbounced = kwargs['emailbounced'] else: emailbounced = False if not emailbounced: res = email.send() return 1 # send email to me when an unrecognized file is uploaded @app.task def handle_sendemail_unrecognized(unrecognizedfile, useremail, debug=False,**kwargs): # send email with attachment fullemail = 'roosendaalsander@gmail.com' subject = "Unrecognized file from Rowsandall.com" message = "Dear Sander,\n\n" message += "Please find attached a file that someone tried to upload to rowsandall.com. The file was not recognized as a valid file type.\n\n" message += "User Email " + useremail + "\n\n" message += "Best Regards, the Rowsandall Team" email = EmailMessage(subject, message, 'Rowsandall ', [fullemail]) try: email.attach_file(unrecognizedfile) except IOError: pass if 'emailbounced' in kwargs: emailbounced = kwargs['emailbounced'] else: emailbounced = False if not emailbounced: res = email.send() # remove tcx file try: os.remove(unrecognizedfile) except: pass return 1 # send email to owner when an unrecognized file is uploaded @app.task def handle_sendemail_unrecognizedowner(useremail, userfirstname, debug=False,**kwargs): # send email with attachment fullemail = useremail subject = "Unrecognized file from Rowsandall.com" d = { 'first_name':userfirstname, 'siteurl':siteurl, } from_email = 'Rowsandall ' res = send_template_email(from_email,[fullemail], subject,'unrecognizedemail.html',d, **kwargs) return 1 # Send email with TCX attachment @app.task def handle_sendemailtcx(first_name, last_name, email, tcxfile,**kwargs): # send email with attachment fullemail = first_name + " " + last_name + " " + "<" + email + ">" subject = "File from Rowsandall.com" d = {'first_name':first_name, 'siteurl':siteurl, } from_email = 'Rowsandall ' res = send_template_email(from_email,[fullemail], subject,'tcxemail.html',d, attach_file=tcxfile,**kwargs) os.remove(tcxfile) return 1 @app.task def handle_zip_file(emailfrom, subject, file,**kwargs): message = "... zip processing ... " try: debug = kwargs['debug'] except KeyError: debug = False if debug: print message email = EmailMessage(subject, message, emailfrom, ['workouts@rowsandall.com']) email.attach_file(file) if debug: print "attaching" res = email.send() if debug: print "sent" time.sleep(60) return 1 # Send email with CSV attachment @app.task def handle_sendemailsummary(first_name, last_name, email, csvfile, **kwargs): fullemail = first_name + " " + last_name + " " + "<" + email + ">" subject = "File from Rowsandall.com" d = {'first_name':first_name, 'siteurl':siteurl, } from_email = 'Rowsandall ' res = send_template_email(from_email,[fullemail], subject,'summarymail.html',d, attach_file=csvfile, **kwargs) try: os.remove(csvfile) except: pass return 1 #from rowers.emails import sendemail @app.task def handle_sendemailcsv(first_name, last_name, email, csvfile,**kwargs): # send email with attachment fullemail = first_name + " " + last_name + " " + "<" + email + ">" subject = "File from Rowsandall.com" d = {'first_name':first_name, 'siteurl':siteurl, } from_email = 'Rowsandall ' res = send_template_email(from_email,[fullemail], subject,'csvemail.html',d, attach_file=csvfile,**kwargs) return 1 # Calculate wind and stream corrections for OTW rowing @app.task(bind=True) def handle_otwsetpower(self,f1, boattype, weightvalue, first_name, last_name, email, workoutid, **kwargs): job = self.request job_id = job.id if 'jobkey' in kwargs: job_id = kwargs.pop('jobkey') if 'ps' in kwargs: ps = kwargs['ps'] else: ps = [1,1,1,1] if 'ratio' in kwargs: ratio = kwargs['ratio'] else: ratio = 1.0 if 'debug' in kwargs: debug = kwargs['debug'] else: debug = False if 'quick_calc' in kwargs: usetable = kwargs['quick_calc'] else: usetable = False kwargs['jobid'] = job_id try: rowdata = rdata(f1) except IOError: try: rowdata = rdata(f1 + '.csv') except IOError: rowdata = rdata(f1 + '.gz') weightvalue = float(weightvalue) # do something with boat type boatfile = { '1x': 'static/rigging/1x.txt', '2x': 'static/rigging/2x.txt', '2-': 'static/rigging/2-.txt', '4x': 'static/rigging/4x.txt', '4-': 'static/rigging/4-.txt', '8+': 'static/rigging/8+.txt', } try: rg = rowingdata.getrigging(boatfile[boattype]) except KeyError: rg = rowingdata.getrigging('static/rigging/1x.txt') # do calculation, but do not overwrite NK Empower Power data powermeasured = False try: w = rowdata.df['wash'] if w.mean() != 0: powermeasured = True except KeyError: pass progressurl = SITE_URL siteurl = SITE_URL if debug: progressurl = SITE_URL_DEV siteurl = SITE_URL_DEV secret = PROGRESS_CACHE_SECRET progressurl += "/rowers/record-progress/" progressurl += job_id # determine cache file name physics_cache = 'media/'+str(boattype)+'_'+str(int(weightvalue)) rowdata.otw_setpower(skiprows=5, mc=weightvalue, rg=rg, powermeasured=powermeasured, progressurl=progressurl, secret=secret, silent=True, usetable=usetable,storetable=physics_cache, ) # save data rowdata.write_csv(f1, gzip=True) update_strokedata(workoutid, rowdata.df, debug=debug) totaltime = rowdata.df['TimeStamp (sec)'].max( ) - rowdata.df['TimeStamp (sec)'].min() try: totaltime = totaltime + rowdata.df.ix[0, ' ElapsedTime (sec)'] except KeyError: pass df = getsmallrowdata_db( ['power', 'workoutid', 'time'], ids=[workoutid], debug=debug) thesecs = totaltime maxt = 1.05 * thesecs logarr = datautils.getlogarr(maxt) dfgrouped = df.groupby(['workoutid']) delta, cpvalues, avgpower = datautils.getcp(dfgrouped, logarr) #delta,cpvalues,avgpower = datautils.getsinglecp(rowdata.df) res, btvalues, res2 = utils.isbreakthrough( delta, cpvalues, ps[0], ps[1], ps[2], ps[3], ratio) if res: handle_sendemail_breakthrough( workoutid, email, first_name, last_name, btvalues=btvalues.to_json()) subject = "Your OTW Physics Calculations are ready" from_email = 'Rowsandall ' fullemail = first_name + " " + last_name + " " + "<" + email + ">" d = { 'first_name':first_name, 'siteurl':siteurl, 'workoutid':workoutid, } res = send_template_email(from_email,[fullemail], subject,'otwpoweremail.html',d, **kwargs) return 1 @app.task def handle_updateergcp(rower_id,workoutfilenames,debug=False,**kwargs): therows = [] for f1 in workoutfilenames: try: rowdata = rdata(f1) except IOError: try: rowdata = rdata(f1 + '.csv') except IOError: try: rowdata = rdata(f1 + '.gz') except IOError: rowdata = 0 if rowdata != 0: therows.append(rowdata) cpdata = rowingdata.cumcpdata(therows) cpdata.columns = cpdata.columns.str.lower() updatecpdata_sql(rower_id,cpdata['delta'],cpdata['cp'], table='ergcpdata',distance=cpdata['distance'], debug=debug) return 1 def cp_from_workoutids(workoutids,debug=False): columns = ['power','workoutid','time'] df = getsmallrowdata_db(columns,ids=workoutids,debug=debug) df.dropna(inplace=True,axis=0) if df.empty: # change this return 0,0,0 # df is not empty. We continue dfgrouped = df.groupby(['workoutid']) maxt = 1.05*df['time'].max()/1000. logarr = datautils.getlogarr(maxt) delta,cpvalue,avgpower = datautils.getcp(dfgrouped,logarr) powerdf = pd.DataFrame({ 'Delta':delta, 'CP':cpvalue, }) powerdf = powerdf[powerdf['CP']>0] powerdf.dropna(axis=0,inplace=True) powerdf.sort_values(['Delta','CP'],ascending=[1,0],inplace=True) powerdf.drop_duplicates(subset='Delta',keep='first',inplace=True) p1,fitt,fitpower,ratio = datautils.cpfit(powerdf) # This is code duplication from datautils -- correct asap fitfunc = lambda pars,x: abs(pars[0])/(1+(x/abs(pars[2]))) + abs(pars[1])/(1+(x/abs(pars[3]))) powerfourmin = fitfunc(p1,240.) powerhour = fitfunc(p1,3600.) # 2k power velofourmin = (powerfourmin/2.8)**(1./3.) dfourmin = 240.*velofourmin dratio = 2000./dfourmin pacefourmin = 500./velofourmin # assume 5 sec per doubling drop pace2k = pacefourmin + 5.*np.log10(dratio)/np.log10(2.) velo2k = 500./pace2k t2k = 2000./velo2k pwr2k = fitfunc(p1,t2k) velo2 = (pwr2k/2.8)**(1./3.) if np.isnan(velo2) or velo2 <= 0: velo2 = 1.0 t2 = 2000./velo2 pwr2k = fitfunc(p1,t2) velo3 = (pwr2k/2.8)**(1./3.) t3 = 2000./velo3 power2k = fitfunc(p1,t3) return powerfourmin,power2k,powerhour @app.task def handle_updatefitnessmetric(user_id,mode,workoutids,debug=False, **kwargs): powerfourmin = -1 power2k = -1 powerhour = -1 mdict = { 'user_id': user_id, 'PowerFourMin': powerfourmin, 'PowerTwoK': power2k, 'PowerOneHour': powerhour, 'workoutmode': mode, 'last_workout': max(workoutids), 'date': timezone.now().strftime('%Y-%m-%d'), } result = fitnessmetric_to_sql(mdict,debug=debug,doclean=False) powerfourmin,power2k,powerhour = cp_from_workoutids(workoutids,debug=debug) if powerfourmin > 0 and power2k > 0 and powerhour > 0: mdict = { 'user_id': user_id, 'PowerFourMin': powerfourmin, 'PowerTwoK': power2k, 'PowerOneHour': powerhour, 'workoutmode': mode, 'last_workout': max(workoutids), 'date': timezone.now().strftime('%Y-%m-%d'), } result = fitnessmetric_to_sql(mdict,debug=debug,doclean=True) else: result = 0 return result @app.task def handle_updatecp(rower_id,workoutids,debug=False,table='cpdata',**kwargs): columns = ['power','workoutid','time'] df = getsmallrowdata_db(columns,ids=workoutids,debug=debug) dfgrouped = df.groupby(['workoutid']) if not df.empty: maxt = 1.05*df['time'].max()/1000. else: maxt = 1000. logarr = datautils.getlogarr(maxt) delta,cpvalue,avgpower = datautils.getcp(dfgrouped,logarr) updatecpdata_sql(rower_id,delta,cpvalue,debug=debug,table=table) return 1 @app.task def handle_makeplot(f1, f2, t, hrdata, plotnr, imagename, debug=False,**kwargs): hrmax = hrdata['hrmax'] hrut2 = hrdata['hrut2'] hrut1 = hrdata['hrut1'] hrat = hrdata['hrat'] hrtr = hrdata['hrtr'] hran = hrdata['hran'] ftp = hrdata['ftp'] powerzones = deserialize_list(hrdata['powerzones']) powerperc = np.array(deserialize_list(hrdata['powerperc'])).astype(int) rr = rowingdata.rower(hrmax=hrmax, hrut2=hrut2, hrut1=hrut1, hrat=hrat, hrtr=hrtr, hran=hran, ftp=ftp, powerperc=powerperc, powerzones=powerzones) try: row = rdata(f2, rower=rr) except IOError: row = rdata(f2 + '.gz', rower=rr) haspower = row.df[' Power (watts)'].mean() > 50 nr_rows = len(row.df) if (plotnr in [1, 2, 4, 5, 8, 11, 9, 12]) and (nr_rows > 1200): bin = int(nr_rows / 1200.) df = row.df.groupby(lambda x: x / bin).mean() row.df = df nr_rows = len(row.df) if (plotnr == 1): fig1 = row.get_timeplot_erg(t) elif (plotnr == 2): fig1 = row.get_metersplot_erg(t) elif (plotnr == 3): t += ' - Heart Rate Distribution' fig1 = row.get_piechart(t) elif (plotnr == 4): if haspower: fig1 = row.get_timeplot_otwempower(t) else: fig1 = row.get_timeplot_otw(t) elif (plotnr == 5): if haspower: fig1 = row.get_metersplot_otwempower(t) else: fig1 = row.get_metersplot_otw(t) elif (plotnr == 6): t += ' - Heart Rate Distribution' fig1 = row.get_piechart(t) elif (plotnr == 7) or (plotnr == 10): fig1 = row.get_metersplot_erg2(t) elif (plotnr == 8) or (plotnr == 11): fig1 = row.get_timeplot_erg2(t) elif (plotnr == 9) or (plotnr == 12): fig1 = row.get_time_otwpower(t) elif (plotnr == 13) or (plotnr == 16): t += ' - Power Distribution' fig1 = row.get_power_piechart(t) canvas = FigureCanvas(fig1) # plt.savefig('static/plots/'+imagename,format='png') canvas.print_figure('static/plots/' + imagename) # plt.imsave(fname='static/plots/'+imagename) plt.close(fig1) fig1.clf() gc.collect() return imagename # Team related remote tasks @app.task def handle_sendemail_invite(email, name, code, teamname, manager, debug=False,**kwargs): fullemail = name + ' <' + email + '>' subject = 'Invitation to join team ' + teamname siteurl = SITE_URL if debug: siteurl = SITE_URL_DEV d = { 'name':name, 'manager':manager, 'code':code, 'teamname':teamname, 'siteurl':siteurl } from_email = 'Rowsandall ' res = send_template_email(from_email,[fullemail], subject,'teaminviteemail.html',d, **kwargs) return 1 @app.task def handle_sendemailnewresponse(first_name, last_name, email, commenter_first_name, commenter_last_name, comment, workoutname, workoutid, commentid, debug=False,**kwargs): fullemail = first_name + ' ' + last_name + ' <' + email + '>' from_email = 'Rowsandall ' subject = 'New comment on workout ' + workoutname siteurl = SITE_URL if debug: siteurl = SITE_URL_DEV d = { 'first_name':first_name, 'commenter_first_name':commenter_first_name, 'commenter_last_name':commenter_last_name, 'comment':comment, 'workoutname':workoutname, 'siteurl':siteurl, 'workoutid':workoutid, 'commentid':commentid } res = send_template_email(from_email,[fullemail],subject,'teamresponseemail.html',d,**kwargs) return 1 @app.task def handle_sendemailnewcomment(first_name, last_name, email, commenter_first_name, commenter_last_name, comment, workoutname, workoutid, debug=False,**kwargs): fullemail = first_name + ' ' + last_name + ' <' + email + '>' from_email = 'Rowsandall ' subject = 'New comment on workout ' + workoutname siteurl = SITE_URL if debug: siteurl = SITE_URL_DEV d = { 'first_name':first_name, 'commenter_first_name':commenter_first_name, 'commenter_last_name':commenter_last_name, 'comment':comment, 'workoutname':workoutname, 'siteurl':siteurl, 'workoutid':workoutid, } res = send_template_email(from_email,[fullemail],subject, 'teamresponseemail.html',d,**kwargs) return 1 @app.task def handle_sendemail_request(email, name, code, teamname, requestor, id, debug=False,**kwargs): fullemail = name + ' <' + email + '>' subject = 'Request to join team ' + teamname from_email = 'Rowsandall ' siteurl = SITE_URL if debug: siteurl = SITE_URL_DEV d = { 'requestor':requestor, 'teamname':teamname, 'siteurl':siteurl, 'id':id, 'first_name':name, } res = send_template_email(from_email,[fullemail],subject, 'teamrequestemail.html',d,**kwargs) return 1 @app.task def handle_sendemail_request_accept(email, name, teamname, managername, debug=False,**kwargs): fullemail = name + ' <' + email + '>' subject = 'Welcome to ' + teamname from_email = 'Rowsandall ' siteurl = SITE_URL if debug: siteurl = SITE_URL_DEV d = { 'first_name':name, 'managername':managername, 'teamname':teamname, 'siteurl':siteurl, } res = send_template_email(from_email,[fullemail],subject, 'teamwelcomeemail.html',d,**kwargs) return 1 @app.task def handle_sendemail_request_reject(email, name, teamname, managername, debug=False,**kwargs): fullemail = name + ' <' + email + '>' subject = 'Your application to ' + teamname + ' was rejected' from_email = 'Rowsandall ' siteurl = SITE_URL if debug: siteurl = SITE_URL_DEV d = { 'first_name':name, 'managername':managername, 'teamname':teamname, 'siteurl':siteurl, } res = send_template_email(from_email,[fullemail],subject, 'teamrejectemail.html',d,**kwargs) return 1 @app.task def handle_sendemail_member_dropped(email, name, teamname, managername, debug=False,**kwargs): fullemail = name + ' <' + email + '>' subject = 'You were removed from ' + teamname from_email = 'Rowsandall ' siteurl = SITE_URL if debug: siteurl = SITE_URL_DEV d = { 'first_name':name, 'managername':managername, 'teamname':teamname, 'siteurl':siteurl, } res = send_template_email(from_email,[fullemail],subject, 'teamdropemail.html',d,**kwargs) return 1 @app.task def handle_sendemail_team_removed(email, name, teamname, managername, debug=False,**kwargs): fullemail = name + ' <' + email + '>' subject = 'You were removed from ' + teamname from_email = 'Rowsandall ' siteurl = SITE_URL if debug: siteurl = SITE_URL_DEV d = { 'first_name':name, 'managername':managername, 'teamname':teamname, 'siteurl':siteurl, } res = send_template_email(from_email,[fullemail],subject, 'teamremoveemail.html',d,**kwargs) return 1 @app.task def handle_sendemail_invite_reject(email, name, teamname, managername, debug=False,**kwargs): fullemail = managername + ' <' + email + '>' subject = 'Your invitation to ' + name + ' was rejected' from_email = 'Rowsandall ' siteurl = SITE_URL if debug: siteurl = SITE_URL_DEV d = { 'first_name':name, 'managername':managername, 'teamname':teamname, 'siteurl':siteurl, } res = send_template_email(from_email,[fullemail],subject, 'teaminviterejectemail.html',d,**kwargs) return 1 @app.task def handle_sendemail_invite_accept(email, name, teamname, managername, debug=False,**kwargs): fullemail = managername + ' <' + email + '>' subject = 'Your invitation to ' + name + ' was accepted' from_email = 'Rowsandall ' siteurl = SITE_URL if debug: siteurl = SITE_URL_DEV d = { 'first_name':name, 'managername':managername, 'teamname':teamname, 'siteurl':siteurl, } res = send_template_email(from_email,[fullemail],subject, 'teaminviteacceptemail.html',d,**kwargs) return 1 # Another simple task for debugging purposes def add2(x, y,debug=False,**kwargs): return x + y