rowingdata 3.6.8__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. rowingdata/__init__.py +2 -0
  2. rowingdata/__main__.py +2 -0
  3. rowingdata/boatedit.py +15 -0
  4. rowingdata/checkdatafiles.py +216 -0
  5. rowingdata/copystats.py +22 -0
  6. rowingdata/crewnerdplot.py +37 -0
  7. rowingdata/crewnerdplottime.py +37 -0
  8. rowingdata/csvparsers.py +3114 -0
  9. rowingdata/ergdataplot.py +31 -0
  10. rowingdata/ergdataplottime.py +31 -0
  11. rowingdata/ergdatatotcx.py +32 -0
  12. rowingdata/ergstickplot.py +31 -0
  13. rowingdata/ergstickplottime.py +32 -0
  14. rowingdata/ergsticktotcx.py +32 -0
  15. rowingdata/example.csv +5171 -0
  16. rowingdata/gpxtools.py +70 -0
  17. rowingdata/gpxwrite.py +151 -0
  18. rowingdata/konkatenaadje.py +19 -0
  19. rowingdata/laptesting.py +293 -0
  20. rowingdata/obsolete.py +654 -0
  21. rowingdata/otherparsers.py +718 -0
  22. rowingdata/painsled_desktop_plot.py +30 -0
  23. rowingdata/painsled_desktop_plottime.py +29 -0
  24. rowingdata/painsled_desktop_toc2.py +30 -0
  25. rowingdata/painsledplot.py +27 -0
  26. rowingdata/painsledplottime.py +27 -0
  27. rowingdata/painsledtoc2.py +23 -0
  28. rowingdata/roweredit.py +15 -0
  29. rowingdata/rowingdata.py +6941 -0
  30. rowingdata/rowproplot.py +31 -0
  31. rowingdata/rowproplottime.py +31 -0
  32. rowingdata/speedcoachplot.py +31 -0
  33. rowingdata/speedcoachplottime.py +31 -0
  34. rowingdata/speedcoachtoc2.py +36 -0
  35. rowingdata/tcxplot.py +38 -0
  36. rowingdata/tcxplot_nogeo.py +38 -0
  37. rowingdata/tcxplottime.py +33 -0
  38. rowingdata/tcxplottime_nogeo.py +33 -0
  39. rowingdata/tcxtoc2.py +30 -0
  40. rowingdata/tcxtools.py +417 -0
  41. rowingdata/trainingparser.py +302 -0
  42. rowingdata/utils.py +135 -0
  43. rowingdata/windcorrected.py +48 -0
  44. rowingdata/writetcx.py +312 -0
  45. rowingdata-3.6.8.dist-info/LICENSE +21 -0
  46. rowingdata-3.6.8.dist-info/METADATA +1149 -0
  47. rowingdata-3.6.8.dist-info/RECORD +49 -0
  48. rowingdata-3.6.8.dist-info/WHEEL +5 -0
  49. rowingdata-3.6.8.dist-info/top_level.txt +1 -0
