diff --git a/rowers/dataprep.py b/rowers/dataprep.py index c3ba06d2..cb3d281b 100644 --- a/rowers/dataprep.py +++ b/rowers/dataprep.py @@ -174,7 +174,7 @@ def get_video_data(w,groups=['basic'],mode='water'): try: coordinates = get_latlon_time(w.id) - except KeyError: + except KeyError: # pragma: no cover nulseries = df['time']*0 coordinates = pd.DataFrame({ 'time': df['time'], @@ -203,7 +203,7 @@ def get_video_data(w,groups=['basic'],mode='water'): for c in columns: if c != 'time': try: - if dict(rowingmetrics)[c]['numtype'] == 'integer': + if dict(rowingmetrics)[c]['numtype'] == 'integer': # pragma: no cover data[c] = df2[c].astype(int).tolist() else: sigfigs = dict(rowingmetrics)[c]['sigfigs'] @@ -217,7 +217,7 @@ def get_video_data(w,groups=['basic'],mode='water'): 'metric': c, 'unit': '' } - except KeyError: + except KeyError: # pragma: no cover pass metrics['boatspeed'] = metrics.pop('velo') @@ -258,13 +258,13 @@ def polarization_index(df,rower): def get_latlon(id): try: w = Workout.objects.get(id=id) - except Workout.DoesNotExist: + except Workout.DoesNotExist: # pragma: no cover return False rowdata = rdata(w.csvfilename) - if rowdata.df.empty: + if rowdata.df.empty: # pragma: no cover return [pd.Series([]), pd.Series([])] try: @@ -275,31 +275,31 @@ def get_latlon(id): latitude = 0 * rowdata.df.loc[:, 'TimeStamp (sec)'] longitude = 0 * rowdata.df.loc[:, 'TimeStamp (sec)'] return [latitude, longitude] - except AttributeError: + except AttributeError: # pragma: no cover return [pd.Series([]), pd.Series([])] - return [pd.Series([]), pd.Series([])] + return [pd.Series([]), pd.Series([])] # pragma: no cover def get_latlon_time(id): try: w = Workout.objects.get(id=id) - except Workout.DoesNotExist: + except Workout.DoesNotExist: # pragma: no cover return False rowdata = rdata(w.csvfilename) - if rowdata.df.empty: + if rowdata.df.empty: # pragma: no cover return [pd.Series([]), pd.Series([])] try: try: latitude = rowdata.df.loc[:, ' latitude'] longitude = rowdata.df.loc[:, ' longitude'] - except KeyError: + except KeyError: # pragma: no cover latitude = 0 * rowdata.df.loc[:, 'TimeStamp (sec)'] longitude = 0 * rowdata.df.loc[:, 'TimeStamp (sec)'] - except AttributeError: + except AttributeError: # pragma: no cover return pd.DataFrame() df = pd.DataFrame({ @@ -347,7 +347,7 @@ def workout_summary_to_df( for w in ws: counter1 += 1 - if counter1 % 10 == 0: + if counter1 % 10 == 0: # pragma: no cover print(counter1,'/',counter2) types.append(w.workouttype) names.append(w.name) @@ -408,7 +408,7 @@ def workout_summary_to_df( return df -def get_workouts(ids, userid): +def get_workouts(ids, userid): # pragma: no cover goodids = [] for id in ids: w = Workout.objects.get(id=id) @@ -446,7 +446,7 @@ def join_workouts(r,ids,title='Joined Workout', message = None summary = '' - if parent: + if parent: # pragma: no cover oarlength = parent.oarlength inboard = parent.inboard workouttype = parent.workouttype @@ -467,9 +467,9 @@ def join_workouts(r,ids,title='Joined Workout', makeprivate = False startdatetime = timezone.now() - if setprivate == True and makeprivate == False: + if setprivate == True and makeprivate == False: # pragma: no cover makeprivate = True - elif setprivate == False and makeprivate == True: + elif setprivate == False and makeprivate == True: # pragma: no cover makeprivate = False @@ -510,7 +510,7 @@ def join_workouts(r,ids,title='Joined Workout', dosmooth=False, consistencychecks=False) - if killparents: + if killparents: # pragma: no cover for w in ws: w.delete() @@ -640,7 +640,7 @@ def clean_df_stats(datadf, workstrokesonly=True, ignorehr=True, try: mask = datadf['hr'] < 30 datadf.mask(mask,inplace=True) - except (KeyError,TypeError): + except (KeyError,TypeError): # pragma: no cover pass try: @@ -807,9 +807,9 @@ def getpartofday(row,r): tf = TimezoneFinder() try: timezone_str = tf.timezone_at(lng=lonavg, lat=latavg) - except (ValueError,OverflowError): + except (ValueError,OverflowError): # pragma: no cover timezone_str = 'UTC' - if timezone_str == None: + if timezone_str == None: # pragma: no cover timezone_str = tf.closest_timezone_at(lng=lonavg, lat=latavg) if timezone_str == None: @@ -826,16 +826,16 @@ def getpartofday(row,r): h = workoutstartdatetime.astimezone(pytz.timezone(timezone_str)).hour - if h < 12: + if h < 12: # pragma: no cover return "Morning" - elif h < 18: + elif h < 18: # pragma: no cover return "Afternoon" - elif h < 22: + elif h < 22: # pragma: no cover return "Evening" - else: + else: # pragma: no cover return "Night" - return None + return None # pragma: no cover def getstatsfields(): fielddict = {name:d['verbose_name'] for name,d in rowingmetrics} @@ -887,7 +887,7 @@ def strfdelta(tdelta): try: minutes, seconds = divmod(tdelta.seconds, 60) tenths = int(tdelta.microseconds / 1e5) - except AttributeError: + except AttributeError: # pragma: no cover minutes, seconds = divmod(tdelta.view(np.int64), 60e9) seconds, rest = divmod(seconds, 1e9) tenths = int(rest / 1e8) @@ -899,7 +899,7 @@ def strfdelta(tdelta): return res -def timedelta_to_seconds(tdelta): +def timedelta_to_seconds(tdelta): # pragma: no cover return 60.*tdelta.minute+tdelta.second @@ -962,7 +962,7 @@ def getcpdata_sql(rower_id,table='cpdata'): return df -def deletecpdata_sql(rower_id,table='cpdata'): +def deletecpdata_sql(rower_id,table='cpdata'): # pragma: no cover engine = create_engine(database_url, echo=False) query = sa.text('DELETE from {table} WHERE user={rower_id};'.format( rower_id=rower_id, @@ -978,7 +978,7 @@ def deletecpdata_sql(rower_id,table='cpdata'): -def updatecpdata_sql(rower_id,delta,cp,table='cpdata',distance=[]): +def updatecpdata_sql(rower_id,delta,cp,table='cpdata',distance=[]): # pragma: no cover deletecpdata_sql(rower_id) df = pd.DataFrame( { @@ -1014,7 +1014,7 @@ from rowers.datautils import p0 from rowers.utils import calculate_age from scipy import optimize -def get_workoutsummaries(userid,startdate): +def get_workoutsummaries(userid,startdate): # pragma: no cover u = User.objects.get(id=userid) r = u.rower df = workout_summary_to_df(r,startdate=startdate) @@ -1063,7 +1063,7 @@ def check_marker(workout): 'gms':gms, }) - if df.empty: + if df.empty: # pragma: no cover workout.ranking = True workout.save() return workout @@ -1083,11 +1083,11 @@ def check_marker(workout): return wmax lastranking = rankingworkouts[len(rankingworkouts)-1] - if lastranking.goldmedalstandard+0.2 < wmax.goldmedalstandard: + if lastranking.goldmedalstandard+0.2 < wmax.goldmedalstandard: # pragma: no cover wmax.rankingpiece = True wmax.save() return wmax - else: + else: # pragma: no cover return wmax return None @@ -1103,7 +1103,7 @@ def calculate_goldmedalstandard(rower,workout,recurrance=True): if df.empty: return 0,0 - if df.empty and recurrance: + if df.empty and recurrance: # pragma: no cover df, delta, cpvalues = setcp(workout,recurrance=False,background=True) if df.empty: return 0,0 @@ -1118,15 +1118,19 @@ def calculate_goldmedalstandard(rower,workout,recurrance=True): wcdurations = [] wcpower = [] - getrecords = len(agerecords) == 0 - for record in agerecords: + getrecords = False + if not settings.TESTING: # pragma: no cover + if len(agerecords) == 0: # pragma: no cover + getrecords = True + + for record in agerecords: # pragma: no cover if record.power > 0: wcdurations.append(record.duration) wcpower.append(record.power) else: getrecords = True - if getrecords: + if getrecords: # pragma: no cover durations = [1,4,30,60] distances = [100,500,1000,2000,5000,6000,10000,21097,42195] df2 = pd.DataFrame( @@ -1147,7 +1151,7 @@ def calculate_goldmedalstandard(rower,workout,recurrance=True): 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 - if len(wcdurations)>=4: + if len(wcdurations)>=4: # pragma: no cover p1wc, success = optimize.leastsq(errfunc, p0[:],args=(wcdurations,wcpower)) else: factor = fitfunc(p0,wcdurations.mean()/wcpower.mean()) @@ -1166,7 +1170,7 @@ def calculate_goldmedalstandard(rower,workout,recurrance=True): indexmax = scores.idxmax() delta = int(df.loc[indexmax,'delta']) maxvalue = scores.max() - except (ValueError,TypeError): + except (ValueError,TypeError): # pragma: no cover indexmax = 0 delta = 0 maxvalue = 0 @@ -1198,7 +1202,7 @@ def fetchcp_new(rower,workouts): try: df = df[df['cp'] == df.groupby(['delta'])['cp'].transform('max')] - except KeyError: + except KeyError: # pragma: no cover pd.Series(),pd.Series(),0,pd.Series(),pd.Series() @@ -1225,7 +1229,7 @@ def setcp(workout,background=False,recurrance=True): totaltime = strokesdf['time'].max() try: powermean = strokesdf['power'].mean() - except KeyError: + except KeyError: # pragma: no cover powermean = 0 if powermean != 0: @@ -1294,7 +1298,7 @@ def update_rolling_cp(r,types,mode='water'): return True return False -def fetchcp(rower,theworkouts,table='cpdata'): +def fetchcp(rower,theworkouts,table='cpdata'): # pragma: no cover # get all power data from database (plus workoutid) theids = [int(w.id) for w in theworkouts] columns = ['power','workoutid','time'] @@ -1349,24 +1353,24 @@ def create_row_df(r,distance,duration,startdatetime,workouttype='rower', totalseconds += duration.minute*60. totalseconds += duration.second totalseconds += duration.microsecond/1.e6 - else: + else: # pragma: no cover totalseconds = 60. - if distance is None: + if distance is None: # pragma: no cover distance = 0 try: nr_strokes = int(distance/10.) - except TypeError: + except TypeError: # pragma: no cover nr_strokes = int(20.*totalseconds) - if nr_strokes == 0: + if nr_strokes == 0: # pragma: no cover nr_strokes = 100 unixstarttime = arrow.get(startdatetime).timestamp() - if not avgspm: + if not avgspm: # pragma: no cover try: spm = 60.*nr_strokes/totalseconds except ZeroDivisionError: @@ -1386,23 +1390,23 @@ def create_row_df(r,distance,duration,startdatetime,workouttype='rower', try: pace = 500.*totalseconds/distance - except ZeroDivisionError: + except ZeroDivisionError: # pragma: no cover pace = 240. if workouttype in ['rower','slides','dynamic']: try: velo = distance/totalseconds - except ZeroDivisionError: + except ZeroDivisionError: # pragma: no cover velo = 2.4 power = 2.8*velo**3 - elif avgpwr is not None: + elif avgpwr is not None: # pragma: no cover power = avgpwr - else: + else: # pragma: no cover power = 0 if avghr is not None: hr = avghr - else: + else: # pragma: no cover hr = 0 df = pd.DataFrame({ @@ -1456,12 +1460,12 @@ def checkbreakthrough(w, r): res, btvalues, res2 = utils.isbreakthrough( delta, cpvalues, r.ep0, r.ep1, r.ep2, r.ep3, r.ecpratio) success = update_rolling_cp(r,otetypes,'erg') - else: + else: # pragma: no cover res = 0 res2 = 0 if res: isbreakthrough = True - if res2 and not isbreakthrough: + if res2 and not isbreakthrough: # pragma: no cover ishard = True # submit email task to send email about breakthrough workout @@ -1469,7 +1473,7 @@ def checkbreakthrough(w, r): if not w.duplicate: w.rankingpiece = True w.save() - if r.getemailnotifications and not r.emailbounced: + if r.getemailnotifications and not r.emailbounced: # pragma: no cover job = myqueue(queuehigh,handle_sendemail_breakthrough, w.id, r.user.email, @@ -1478,7 +1482,7 @@ def checkbreakthrough(w, r): btvalues=btvalues.to_json()) # submit email task to send email about breakthrough workout - if ishard: + if ishard: # pragma: no cover if not w.duplicate: w.rankingpiece = True w.save() @@ -1549,7 +1553,7 @@ def save_workout_database(f2, r, dosmooth=True, workouttype='rower', hrtr=r.tr, hran=r.an, ftp=r.ftp, powerperc=powerperc, powerzones=r.powerzones) row = rdata(f2, rower=rr) - if startdatetime != '': + if startdatetime != '': # pragma: no cover row.rowdatetime = arrow.get(startdatetime).datetime @@ -1564,7 +1568,7 @@ def save_workout_database(f2, r, dosmooth=True, workouttype='rower', workouttype=workouttype, ) - if row.df.empty: + if row.df.empty: # pragma: no cover return (0, 'Error: CSV data file was empty') dtavg = row.df['TimeStamp (sec)'].diff().mean() @@ -1585,14 +1589,14 @@ def save_workout_database(f2, r, dosmooth=True, workouttype='rower', for key, value in checks.items(): if not value: allchecks = 0 - except ZeroDivisionError: + except ZeroDivisionError: # pragma: no cover pass if not allchecks and consistencychecks: # row.repair() pass - if row == 0: + if row == 0: # pragma: no cover return (0, 'Error: CSV data file not found') try: @@ -1610,14 +1614,14 @@ def save_workout_database(f2, r, dosmooth=True, workouttype='rower', f = row.df['TimeStamp (sec)'].diff().mean() if f != 0 and not np.isnan(f): windowsize = 2 * (int(10. / (f))) + 1 - else: + else: # pragma: no cover windowsize = 1 if not 'originalvelo' in row.df: row.df['originalvelo'] = velo if windowsize > 3 and windowsize < len(velo): velo2 = savgol_filter(velo, windowsize, 3) - else: + else: # pragma: no cover velo2 = velo velo3 = pd.Series(velo2) @@ -1655,10 +1659,10 @@ def save_workout_database(f2, r, dosmooth=True, workouttype='rower', ) - row.df['TimeStamp (sec)'].min() try: totaltime = totaltime + row.df.loc[:, ' ElapsedTime (sec)'].iloc[0] - except KeyError: + except KeyError: # pragma: no cover pass - if np.isnan(totaltime): + if np.isnan(totaltime): # pragma: no cover totaltime = 0 @@ -1666,7 +1670,7 @@ def save_workout_database(f2, r, dosmooth=True, workouttype='rower', summary = row.allstats() - if startdatetime != '': + if startdatetime != '': # pragma: no cover workoutstartdatetime = arrow.get(startdatetime).datetime else: workoutstartdatetime = row.rowdatetime @@ -1688,12 +1692,12 @@ def save_workout_database(f2, r, dosmooth=True, workouttype='rower', tf = TimezoneFinder() try: timezone_str = tf.timezone_at(lng=lonavg, lat=latavg) - except (ValueError,OverflowError): + except (ValueError,OverflowError): # pragma: no cover timezone_str = 'UTC' - if timezone_str == None: + if timezone_str == None: # pragma: no cover timezone_str = tf.closest_timezone_at(lng=lonavg, lat=latavg) - if timezone_str == None: + if timezone_str == None: # pragma: no cover timezone_str = r.defaulttimezone try: workoutstartdatetime = pytz.timezone(timezone_str).localize( @@ -1716,7 +1720,7 @@ def save_workout_database(f2, r, dosmooth=True, workouttype='rower', ).strftime('%H:%M:%S') - if makeprivate: + if makeprivate: # pragma: no cover privacy = 'hidden' else: privacy = 'visible' @@ -1742,7 +1746,7 @@ def save_workout_database(f2, r, dosmooth=True, workouttype='rower', rankingpiece = False # test title length - if title is not None and len(title)>140: + if title is not None and len(title)>140: # pragma: no cover title = title[0:140] w = Workout(user=r, name=title, date=workoutdate, @@ -1767,7 +1771,7 @@ def save_workout_database(f2, r, dosmooth=True, workouttype='rower', impeller=impeller) try: w.save() - except ValidationError: + except ValidationError: # pragma: no cover try: w.startdatetime = timezone.now() w.save() @@ -1817,17 +1821,17 @@ parsers = { def parsenonpainsled(fileformat,f2,summary,startdatetime='',empowerfirmware=None,inboard=None,oarlength=None): try: - if fileformat == 'nklinklogbook' and empowerfirmware is not None: + if fileformat == 'nklinklogbook' and empowerfirmware is not None: # pragma: no cover if inboard is not None and oarlength is not None: row = NKLiNKLogbookParser(f2,firmware=empowerfirmware,inboard=inboard,oarlength=oarlength) else: row = NKLiNKLogbookParser(f2) else: row = parsers[fileformat](f2) - if startdatetime != '': + if startdatetime != '': # pragma: no cover row.rowdatetime = arrow.get(startdatetime).datetime hasrecognized = True - except (KeyError,IndexError,ValueError): + except (KeyError,IndexError,ValueError): # pragma: no cover hasrecognized = False return None, hasrecognized, '', 'unknown' @@ -1837,17 +1841,17 @@ def parsenonpainsled(fileformat,f2,summary,startdatetime='',empowerfirmware=None empowerfirmware = get_empower_firmware(f2) if empowerfirmware != '': fileformat = fileformat+'v'+str(empowerfirmware) - else: + else: # pragma: no cover fileformat = 'speedcoach2v0' try: summary = row.allstats() - except ZeroDivisionError: + except ZeroDivisionError: # pragma: no cover summary = '' else: fileformat = fileformat+'v'+str(empowerfirmware) # handle FIT - if (fileformat == 'fit'): + if (fileformat == 'fit'): # pragma: no cover try: s = fitsummarydata(f2) s.setsummary() @@ -1869,10 +1873,10 @@ def handle_nonpainsled(f2, fileformat, summary='',startdatetime='',empowerfirmwa empowerfirmware=empowerfirmware) # Handle c2log - if (fileformat == 'c2log' or fileformat == 'rowprolog'): + if (fileformat == 'c2log' or fileformat == 'rowprolog'): # pragma: no cover return (0,'',0,0,'',impeller) - if not hasrecognized: + if not hasrecognized: # pragma: no cover return (0,'',0,0,'',impeller) f_to_be_deleted = f2 @@ -1896,7 +1900,7 @@ def handle_nonpainsled(f2, fileformat, summary='',startdatetime='',empowerfirmwa # os.remove(f2) try: os.remove(f_to_be_deleted) - except: + except: # pragma: no cover try: os.remove(f_to_be_deleted + '.gz') except: @@ -1911,7 +1915,7 @@ def handle_nonpainsled(f2, fileformat, summary='',startdatetime='',empowerfirmwa def get_workouttype_from_fit(filename,workouttype='water'): try: fitfile = FitFile(filename,check_crc=False) - except FitHeaderError: + except FitHeaderError: # pragma: no cover return workouttype records = fitfile.messages @@ -1920,11 +1924,11 @@ def get_workouttype_from_fit(filename,workouttype='water'): if record.name in ['sport','lap']: try: fittype = record.get_values()['sport'].lower() - except (KeyError,AttributeError): + except (KeyError,AttributeError): # pragma: no cover return 'water' try: workouttype = mytypes.fitmappinginv[fittype] - except KeyError: + except KeyError: # pragma: no cover return workouttype return workouttype @@ -1935,7 +1939,7 @@ def get_workouttype_from_tcx(filename,workouttype='water'): tcxtype = 'rowing' if workouttype in mytypes.otwtypes: return workouttype - try: + try: # pragma: no cover d = tcxtools.tcx_getdict(filename) try: tcxtype = d['Activities']['Activity']['@Sport'].lower() @@ -1944,15 +1948,15 @@ def get_workouttype_from_tcx(filename,workouttype='water'): except KeyError: return workouttype - except TypeError: + except TypeError: # pragma: no cover pass - try: + try: # pragma: no cover workouttype = mytypes.garminmappinginv[tcxtype.upper()] - except KeyError: + except KeyError: # pragma: no cover return workouttype - return workouttype + return workouttype # pragma: no cover def new_workout_from_file(r, f2, workouttype='rower', @@ -1972,7 +1976,7 @@ def new_workout_from_file(r, f2, try: fileformat = get_file_type(f2) - except (IOError,UnicodeDecodeError): + except (IOError,UnicodeDecodeError): # pragma: no cover os.remove(f2) message = "Rowsandall could not process this file. The extension is supported but the file seems corrupt. Contact info@rowsandall.com if you think this is incorrect." return (0, message, f2) @@ -1982,7 +1986,7 @@ def new_workout_from_file(r, f2, inboard = 0.88 # Save zip files to email box for further processing - if len(fileformat) == 3 and fileformat[0] == 'zip': + if len(fileformat) == 3 and fileformat[0] == 'zip': # pragma: no cover uploadoptions['fromuploadform'] = True bodyyaml = yaml.safe_dump(uploadoptions,default_flow_style=False) f_to_be_deleted = f2 @@ -2007,24 +2011,24 @@ def new_workout_from_file(r, f2, message = "This summary does not contain stroke data. Use the files containing stroke by stroke data." return (0, message, f2) - if fileformat == 'nostrokes': + if fileformat == 'nostrokes': # pragma: no cover os.remove(f2) message = "It looks like this file doesn't contain stroke data." return (0, message, f2) - if fileformat == 'kml': + if fileformat == 'kml': # pragma: no cover os.remove(f2) message = "KML files are not supported" return (0, message, f2) # Some people upload corrupted zip files - if fileformat == 'notgzip': + if fileformat == 'notgzip': # pragma: no cover os.remove(f2) message = "Rowsandall could not process this file. The extension is supported but the file seems corrupt. Contact info@rowsandall.com if you think this is incorrect." return (0, message, f2) # Some people try to upload RowPro summary logs - if fileformat == 'rowprolog': + if fileformat == 'rowprolog': # pragma: no cover os.remove(f2) message = "This RowPro logbook summary does not contain stroke data. Please use the Stroke Data CSV file for the individual workout in your log." return (0, message, f2) @@ -2033,13 +2037,13 @@ def new_workout_from_file(r, f2, # Send an email to info@rowsandall.com with the file attached # for me to check if it is a bug, or a new file type # worth supporting - if fileformat == 'gpx': + if fileformat == 'gpx': # pragma: no cover os.remove(f2) message = "GPX files support is on our roadmap. Check back soon." return (0, message, f2) - if fileformat == 'unknown': + if fileformat == 'unknown': # pragma: no cover message = "We couldn't recognize the file type" extension = os.path.splitext(f2)[1] filename = os.path.splitext(f2)[0] @@ -2056,12 +2060,12 @@ def new_workout_from_file(r, f2, return (0, message, f2) - if fileformat == 'att': + if fileformat == 'att': # pragma: no cover # email attachment which can safely be ignored return (0, '', f2) # Get workout type from fit & tcx - if (fileformat == 'fit'): + if (fileformat == 'fit'): # pragma: no cover workouttype = get_workouttype_from_fit(f2,workouttype=workouttype) if (fileformat == 'tcx'): workouttype = get_workouttype_from_tcx(f2,workouttype=workouttype) @@ -2076,7 +2080,7 @@ def new_workout_from_file(r, f2, empowerfirmware=oarlockfirmware, impeller=impeller, ) - if not f2: + if not f2: # pragma: no cover message = 'Something went wrong' return (0, message, '') @@ -2155,7 +2159,7 @@ def split_workout(r, parent, splitsecond, splitmode): ids = [] if 'keep first' in splitmode: - if 'firstprivate' in splitmode: + if 'firstprivate' in splitmode: # pragma: no cover setprivate = True else: setprivate = False @@ -2180,7 +2184,7 @@ def split_workout(r, parent, splitsecond, splitmode): 0, data2.columns.get_loc('time') ] - if 'secondprivate' in splitmode: + if 'secondprivate' in splitmode: # pragma: no cover setprivate = True else: setprivate = False @@ -2195,14 +2199,14 @@ def split_workout(r, parent, splitsecond, splitmode): messages.append(message) ids.append(encoder.encode_hex(id)) - if not 'keep original' in splitmode: + if not 'keep original' in splitmode: # pragma: no cover if 'keep second' in splitmode or 'keep first' in splitmode: parent.delete() messages.append('Deleted Workout: ' + parent.name) else: messages.append('That would delete your workout') ids.append(encoder.encode_hex(parent.id)) - elif 'originalprivate' in splitmode: + elif 'originalprivate' in splitmode: # pragma: no cover parent.privacy = 'hidden' parent.save() @@ -2237,7 +2241,7 @@ def new_workout_from_df(r, df, notes = parent.notes summary = parent.summary rpe = parent.rpe - if parent.privacy == 'hidden': + if parent.privacy == 'hidden': # pragma: no cover makeprivate = True else: makeprivate = False @@ -2253,7 +2257,7 @@ def new_workout_from_df(r, df, if startdatetime == '': startdatetime = timezone.now() - if setprivate: + if setprivate: # pragma: no cover makeprivate = True timestr = strftime("%Y%m%d-%H%M%S") @@ -2304,16 +2308,16 @@ def new_workout_from_df(r, df, def rdata(file, rower=rrower()): try: res = rrdata(csvfile=file, rower=rower) - except (IOError, IndexError): + except (IOError, IndexError): # pragma: no cover try: res = rrdata(csvfile=file + '.gz', rower=rower) except (IOError, IndexError): res = rrdata() except: res = rrdata() - except EOFError: + except EOFError: # pragma: no cover res = rrdata() - except: + except: # pragma: no cover res = rrdata() return res @@ -2330,7 +2334,7 @@ def delete_strokedata(id): os.remove(dirname) except FileNotFoundError: pass - except FileNotFoundError: + except FileNotFoundError: # pragma: no cover pass # Replace stroke data in DB with data from CSV file @@ -2343,7 +2347,7 @@ def update_strokedata(id, df): # Test that all data are of a numerical time -def testdata(time, distance, pace, spm): +def testdata(time, distance, pace, spm): # pragma: no cover t1 = np.issubdtype(time, np.number) t2 = np.issubdtype(distance, np.number) t3 = np.issubdtype(pace, np.number) @@ -2360,7 +2364,7 @@ def getrowdata_db(id=0, doclean=False, convertnewtons=True, data = read_df_sql(id) try: data['deltat'] = data['time'].diff() - except KeyError: + except KeyError: # pragma: no cover data = pd.DataFrame() if data.empty: @@ -2377,12 +2381,12 @@ def getrowdata_db(id=0, doclean=False, convertnewtons=True, if checkefficiency==True and not data.empty: try: - if data['efficiency'].mean() == 0 and data['power'].mean() != 0: + if data['efficiency'].mean() == 0 and data['power'].mean() != 0: # pragma: no cover data = add_efficiency(id=id) except KeyError: data = add_efficiency(id=id) - if doclean: + if doclean: # pragma: no cover data = clean_df_stats(data, ignorehr=True) @@ -2426,7 +2430,7 @@ def getsmallrowdata_db(columns, ids=[], doclean=True,workstrokesonly=True,comput df = pd.read_parquet(csvfilenames[0],columns=columns) except (OSError,ArrowInvalid): rowdata,row = getrowdata(id=ids[0]) - if rowdata and len(rowdata.df): + if rowdata and len(rowdata.df): # pragma: no cover data = dataprep(rowdata.df,id=ids[0],bands=True,otwpower=True,barchart=True) df = pd.read_parquet(csvfilenames[0],columns=columns) # df = dd.read_parquet(csvfilenames[0], @@ -2484,7 +2488,7 @@ def getrowdata(id=0): import glob -def prepmultipledata(ids, verbose=False): +def prepmultipledata(ids, verbose=False): # pragma: no cover filenames = glob.glob('media/*.parquet') ids = [id for id in ids if 'media/strokedata_{id}.parquet.gz'.format(id=id) not in filenames] @@ -2515,9 +2519,9 @@ def read_cols_df_sql(ids, columns, convertnewtons=True): df = pd.DataFrame() - if len(ids) == 0: + if len(ids) == 0: # pragma: no cover return pd.DataFrame(),extracols - elif len(ids) == 1: + elif len(ids) == 1: # pragma: no cover try: filename = 'media/strokedata_{id}.parquet.gz'.format(id=ids[0]) df = pd.read_parquet(filename,columns=columns) @@ -2535,14 +2539,14 @@ def read_cols_df_sql(ids, columns, convertnewtons=True): data.append(df) except (OSError,IndexError,ArrowInvalid): rowdata,row = getrowdata(id=id) - if rowdata and len(rowdata.df): + if rowdata and len(rowdata.df): # pragma: no cover datadf = dataprep(rowdata.df,id=id,bands=True,otwpower=True,barchart=True) df = pd.read_parquet(f,columns=columns) data.append(df) try: df = pd.concat(data,axis=0) - except ValueError: + except ValueError: # pragma: no cover return pd.DataFrame(), extracols @@ -2576,7 +2580,7 @@ def read_df_sql(id): try: f = 'media/strokedata_{id}.parquet.gz'.format(id=id) df = pd.read_parquet(f) - except (OSError,ArrowInvalid,IndexError): + except (OSError,ArrowInvalid,IndexError): # pragma: no cover rowdata,row = getrowdata(id=id) if rowdata and len(rowdata.df): data = dataprep(rowdata.df,id=id,bands=True,otwpower=True,barchart=True) @@ -2655,7 +2659,7 @@ def datafusion(id1, id2, columns, offset): return df, forceunit -def fix_newtons(id=0, limit=3000): +def fix_newtons(id=0, limit=3000): # pragma: no cover # rowdata,row = getrowdata_db(id=id,doclean=False,convertnewtons=False) rowdata = getsmallrowdata_db(['peakforce'], ids=[id], doclean=False) try: @@ -2670,14 +2674,14 @@ def fix_newtons(id=0, limit=3000): except KeyError: pass -def remove_invalid_columns(df): +def remove_invalid_columns(df): # pragma: no cover for c in df.columns: if not c in allowedcolumns: df.drop(labels=c,axis=1,inplace=True) return df -def add_efficiency(id=0): +def add_efficiency(id=0): # pragma: no cover rowdata, row = getrowdata_db(id=id, doclean=False, convertnewtons=False, @@ -2728,7 +2732,7 @@ def dataprep(rowdatadf, id=0, bands=True, barchart=True, otwpower=True, p = rowdatadf.loc[:, ' Stroke500mPace (sec/500m)'] try: velo = rowdatadf.loc[:,' AverageBoatSpeed (m/s)'] - except KeyError: + except KeyError: # pragma: no cover velo = 500./p hr = rowdatadf.loc[:, ' HRCur (bpm)'] @@ -2739,7 +2743,7 @@ def dataprep(rowdatadf, id=0, bands=True, barchart=True, otwpower=True, drivelength = rowdatadf.loc[:, ' DriveLength (meters)'] try: workoutstate = rowdatadf.loc[:, ' WorkoutState'] - except KeyError: + except KeyError: # pragma: no cover workoutstate = 0 * hr peakforce = rowdatadf.loc[:, ' PeakDriveForce (lbs)'] @@ -2752,14 +2756,14 @@ def dataprep(rowdatadf, id=0, bands=True, barchart=True, otwpower=True, recoverytime = rowdatadf.loc[:, ' StrokeRecoveryTime (ms)'] rhythm = 100. * drivetime / (recoverytime + drivetime) rhythm = rhythm.fillna(value=0) - except: + except: # pragma: no cover rhythm = 0.0 * forceratio f = rowdatadf['TimeStamp (sec)'].diff().mean() if f != 0 and not np.isinf(f): try: windowsize = 2 * (int(10. / (f))) + 1 - except ValueError: + except ValueError: # pragma: no cover windowsize = 1 else: windowsize = 1 @@ -2774,7 +2778,7 @@ def dataprep(rowdatadf, id=0, bands=True, barchart=True, otwpower=True, try: t2 = t.fillna(method='ffill').apply(lambda x: timedeltaconv(x)) - except TypeError: + except TypeError: # pragma: no cover t2 = 0 * t p2 = p.fillna(method='ffill').apply(lambda x: timedeltaconv(x)) @@ -2788,7 +2792,7 @@ def dataprep(rowdatadf, id=0, bands=True, barchart=True, otwpower=True, try: driveenergy = rowdatadf['driveenergy'] - except KeyError: + except KeyError: # pragma: no cover if forceunit == 'lbs': driveenergy = drivelength * averageforce * lbstoN else: @@ -2848,7 +2852,7 @@ def dataprep(rowdatadf, id=0, bands=True, barchart=True, otwpower=True, try: tel = rowdatadf.loc[:, ' ElapsedTime (sec)'] - except KeyError: + except KeyError: # pragma: no cover rowdatadf[' ElapsedTime (sec)'] = rowdatadf['TimeStamp (sec)'] if empower: @@ -2872,7 +2876,7 @@ def dataprep(rowdatadf, id=0, bands=True, barchart=True, otwpower=True, except KeyError: peakforceangle = 0 * power - if data['driveenergy'].mean() == 0: + if data['driveenergy'].mean() == 0: # pragma: no cover try: driveenergy = rowdatadf.loc[:, 'driveenergy'] except KeyError: @@ -2894,46 +2898,46 @@ def dataprep(rowdatadf, id=0, bands=True, barchart=True, otwpower=True, try: totalangle = finish - catch effectiveangle = finish - wash - catch - slip - except ValueError: + except ValueError: # pragma: no cover totalangle = 0 * power effectiveangle = 0 * power if windowsize > 3 and windowsize < len(slip): try: wash = savgol_filter(wash, windowsize, 3) - except TypeError: + except TypeError: # pragma: no cover pass try: slip = savgol_filter(slip, windowsize, 3) - except TypeError: + except TypeError: # pragma: no cover pass try: catch = savgol_filter(catch, windowsize, 3) - except TypeError: + except TypeError: # pragma: no cover pass try: finish = savgol_filter(finish, windowsize, 3) - except TypeError: + except TypeError: # pragma: no cover pass try: peakforceangle = savgol_filter(peakforceangle, windowsize, 3) - except TypeError: + except TypeError: # pragma: no cover pass try: driveenergy = savgol_filter(driveenergy, windowsize, 3) - except TypeError: + except TypeError: # pragma: no cover pass try: drivelength = savgol_filter(drivelength, windowsize, 3) - except TypeError: + except TypeError: # pragma: no cover pass try: totalangle = savgol_filter(totalangle, windowsize, 3) - except TypeError: + except TypeError: # pragma: no cover pass try: effectiveangle = savgol_filter(effectiveangle, windowsize, 3) - except TypeError: + except TypeError: # pragma: no cover pass velo = 500. / p @@ -2955,7 +2959,7 @@ def dataprep(rowdatadf, id=0, bands=True, barchart=True, otwpower=True, data['totalangle'] = totalangle data['effectiveangle'] = effectiveangle data['efficiency'] = efficiency - except ValueError: + except ValueError: # pragma: no cover pass if otwpower: @@ -2991,7 +2995,7 @@ def dataprep(rowdatadf, id=0, bands=True, barchart=True, otwpower=True, for k, v in dtypes.items(): try: data[k] = data[k].astype(v) - except KeyError: + except KeyError: # pragma: no cover pass @@ -3026,7 +3030,7 @@ def workout_trimp(w,reset=False): try: avghr = rowdata.df[' HRCur (bpm)'].mean() maxhr = rowdata.df[' HRCur (bpm)'].max() - except KeyError: + except KeyError: # pragma: no cover avghr = None maxhr = None @@ -3077,7 +3081,7 @@ def workout_rscore(w,reset=False): return 0,0 def workout_normv(w,pp=4.0): - if w.normv > 0: + if w.normv > 0: # pragma: no cover return w.normv,w.normw r = w.user @@ -3085,7 +3089,7 @@ def workout_normv(w,pp=4.0): if w.workouttype in otwtypes: ftp = ftp*(100.-r.otwslack)/100. - if r.hrftp == 0: + if r.hrftp == 0: # pragma: no cover hrftp = (r.an+r.tr)/2. r.hrftp = int(hrftp) r.save() diff --git a/rowers/tests/test_unit_tests.py b/rowers/tests/test_unit_tests.py index 0008e970..8d9ff8aa 100644 --- a/rowers/tests/test_unit_tests.py +++ b/rowers/tests/test_unit_tests.py @@ -6,7 +6,9 @@ from __future__ import unicode_literals from .statements import * from rowers.mytypes import rowtypes from rowers.utils import allmonths,allsundays +from rowers.models import update_records +from django.db import transaction nu = datetime.datetime.now() @@ -308,9 +310,13 @@ class DataPrepTests(TestCase): self.r = Rower.objects.create(user=self.u, birthdate=faker.profile()['birthdate'], gdproptin=True,surveydone=True, + sex='male', gdproptindate=timezone.now(), rowerplan='coach') + self.r.birthdate = timezone.now()-datetime.timedelta(days=25*365) + self.r.save() + self.c = Client() self.user_workouts = WorkoutFactory.create_batch(5, user=self.r) self.factory = RequestFactory() @@ -329,10 +335,37 @@ class DataPrepTests(TestCase): workouttype = 'water', ) + with open('rowers/tests/testdata/c2records.json','r') as f: + s = f.read() + + data = json.loads(s) + for obj in data: + m = obj['fields'] + record = C2WorldClassAgePerformance(**m) + record.save() + + with open('rowers/tests/testdata/calcageperformance.json','r') as f: + s = f.read() + + data = json.loads(s) + for obj in data: + m = obj['fields'] + record = CalcAgePerformance(**m) + #print(record.sex,record.age,record.weightcategory,record.duration,record.power) + record.save() def tearDown(self): pass + def test_goldmedalstandard(self): + maxvalue, delta = dataprep.calculate_goldmedalstandard(self.r,self.wuh_otw) + records = CalcAgePerformance.objects.filter( + age=dataprep.calculate_age(self.r.birthdate), + weightcategory=self.r.weightcategory, + sex=self.r.sex) + self.assertEqual(int(maxvalue),9) + self.assertEqual(delta,6) + @patch('rowers.dataprep.getsmallrowdata_db',side_effect=mocked_getsmallrowdata_uh) def test_get_videodata(self,mocked_getsmallrowdata_uh): data, metrics, maxtime = dataprep.get_video_data(self.wuh_otw)