diff --git a/rowers/interactiveplots.py b/rowers/interactiveplots.py index 8b1d78e4..d5a2842a 100644 --- a/rowers/interactiveplots.py +++ b/rowers/interactiveplots.py @@ -1731,35 +1731,35 @@ def interactive_flexchart_stacked(id, r, xparam='time', try: tseconds = rowdata['time'] - except KeyError: # pragma: no cover + except (KeyError, ColumnNotFoundError): # pragma: no cover return '', 'No time data - cannot make flex plot' try: rowdata = rowdata.with_columns(x1=pl.col(xparam)) - except KeyError: # pragma: no cover + except (KeyError, ColumnNotFoundError): # pragma: no cover rowdata = rowdata.with_columns(x1=pl.lit(0)) try: rowdata = rowdata.with_columns(y1=pl.col(yparam1)) - except KeyError: # pragma: no cover + except (KeyError, ColumnNotFoundError): # pragma: no cover rowdata = rowdata.with_columns(y1=pl.col("time")) rowdata = rowdata.with_columns((pl.col("y1")).alias(yparam1)) try: rowdata = rowdata.with_columns(y2=pl.col(yparam2)) - except KeyError: # pragma: no cover + except (KeyError, ColumnNotFoundError): # pragma: no cover rowdata = rowdata.with_columns(y2=pl.col("time")) rowdata = rowdata.with_columns((pl.col("y2")).alias(yparam2)) try: rowdata = rowdata.with_columns(y1=pl.col(yparam3)) - except KeyError: # pragma: no cover + except (KeyError, ColumnNotFoundError): # pragma: no cover rowdata = rowdata.with_columns(y3=pl.col("time")) rowdata = rowdata.with_columns((pl.col("y3")).alias(yparam3)) try: rowdata = rowdata.with_columns(y4=pl.col(yparam1)) - except KeyError: # pragma: no cover + except (KeyError, ColumnNotFoundError): # pragma: no cover rowdata = rowdata.with_columns(y4=pl.col("time")) rowdata = rowdata.with_columns((pl.col("y4")).alias(yparam4)) @@ -1800,8 +1800,8 @@ def interactive_flex_chart2(id, r, promember=0, columns = [name for name, d in metrics.rowingmetrics] columns_basic = [name for name, d in metrics.rowingmetrics if d['group'] == 'basic'] - columns = columns + ['spm', 'driveenergy', 'distance'] - columns_basic = columns_basic + ['spm', 'driveenergy', 'distance'] + columns = columns + ['spm', 'driveenergy', 'distance','workoutstate'] + columns_basic = columns_basic + ['spm', 'driveenergy', 'distance','workoutstate'] datadf = pd.DataFrame() if promember: @@ -1838,24 +1838,24 @@ def interactive_flex_chart2(id, r, promember=0, workstrokesonly = False try: _ = rowdata[yparam2] - except (KeyError, TypeError): # pragma: no cover + except (KeyError, TypeError, ColumnNotFoundError): # pragma: no cover yparam2 = 'None' try: _ = rowdata[yparam1] - except (TypeError, KeyError): # pragma: no cover + except (TypeError, KeyError, ColumnNotFoundError): # pragma: no cover yparam1 = 'None' # test if we have drive energy try: _ = rowdata['driveenergy'].mean() - except (KeyError, TypeError): + except (KeyError, TypeError, ColumnNotFoundError): rowdata = rowdata.with_columns(driveenergy=pl.lit(500)) # test if we have power try: _ = rowdata['power'].mean() - except (KeyError, TypeError): + except (KeyError, TypeError, ColumnNotFoundError): rowdata = rowdata.with_columns(power=pl.lit(50)) # replace nans @@ -1870,22 +1870,22 @@ def interactive_flex_chart2(id, r, promember=0, if workstrokesonly: # pragma: no cover try: rowdata = rowdata.filter(~pl.col("workoutstate").is_in(workoutstatesrest)) - except KeyError: + except (KeyError, ColumnNotFoundError): pass try: tseconds = rowdata['time'] - except KeyError: # pragma: no cover + except (KeyError, ColumnNotFoundError): # pragma: no cover return '', 'No time data - cannot make flex plot', workstrokesonly try: rowdata = rowdata.with_columns(x1 = pl.col(xparam)) - except KeyError: # pragma: no cover + except (KeyError, ColumnNotFoundError): # pragma: no cover rowdata = rowdata.with_columns(x1 = pl.col("time")) try: rowdata = rowdata.with_columns(y1 = pl.col(yparam1)) - except KeyError: # pragma: no cover + except (KeyError, ColumnNotFoundError): # pragma: no cover rowdata = rowdata.with_columns(y1 = pl.col("time")) rowdata = rowdata.with_columns(yparam1 = pl.col("y1")) @@ -1893,7 +1893,7 @@ def interactive_flex_chart2(id, r, promember=0, if yparam2 != 'None': try: rowdata = rowdata.with_columns(y2 = pl.col(yparam2)) - except KeyError: # pragma: no cover + except (KeyError, ColumnNotFoundError): # pragma: no cover rowdata = rowdata.with_columns(y2 = pl.col("time")) rowdata = rowdata.with_columns(yparam2 = pl.col("y2")) @@ -1916,18 +1916,18 @@ def interactive_flex_chart2(id, r, promember=0, try: rowdata = rowdata.with_columns((pl.lit(axlabels[xparam])).alias("xname")) - except KeyError: # pragma: no cover + except (KeyError, ColumnNotFoundError): # pragma: no cover rowdata = rowdata.with_columns((pl.lit(xparam)).alias("xname")) try: rowdata = rowdata.with_columns((pl.lit(axlabels[yparam1])).alias("yname1")) - except KeyError: # pragma: no cover + except (KeyError, ColumnNotFoundError): # pragma: no cover rowdata = rowdata.with_columns((pl.lit(yparam1)).alias("yname1")) if yparam2 != 'None': try: rowdata = rowdata.with_columns((pl.lit(axlabels[yparam2])).alias("yname2")) - except KeyError: # pragma: no cover + except (KeyError, ColumnNotFoundError): # pragma: no cover rowdata = rowdata.with_columns((pl.lit(yparam2)).alias("yname2")) else: # pragma: no cover @@ -2185,210 +2185,6 @@ def interactive_multiple_compare_chart(ids, xparam, yparam, plottype='line', script, div = get_chart("/compare", chart_data) return script, div, message, errormessage - if xparam != 'distance' and xparam != 'time' and xparam != 'cumdist': # pragma: no cover - xaxmax = yaxmaxima[xparam] - xaxmin = yaxminima[xparam] - elif xparam == 'time' and not startenddict: - xaxmax = tseconds.max() - xaxmin = tseconds.min() - elif xparam == 'time' and startenddict: # pragma: no cover - deltas = [pair[1]-pair[0] for key, pair in startenddict.items()] - xaxmin = 0 - xaxmax = pd.Series(deltas).max()*1000. - if xaxmax == 0: - xaxmax = tseconds.max() - else: - xaxmax = datadf['distance'].max() - xaxmin = datadf['distance'].min() - - if yparam == 'distance': # pragma: no cover - yaxmin = datadf['distance'].min() - yaxmax = datadf['distance'].max() - elif yparam == 'cumdist': # pragma: no cover - 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,crosshair' - else: # pragma: no cover - 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' - - plot = figure(x_axis_type=x_axis_type, y_axis_type=y_axis_type, - tools=TOOLS, - toolbar_location="above", - width=920, height=500, - toolbar_sticky=False) - - # add watermark - watermarkurl = "/static/img/logo7.png" - watermarkrange = Range1d(start=0, end=1) - watermarkalpha = 0.6 - watermarkw = 184 - watermarkh = 35 - plot.extra_y_ranges = {"watermark": watermarkrange} - plot.extra_x_ranges = {"watermark": watermarkrange} - #plot.sizing_mode = 'stretch_both' - - 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 - l1 = [] - - try: - items = itertools.izip(ids, colors) - except AttributeError: - items = zip(ids, colors) - - for id, color in items: - group = datadf[datadf['workoutid'] == int(id)].copy() - try: - startsecond, endsecond = startenddict[id] - except KeyError: - startsecond = 0 - endsecond = 0 - - group.sort_values(by='time', ascending=True, inplace=True) - - if endsecond > 0: - group['time'] = group['time'] - 1.e3*startsecond - mask = group['time'] < 0 - group.mask(mask, inplace=True) - mask = group['time'] > 1.e3*(endsecond-startsecond) - group.mask(mask, inplace=True) - - if xparam == 'cumdist': - group['cumdist'] = group['cumdist'] - group['cumdist'].min() - res = make_cumvalues(group[xparam]) - group[xparam] = res[0] - elif xparam == 'distance': - group['distance'] = group['distance'] - group['distance'].min() - - try: - group['x'] = group[xparam] - except KeyError: # pragma: no cover - group['x'] = group['time'] - errormessage = xparam+' has no values. Plot invalid' - try: - group['y'] = group[yparam] - except KeyError: - group['y'] = 0.0*group['x'] - - ymean = group['y'].mean() - f = group['time'].diff().mean() - if f != 0 and not np.isnan(f): - windowsize = 2 * (int(20000./(f))) + 1 - else: - windowsize = 1 - - if windowsize > 3 and windowsize < len(group['y']): - try: - group['y'] = savgol_filter(group['y'], windowsize, 3) - except ValueError: # pragma: no cover - pass - - 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: - try: - legend_label = labeldict[id] - except KeyError: # pragma: no cover - legend_label = str(id) - else: # pragma: no cover - legend_label = str(id) - - if plottype == 'line': - l1.append(plot.line('x', 'y', source=source, color=color, - legend_label=legend_label, line_width=2)) - else: - l1.append(plot.scatter('x', 'y', source=source, color=color, legend_label=legend_label, - fill_alpha=0.4, line_color=None)) - - plot.add_tools(HoverTool(renderers=[l1[cntr]], tooltips=TIPS)) - cntr += 1 - - plot.legend.location = 'top_right' - plot.xaxis.axis_label = axlabels[xparam] - plot.yaxis.axis_label = axlabels[yparam] - - if (xparam != 'time') and (xparam != 'distance') and (xparam != 'cumdist'): # pragma: no cover - 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, message, errormessage] - def get_zones_report(rower, startdate, enddate, trainingzones='hr', date_agg='week', yaxis='time'): diff --git a/rowers/tests/mocks.py b/rowers/tests/mocks.py index b379eb83..80a12eb1 100644 --- a/rowers/tests/mocks.py +++ b/rowers/tests/mocks.py @@ -38,6 +38,7 @@ from nose.tools import assert_true from mock import Mock, patch #from minimocktest import MockTestCase import pandas as pd +import polars as pl import arrow from django.http import HttpResponseRedirect @@ -335,6 +336,11 @@ def mocked_getsmallrowdata_db(*args, **kwargs): return df +def mocked_getsmallrowdata_pl(*args, **kwargs): + df = pl.read_csv('rowers/tests/testdata/colsfromdb.csv') + + return df + def mocked_getsmallrowdata_db_updatecp(*args, **kwargs): # pragma: no cover df = pd.read_csv('rowers/tests/testdata/colsfromdb.csv') diff --git a/rowers/tests/statements.py b/rowers/tests/statements.py index 3b88c2e2..c809c60e 100644 --- a/rowers/tests/statements.py +++ b/rowers/tests/statements.py @@ -65,6 +65,7 @@ from nose.tools import assert_true from mock import Mock, patch #from minimocktest import MockTestCase import pandas as pd +import polars as pl import rowers.c2stuff as c2stuff import rowers.rojabo_stuff as rojabo_stuff diff --git a/rowers/tests/test_unit_tests.py b/rowers/tests/test_unit_tests.py index 650362d8..92903b5e 100644 --- a/rowers/tests/test_unit_tests.py +++ b/rowers/tests/test_unit_tests.py @@ -735,9 +735,9 @@ class InteractivePlotTests(TestCase): self.assertFalse(len(div)==0) @patch('rowers.dataprep.create_engine') - @patch('rowers.dataprep.getsmallrowdata_db', side_effect=mocked_getsmallrowdata_db) + @patch('rowers.dataprep.getsmallrowdata_pl', side_effect=mocked_getsmallrowdata_pl) def test_interactive_flexchart_stacked(self, mocked_sqlalchemy, - mocked_getsmallrowdata_db): + mocked_getsmallrowdata_pl): workout = Workout.objects.filter(user=self.r,workouttype__in=mytypes.rowtypes)[0] id = workout.id diff --git a/rowers/tests/testdata/testdata.tcx.gz b/rowers/tests/testdata/testdata.tcx.gz index 62c65b68..2f3f0980 100644 Binary files a/rowers/tests/testdata/testdata.tcx.gz and b/rowers/tests/testdata/testdata.tcx.gz differ