rowingdata/obsolete.py ADDED
@@ -0,0 +1,654 @@
1
+ from six.moves import range
2
+ class OldTCXParser(object):
3
+ """ Parser for reading TCX files, e.g. from CrewNerd
4
+
5
+ Use: data = rowingdata.TCXParser("crewnerd_data.tcx")
6
+
7
+ data.write_csv("crewnerd_data_out.csv")
8
+
9
+ """
10
+
11
+
12
+ def __init__(self, tcx_file):
13
+ tree = objectify.parse(tcx_file)
14
+ self.root = tree.getroot()
15
+ self.data = DataFrame()
16
+ try:
17
+ self.activity = self.root.Activities.Activity
18
+ except AttributeError:
19
+ self.activity = self.root.Courses.Course.Track
20
+
21
+ # need to select only trackpoints with Cadence, Distance, Time & HR data
22
+ self.selectionstring = '//ns:Trackpoint[descendant::ns:HeartRateBpm]'
23
+ self.selectionstring += '[descendant::ns:Cadence]'
24
+ self.selectionstring += '[descendant::ns:DistanceMeters]'
25
+ self.selectionstring += '[descendant::ns:Time]'
26
+
27
+
28
+ hr_values = self.root.xpath(self.selectionstring
29
+ +'//ns:HeartRateBpm/ns:Value',
30
+ namespaces={'ns': NAMESPACE})
31
+
32
+
33
+
34
+ distance_values = self.root.xpath(self.selectionstring
35
+ +'/ns:DistanceMeters',
36
+ namespaces={'ns': NAMESPACE})
37
+
38
+ spm_values = self.root.xpath(self.selectionstring
39
+ +'/ns:Cadence',
40
+ namespaces={'ns': NAMESPACE})
41
+
42
+
43
+ # time stamps (ISO)
44
+ timestamps = self.root.xpath(self.selectionstring
45
+ +'/ns:Time',
46
+ namespaces={'ns': NAMESPACE})
47
+
48
+ lat_values = self.root.xpath(self.selectionstring
49
+ +'/ns:Position/ns:LatitudeDegrees',
50
+ namespaces={'ns':NAMESPACE})
51
+
52
+ long_values = self.root.xpath(self.selectionstring
53
+ +'/ns:Position/ns:LongitudeDegrees',
54
+ namespaces={'ns':NAMESPACE})
55
+
56
+ # Some TCX have no lat/lon
57
+ if not lat_values:
58
+ lat_values = list(0.0*np.array([int(spm) for spm in spm_values]))
59
+
60
+ if not long_values:
61
+ long_values = list(0.0*np.array([int(spm) for spm in spm_values]))
62
+
63
+ # and here are the trackpoints for "no stroke"
64
+ self.selectionstring2 = '//ns:Trackpoint[descendant::ns:HeartRateBpm]'
65
+ self.selectionstring2 += '[descendant::ns:DistanceMeters]'
66
+ self.selectionstring2 += '[descendant::ns:Time]'
67
+
68
+ hr_values2 = self.root.xpath(self.selectionstring2
69
+ +'//ns:HeartRateBpm/ns:Value',
70
+ namespaces={'ns': NAMESPACE})
71
+
72
+
73
+
74
+ distance_values2 = self.root.xpath(self.selectionstring2
75
+ +'/ns:DistanceMeters',
76
+ namespaces={'ns': NAMESPACE})
77
+
78
+ spm_values2 = np.zeros(len(distance_values2)).tolist()
79
+
80
+
81
+ # time stamps (ISO)
82
+ timestamps2 = self.root.xpath(self.selectionstring2
83
+ +'/ns:Time',
84
+ namespaces={'ns': NAMESPACE})
85
+
86
+ lat_values2 = self.root.xpath(self.selectionstring2
87
+ +'/ns:Position/ns:LatitudeDegrees',
88
+ namespaces={'ns':NAMESPACE})
89
+
90
+ long_values2 = self.root.xpath(self.selectionstring2
91
+ +'/ns:Position/ns:LongitudeDegrees',
92
+ namespaces={'ns':NAMESPACE})
93
+
94
+ # Some TCX have no lat/lon
95
+ if not lat_values2:
96
+ lat_values2 = list(0.0*np.array([int(spm) for spm in spm_values2]))
97
+
98
+ if not long_values2:
99
+ long_values2 = list(0.0*np.array([int(spm) for spm in spm_values2]))
100
+
101
+ # merge the two datasets
102
+
103
+ timestamps = timestamps+timestamps2
104
+
105
+ self.hr_values = hr_values+hr_values2
106
+ self.distance_values = distance_values+distance_values2
107
+
108
+ self.spm_values = spm_values+spm_values2
109
+
110
+ self.long_values = long_values+long_values2
111
+ self.lat_values = lat_values+lat_values2
112
+
113
+
114
+ # sort the two datasets
115
+ try:
116
+ data = pd.DataFrame({
117
+ 't':timestamps,
118
+ 'hr':self.hr_values,
119
+ 'd':self.distance_values,
120
+ 'spm':self.spm_values,
121
+ 'long':self.long_values,
122
+ 'lat':self.lat_values
123
+ })
124
+ except ValueError:
125
+ try:
126
+ surro = 0*np.arange(len(timestamps))
127
+ data = pd.DataFrame({
128
+ 't':timestamps,
129
+ 'hr':self.hr_values,
130
+ 'd':self.distance_values,
131
+ 'spm':self.spm_values,
132
+ 'long': surro,
133
+ 'lat': surro
134
+ })
135
+ except ValueError:
136
+ data = pd.DataFrame({
137
+ 't':timestamps,
138
+ 'hr':self.hr_values,
139
+ 'd':self.distance_values,
140
+ 'spm':surro,
141
+ 'long': surro,
142
+ 'lat': surro,
143
+ })
144
+
145
+
146
+
147
+
148
+ data = data.drop_duplicates(subset='t')
149
+ data = data.sort_values(by='t', ascending=1)
150
+
151
+ timestamps = data.ix[:, 't'].values
152
+ self.hr_values = data.ix[:, 'hr'].values
153
+ self.distance_values = data.ix[:, 'd'].values
154
+ self.spm_values = data.ix[:, 'spm'].values
155
+ self.long_values = data.ix[:, 'long'].values
156
+ self.lat_values = data.ix[:, 'lat'].values
157
+
158
+
159
+ # convert to unix style time stamp
160
+ unixtimes = np.array([])
161
+
162
+ # Activity ID timestamp (start)
163
+ try:
164
+ iso_string = str(self.root.Activities.Activity.Id)
165
+ startdatetimeobj = iso8601.parse_date(iso_string)
166
+ starttime = arrow.get(startdatetimeobj).timestamp+startdatetimeobj.microsecond/1.e6
167
+ except AttributeError:
168
+ startdatetimeobj = iso8601.parse_date(str(timestamps[0]))
169
+ starttime = arrow.get(startdatetimeobj).timestamp+startdatetimeobj.microsecond/1.e6
170
+
171
+ self.activity_starttime = starttime
172
+
173
+ # there may be a more elegant and faster way with arrays
174
+ # for i in range(len(timestamps)):
175
+ for time_string in timestamps:
176
+ # time_string = str(timestamps[i])
177
+ time_parsed = iso8601.parse_date(str(time_string))
178
+ unixtimes = np.append(unixtimes,arrow.get(time_parsed).timestamp+time_parsed.microsecond/1.e6)
179
+
180
+ self.time_values = unixtimes
181
+
182
+ longitude = self.long_values
183
+ lat = self.lat_values
184
+ spm = self.spm_values
185
+
186
+ nr_rows = len(lat)
187
+ velo = np.zeros(nr_rows)
188
+ dist2 = np.zeros(nr_rows)
189
+ strokelength = np.zeros(nr_rows)
190
+
191
+ for i in range(nr_rows-1):
192
+ res = geo_distance(lat[i], longitude[i], lat[i+1], longitude[i+1])
193
+ deltal = 1000.*res[0]
194
+ dist2[i+1] = dist2[i]+deltal
195
+ velo[i+1] = deltal/(1.0*(unixtimes[i+1]-unixtimes[i]))
196
+ if spm[i] != 0:
197
+ strokelength[i] = deltal*60/spm[i]
198
+ else:
199
+ strokelength[i] = 0.
200
+
201
+
202
+ self.strokelength = strokelength
203
+ self.dist2 = dist2
204
+ self.velo = velo
205
+
206
+ def write_csv(self, writefile='example.csv', window_size=5, gzip=False):
207
+ # determine if geo data
208
+ lat = pd.Series(self.lat_values)
209
+ lon = pd.Series(self.long_values)
210
+
211
+ if lat.std() or lon.std():
212
+ self.write_geo_csv(writefile=writefile,
213
+ window_size=window_size,
214
+ gzip=gzip)
215
+ else:
216
+ self.write_nogeo_csv(writefile=writefile,
217
+ window_size=window_size,
218
+ gzip=gzip)
219
+
220
+
221
+
222
+ def write_geo_csv(self, writefile='example.csv', window_size=5, gzip=False):
223
+ """ Exports TCX data to the CSV format that
224
+ I use in rowingdata
225
+ """
226
+
227
+ # Time stamps
228
+ unixtimes = self.time_values
229
+
230
+ # Stroke Rate
231
+ spm = self.spm_values
232
+
233
+ # Heart Rate
234
+ heartrate = self.hr_values
235
+
236
+ longitude = self.long_values
237
+ lat = self.lat_values
238
+
239
+ nr_rows = len(spm)
240
+ velo = np.zeros(nr_rows)
241
+ dist2 = np.zeros(nr_rows)
242
+ strokelength = np.zeros(nr_rows)
243
+
244
+ velo = self.velo
245
+ strokelength = self.strokelength
246
+ dist2 = self.dist2
247
+
248
+ velo2 = ewmovingaverage(velo, window_size)
249
+ strokelength2 = ewmovingaverage(strokelength, window_size)
250
+
251
+ pace = 500./velo2
252
+ pace = np.clip(pace, 0, 1e4)
253
+
254
+
255
+ # Create data frame with all necessary data to write to csv
256
+ data = DataFrame({
257
+ 'TimeStamp (sec)':unixtimes,
258
+ ' Horizontal (meters)': dist2,
259
+ ' Cadence (stokes/min)':spm,
260
+ ' HRCur (bpm)':heartrate,
261
+ ' longitude':longitude,
262
+ ' latitude':lat,
263
+ ' Stroke500mPace (sec/500m)':pace,
264
+ ' Power (watts)':np.zeros(nr_rows),
265
+ ' DriveLength (meters)':np.zeros(nr_rows),
266
+ ' StrokeDistance (meters)':strokelength2,
267
+ ' DragFactor':np.zeros(nr_rows),
268
+ ' DriveTime (ms)':np.zeros(nr_rows),
269
+ ' StrokeRecoveryTime (ms)':np.zeros(nr_rows),
270
+ ' AverageDriveForce (lbs)':np.zeros(nr_rows),
271
+ ' PeakDriveForce (lbs)':np.zeros(nr_rows),
272
+ ' lapIdx':np.zeros(nr_rows),
273
+ ' ElapsedTime (sec)':unixtimes-self.activity_starttime
274
+ })
275
+
276
+
277
+ self.data = data
278
+
279
+ if gzip:
280
+ return data.to_csv(writefile+'.gz', index_label='index',
281
+ compression='gzip')
282
+ else:
283
+ return data.to_csv(writefile, index_label='index')
284
+
285
+
286
+
287
+ def write_nogeo_csv(self, writefile='example.csv', window_size=5, gzip=False):
288
+ """ Exports TCX data without position data (indoor)
289
+ to the CSV format that
290
+ I use in rowingdata
291
+ """
292
+
293
+ # Time stamps
294
+ unixtimes = self.time_values
295
+
296
+ # Distance
297
+ distance = self.distance_values
298
+
299
+ # Stroke Rate
300
+ spm = self.spm_values
301
+
302
+ # Heart Rate
303
+ heartrate = self.hr_values
304
+
305
+
306
+ nr_rows = len(spm)
307
+ velo = np.zeros(nr_rows)
308
+
309
+ strokelength = np.zeros(nr_rows)
310
+
311
+ for i in range(nr_rows-1):
312
+ deltal = distance[i+1]-distance[i]
313
+ if unixtimes[i+1] != unixtimes[i]:
314
+ velo[i+1] = deltal/(unixtimes[i+1]-unixtimes[i])
315
+ else:
316
+ velo[i+1] = 0
317
+
318
+ if spm[i] != 0:
319
+ strokelength[i] = deltal*60/spm[i]
320
+ else:
321
+ strokelength[i] = 0.
322
+
323
+
324
+ velo2 = ewmovingaverage(velo, window_size)
325
+ strokelength2 = ewmovingaverage(strokelength, window_size)
326
+ pace = 500./velo2
327
+
328
+
329
+
330
+ # Create data frame with all necessary data to write to csv
331
+ data = DataFrame({
332
+ 'TimeStamp (sec)':unixtimes,
333
+ ' Horizontal (meters)': distance,
334
+ ' Cadence (stokes/min)':spm,
335
+ ' HRCur (bpm)':heartrate,
336
+ ' Stroke500mPace (sec/500m)':pace,
337
+ ' Power (watts)':np.zeros(nr_rows),
338
+ ' DriveLength (meters)':np.zeros(nr_rows),
339
+ ' StrokeDistance (meters)':strokelength2,
340
+ ' DragFactor':np.zeros(nr_rows),
341
+ ' DriveTime (ms)':np.zeros(nr_rows),
342
+ ' StrokeRecoveryTime (ms)':np.zeros(nr_rows),
343
+ ' AverageDriveForce (lbs)':np.zeros(nr_rows),
344
+ ' PeakDriveForce (lbs)':np.zeros(nr_rows),
345
+ ' lapIdx':np.zeros(nr_rows),
346
+ ' ElapsedTime (sec)':unixtimes-self.activity_starttime
347
+ })
348
+
349
+ if gzip:
350
+ return data.to_csv(writefile+'.gz', index_label='index',
351
+ compression='gzip')
352
+ else:
353
+ return data.to_csv(writefile, index_label='index')
354
+
355
+
356
+
357
+ class TCXParserNoHR(object):
358
+ """ Parser for reading TCX files, e.g. from CrewNerd
359
+
360
+ Use: data = rowingdata.TCXParser("crewnerd_data.tcx")
361
+
362
+ data.write_csv("crewnerd_data_out.csv")
363
+
364
+ """
365
+
366
+
367
+ def __init__(self, tcx_file):
368
+ tree = objectify.parse(tcx_file)
369
+ self.root = tree.getroot()
370
+ self.activity = self.root.Activities.Activity
371
+ self.data = DataFrame()
372
+ # need to select only trackpoints with Cadence, Distance, Time & HR data
373
+ self.selectionstring = '//ns:Trackpoint[descendant::ns:Cadence]'
374
+ self.selectionstring += '[descendant::ns:DistanceMeters]'
375
+ self.selectionstring += '[descendant::ns:Time]'
376
+
377
+
378
+ distance_values = self.root.xpath(self.selectionstring
379
+ +'/ns:DistanceMeters',
380
+ namespaces={'ns': NAMESPACE})
381
+
382
+ spm_values = self.root.xpath(self.selectionstring
383
+ +'/ns:Cadence',
384
+ namespaces={'ns': NAMESPACE})
385
+
386
+
387
+ # time stamps (ISO)
388
+ timestamps = self.root.xpath(self.selectionstring
389
+ +'/ns:Time',
390
+ namespaces={'ns': NAMESPACE})
391
+
392
+ lat_values = self.root.xpath(self.selectionstring
393
+ +'/ns:Position/ns:LatitudeDegrees',
394
+ namespaces={'ns':NAMESPACE})
395
+
396
+ long_values = self.root.xpath(self.selectionstring
397
+ +'/ns:Position/ns:LongitudeDegrees',
398
+ namespaces={'ns':NAMESPACE})
399
+
400
+ # and here are the trackpoints for "no stroke"
401
+ self.selectionstring2 = '//ns:Trackpoint[descendant::ns:DistanceMeters]'
402
+ self.selectionstring2 += '[descendant::ns:Time]'
403
+
404
+
405
+ distance_values2 = self.root.xpath(self.selectionstring2
406
+ +'/ns:DistanceMeters',
407
+ namespaces={'ns': NAMESPACE})
408
+
409
+ spm_values2 = np.zeros(len(distance_values2)).tolist()
410
+
411
+
412
+ # time stamps (ISO)
413
+ timestamps2 = self.root.xpath(self.selectionstring2
414
+ +'/ns:Time',
415
+ namespaces={'ns': NAMESPACE})
416
+
417
+ lat_values2 = self.root.xpath(self.selectionstring2
418
+ +'/ns:Position/ns:LatitudeDegrees',
419
+ namespaces={'ns':NAMESPACE})
420
+
421
+ long_values2 = self.root.xpath(self.selectionstring2
422
+ +'/ns:Position/ns:LongitudeDegrees',
423
+ namespaces={'ns':NAMESPACE})
424
+
425
+ # merge the two datasets
426
+
427
+ timestamps = timestamps+timestamps2
428
+
429
+ self.distance_values = distance_values+distance_values2
430
+
431
+ self.spm_values = spm_values+spm_values2
432
+
433
+ self.long_values = long_values+long_values2
434
+ self.lat_values = lat_values+lat_values2
435
+
436
+ # correct lat, long if empty
437
+ if not len(self.lat_values):
438
+ self.lat_values = np.zeros(len(self.spm_values))
439
+ self.long_values = np.zeros(len(self.spm_values))
440
+
441
+
442
+ # sort the two datasets
443
+ data = pd.DataFrame({
444
+ 't':timestamps,
445
+ 'd':self.distance_values,
446
+ 'spm':self.spm_values,
447
+ 'long':self.long_values,
448
+ 'lat':self.lat_values
449
+ })
450
+
451
+ data = data.drop_duplicates(subset='t')
452
+ data = data.sort_values(by='t', ascending=1)
453
+
454
+ timestamps = data.ix[:, 't'].values
455
+ self.distance_values = data.ix[:, 'd'].values
456
+ self.spm_values = data.ix[:, 'spm'].values
457
+ self.long_values = data.ix[:, 'long'].values
458
+ self.lat_values = data.ix[:, 'lat'].values
459
+
460
+ # convert to unix style time stamp
461
+ unixtimes = np.array([])
462
+
463
+ # Activity ID timestamp (start)
464
+ iso_string = str(self.root.Activities.Activity.Id)
465
+ startdatetimeobj = iso8601.parse_date(iso_string)
466
+
467
+ starttime = arrow.get(startdatetimeobj).timestamp+startdatetimeobj.microsecond/1.e6
468
+
469
+ self.activity_starttime = starttime
470
+
471
+ # there may be a more elegant and faster way with arrays
472
+ # for i in range(len(timestamps)):
473
+ for time_string in timestamps:
474
+ # time_string = str(timestamps[i])
475
+ time_parsed = iso8601.parse_date(str(time_string))
476
+ unixtimes = np.append(unixtimes,
477
+ [arrow.get(time_parsed).timestamp+time_parsed.microsecond/1.0e6])
478
+
479
+ self.time_values = unixtimes
480
+
481
+ longitude = self.long_values
482
+ lat = self.lat_values
483
+ spm = self.spm_values
484
+
485
+ nr_rows = len(lat)
486
+ velo = np.zeros(nr_rows)
487
+ dist2 = np.zeros(nr_rows)
488
+ strokelength = np.zeros(nr_rows)
489
+
490
+ for i in range(nr_rows-1):
491
+ res = geo_distance(lat[i], longitude[i], lat[i+1], longitude[i+1])
492
+ deltal = 1000.*res[0]
493
+ dist2[i+1] = dist2[i]+deltal
494
+ velo[i+1] = deltal/(1.0*(unixtimes[i+1]-unixtimes[i]))
495
+ if spm[i] != 0:
496
+ strokelength[i] = deltal*60/spm[i]
497
+ else:
498
+ strokelength[i] = 0.
499
+
500
+
501
+ self.strokelength = strokelength
502
+ self.dist2 = dist2
503
+ self.velo = velo
504
+
505
+
506
+ def write_csv(self, writefile='example.csv', window_size=5, gzip=False):
507
+ # determine if geo data
508
+ lat = pd.Series(self.lat_values)
509
+ lon = pd.Series(self.long_values)
510
+
511
+ if lat.std() or lon.std():
512
+ self.write_geo_csv(writefile=writefile,
513
+ window_size=window_size,
514
+ gzip=gzip)
515
+ else:
516
+ self.write_nogeo_csv(writefile=writefile,
517
+ window_size=window_size,
518
+ gzip=gzip)
519
+
520
+
521
+ def write_geo_csv(self, writefile='example.csv', window_size=5, gzip=False):
522
+ """ Exports TCX data to the CSV format that
523
+ I use in rowingdata
524
+ """
525
+
526
+ # Time stamps
527
+ unixtimes = self.time_values
528
+
529
+
530
+ # Stroke Rate
531
+ spm = self.spm_values
532
+
533
+ # Heart Rate
534
+
535
+ longitude = self.long_values
536
+ lat = self.lat_values
537
+
538
+ nr_rows = len(spm)
539
+ velo = np.zeros(nr_rows)
540
+ dist2 = np.zeros(nr_rows)
541
+ strokelength = np.zeros(nr_rows)
542
+
543
+ velo = self.velo
544
+ strokelength = self.strokelength
545
+ dist2 = self.dist2
546
+
547
+ velo2 = ewmovingaverage(velo, window_size)
548
+ strokelength2 = ewmovingaverage(strokelength, window_size)
549
+
550
+ pace = 500./velo2
551
+ pace = np.clip(pace, 0, 1e4)
552
+
553
+
554
+
555
+ # Create data frame with all necessary data to write to csv
556
+ data = DataFrame({
557
+ 'TimeStamp (sec)':unixtimes,
558
+ ' Horizontal (meters)': dist2,
559
+ ' Cadence (stokes/min)':spm,
560
+ ' HRCur (bpm)':np.zeros(nr_rows),
561
+ ' longitude':longitude,
562
+ ' latitude':lat,
563
+ ' Stroke500mPace (sec/500m)':pace,
564
+ ' Power (watts)':np.zeros(nr_rows),
565
+ ' DriveLength (meters)':np.zeros(nr_rows),
566
+ ' StrokeDistance (meters)':strokelength2,
567
+ ' DragFactor':np.zeros(nr_rows),
568
+ ' DriveTime (ms)':np.zeros(nr_rows),
569
+ ' StrokeRecoveryTime (ms)':np.zeros(nr_rows),
570
+ ' AverageDriveForce (lbs)':np.zeros(nr_rows),
571
+ ' PeakDriveForce (lbs)':np.zeros(nr_rows),
572
+ ' lapIdx':np.zeros(nr_rows),
573
+ ' ElapsedTime (sec)':unixtimes-self.activity_starttime
574
+ })
575
+
576
+
577
+ self.data = data
578
+
579
+ if gzip:
580
+
581
+ return data.to_csv(writefile+'.gz', index_label='index',
582
+ compression='gzip')
583
+ else:
584
+ return data.to_csv(writefile, index_label='index')
585
+
586
+
587
+
588
+ def write_nogeo_csv(self, writefile='example.csv', window_size=5, gzip=False):
589
+ """ Exports TCX data without position data (indoor)
590
+ to the CSV format that
591
+ I use in rowingdata
592
+ """
593
+
594
+ # Time stamps
595
+ unixtimes = self.time_values
596
+
597
+
598
+ # Distance Meters
599
+ distance = self.distance_values
600
+
601
+ # Stroke Rate
602
+ spm = self.spm_values
603
+
604
+
605
+ nr_rows = len(spm)
606
+ velo = np.zeros(nr_rows)
607
+
608
+ strokelength = np.zeros(nr_rows)
609
+
610
+ for i in range(nr_rows-1):
611
+ deltal = distance[i+1]-distance[i]
612
+ if unixtimes[i+1] != unixtimes[i]:
613
+ velo[i+1] = deltal/(unixtimes[i+1]-unixtimes[i])
614
+ else:
615
+ velo[i+1] = 0
616
+
617
+ if spm[i] != 0:
618
+ strokelength[i] = deltal*60/spm[i]
619
+ else:
620
+ strokelength[i] = 0.
621
+
622
+
623
+ velo2 = ewmovingaverage(velo, window_size)
624
+ strokelength2 = ewmovingaverage(strokelength, window_size)
625
+ pace = 500./velo2
626
+
627
+
628
+
629
+ # Create data frame with all necessary data to write to csv
630
+ data = DataFrame({
631
+ 'TimeStamp (sec)':unixtimes,
632
+ ' Horizontal (meters)': distance,
633
+ ' Cadence (stokes/min)':spm,
634
+ ' HRCur (bpm)':np.zeros(nr_rows),
635
+ ' Stroke500mPace (sec/500m)':pace,
636
+ ' Power (watts)':np.zeros(nr_rows),
637
+ ' DriveLength (meters)':np.zeros(nr_rows),
638
+ ' StrokeDistance (meters)':strokelength2,
639
+ ' DragFactor':np.zeros(nr_rows),
640
+ ' DriveTime (ms)':np.zeros(nr_rows),
641
+ ' StrokeRecoveryTime (ms)':np.zeros(nr_rows),
642
+ ' AverageDriveForce (lbs)':np.zeros(nr_rows),
643
+ ' PeakDriveForce (lbs)':np.zeros(nr_rows),
644
+ ' lapIdx':np.zeros(nr_rows),
645
+ ' ElapsedTime (sec)':unixtimes-self.activity_starttime,
646
+ })
647
+
648
+ if gzip:
649
+ return data.to_csv(writefile+'.gz',
650
+ index_label='index',
651
+ compression='gzip')
652
+ else:
653
+ return data.to_csv(writefile, index_label='index')
654
+