Private
Public Access
1
0
This commit is contained in:
2024-03-13 18:57:18 +01:00
parent 4b83a251db
commit 5149f08de7
9 changed files with 97 additions and 228 deletions

View File

@@ -502,8 +502,28 @@ def calculate_goldmedalstandard(rower, workout, recurrance=True):
def setcp(workout, background=False, recurrance=True):
filename = 'media/cpdata_{id}.parquet.gz'.format(id=workout.id)
try:
filename = 'media/cpdata_{id}.parquet.gz'.format(id=workout.id)
df = pd.read_parquet(filename)
if not df.empty:
# check dts
tarr = datautils.getlogarr(4000)
if df['delta'][0] in tarr:
return(df, df['delta'], df['cp'])
except:
pass
strokesdf = getsmallrowdata_db(
['power', 'workoutid', 'time'], ids=[workout.id])
if strokesdf.empty:
return pd.DataFrame({'delta': [], 'cp': []}), pd.Series(dtype='float'), pd.Series(dtype='float')
totaltime = strokesdf['time'].max()
maxt = totaltime/1000.
logarr = datautils.getlogarr(maxt)
csvfilename = workout.csvfilename
# check what the real file name is
if os.path.exists(csvfilename):
@@ -514,80 +534,53 @@ def setcp(workout, background=False, recurrance=True):
csvfile = csvfilename+'.gz'
else: # pragma: no cover
return pd.DataFrame({'delta': [], 'cp': []}), pd.Series(dtype='float'), pd.Series(dtype='float')
csvfile = os.path.abspath(csvfile)
strokesdf = getsmallrowdata_db(
['power', 'workoutid', 'time'], ids=[workout.id])
protos = grpc.protos("rowing_workout_metrics.proto")
services = grpc.services("rowing_workout_metrics.proto")
req = protos.CPRequest(
filename = csvfile,
filetype = "CSV",
tarr = datautils.getlogarr(1.05*strokesdf['time'].max())
)
response = services.GetCP(req, "localhost:50052", insecure=True)
delta = response.delta
cpvalues = response.power
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:
grpc.channel_ready_future(channel).result(timeout=10)
except grpc.FutureTimeoutError: # pragma: no cover
dologging('metrics.log','grpc channel time out in setcp')
return pd.DataFrame({'delta': [], 'cp': []}), pd.Series(dtype='float'), pd.Series(dtype='float')
stub = metrics_pb2_grpc.MetricsStub(channel)
req = metrics_pb2.CPRequest(filename = csvfile, filetype = "CSV", tarr = logarr)
try:
response = stub.GetCP(req, timeout=60)
except Exception as e:
dologging('metrics.log', traceback.format_exc())
return pd.DataFrame({'delta': [], 'cp': []}), pd.Series(dtype='float'), pd.Series(dtype='float')
delta = pd.Series(np.array(response.delta))
cpvalues = pd.Series(np.array(response.power))
powermean = response.avgpower
df = pd.DataFrame({
'delta': delta,
'cp': cpvalues,
'id': workout.id,
})
df.to_parquet(filename, engine='fastparquet', compression='GZIP')
if recurrance:
goldmedalstandard, goldmedalduration = calculate_goldmedalstandard(
workout.user, workout)
workout.goldmedalstandard = goldmedalstandard
workout.goldmedalduration = goldmedalduration
workout.save()
return df, delta, cpvalues
try:
if strokesdf['power'].std() == 0:
return pd.DataFrame(), pd.Series(dtype='float'), pd.Series(dtype='float')
except (KeyError, TypeError):
return pd.DataFrame(), pd.Series(dtype='float'), pd.Series(dtype='float')
if background: # pragma: no cover
_ = myqueue(queuelow, handle_setcp, strokesdf, filename, workout.id)
return pd.DataFrame({'delta': [], 'cp': []}), pd.Series(dtype='float'), pd.Series(dtype='float')
if not strokesdf.empty:
totaltime = strokesdf['time'].max()
try:
powermean = strokesdf['power'].mean()
except KeyError: # pragma: no cover
powermean = 0
if powermean != 0:
thesecs = totaltime
maxt = 1.05 * thesecs
if maxt > 0:
logarr = datautils.getlogarr(maxt)
dfgrouped = strokesdf.groupby(['workoutid'])
delta, cpvalues, avgpower = datautils.getcp(dfgrouped, logarr)
df = pd.DataFrame({
'delta': delta,
'cp': cpvalues,
'id': workout.id,
})
df.to_parquet(filename, engine='fastparquet',
compression='GZIP')
if recurrance:
goldmedalstandard, goldmedalduration = calculate_goldmedalstandard(
workout.user, workout)
workout.goldmedalstandard = goldmedalstandard
workout.goldmedalduration = goldmedalduration
workout.save()
return df, delta, cpvalues
return pd.DataFrame({'delta': [], 'cp': []}), pd.Series(dtype='float'), pd.Series(dtype='float')
def update_wps(r, types, mode='water', asynchron=True):
@@ -723,6 +716,7 @@ def join_workouts(r, ids, title='Joined Workout',
def fetchcp_new(rower, workouts):
data = []
for workout in workouts:
cpfile = 'media/cpdata_{id}.parquet.gz'.format(id=workout.id)
try:
@@ -743,12 +737,15 @@ def fetchcp_new(rower, workouts):
if len(data) > 1:
df = pd.concat(data, axis=0)
try:
df = df[df['cp'] == df.groupby(['delta'])['cp'].transform('max')]
except KeyError: # pragma: no cover
return pd.Series(dtype='float'), pd.Series(dtype='float'), 0, pd.Series(dtype='float'), pd.Series(dtype='float')
df = df.sort_values(['delta']).reset_index()
df = df[df['cp']>20]
return df['delta'], df['cp'], 0, df['workout'], df['url']

View File

@@ -123,18 +123,18 @@ def cpfit(powerdf, fraclimit=0.0001, nmax=1000):
def getlogarr(maxt):
maxlog10 = np.log10(maxt-5)
dtmin = 10
maxlog10 = np.log10(maxt)
# print(maxlog10,round(maxlog10))
aantal = 10*round(maxlog10)
aantal = 40
logarr = np.arange(aantal+1)/10.
vs = 10.**logarr
res = []
for la in logarr:
try:
v = 5+int(10.**(la))
except ValueError: # pragma: no cover
v = 0
res.append(v)
for v in vs:
if v > dtmin and v<maxt:
res.append(int(v))
logarr = pd.Series(res, dtype='float')
logarr.drop_duplicates(keep='first', inplace=True)

View File

@@ -1823,15 +1823,18 @@ class InstantPlan(models.Model):
authorizationstring = 'Bearer '+settings.WORKOUTS_FIT_TOKEN
url = settings.WORKOUTS_FIT_URL+"/trainingplan/"
headers = {'Authorization': authorizationstring}
response = requests.post(url=url, headers=headers, data=yamltext)
if response.status_code == 200:
data = response.json()
self.yaml.name = data['filename']
self.uuid = data['ID']
self.name = data['name']
self.description = data['description']
self.duration = data['duration']
self.yaml = None
try:
response = requests.post(url=url, headers=headers, data=yamltext)
if response.status_code == 200:
data = response.json()
self.yaml.name = data['filename']
self.uuid = data['ID']
self.name = data['name']
self.description = data['description']
self.duration = data['duration']
self.yaml = None
except:
pass
super(InstantPlan, self).save(*args, **kwargs)

View File

@@ -1,49 +0,0 @@
syntax = "proto3";
package rowing_workout_metrics;
option go_package = "./rowing-workout-metrics";
// OTW-metrics service definition
service Metrics {
rpc CalcMetrics (WorkoutMetricsRequest) returns (WorkoutMetricsResponse);
};
// GetCP service definition
service CP {
rpc GetCP (CPRequest) returns (CPResponse);
}
// WorkoutMetricsRequest message
message WorkoutMetricsRequest {
string filename = 1;
string sex = 2;
double ftp = 3;
double hrftp = 4;
double hrmax = 5;
double hrmin = 6;
};
// WorkoutMetricsReponse message
message WorkoutMetricsResponse {
double tss = 1;
double normp = 2;
double trimp = 3;
double hrtss = 4;
double normv = 5;
double normw = 6;
};
// CPRequest message
message CPRequest {
string filename = 1;
string filetype = 2; // CSV or Parquet
repeated double tarr = 3;
}
message CPResponse {
repeated double delta = 1;
repeated double power = 2;
double avgpower = 3;
}

View File

@@ -1,49 +0,0 @@
syntax = "proto3";
package rowing_workout_metrics;
option go_package = "./rowing-workout-metrics";
// OTW-metrics service definition
service Metrics {
rpc CalcMetrics (WorkoutMetricsRequest) returns (WorkoutMetricsResponse);
};
// GetCP service definition
service CP {
rpc GetCP (CPRequest) returns (CPResponse);
}
// WorkoutMetricsRequest message
message WorkoutMetricsRequest {
string filename = 1;
string sex = 2;
double ftp = 3;
double hrftp = 4;
double hrmax = 5;
double hrmin = 6;
};
// WorkoutMetricsReponse message
message WorkoutMetricsResponse {
double tss = 1;
double normp = 2;
double trimp = 3;
double hrtss = 4;
double normv = 5;
double normw = 6;
};
// CPRequest message
message CPRequest {
string filename = 1;
string filetype = 2; // CSV or Parquet
repeated double tarr = 3;
}
message CPResponse {
repeated double delta = 1;
repeated double power = 2;
double avgpower = 3;
}

View File

@@ -14,7 +14,7 @@ _sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(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\"=\n\tCPRequest\x12\x10\n\x08\x66ilename\x18\x01 \x01(\t\x12\x10\n\x08\x66iletype\x18\x02 \x01(\t\x12\x0c\n\x04tarr\x18\x03 \x03(\x01\"<\n\nCPResponse\x12\r\n\x05\x64\x65lta\x18\x01 \x03(\x01\x12\r\n\x05power\x18\x02 \x03(\x01\x12\x10\n\x08\x61vgpower\x18\x03 \x01(\x01\x32w\n\x07Metrics\x12l\n\x0b\x43\x61lcMetrics\x12-.rowing_workout_metrics.WorkoutMetricsRequest\x1a..rowing_workout_metrics.WorkoutMetricsResponse2T\n\x02\x43P\x12N\n\x05GetCP\x12!.rowing_workout_metrics.CPRequest\x1a\".rowing_workout_metrics.CPResponseB\x1aZ\x18./rowing-workout-metricsb\x06proto3')
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(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\"=\n\tCPRequest\x12\x10\n\x08\x66ilename\x18\x01 \x01(\t\x12\x10\n\x08\x66iletype\x18\x02 \x01(\t\x12\x0c\n\x04tarr\x18\x03 \x03(\x01\"<\n\nCPResponse\x12\r\n\x05\x64\x65lta\x18\x01 \x03(\x01\x12\r\n\x05power\x18\x02 \x03(\x01\x12\x10\n\x08\x61vgpower\x18\x03 \x01(\x01\x32\xc7\x01\n\x07Metrics\x12l\n\x0b\x43\x61lcMetrics\x12-.rowing_workout_metrics.WorkoutMetricsRequest\x1a..rowing_workout_metrics.WorkoutMetricsResponse\x12N\n\x05GetCP\x12!.rowing_workout_metrics.CPRequest\x1a\".rowing_workout_metrics.CPResponseB\x1aZ\x18./rowing-workout-metricsb\x06proto3')
_globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
@@ -30,8 +30,6 @@ if _descriptor._USE_C_DESCRIPTORS == False:
_globals['_CPREQUEST']._serialized_end=345
_globals['_CPRESPONSE']._serialized_start=347
_globals['_CPRESPONSE']._serialized_end=407
_globals['_METRICS']._serialized_start=409
_globals['_METRICS']._serialized_end=528
_globals['_CP']._serialized_start=530
_globals['_CP']._serialized_end=614
_globals['_METRICS']._serialized_start=410
_globals['_METRICS']._serialized_end=609
# @@protoc_insertion_point(module_scope)

View File

@@ -20,6 +20,11 @@ class MetricsStub(object):
request_serializer=rowing__workout__metrics__pb2.WorkoutMetricsRequest.SerializeToString,
response_deserializer=rowing__workout__metrics__pb2.WorkoutMetricsResponse.FromString,
)
self.GetCP = channel.unary_unary(
'/rowing_workout_metrics.Metrics/GetCP',
request_serializer=rowing__workout__metrics__pb2.CPRequest.SerializeToString,
response_deserializer=rowing__workout__metrics__pb2.CPResponse.FromString,
)
class MetricsServicer(object):
@@ -32,6 +37,12 @@ class MetricsServicer(object):
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def GetCP(self, request, context):
"""Missing associated documentation comment in .proto file."""
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 = {
@@ -40,6 +51,11 @@ def add_MetricsServicer_to_server(servicer, server):
request_deserializer=rowing__workout__metrics__pb2.WorkoutMetricsRequest.FromString,
response_serializer=rowing__workout__metrics__pb2.WorkoutMetricsResponse.SerializeToString,
),
'GetCP': grpc.unary_unary_rpc_method_handler(
servicer.GetCP,
request_deserializer=rowing__workout__metrics__pb2.CPRequest.FromString,
response_serializer=rowing__workout__metrics__pb2.CPResponse.SerializeToString,
),
}
generic_handler = grpc.method_handlers_generic_handler(
'rowing_workout_metrics.Metrics', rpc_method_handlers)
@@ -68,53 +84,6 @@ class Metrics(object):
options, channel_credentials,
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
class CPStub(object):
"""GetCP service definition
"""
def __init__(self, channel):
"""Constructor.
Args:
channel: A grpc.Channel.
"""
self.GetCP = channel.unary_unary(
'/rowing_workout_metrics.CP/GetCP',
request_serializer=rowing__workout__metrics__pb2.CPRequest.SerializeToString,
response_deserializer=rowing__workout__metrics__pb2.CPResponse.FromString,
)
class CPServicer(object):
"""GetCP service definition
"""
def GetCP(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def add_CPServicer_to_server(servicer, server):
rpc_method_handlers = {
'GetCP': grpc.unary_unary_rpc_method_handler(
servicer.GetCP,
request_deserializer=rowing__workout__metrics__pb2.CPRequest.FromString,
response_serializer=rowing__workout__metrics__pb2.CPResponse.SerializeToString,
),
}
generic_handler = grpc.method_handlers_generic_handler(
'rowing_workout_metrics.CP', rpc_method_handlers)
server.add_generic_rpc_handlers((generic_handler,))
# This class is part of an EXPERIMENTAL API.
class CP(object):
"""GetCP service definition
"""
@staticmethod
def GetCP(request,
target,
@@ -126,7 +95,7 @@ class CP(object):
wait_for_ready=None,
timeout=None,
metadata=None):
return grpc.experimental.unary_unary(request, target, '/rowing_workout_metrics.CP/GetCP',
return grpc.experimental.unary_unary(request, target, '/rowing_workout_metrics.Metrics/GetCP',
rowing__workout__metrics__pb2.CPRequest.SerializeToString,
rowing__workout__metrics__pb2.CPResponse.FromString,
options, channel_credentials,

Binary file not shown.

View File

@@ -347,9 +347,9 @@ def isbreakthrough(delta, cpvalues, p0, p1, p2, p3, ratio):
pwr *= ratio
delta = delta.values.astype(int)
cpvalues = cpvalues.values.astype(int)
pwr = pwr.astype(int)
delta = delta.astype(int, errors='ignore').values
cpvalues = cpvalues.astype(int, errors='ignore').values
pwr = pwr.astype(int, errors='ignore').values
res = np.sum(cpvalues > pwr+1)
res2 = np.sum(cpvalues > pwr2+1)