From 7f6112462fc0d9a888e4b93f44ffe35003c6cb6e Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Mon, 23 Dec 2019 21:08:05 +0100 Subject: [PATCH 1/3] helper files --- rowers/rowing_workout_metrics_pb2.py | 203 ++++++++++++++++++++++ rowers/rowing_workout_metrics_pb2_grpc.py | 46 +++++ 2 files changed, 249 insertions(+) create mode 100644 rowers/rowing_workout_metrics_pb2.py create mode 100644 rowers/rowing_workout_metrics_pb2_grpc.py diff --git a/rowers/rowing_workout_metrics_pb2.py b/rowers/rowing_workout_metrics_pb2.py new file mode 100644 index 00000000..53d92d53 --- /dev/null +++ b/rowers/rowing_workout_metrics_pb2.py @@ -0,0 +1,203 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: rowing-workout-metrics.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='rowing-workout-metrics.proto', + package='rowing_workout_metrics', + syntax='proto3', + serialized_options=None, + serialized_pb=_b('\n\x1crowing-workout-metrics.proto\x12\x16rowing_workout_metrics\"p\n\x15WorkoutMetricsRequest\x12\x10\n\x08\x66ilename\x18\x01 \x01(\t\x12\x0b\n\x03sex\x18\x02 \x01(\t\x12\x0b\n\x03\x66tp\x18\x03 \x01(\x01\x12\r\n\x05hrftp\x18\x04 \x01(\x01\x12\r\n\x05hrmax\x18\x05 \x01(\x01\x12\r\n\x05hrmin\x18\x06 \x01(\x01\"p\n\x16WorkoutMetricsResponse\x12\x0b\n\x03tss\x18\x01 \x01(\x01\x12\r\n\x05normp\x18\x02 \x01(\x01\x12\r\n\x05trimp\x18\x03 \x01(\x01\x12\r\n\x05hrtss\x18\x04 \x01(\x01\x12\r\n\x05normv\x18\x05 \x01(\x01\x12\r\n\x05normw\x18\x06 \x01(\x01\x32w\n\x07Metrics\x12l\n\x0b\x43\x61lcMetrics\x12-.rowing_workout_metrics.WorkoutMetricsRequest\x1a..rowing_workout_metrics.WorkoutMetricsResponseb\x06proto3') +) + + + + +_WORKOUTMETRICSREQUEST = _descriptor.Descriptor( + name='WorkoutMetricsRequest', + full_name='rowing_workout_metrics.WorkoutMetricsRequest', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='filename', full_name='rowing_workout_metrics.WorkoutMetricsRequest.filename', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='sex', full_name='rowing_workout_metrics.WorkoutMetricsRequest.sex', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='ftp', full_name='rowing_workout_metrics.WorkoutMetricsRequest.ftp', index=2, + number=3, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='hrftp', full_name='rowing_workout_metrics.WorkoutMetricsRequest.hrftp', index=3, + number=4, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='hrmax', full_name='rowing_workout_metrics.WorkoutMetricsRequest.hrmax', index=4, + number=5, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='hrmin', full_name='rowing_workout_metrics.WorkoutMetricsRequest.hrmin', index=5, + number=6, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=56, + serialized_end=168, +) + + +_WORKOUTMETRICSRESPONSE = _descriptor.Descriptor( + name='WorkoutMetricsResponse', + full_name='rowing_workout_metrics.WorkoutMetricsResponse', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='tss', full_name='rowing_workout_metrics.WorkoutMetricsResponse.tss', index=0, + number=1, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='normp', full_name='rowing_workout_metrics.WorkoutMetricsResponse.normp', index=1, + number=2, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='trimp', full_name='rowing_workout_metrics.WorkoutMetricsResponse.trimp', index=2, + number=3, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='hrtss', full_name='rowing_workout_metrics.WorkoutMetricsResponse.hrtss', index=3, + number=4, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='normv', full_name='rowing_workout_metrics.WorkoutMetricsResponse.normv', index=4, + number=5, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='normw', full_name='rowing_workout_metrics.WorkoutMetricsResponse.normw', index=5, + number=6, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=170, + serialized_end=282, +) + +DESCRIPTOR.message_types_by_name['WorkoutMetricsRequest'] = _WORKOUTMETRICSREQUEST +DESCRIPTOR.message_types_by_name['WorkoutMetricsResponse'] = _WORKOUTMETRICSRESPONSE +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +WorkoutMetricsRequest = _reflection.GeneratedProtocolMessageType('WorkoutMetricsRequest', (_message.Message,), { + 'DESCRIPTOR' : _WORKOUTMETRICSREQUEST, + '__module__' : 'rowing_workout_metrics_pb2' + # @@protoc_insertion_point(class_scope:rowing_workout_metrics.WorkoutMetricsRequest) + }) +_sym_db.RegisterMessage(WorkoutMetricsRequest) + +WorkoutMetricsResponse = _reflection.GeneratedProtocolMessageType('WorkoutMetricsResponse', (_message.Message,), { + 'DESCRIPTOR' : _WORKOUTMETRICSRESPONSE, + '__module__' : 'rowing_workout_metrics_pb2' + # @@protoc_insertion_point(class_scope:rowing_workout_metrics.WorkoutMetricsResponse) + }) +_sym_db.RegisterMessage(WorkoutMetricsResponse) + + + +_METRICS = _descriptor.ServiceDescriptor( + name='Metrics', + full_name='rowing_workout_metrics.Metrics', + file=DESCRIPTOR, + index=0, + serialized_options=None, + serialized_start=284, + serialized_end=403, + methods=[ + _descriptor.MethodDescriptor( + name='CalcMetrics', + full_name='rowing_workout_metrics.Metrics.CalcMetrics', + index=0, + containing_service=None, + input_type=_WORKOUTMETRICSREQUEST, + output_type=_WORKOUTMETRICSRESPONSE, + serialized_options=None, + ), +]) +_sym_db.RegisterServiceDescriptor(_METRICS) + +DESCRIPTOR.services_by_name['Metrics'] = _METRICS + +# @@protoc_insertion_point(module_scope) diff --git a/rowers/rowing_workout_metrics_pb2_grpc.py b/rowers/rowing_workout_metrics_pb2_grpc.py new file mode 100644 index 00000000..099bf538 --- /dev/null +++ b/rowers/rowing_workout_metrics_pb2_grpc.py @@ -0,0 +1,46 @@ +# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! +import grpc + +import rowing_workout_metrics_pb2 as rowing__workout__metrics__pb2 + + +class MetricsStub(object): + """OTW-metrics service definition + """ + + def __init__(self, channel): + """Constructor. + + Args: + channel: A grpc.Channel. + """ + self.CalcMetrics = channel.unary_unary( + '/rowing_workout_metrics.Metrics/CalcMetrics', + request_serializer=rowing__workout__metrics__pb2.WorkoutMetricsRequest.SerializeToString, + response_deserializer=rowing__workout__metrics__pb2.WorkoutMetricsResponse.FromString, + ) + + +class MetricsServicer(object): + """OTW-metrics service definition + """ + + def CalcMetrics(self, request, context): + # missing associated documentation comment in .proto file + pass + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + +def add_MetricsServicer_to_server(servicer, server): + rpc_method_handlers = { + 'CalcMetrics': grpc.unary_unary_rpc_method_handler( + servicer.CalcMetrics, + request_deserializer=rowing__workout__metrics__pb2.WorkoutMetricsRequest.FromString, + response_serializer=rowing__workout__metrics__pb2.WorkoutMetricsResponse.SerializeToString, + ), + } + generic_handler = grpc.method_handlers_generic_handler( + 'rowing_workout_metrics.Metrics', rpc_method_handlers) + server.add_generic_rpc_handlers((generic_handler,)) From 2388edcf6d43308ad0cc2e93d313498d78a7cafe Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Mon, 23 Dec 2019 21:25:00 +0100 Subject: [PATCH 2/3] async calctrimp task using microservice --- rowers/rowing_workout_metrics_pb2_grpc.py | 2 +- rowers/tasks.py | 128 ++++++---------------- 2 files changed, 34 insertions(+), 96 deletions(-) diff --git a/rowers/rowing_workout_metrics_pb2_grpc.py b/rowers/rowing_workout_metrics_pb2_grpc.py index 099bf538..b58e9986 100644 --- a/rowers/rowing_workout_metrics_pb2_grpc.py +++ b/rowers/rowing_workout_metrics_pb2_grpc.py @@ -1,7 +1,7 @@ # Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! import grpc -import rowing_workout_metrics_pb2 as rowing__workout__metrics__pb2 +import rowers.rowing_workout_metrics_pb2 as rowing__workout__metrics__pb2 class MetricsStub(object): diff --git a/rowers/tasks.py b/rowers/tasks.py index 8c455a4e..727c3b41 100644 --- a/rowers/tasks.py +++ b/rowers/tasks.py @@ -38,6 +38,8 @@ from matplotlib import path import grpc import rowers.otw_power_calculator_pb2 as calculator_pb2 import rowers.otw_power_calculator_pb2_grpc as calculator_pb2_grpc +import rowers.rowing_workout_metrics_pb2 as metrics_pb2 +import rowers.rowing_workout_metrics_pb2_grpc as metrics_pb2_grpc from rowsandall_app.settings import SITE_URL from rowsandall_app.settings_dev import SITE_URL as SITE_URL_DEV @@ -609,105 +611,41 @@ def handle_calctrimp(id, else: engine = create_engine(database_url, echo=False) - try: - rowdata = rdata(csvfile=csvfilename) - except IOError: + tss = 0 + normp = 0 + trimp = 0 + hrtss = 0 + normv = 0 + normw = 0 + + with grpc.insecure_channel( + target='localhost:50052', + options=[('grpc.lb_policy_name', 'pick_first'), + ('grpc.enable_retries', 0), ('grpc.keepalive_timeout_ms', + 10000)] + ) as channel: try: - rowdata = rdata(csvfile=csvfilename + '.csv') - except IOError: - try: - rowdata = rdata(csvfile=csvfilename + '.gz') - except IOError: - return 0 + grpc.channel_ready_future(channel).result(timeout=10) + except grpc.FutureTimeoutError: + return 0 - df = rowdata.df - - try: - df['deltat'] = df[' ElapsedTime (sec)'].diff().abs() - except KeyError: - return 0 - - df2 = df.copy() - - df2['time'] = df2[' ElapsedTime (sec)'] - df2['time'] = df2['time'].apply( - lambda x:safetimedelta(x) + stub = metrics_pb2_grpc.MetricsStub(channel) + req = metrics_pb2.WorkoutMetricsRequest( + filename = csvfilename, + ftp=ftp, + sex=sex, + hrftp=hrftp, + hrmax=hrmax, + hrmin=hrmin, ) + response = stub.CalcMetrics(req,timeout=60) - duration = df['TimeStamp (sec)'].max()-df['TimeStamp (sec)'].min() - df2 = df2.resample('1s',on='time').mean() - df2.fillna(method='ffill',inplace=True) - df2 = df2.rolling(30).mean() + tss = response.tss + normp = response.normp + trimp = response.trimp + normv = response.normv + normw = response.normw - df2[' Power (watts)'] = df2[' Power (watts)'].abs() - - df2['pwr4'] = df2[' Power (watts)']**(4.0) - # pwr4mean = wavg(df,'pwr4','deltat') - pwr4mean = df2['pwr4'].mean() - pwrmean = df2[' Power (watts)'].mean() - # pwrmean = wavg(df,' Power (watts)','deltat') - if pwr4mean > 0: - normp = (pwr4mean)**(0.25) - else: - normp = pwrmean - - intensityfactor = normp/float(ftp) - tss = 100.*((duration*normp*intensityfactor)/(3600.*ftp)) - - - if sex == 'male': - f = 1.92 - else: - f = 1.67 - - dt = df['TimeStamp (sec)'].diff()/60. - - hrr = (df[' HRCur (bpm)']-hrmin)/(hrmax-hrmin) - hrrftp = (hrftp-hrmin)/float(hrmax-hrmin) - trimp1hr = 60.*hrrftp*0.64*np.exp(f*hrrftp) - - trimpdata = dt*hrr*0.64*np.exp(f*hrr) - trimp = trimpdata.sum() - - hrtss = 100.*trimp/trimp1hr - - pp = 8.0 - - df['v4'] = df[' AverageBoatSpeed (m/s)']**(pp) - v4mean = wavg(df,'v4','deltat') - normv = v4mean**(1./pp) - - try: - df['w4'] = df['driveenergy']**(pp) - w4mean = wavg(df,'w4','deltat') - normw = w4mean**(1./pp) - except KeyError: - normw = 0 - - - if not np.isfinite(normv): - normv = 500./120. - - if not np.isfinite(normw): - normw = 0 - - try: - dum = int(tss) - except ValueError: - tss = 0 - - try: - dum = int(normp) - except ValueError: - normp = 0 - try: - dump = int(trimp) - except ValueError: - trimp = 0 - try: - dump = int(hrtss) - except ValueError: - hrtss = 0 query = 'UPDATE rowers_workout SET rscore = {tss}, normp = {normp}, trimp={trimp}, hrtss={hrtss}, normv={normv}, normw={normw} WHERE id={id}'.format( tss = int(tss), @@ -1603,7 +1541,7 @@ def handle_otwsetpower(self,f1, boattype, weightvalue, try: rowdata = rdata(csvfile) except IOError: - rowdata = rdata(csvfile) + rowdata = rdata(csvfile) else: boatfile = { From 9b653d4d1be8d90baf9d59b527268a420bf9f5c1 Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Mon, 23 Dec 2019 21:30:26 +0100 Subject: [PATCH 3/3] tasks updated --- rowers/tasks.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/rowers/tasks.py b/rowers/tasks.py index 727c3b41..259a7acd 100644 --- a/rowers/tasks.py +++ b/rowers/tasks.py @@ -618,6 +618,16 @@ def handle_calctrimp(id, normv = 0 normw = 0 + # check what the real file name is + if os.path.exists(csvfilename): + csvfile = csvfilename + elif os.path.exists(csvfilename+'.csv'): + csvfile = csvfilename+'.csv' + elif os.path.exists(csvfilename+'.gz'): + csvfile = csvfilename+'.gz' + + csvfile = os.path.abspath(csvfile) + with grpc.insecure_channel( target='localhost:50052', options=[('grpc.lb_policy_name', 'pick_first'), @@ -631,7 +641,7 @@ def handle_calctrimp(id, stub = metrics_pb2_grpc.MetricsStub(channel) req = metrics_pb2.WorkoutMetricsRequest( - filename = csvfilename, + filename = csvfile, ftp=ftp, sex=sex, hrftp=hrftp, @@ -645,6 +655,7 @@ def handle_calctrimp(id, trimp = response.trimp normv = response.normv normw = response.normw + hrtss = response.hrtss query = 'UPDATE rowers_workout SET rscore = {tss}, normp = {normp}, trimp={trimp}, hrtss={hrtss}, normv={normv}, normw={normw} WHERE id={id}'.format(