Private
Public Access
1
0

Merge branch 'release/v6.36'

This commit is contained in:
Sander Roosendaal
2018-04-02 09:36:45 +02:00
21 changed files with 92 additions and 56 deletions
+5 -4
View File
@@ -1586,9 +1586,9 @@ def rdata(file, rower=rrower()):
try: try:
res = rrdata(csvfile=file + '.gz', rower=rower) res = rrdata(csvfile=file + '.gz', rower=rower)
except IOError, IndexError: except IOError, IndexError:
res = 0 res = rrdata()
except: except:
res = 0 res = rrdata()
return res return res
@@ -1637,7 +1637,7 @@ def getrowdata_db(id=0, doclean=False, convertnewtons=True):
if data.empty: if data.empty:
rowdata, row = getrowdata(id=id) rowdata, row = getrowdata(id=id)
if rowdata: if not rowdata.empty:
data = dataprep(rowdata.df, id=id, bands=True, data = dataprep(rowdata.df, id=id, bands=True,
barchart=True, otwpower=True) barchart=True, otwpower=True)
else: else:
@@ -1645,7 +1645,8 @@ def getrowdata_db(id=0, doclean=False, convertnewtons=True):
else: else:
row = Workout.objects.get(id=id) row = Workout.objects.get(id=id)
if data['efficiency'].mean() == 0 and data['power'].mean() != 0:
if not data.empty and data['efficiency'].mean() == 0 and data['power'].mean() != 0:
data = add_efficiency(id=id) data = add_efficiency(id=id)
if doclean: if doclean:
+18 -18
View File
@@ -42,8 +42,8 @@ def add_workouts_plannedsession(ws,ps,r):
errors.append('For tests, you can only attach one workout') errors.append('For tests, you can only attach one workout')
return result,comments,errors return result,comments,errors
wold = Workout.objects.filter(plannedsession=ps,user=r) wold = Workout.objects.filter(plannedsession=ps,user=r)
ids = [w.id for w in wold] + [w.id for w in ws] ids = [w.id for w in wold] + [w.id for w in ws]
ids = list(set(ids)) ids = list(set(ids))
@@ -51,7 +51,7 @@ def add_workouts_plannedsession(ws,ps,r):
if len(ids)>1 and ps.sessiontype in ['test','coursetest']: if len(ids)>1 and ps.sessiontype in ['test','coursetest']:
errors.append('For tests, you can only attach one workout') errors.append('For tests, you can only attach one workout')
return result,comments,errors return result,comments,errors
# start adding sessions # start adding sessions
for w in ws: for w in ws:
if w.date>=ps.startdate and w.date<=ps.enddate: if w.date>=ps.startdate and w.date<=ps.enddate:
@@ -63,7 +63,7 @@ def add_workouts_plannedsession(ws,ps,r):
errors.append('Workout %i did not match session dates' % w.id) errors.append('Workout %i did not match session dates' % w.id)
return result,comments,errors return result,comments,errors
def remove_workout_plannedsession(w,ps): def remove_workout_plannedsession(w,ps):
if w.plannedsession == ps: if w.plannedsession == ps:
@@ -98,7 +98,7 @@ def get_session_metrics(ps):
status = [] status = []
for r in rowers: for r in rowers:
rscorev = 0 rscorev = 0
trimpv = 0 trimpv = 0
durationv = 0 durationv = 0
distancev = 0 distancev = 0
@@ -113,7 +113,7 @@ def get_session_metrics(ps):
durationv += timefield_to_seconds_duration(w.duration) durationv += timefield_to_seconds_duration(w.duration)
trimpv += dataprep.workout_trimp(w) trimpv += dataprep.workout_trimp(w)
rscorev += dataprep.workout_rscore(w)[0] rscorev += dataprep.workout_rscore(w)[0]
ratio,statusv,completiondate = is_session_complete_ws(ws,ps) ratio,statusv,completiondate = is_session_complete_ws(ws,ps)
try: try:
completedatev = completiondate.strftime('%Y-%m-%d') completedatev = completiondate.strftime('%Y-%m-%d')
@@ -139,7 +139,7 @@ def get_session_metrics(ps):
'rscore':rscore, 'rscore':rscore,
'trimp':trimp, 'trimp':trimp,
'completedate':completedate, 'completedate':completedate,
'status':status, 'status':status,
} }
return thedict return thedict
@@ -154,7 +154,7 @@ def is_session_complete_ws(ws,ps):
return ratio,status,None return ratio,status,None
else: else:
return 0,'not done',None return 0,'not done',None
value = ps.sessionvalue value = ps.sessionvalue
if ps.sessionunit == 'min': if ps.sessionunit == 'min':
value *= 60. value *= 60.
@@ -171,7 +171,7 @@ def is_session_complete_ws(ws,ps):
cratiomin = 0.9167 cratiomin = 0.9167
cratiomax = 1.0833 cratiomax = 1.0833
score = 0 score = 0
completiondate = None completiondate = None
for w in ws: for w in ws:
@@ -236,7 +236,7 @@ def is_session_complete_ws(ws,ps):
else: else:
if not completiondate: if not completiondate:
completiondate = ws.reverse()[0].date completiondate = ws.reverse()[0].date
return ratio,'partial',completiondate return ratio,'partial',completiondate
elif ps.sessiontype == 'coursetest': elif ps.sessiontype == 'coursetest':
if ps.course: if ps.course:
( (
@@ -274,19 +274,19 @@ def is_session_complete_ws(ws,ps):
if not completiondate: if not completiondate:
completiondate = ws.reverse()[0].date completiondate = ws.reverse()[0].date
return ratio,status,completiondate return ratio,status,completiondate
def is_session_complete(r,ps): def is_session_complete(r,ps):
status = 'not done' status = 'not done'
if r not in ps.rower.all(): if r not in ps.rower.all():
return 0,'not assigned',None return 0,'not assigned',None
ws = Workout.objects.filter(user=r,plannedsession=ps) ws = Workout.objects.filter(user=r,plannedsession=ps)
return is_session_complete_ws(ws,ps) return is_session_complete_ws(ws,ps)
def rank_results(ps): def rank_results(ps):
return 1 return 1
@@ -299,7 +299,7 @@ def add_team_session(t,ps):
def add_rower_session(r,ps): def add_rower_session(r,ps):
ps.rower.add(r) ps.rower.add(r)
ps.save() ps.save()
return 1 return 1
def remove_team_session(t,ps): def remove_team_session(t,ps):
@@ -377,9 +377,9 @@ def get_sessions_manager(m,teamid=0,startdate=date.today(),
startdate__lte=enddate, startdate__lte=enddate,
enddate__gte=startdate, enddate__gte=startdate,
).order_by("preferreddate","startdate","enddate") ).order_by("preferreddate","startdate","enddate")
return sps return sps
def get_sessions(r,startdate=date.today(), def get_sessions(r,startdate=date.today(),
enddate=date.today()+timezone.timedelta(+1000)): enddate=date.today()+timezone.timedelta(+1000)):
@@ -388,7 +388,7 @@ def get_sessions(r,startdate=date.today(),
startdate__lte=enddate, startdate__lte=enddate,
enddate__gte=startdate, enddate__gte=startdate,
).order_by("preferreddate","startdate","enddate") ).order_by("preferreddate","startdate","enddate")
return sps return sps
def get_workouts_session(r,ps): def get_workouts_session(r,ps):
+22 -1
View File
@@ -21,6 +21,7 @@ class RowerSerializer(serializers.HyperlinkedModelSerializer):
'tr', 'tr',
'an', 'an',
'ftp', 'ftp',
'sex',
) )
class FavoriteChartSerializer(serializers.ModelSerializer): class FavoriteChartSerializer(serializers.ModelSerializer):
@@ -52,6 +53,13 @@ class WorkoutSerializer(serializers.ModelSerializer):
'maxhr', 'maxhr',
'notes', 'notes',
'summary', 'summary',
'boattype',
'timezone',
'forceunit',
'inboard',
'oarlength',
'privacy',
'rankingpiece'
) )
def create(self, validated_data): def create(self, validated_data):
@@ -78,7 +86,13 @@ class WorkoutSerializer(serializers.ModelSerializer):
summary=validated_data['summary'], summary=validated_data['summary'],
averagehr=validated_data['averagehr'], averagehr=validated_data['averagehr'],
maxhr=validated_data['maxhr'], maxhr=validated_data['maxhr'],
startdatetime=rowdatetime) startdatetime=rowdatetime,
timezone=validated_data['timezone'],
forceunit=validated_data['forceunit'],
inboard=validated_data['inboard'],
oarlength=validated_data['oarlength'],
privacy=validated_data['privacy'],
rankingpiece=validated_data['rankingpiece'],)
w.save() w.save()
return w return w
@@ -104,6 +118,13 @@ class WorkoutSerializer(serializers.ModelSerializer):
instance.averagehr=validated_data['averagehr'] instance.averagehr=validated_data['averagehr']
instance.maxhr=validated_data['maxhr'] instance.maxhr=validated_data['maxhr']
instance.startdatetime=rowdatetime instance.startdatetime=rowdatetime
instance.timezone=validated_data['timezone']
instance.forceunit=validated_data['forceunit']
instance.inboard=validated_data['inboard']
instance.oarlength=validated_data['oarlength']
instance.privacy=validated_data['privacy']
instance.rankingpiece=validated_data['rankingpiece']
instance.save() instance.save()
return instance return instance
+1 -1
View File
@@ -92,7 +92,7 @@
{% if user.is_authenticated and user|is_manager %} {% if user.is_authenticated and user|is_manager %}
<div class="grid_2 alpha dropdown"> <div class="grid_2 alpha dropdown">
<button class="grid_2 alpha button green small dropbtn"> <button class="grid_2 alpha button green small dropbtn">
Change Rower {{ theuser.first_name }} {{ theuser.last_name }}
</button> </button>
<div class="dropdown-content"> <div class="dropdown-content">
{% for member in user|team_members %} {% for member in user|team_members %}
+1 -1
View File
@@ -90,7 +90,7 @@
{% if user.is_authenticated and user|is_manager %} {% if user.is_authenticated and user|is_manager %}
<div class="grid_2 alpha dropdown"> <div class="grid_2 alpha dropdown">
<button class="grid_2 alpha button green small dropbtn"> <button class="grid_2 alpha button green small dropbtn">
Change Rower {{ theuser.first_name }} {{ theuser.last_name }}
</button> </button>
<div class="dropdown-content"> <div class="dropdown-content">
{% for member in user|team_members %} {% for member in user|team_members %}
+10 -10
View File
@@ -132,17 +132,11 @@
Developers of iOS or Android apps should contact me directly if Developers of iOS or Android apps should contact me directly if
this doesn't work for them. I can add exceptions.</p> this doesn't work for them. I can add exceptions.</p>
<p>The POST call must have content-type: <i>x-www-form-urlencoded</i>.
I set it this way to support the handy testing utility mentioned
belower. However,
I really would like to support <i>application/json</i> but with the
current framework I cannot support both at the same time. Expect
changes. Write to me if you want to be notified of changes.</p>
<ul> <ul>
<li>Authorization URL: <b>https://rowsandall.com/rowers/o/authorize</b></li> <li>Authorization URL: <b>https://{{ request.get_host }}/rowers/o/authorize</b></li>
<li>Access Token request: <b>https://rowsandall.com/rowers/o/token/</b></li> <li>Access Token request: <b>https://{{ request.get_host }}/rowers/o/token/</b></li>
<li>Access Token refresh: <b>https://rowsandall.com/rowers/o/token/</b></li> <li>Access Token refresh: <b>https://{{ request.get_host }}/rowers/o/token/</b></li>
<li>Handy utility for testing: <b><a href="http://django-oauth-toolkit.herokuapp.com/consumer/">http://django-oauth-toolkit.herokuapp.com/consumer/</a></b></li> <li>Handy utility for testing: <b><a href="http://django-oauth-toolkit.herokuapp.com/consumer/">http://django-oauth-toolkit.herokuapp.com/consumer/</a></b></li>
</ul> </ul>
@@ -169,7 +163,7 @@
posted to:</p> posted to:</p>
<ul> <ul>
<li><b>https://rowsandall.com/rowers/api/workouts/{id}/strokedata</b></li> <li><b>https://{{ request.get_host }}/rowers/api/workouts/{id}/strokedata</b></li>
</ul> </ul>
<p>The payload is application/json data and looks as follows:</p> <p>The payload is application/json data and looks as follows:</p>
@@ -203,6 +197,12 @@
<li><b>peakdriveforce</b>: Peak handle force (lbs)</li> <li><b>peakdriveforce</b>: Peak handle force (lbs)</li>
<li><b>lapidx</b>: Lap identifier</li> <li><b>lapidx</b>: Lap identifier</li>
<li><b>hr</b>: Heart rate (beats per minute)</li> <li><b>hr</b>: Heart rate (beats per minute)</li>
<li><b>wash</b>: Wash as defined per Empower oarlock (degrees)</li>
<li><b>catch</b>: Catch angle per Empower oarlock (degrees)</li>
<li><b>finish</b>: Finish angle per Empower oarlock (degrees)</li>
<li><b>peakforceangle</b>: Peak Force Angle per Empower oarlock (degrees)</li>
<li><b>slip</b>: Wash as defined per Empower oarlock (degrees)</li>
</ul> </ul>
<p>Consistency checks will be done and the stroke data will be <p>Consistency checks will be done and the stroke data will be
+1 -1
View File
@@ -88,7 +88,7 @@
{% if user.is_authenticated and user|is_manager %} {% if user.is_authenticated and user|is_manager %}
<div class="grid_2 alpha dropdown"> <div class="grid_2 alpha dropdown">
<button class="grid_2 alpha button green small dropbtn"> <button class="grid_2 alpha button green small dropbtn">
Change Rower {{ theuser.first_name }} {{ theuser.last_name }}
</button> </button>
<div class="dropdown-content"> <div class="dropdown-content">
{% for member in user|team_members %} {% for member in user|team_members %}
+1 -1
View File
@@ -69,7 +69,7 @@
{% if user.is_authenticated and user|is_manager %} {% if user.is_authenticated and user|is_manager %}
<div class="grid_2 omega dropdown"> <div class="grid_2 omega dropdown">
<button class="grid_2 alpha button green small dropbtn"> <button class="grid_2 alpha button green small dropbtn">
Change Rower {{ rower.user.first_name }} {{ rower.user.last_name }}
</button> </button>
<div class="dropdown-content"> <div class="dropdown-content">
{% for member in user|team_members %} {% for member in user|team_members %}
+1 -1
View File
@@ -50,7 +50,7 @@
{% if user.is_authenticated and user|is_manager %} {% if user.is_authenticated and user|is_manager %}
<div class="grid_2 alpha dropdown"> <div class="grid_2 alpha dropdown">
<button class="grid_2 alpha button green small dropbtn"> <button class="grid_2 alpha button green small dropbtn">
Change Rower {{ theuser.first_name }} {{ theuser.last_name }}
</button> </button>
<div class="dropdown-content"> <div class="dropdown-content">
{% for member in user|team_members %} {% for member in user|team_members %}
+1 -1
View File
@@ -50,7 +50,7 @@
{% if user.is_authenticated and user|is_manager %} {% if user.is_authenticated and user|is_manager %}
<div class="grid_2 alpha dropdown"> <div class="grid_2 alpha dropdown">
<button class="grid_2 alpha button green small dropbtn"> <button class="grid_2 alpha button green small dropbtn">
Change Rower {{ theuser.first_name }} {{ theuser.last_name }}
</button> </button>
<div class="dropdown-content"> <div class="dropdown-content">
{% for member in user|team_members %} {% for member in user|team_members %}
@@ -49,7 +49,7 @@
{% if user.is_authenticated and user|is_manager %} {% if user.is_authenticated and user|is_manager %}
<div class="grid_2 dropdown"> <div class="grid_2 dropdown">
<button class="grid_2 alpha button green small dropbtn"> <button class="grid_2 alpha button green small dropbtn">
Change Rower {{ rower.user.first_name }} {{ rower.user.last_name }}
</button> </button>
<div class="dropdown-content"> <div class="dropdown-content">
{% for member in user|team_rowers %} {% for member in user|team_rowers %}
+1 -1
View File
@@ -49,7 +49,7 @@
{% if user.is_authenticated and user|is_manager %} {% if user.is_authenticated and user|is_manager %}
<div class="grid_2 dropdown"> <div class="grid_2 dropdown">
<button class="grid_2 alpha button green small dropbtn"> <button class="grid_2 alpha button green small dropbtn">
Change Rower {{ rower.user.first_name }} {{ rower.user.last_name }}
</button> </button>
<div class="dropdown-content"> <div class="dropdown-content">
{% for member in user|team_rowers %} {% for member in user|team_rowers %}
+1 -1
View File
@@ -47,7 +47,7 @@
{% if user.is_authenticated and user|is_manager %} {% if user.is_authenticated and user|is_manager %}
<div class="grid_2 dropdown"> <div class="grid_2 dropdown">
<button class="grid_2 alpha button green small dropbtn"> <button class="grid_2 alpha button green small dropbtn">
Change Rower {{ rower.user.first_name }} {{ rower.user.last_name }}
</button> </button>
<div class="dropdown-content"> <div class="dropdown-content">
{% for member in user|team_rowers %} {% for member in user|team_rowers %}
+1 -1
View File
@@ -50,7 +50,7 @@
{% if user.is_authenticated and user|is_manager %} {% if user.is_authenticated and user|is_manager %}
<div class="grid_2 dropdown"> <div class="grid_2 dropdown">
<button class="grid_2 alpha button green small dropbtn"> <button class="grid_2 alpha button green small dropbtn">
Change Rower {{ rower.user.first_name }} {{ rower.user.last_name }}
</button> </button>
<div class="dropdown-content"> <div class="dropdown-content">
{% for member in user|team_rowers %} {% for member in user|team_rowers %}
+1 -1
View File
@@ -61,7 +61,7 @@
{% if user.is_authenticated and user|is_manager %} {% if user.is_authenticated and user|is_manager %}
<div class="grid_2 dropdown"> <div class="grid_2 dropdown">
<button class="grid_2 alpha button green small dropbtn"> <button class="grid_2 alpha button green small dropbtn">
Change Rower {{ rower.user.first_name }} {{ rower.user.last_name }}
</button> </button>
<div class="dropdown-content"> <div class="dropdown-content">
{% for member in user|team_rowers %} {% for member in user|team_rowers %}
+1 -1
View File
@@ -53,7 +53,7 @@
{% if user.is_authenticated and user|is_manager %} {% if user.is_authenticated and user|is_manager %}
<div class="grid_2 alpha dropdown"> <div class="grid_2 alpha dropdown">
<button class="grid_2 alpha button green small dropbtn"> <button class="grid_2 alpha button green small dropbtn">
Change Rower {{ theuser.first_name }} {{ theuser.last_name }}
</button> </button>
<div class="dropdown-content"> <div class="dropdown-content">
{% for member in user|team_members %} {% for member in user|team_members %}
+1 -1
View File
@@ -12,7 +12,7 @@
</div> </div>
<div class="grid_2 suffix_2 omega dropdown"> <div class="grid_2 suffix_2 omega dropdown">
<button class="grid_2 alpha button green small dropbtn"> <button class="grid_2 alpha button green small dropbtn">
Change Rower {{ rower.user.first_name }} {{ rower.user.last_name }}
</button> </button>
<div class="dropdown-content"> <div class="dropdown-content">
{% for rower in user|team_rowers %} {% for rower in user|team_rowers %}
+1 -3
View File
@@ -1,7 +1,5 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block title %}Change Rower {% endblock %}
{% block content %} {% block content %}
{% if form.errors %} {% if form.errors %}
<p style="color: red;"> <p style="color: red;">
@@ -11,7 +9,7 @@
<div class="grid_12 alpha"> <div class="grid_12 alpha">
<h1>Stroke Data for workout {{ id }}</h1> <h1>Stroke Data for workout {{ id }}</h1>
<form enctype="multipart/form-data" action="/rowers/api/workouts/{{ id }}/strokedata" method="post"> <form enctype="application/json" action="/rowers/api/workouts/{{ id }}/strokedata" method="post">
<table> <table>
{{ form.as_table }} {{ form.as_table }}
</table> </table>
+1 -1
View File
@@ -81,7 +81,7 @@
{% if user.is_authenticated and user|is_manager %} {% if user.is_authenticated and user|is_manager %}
<div class="grid_2 alpha dropdown"> <div class="grid_2 alpha dropdown">
<button class="grid_2 alpha button green small dropbtn"> <button class="grid_2 alpha button green small dropbtn">
Change Rower {{ theuser.first_name }} {{ theuser.last_name }}
</button> </button>
<div class="dropdown-content"> <div class="dropdown-content">
{% for member in user|team_members %} {% for member in user|team_members %}
+1 -1
View File
@@ -81,7 +81,7 @@
{% if user.is_authenticated and user|is_manager %} {% if user.is_authenticated and user|is_manager %}
<div class="grid_2 alpha dropdown"> <div class="grid_2 alpha dropdown">
<button class="grid_2 alpha button green small dropbtn"> <button class="grid_2 alpha button green small dropbtn">
Change Rower {{ theuser.first_name }} {{ theuser.last_name }}
</button> </button>
<div class="dropdown-content"> <div class="dropdown-content">
{% for member in user|team_members %} {% for member in user|team_members %}
+21 -5
View File
@@ -11480,7 +11480,10 @@ def strokedatajson(request,id):
df.index = df.index.astype(int) df.index = df.index.astype(int)
df.sort_index(inplace=True) df.sort_index(inplace=True)
# time, hr, pace, spm, power, drivelength, distance, drivespeed, dragfactor, strokerecoverytime, averagedriveforce, peakdriveforce, lapidx # time, hr, pace, spm, power, drivelength, distance, drivespeed, dragfactor, strokerecoverytime, averagedriveforce, peakdriveforce, lapidx
time = df['time']/1.e3 try:
time = df['time']/1.e3
except KeyError:
return HttpResponse("There must be time values",status=400)
aantal = len(time) aantal = len(time)
pace = df['pace']/1.e3 pace = df['pace']/1.e3
if len(pace) != aantal: if len(pace) != aantal:
@@ -11505,14 +11508,20 @@ def strokedatajson(request,id):
strokerecoverytime = trydf(df,aantal,'strokerecoverytime') strokerecoverytime = trydf(df,aantal,'strokerecoverytime')
averagedriveforce = trydf(df,aantal,'averagedriveforce') averagedriveforce = trydf(df,aantal,'averagedriveforce')
peakdriveforce = trydf(df,aantal,'peakdriveforce') peakdriveforce = trydf(df,aantal,'peakdriveforce')
wash = trydf(df,aantal,'wash')
catch = trydf(df,aantal,'catch')
finish = trydf(df,aantal,'finish')
peakforceangle = trydf(df,aantal,'peakforceangle')
driveenergy = trydf(df,aantal,'driveenergy')
slip = trydf(df,aantal,'slip')
lapidx = trydf(df,aantal,'lapidx') lapidx = trydf(df,aantal,'lapidx')
hr = trydf(df,aantal,'hr') hr = trydf(df,aantal,'hr')
starttime = totimestamp(row.startdatetime)+time starttime = totimestamp(row.startdatetime)+time[0]
unixtime = starttime+time unixtime = starttime+time
with open('media/apilog.log','a') as logfile: with open('media/apilog.log','a') as logfile:
logfile.write(starttime+": ") logfile.write(str(starttime)+": ")
logfile.write(request.user.username+"(POST) \r\n") logfile.write(request.user.username+"(POST) \r\n")
data = pd.DataFrame({'TimeStamp (sec)':unixtime, data = pd.DataFrame({'TimeStamp (sec)':unixtime,
@@ -11529,10 +11538,18 @@ def strokedatajson(request,id):
' PeakDriveForce (lbs)':peakdriveforce, ' PeakDriveForce (lbs)':peakdriveforce,
' lapIdx':lapidx, ' lapIdx':lapidx,
' ElapsedTime (sec)':time, ' ElapsedTime (sec)':time,
'catch':catch,
'slip':slip,
'finish':finish,
'wash':wash,
'driveenergy':driveenergy,
'peakforceangle':peakforceangle,
}) })
# Following part should be replaced with dataprep.new_workout_from_df # Following part should be replaced with dataprep.new_workout_from_df
r = getrower(request.user)
timestr = row.startdatetime.strftime("%Y%m%d-%H%M%S") timestr = row.startdatetime.strftime("%Y%m%d-%H%M%S")
csvfilename ='media/Import_'+timestr+'.csv' csvfilename ='media/Import_'+timestr+'.csv'
@@ -11541,7 +11558,6 @@ def strokedatajson(request,id):
row.csvfilename = csvfilename row.csvfilename = csvfilename
row.save() row.save()
r = getrower(request.user)
powerperc = 100*np.array([r.pw_ut2, powerperc = 100*np.array([r.pw_ut2,
r.pw_ut1, r.pw_ut1,
r.pw_at, r.pw_at,