diff --git a/rowers/dataprep.py b/rowers/dataprep.py index 223ad583..91ca3d6a 100644 --- a/rowers/dataprep.py +++ b/rowers/dataprep.py @@ -433,6 +433,7 @@ def save_workout_database(f2,r,dosmooth=True,workouttype='rower', summary='', makeprivate=False, oarlength=2.89,inboard=0.88, + forceunit='lbs', consistencychecks=False): message = None powerperc = 100*np.array([r.pw_ut2, @@ -447,7 +448,6 @@ def save_workout_database(f2,r,dosmooth=True,workouttype='rower', powerperc=powerperc,powerzones=r.powerzones) row = rdata(f2,rower=rr) - dtavg = row.df['TimeStamp (sec)'].diff().mean() if dtavg < 1: @@ -640,6 +640,7 @@ def save_workout_database(f2,r,dosmooth=True,workouttype='rower', weightcategory=r.weightcategory, starttime=workoutstarttime, workoutsource=workoutsource, + forceunit=forceunit, csvfilename=f2,notes=notes,summary=summary, maxhr=maxhr,averagehr=averagehr, startdatetime=workoutstartdatetime, @@ -925,7 +926,8 @@ def split_workout(r,parent,splitsecond,splitmode): id,message = new_workout_from_df(r,data1, title=parent.name+' (1)', parent=parent, - setprivate=setprivate) + setprivate=setprivate, + forceunit='N') messages.append(message) ids.append(id) if 'keep second' in splitmode: @@ -938,12 +940,12 @@ def split_workout(r,parent,splitsecond,splitmode): setprivate = False dt = datetime.timedelta(seconds=splitsecond) - + id,message = new_workout_from_df(r,data2, title=parent.name+' (2)', parent=parent, setprivate=setprivate, - dt=dt) + dt=dt,forceunit='N') messages.append(message) ids.append(id) @@ -968,6 +970,7 @@ def new_workout_from_df(r,df, title='New Workout', parent=None, setprivate=False, + forceunit='lbs', dt=datetime.timedelta()): message = None @@ -1001,7 +1004,10 @@ def new_workout_from_df(r,df, timestr = strftime("%Y%m%d-%H%M%S") csvfilename ='media/df_'+timestr+'.csv' - + if forceunit == 'N': + # change to lbs for now + df['peakforce'] /= lbstoN + df['averageforce'] /= lbstoN df.rename(columns = columndict,inplace=True) @@ -1166,23 +1172,17 @@ def getrowdata_db(id=0,doclean=False,convertnewtons=True): if doclean: data = clean_df_stats(data,ignorehr=True) - # these two lines seem redundant ?? - #data['averageforce'] = data['averageforce'] - #data['peakforce'] = data['peakforce'] return data,row # Fetch a subset of the data from the DB -def getsmallrowdata_db(columns,ids=[],doclean=True,workstrokesonly=True, - convertnewtons=False): +def getsmallrowdata_db(columns,ids=[],doclean=True,workstrokesonly=True): prepmultipledata(ids) data = read_cols_df_sql(ids,columns) - if convertnewtons: - if 'peakforce' in columns: - data['peakforce'] = data['peakforce']*lbstoN - if 'averageforce' in columns: - data['averageforce'] = data['averageforce']*lbstoN + # convert newtons + + if doclean: data = clean_df_stats(data,ignorehr=True, @@ -1193,7 +1193,7 @@ def getsmallrowdata_db(columns,ids=[],doclean=True,workstrokesonly=True, return data # Fetch both the workout and the workout stroke data (from CSV file) -def getrowdata(id=0,convertnewtons=True): +def getrowdata(id=0): # check if valid ID exists (workout exists) row = Workout.objects.get(id=id) @@ -1254,7 +1254,7 @@ def read_cols_df_sql(ids,columns,convertnewtons=True): if not c in axx: columns.remove(c) - columns = list(columns)+['distance','spm'] + columns = list(columns)+['distance','spm','workoutid'] columns = [x for x in columns if x != 'None'] columns = list(set(columns)) cls = '' @@ -1284,22 +1284,24 @@ def read_cols_df_sql(ids,columns,convertnewtons=True): df = df.fillna(value=0) - if convertnewtons: - try: - df['peakforce'] = df['peakforce']*lbstoN - except KeyError: - pass - - try: - df['averageforce'] = df['averageforce']*lbstoN - except KeyError: - pass + if 'peakforce' in columns: + funits = ((w.id,w.forceunit) for w in Workout.objects.filter(id__in=ids)) + for id,u in funits: + if u=='lbs': + mask = df['workoutid']==id + df.loc[mask,'peakforce'] = df.loc[mask,'peakforce']*lbstoN + if 'averageforce' in columns: + funits = ((w.id,w.forceunit) for w in Workout.objects.filter(id__in=ids)) + for id,u in funits: + if u=='lbs': + mask = df['workoutid']==id + df.loc[mask,'averageforce'] = df.loc[mask,'averageforce']*lbstoN engine.dispose() return df # Read stroke data from the DB for a Workout ID. Returns a pandas dataframe -def read_df_sql(id,convertnewtons=True): +def read_df_sql(id): engine = create_engine(database_url, echo=False) df = pd.read_sql_query(sa.text('SELECT * FROM strokedata WHERE workoutid={id}'.format( @@ -1307,7 +1309,10 @@ def read_df_sql(id,convertnewtons=True): engine.dispose() df = df.fillna(value=0) - if convertnewtons: + + funit = Workout.objects.get(id=id).forceunit + + if funit=='lbs': try: df['peakforce'] = df['peakforce']*lbstoN except KeyError: @@ -1322,7 +1327,7 @@ def read_df_sql(id,convertnewtons=True): # Get the necessary data from the strokedata table in the DB. # For the flex plot -def smalldataprep(therows,xparam,yparam1,yparam2,convertnewtons=True): +def smalldataprep(therows,xparam,yparam1,yparam2): df = pd.DataFrame() if yparam2 == 'None': yparam2 = 'power' @@ -1344,6 +1349,17 @@ def smalldataprep(therows,xparam,yparam1,yparam2,convertnewtons=True): 'spm': rowdata['spm'], } ) + if workout.forceunit == 'lbs': + try: + rowdata['peakforce'] *= lbstoN + except KeyError: + pass + + try: + rowdata['averageforce'] *= lbstoN + except KeyError: + pass + df = pd.concat([df,rowdata],ignore_index=True) except IOError: try: @@ -1355,25 +1371,28 @@ def smalldataprep(therows,xparam,yparam1,yparam2,convertnewtons=True): 'spm': rowdata['spm'], } ) + if workout.forceunit == 'lbs': + try: + rowdata['peakforce'] *= lbstoN + except KeyError: + pass + + try: + rowdata['averageforce'] *= lbstoN + except KeyError: + pass df = pd.concat([df,rowdata],ignore_index=True) except IOError: pass - if convertnewtons: - try: - df['peakforce'] = df['peakforce']*lbstoN - except KeyError: - pass - - try: - df['averageforce'] = df['averageforce']*lbstoN - except KeyError: - pass return df # data fusion def datafusion(id1,id2,columns,offset): + workout1 = Workout.objects.get(id=id1) + workout2 = Workout.objects.get(id=id2) + df1,w1 = getrowdata_db(id=id1) df1 = df1.drop([#'cumdist', 'hr_ut2', @@ -1387,7 +1406,7 @@ def datafusion(id1,id2,columns,offset): 'workoutid', 'id'], 1,errors='ignore') - + # Add coordinates to DataFrame latitude,longitude = get_latlon(id1) @@ -1396,6 +1415,9 @@ def datafusion(id1,id2,columns,offset): df2 = getsmallrowdata_db(['time']+columns,ids=[id2],doclean=False) + + forceunit = 'N' + offsetmillisecs = offset.seconds*1000+offset.microseconds/1000. offsetmillisecs += offset.days*(3600*24*1000) df2['time'] = df2['time']+offsetmillisecs @@ -1426,7 +1448,7 @@ def datafusion(id1,id2,columns,offset): df['pace'] = df['pace']/1000. df['cum_dist'] = df['cumdist'] - return df + return df,forceunit def fix_newtons(id=0,limit=3000): # rowdata,row = getrowdata_db(id=id,doclean=False,convertnewtons=False) diff --git a/rowers/mailprocessing.py b/rowers/mailprocessing.py index bb346b73..f40cebe5 100644 --- a/rowers/mailprocessing.py +++ b/rowers/mailprocessing.py @@ -88,7 +88,8 @@ def processattachments(): wid = [make_new_workout_from_email(rr,a.document,name)] res += wid link = 'https://rowsandall.com/rowers/workout/'+str(wid[0])+'/edit' - dd = send_confirm(u,name,link) + if wid != 1: + dd = send_confirm(u,name,link) except: # replace with code to process error res += ['fail: '+name] @@ -138,9 +139,9 @@ def processattachments_debug(): print name wid = [make_new_workout_from_email(rr,a.document,name)] res += wid - print wid link = 'https://rowsandall.com/rowers/workout/'+str(wid[0])+'/edit' - dd = send_confirm(u,name,link) + if wid != 1: + dd = send_confirm(u,name,link) diff --git a/rowers/management/commands/processemail.py b/rowers/management/commands/processemail.py index e0052064..6c0d9c00 100644 --- a/rowers/management/commands/processemail.py +++ b/rowers/management/commands/processemail.py @@ -70,12 +70,14 @@ class Command(BaseCommand): res += wid link = 'http://rowsandall.com/rowers/workout/'+str(wid[0])+'/edit' try: - dd = send_confirm(rr.user,title,link) + if wid != 1: + dd = send_confirm(rr.user,title,link) time.sleep(10) except: try: time.sleep(10) - dd = send_confirm(rr.user,title,link) + if wid != 1: + dd = send_confirm(rr.user,title,link) except: pass @@ -94,8 +96,10 @@ class Command(BaseCommand): # replace with code to process error res += ['fail: '+name] donotdelete = 1 + wid = 1 try: - dd = send_confirm(rr.user,name,link) + if wid != 1: + dd = send_confirm(rr.user,name,link) time.sleep(10) except: pass diff --git a/rowers/models.py b/rowers/models.py index 047d315c..b7b8d8fd 100644 --- a/rowers/models.py +++ b/rowers/models.py @@ -429,6 +429,12 @@ class Workout(models.Model): uploadedtounderarmour = models.IntegerField(default=0) uploadedtotp = models.IntegerField(default=0) uploadedtorunkeeper = models.IntegerField(default=0) + forceunit = models.CharField(default='lbs', + choices = ( + ('lbs','lbs'), + ('N','N') + ), + max_length=100) # empower stuff inboard = models.FloatField(default=0.88) diff --git a/rowers/views.py b/rowers/views.py index 20d7b897..a640c5fa 100644 --- a/rowers/views.py +++ b/rowers/views.py @@ -5881,9 +5881,9 @@ def workout_flexchart3_view(request,*args,**kwargs): # create interactive plot try: script,div,js_resources,css_resources,workstrokesonly = interactive_flex_chart2(id,xparam=xparam,yparam1=yparam1, - yparam2=yparam2, - promember=promember,plottype=plottype, - workstrokesonly=workstrokesonly) + yparam2=yparam2, + promember=promember,plottype=plottype, + workstrokesonly=workstrokesonly) except ValueError: script,div = interactive_flex_chart2(id,xparam=xparam,yparam1=yparam1, yparam2=yparam2, @@ -8393,11 +8393,13 @@ def workout_fusion_view(request,id1=0,id2=1): timeoffset = -timeoffset # Create DataFrame - df = dataprep.datafusion(id1,id2,columns,timeoffset) + df,forceunit = dataprep.datafusion(id1,id2,columns,timeoffset) + idnew,message = dataprep.new_workout_from_df(r,df, title='Fused data', - parent=w1) + parent=w1, + forceunit=forceunit) if message != None: messages.error(request,message) else: diff --git a/rowsandall_app/settings.py b/rowsandall_app/settings.py index 98d21718..6a7a614a 100644 --- a/rowsandall_app/settings.py +++ b/rowsandall_app/settings.py @@ -176,7 +176,7 @@ AUTH_PASSWORD_VALIDATORS = [ # Internationalization # https://docs.djangoproject.com/en/1.9/topics/i18n/ -#TIME_ZONE = 'UTC' +TIME_ZONE = 'UTC' USE_I18N = True