rowingdata 3.7.3__tar.gz → 3.8.1__tar.gz
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.
- {rowingdata-3.7.3/rowingdata.egg-info → rowingdata-3.8.1}/PKG-INFO +71 -44
- {rowingdata-3.7.3 → rowingdata-3.8.1}/README.rst +70 -23
- rowingdata-3.8.1/rowingdata/data/fit_export_spec.json +88 -0
- rowingdata-3.8.1/rowingdata/fit_garmin_bridge.py +155 -0
- rowingdata-3.8.1/rowingdata/fit_transcode.py +127 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/rowingdata/fitwrite.py +513 -146
- rowingdata-3.8.1/rowingdata/fitwrite_spec.py +212 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/rowingdata/otherparsers.py +263 -8
- {rowingdata-3.7.3 → rowingdata-3.8.1}/rowingdata/rowingdata.py +43 -15
- {rowingdata-3.7.3 → rowingdata-3.8.1}/rowingdata/tcxtools.py +1 -1
- {rowingdata-3.7.3 → rowingdata-3.8.1/rowingdata.egg-info}/PKG-INFO +71 -44
- {rowingdata-3.7.3 → rowingdata-3.8.1}/rowingdata.egg-info/SOURCES.txt +7 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/setup.py +4 -1
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/testdatasummary.csv +3 -3
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/testtcx.tcx +1 -1
- rowingdata-3.8.1/tests/test_fit_instroke_export.py +462 -0
- rowingdata-3.8.1/tests/test_fit_standard.py +316 -0
- rowingdata-3.8.1/tests/test_fit_transcode.py +78 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/tests/test_rowingdata.py +211 -4
- {rowingdata-3.7.3 → rowingdata-3.8.1}/LICENSE +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/MANIFEST.in +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/bin/crewnerddata.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/bin/crewnerddata.tcx +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/bin/testdata.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/docs/_build/html/.buildinfo +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/docs/_build/html/_images/2x20min.png +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/docs/_build/html/_images/editrower.JPG +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/docs/_build/html/_images/greghoc.png +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/docs/_build/html/_images/image001.png +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/docs/_build/html/_images/otwlogbook.JPG +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/docs/_build/html/_images/otwscreenshot.JPG +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/docs/_build/html/_images/screenshot.JPG +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/docs/_build/html/_images/screenshotlogbook.JPG +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/docs/_build/html/_images/woensdag.png +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/docs/_build/html/_sources/index.txt +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/docs/_build/html/_sources/modules.txt +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/docs/_build/html/_sources/rowingdata.txt +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/docs/_build/html/_static/ajax-loader.gif +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/docs/_build/html/_static/alabaster.css +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/docs/_build/html/_static/basic.css +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/docs/_build/html/_static/comment-bright.png +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/docs/_build/html/_static/comment-close.png +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/docs/_build/html/_static/comment.png +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/docs/_build/html/_static/custom.css +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/docs/_build/html/_static/doctools.js +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/docs/_build/html/_static/down-pressed.png +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/docs/_build/html/_static/down.png +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/docs/_build/html/_static/file.png +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/docs/_build/html/_static/jquery-1.11.1.js +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/docs/_build/html/_static/jquery.js +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/docs/_build/html/_static/minus.png +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/docs/_build/html/_static/plus.png +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/docs/_build/html/_static/pygments.css +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/docs/_build/html/_static/searchtools.js +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/docs/_build/html/_static/underscore-1.3.1.js +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/docs/_build/html/_static/underscore.js +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/docs/_build/html/_static/up-pressed.png +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/docs/_build/html/_static/up.png +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/docs/_build/html/_static/websupport.js +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/docs/_build/html/genindex.html +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/docs/_build/html/index.html +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/docs/_build/html/modules.html +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/docs/_build/html/objects.inv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/docs/_build/html/py-modindex.html +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/docs/_build/html/rowingdata.html +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/docs/_build/html/search.html +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/docs/_build/html/searchindex.js +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/rowingdata/__init__.py +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/rowingdata/__main__.py +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/rowingdata/boatedit.py +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/rowingdata/checkdatafiles.py +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/rowingdata/copystats.py +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/rowingdata/crewnerdplot.py +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/rowingdata/crewnerdplottime.py +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/rowingdata/csvparsers.py +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/rowingdata/ergdataplot.py +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/rowingdata/ergdataplottime.py +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/rowingdata/ergdatatotcx.py +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/rowingdata/ergstickplot.py +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/rowingdata/ergstickplottime.py +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/rowingdata/ergsticktotcx.py +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/rowingdata/gpxtools.py +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/rowingdata/gpxwrite.py +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/rowingdata/konkatenaadje.py +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/rowingdata/laptesting.py +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/rowingdata/obsolete.py +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/rowingdata/painsled_desktop_plot.py +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/rowingdata/painsled_desktop_plottime.py +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/rowingdata/painsled_desktop_toc2.py +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/rowingdata/painsledplot.py +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/rowingdata/painsledplottime.py +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/rowingdata/painsledtoc2.py +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/rowingdata/roweredit.py +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/rowingdata/rowproplot.py +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/rowingdata/rowproplottime.py +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/rowingdata/speedcoachplot.py +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/rowingdata/speedcoachplottime.py +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/rowingdata/speedcoachtoc2.py +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/rowingdata/tcxplot.py +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/rowingdata/tcxplot_nogeo.py +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/rowingdata/tcxplottime.py +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/rowingdata/tcxplottime_nogeo.py +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/rowingdata/tcxtoc2.py +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/rowingdata/trainingparser.py +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/rowingdata/utils.py +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/rowingdata/windcorrected.py +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/rowingdata/writetcx.py +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/rowingdata.egg-info/dependency_links.txt +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/rowingdata.egg-info/not-zip-safe +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/rowingdata.egg-info/requires.txt +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/rowingdata.egg-info/top_level.txt +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/setup.cfg +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/2016-03-25-0758.CSV +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/2016-03-25-0758_data.CSV +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/2x20min_o.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/2x2km.tcx +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/3km_cd_o.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/3x250m.tcx +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/EUBoatCoach.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/EmpowerSpeedCoachForce.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/NKEmporfromgreg.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/NKLiNKv130.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/NoHR.tcx +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/PainsledForce.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/RP_interval.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/RP_interval.csv_o.CSV +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/RP_testdata.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/SpdCoach2_imp_inconsistent.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/SpdCoachAmbiguous.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/SpeedCoach GPS Workout.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/SpeedCoach2Link_interval.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/SpeedCoach2Linkv1.27.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/SpeedCoach2v2.12.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/Speedcoach2example.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/aritmo.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/bc1.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/bc2.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/bc3.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/boatcoach.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/boatcoach_fixed_distance.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/boatcoach_otw.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/correctedpainsled.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/cottwich.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/coxmate.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/crewnerd_interval.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/crewnerddata.CSV +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/crewnerddata.tcx +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/crewnerddata_o.CSV +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/cumvalues.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/ergdata_example.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/ergdata_example.csv_o.CSV +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/ergstick.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/ergstick.csv_o.CSV +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/ergstick2.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/ergstick_o.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/example.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/example_data.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/faketcx.tcx +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/float.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/herodata.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/humon.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/impeller_empower.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/invalidchar.tcx +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/kinomap.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/mystery.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/nk_logbook.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/painsled.tcx +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/painsled_desktop_example.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/painsled_out_data.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/painsled_to_csv_20160221-105218_erg-400150318_760465m.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/quiske_per_stroke_left.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/quiske_per_stroke_new.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/quiske_per_stroke_right.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/quiske_per_stroke_seat.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/recover.tcx +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/ritmointervals.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/rowingdata_eth.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/rowinginmotionexample.TCX +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/rowinginmotionexample.TCX_o.CSV +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/rowperfect.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/rowpro5.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/rowpro_carrick.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/rp3_curve.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/rp3intervals.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/rp3intervals2.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/rp_out.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/smartrow.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/smartrow_intervals.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/spdcoach2noheader.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/speedcoach2test2.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/speedcoach3test3.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/speedcoachexample.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/speedcoachexample.csv_o.CSV +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/strava_export.tcx +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/summarytest.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/testdata.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/testdata_part1.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/testdata_part2.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/testlapidx.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/testtcs_210614.tcx +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/testtcx_210614.tcx +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata/tim.csv +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/testdata//345/210/222/350/210/271.csv" +0 -0
- {rowingdata-3.7.3 → rowingdata-3.8.1}/tests/testparser.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: rowingdata
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.8.1
|
|
4
4
|
Summary: The rowingdata library to create colorful plots from CrewNerd, Painsled and other rowing data tools
|
|
5
5
|
Home-page: https://github.com/sanderroosendaal/rowingdata
|
|
6
6
|
Author: Sander Roosendaal
|
|
@@ -9,26 +9,6 @@ License: MIT
|
|
|
9
9
|
Keywords: rowing ergometer concept2
|
|
10
10
|
Classifier: Programming Language :: Python :: 3
|
|
11
11
|
License-File: LICENSE
|
|
12
|
-
Requires-Dist: Cython
|
|
13
|
-
Requires-Dist: numpy
|
|
14
|
-
Requires-Dist: scipy
|
|
15
|
-
Requires-Dist: matplotlib
|
|
16
|
-
Requires-Dist: pandas
|
|
17
|
-
Requires-Dist: fitparse
|
|
18
|
-
Requires-Dist: fit-tool>=0.9.14
|
|
19
|
-
Requires-Dist: arrow>=1.0.2
|
|
20
|
-
Requires-Dist: python-dateutil
|
|
21
|
-
Requires-Dist: docopt
|
|
22
|
-
Requires-Dist: tqdm
|
|
23
|
-
Requires-Dist: rowingphysics>=0.2.3
|
|
24
|
-
Requires-Dist: iso8601
|
|
25
|
-
Requires-Dist: lxml
|
|
26
|
-
Requires-Dist: xmltodict
|
|
27
|
-
Requires-Dist: nose_parameterized
|
|
28
|
-
Requires-Dist: timezonefinder
|
|
29
|
-
Requires-Dist: pycairo
|
|
30
|
-
Requires-Dist: tk
|
|
31
|
-
Requires-Dist: requests
|
|
32
12
|
|
|
33
13
|
**************
|
|
34
14
|
Rowingdata
|
|
@@ -546,8 +526,10 @@ The available data fields are
|
|
|
546
526
|
* ' StrokeDistance (meters)'
|
|
547
527
|
* ' DriveTime (ms)'
|
|
548
528
|
* ' StrokeRecoveryTime (ms)'
|
|
549
|
-
* ' AverageDriveForce (
|
|
550
|
-
* ' PeakDriveForce (
|
|
529
|
+
* ' AverageDriveForce (N)' (preferred; SI units)
|
|
530
|
+
* ' PeakDriveForce (N)' (preferred; SI units)
|
|
531
|
+
* ' AverageDriveForce (lbs)' (legacy; still supported)
|
|
532
|
+
* ' PeakDriveForce (lbs)' (legacy; still supported)
|
|
551
533
|
* 'cum_dist'
|
|
552
534
|
|
|
553
535
|
Oarlock parsers (NK Logbook) may add: ``catch``, ``finish``,
|
|
@@ -556,17 +538,22 @@ Oarlock parsers (NK Logbook) may add: ``catch``, ``finish``,
|
|
|
556
538
|
If imported from TCX, Rowpro, or other tools, some data fields may not contain
|
|
557
539
|
useful information.
|
|
558
540
|
|
|
559
|
-
|
|
560
|
-
CSV
|
|
561
|
-
|
|
541
|
+
=======================
|
|
542
|
+
rowingdata CSV Columns
|
|
543
|
+
=======================
|
|
562
544
|
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
545
|
+
This section describes the dataframe schema used by the ``rowingdata`` class.
|
|
546
|
+
It is this package's own column layout, not a vendor-neutral standard. For a
|
|
547
|
+
cross-vendor interchange format, see the Rowing Data Standard at
|
|
548
|
+
https://github.com/MoveLab-Studio/rowing-data-standard, which rowingdata
|
|
549
|
+
targets when exporting FIT.
|
|
566
550
|
|
|
567
|
-
|
|
551
|
+
Any parser implementation feeding the ``rowingdata`` class should produce at
|
|
552
|
+
least the columns described below.
|
|
553
|
+
|
|
554
|
+
Please send to me any CSV file that follows the layout described here
|
|
568
555
|
but does not parse well in the "rowingdata" module. I will update the module
|
|
569
|
-
and add the file to
|
|
556
|
+
and add the file to regression testing.
|
|
570
557
|
|
|
571
558
|
Field Names (Columns)
|
|
572
559
|
----------------------
|
|
@@ -583,14 +570,23 @@ The standard field names are:
|
|
|
583
570
|
* ' StrokeDistance (meters)'
|
|
584
571
|
* ' DriveTime (ms)'
|
|
585
572
|
* ' StrokeRecoveryTime (ms)'
|
|
586
|
-
* ' AverageDriveForce (
|
|
587
|
-
* ' PeakDriveForce (
|
|
573
|
+
* ' AverageDriveForce (N)' (preferred; SI units)
|
|
574
|
+
* ' PeakDriveForce (N)' (preferred; SI units)
|
|
575
|
+
* ' AverageDriveForce (lbs)' (legacy; still supported)
|
|
576
|
+
* ' PeakDriveForce (lbs)' (legacy; still supported)
|
|
588
577
|
* ' lapIdx'
|
|
589
578
|
* ' ElapsedTime (sec)'
|
|
590
579
|
|
|
591
580
|
Optional (Oarlock/NK Logbook): ``catch``/``catchAngle``, ``finish``/``finishAngle``,
|
|
592
581
|
``slip``, ``wash``, ``peakforceangle``, ``effectiveLength``.
|
|
593
582
|
|
|
583
|
+
Planned for dual oarlock (port/starboard symmetry): ``catch_port``, ``catch_starboard``,
|
|
584
|
+
``finish_port``, ``finish_starboard``, ``slip_port``, ``slip_starboard``, ``wash_port``,
|
|
585
|
+
``wash_starboard``, ``peakforceangle_port``, ``peakforceangle_starboard``,
|
|
586
|
+
``effectiveLength_port``, ``effectiveLength_starboard``. See *Dual oarlock
|
|
587
|
+
(port/starboard)* below. **Note:** rowingdata does not yet implement parsing or
|
|
588
|
+
export for these per-side columns.
|
|
589
|
+
|
|
594
590
|
The CSV file adheres to the US conventions, with fields
|
|
595
591
|
separated by a comma (',')
|
|
596
592
|
and using the dot '.' as the decimal symbol.
|
|
@@ -792,14 +788,12 @@ The duration of the recovery part. See Drive Time for the definition. Drive Time
|
|
|
792
788
|
Average Drive Force
|
|
793
789
|
--------------------
|
|
794
790
|
|
|
795
|
-
Field name: ' AverageDriveForce (
|
|
791
|
+
Field name: ' AverageDriveForce (N)' (preferred) or ' AverageDriveForce (lbs)' (legacy)
|
|
796
792
|
|
|
797
|
-
Unit:
|
|
793
|
+
Unit: newtons (N), or pounds (lb) for older files and tools
|
|
798
794
|
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
This should be the part of the handle force that does actual work.
|
|
795
|
+
Use **Newtons** for new data and integrations. **Pounds** remain supported for
|
|
796
|
+
backward compatibility. This should be the part of the handle force that does actual work.
|
|
803
797
|
|
|
804
798
|
For dynamic ergs and OTW rowing this is not sufficient to describe the
|
|
805
799
|
complete stroke dynamics, so additional fields can be defined, for example
|
|
@@ -822,9 +816,9 @@ as opposed to an average over time or oar angles.
|
|
|
822
816
|
Peak Drive Force
|
|
823
817
|
------------------
|
|
824
818
|
|
|
825
|
-
Field name: ' PeakDriveForce (
|
|
819
|
+
Field name: ' PeakDriveForce (N)' (preferred) or ' PeakDriveForce (lbs)' (legacy)
|
|
826
820
|
|
|
827
|
-
Unit:
|
|
821
|
+
Unit: newtons (N), or pounds (lb) for older files and tools
|
|
828
822
|
|
|
829
823
|
See discussion about measuring forces under Average Drive Force.
|
|
830
824
|
|
|
@@ -840,11 +834,14 @@ source: NK Logbook uses these columns).
|
|
|
840
834
|
These fields come from NK Logbook (Oarlock) and similar OTW
|
|
841
835
|
measurement systems. They describe rigging geometry and blade angles:
|
|
842
836
|
|
|
843
|
-
* **catch**, **finish** – oar angles at catch and finish (degrees)
|
|
844
|
-
|
|
837
|
+
* **catch**, **finish** – oar angles at catch and finish (degrees),
|
|
838
|
+
using the rowing convention where **0° = oar perpendicular to the boat's
|
|
839
|
+
longitudinal axis**. Negative values indicate the catch direction (oar blade
|
|
840
|
+
toward bow, handle toward stern); positive values indicate the finish direction
|
|
841
|
+
(oar blade toward stern, handle toward bow). NK uses catchAngle, finishAngle.
|
|
845
842
|
* **slip** – blade slip angle.
|
|
846
843
|
* **wash** – wash/backwash angle.
|
|
847
|
-
* **peakforceangle** – oar angle at peak force.
|
|
844
|
+
* **peakforceangle** – oar angle at peak force (same 0° = perpendicular convention).
|
|
848
845
|
* **effectiveLength** – effective lever length (rigging geometry). *Not*
|
|
849
846
|
the same as Drive Length: Effective Length is the horizontal component
|
|
850
847
|
from pin to handle (a rigging/setup measure, often in cm), whereas
|
|
@@ -852,6 +849,16 @@ measurement systems. They describe rigging geometry and blade angles:
|
|
|
852
849
|
stroke (typically 1.2–1.5 m). Both may appear in the same dataset;
|
|
853
850
|
they serve different purposes.
|
|
854
851
|
|
|
852
|
+
Dual oarlock (port/starboard)
|
|
853
|
+
..............................
|
|
854
|
+
|
|
855
|
+
When a rower uses two smart oarlocks, oarlock metrics can be reported per side:
|
|
856
|
+
port (left) and starboard (right). Each metric may appear as a per-side column
|
|
857
|
+
(e.g. ``catch_port``, ``catch_starboard``); the unsuffixed summary column
|
|
858
|
+
(``catch``) is the average of the two sides when both exist, and the value of
|
|
859
|
+
whichever side is present otherwise. **Note:** rowingdata does not yet
|
|
860
|
+
implement parsing or FIT export for these per-side columns.
|
|
861
|
+
|
|
855
862
|
Lap Identifier
|
|
856
863
|
-------------------
|
|
857
864
|
|
|
@@ -940,6 +947,26 @@ Boat bearing.
|
|
|
940
947
|
Release Notes:
|
|
941
948
|
================
|
|
942
949
|
|
|
950
|
+
Unreleased
|
|
951
|
+
----------
|
|
952
|
+
|
|
953
|
+
- **Breaking change to exported FIT file contents.** FIT export now follows the
|
|
954
|
+
Rowing Data Standard (https://github.com/MoveLab-Studio/rowing-data-standard,
|
|
955
|
+
Draft v0.1). The ``exporttofit`` API is unchanged, but the bytes it writes are
|
|
956
|
+
not: the developer application ID is now the standard UUID, ``DriveLength``
|
|
957
|
+
and ``EffectiveLength`` are encoded in millimetres rather than metres,
|
|
958
|
+
``AverageBoatSpeed`` uses scale 255, stroke rate moves to field ID 93, and
|
|
959
|
+
stroke work to field ID 19. Consumers that hardcoded the previous rowingdata
|
|
960
|
+
application ID or the old metre-based scales must be updated. ``FITParser``
|
|
961
|
+
still reads files written by rowingdata 3.7.3 and earlier.
|
|
962
|
+
- In-stroke curve fields are emitted under a separate, private application ID,
|
|
963
|
+
because those field IDs are not allocated in the standard's registry and so
|
|
964
|
+
carry no interoperable meaning.
|
|
965
|
+
- Removed ``docs/FIT_STANDARD.md`` and ``docs/FIT_STANDARD.pdf``. The standard is
|
|
966
|
+
maintained by a committee at
|
|
967
|
+
https://github.com/MoveLab-Studio/rowing-data-standard, which is the single
|
|
968
|
+
source of truth; this repository no longer ships a copy.
|
|
969
|
+
|
|
943
970
|
0.97.x
|
|
944
971
|
------
|
|
945
972
|
|
|
@@ -514,8 +514,10 @@ The available data fields are
|
|
|
514
514
|
* ' StrokeDistance (meters)'
|
|
515
515
|
* ' DriveTime (ms)'
|
|
516
516
|
* ' StrokeRecoveryTime (ms)'
|
|
517
|
-
* ' AverageDriveForce (
|
|
518
|
-
* ' PeakDriveForce (
|
|
517
|
+
* ' AverageDriveForce (N)' (preferred; SI units)
|
|
518
|
+
* ' PeakDriveForce (N)' (preferred; SI units)
|
|
519
|
+
* ' AverageDriveForce (lbs)' (legacy; still supported)
|
|
520
|
+
* ' PeakDriveForce (lbs)' (legacy; still supported)
|
|
519
521
|
* 'cum_dist'
|
|
520
522
|
|
|
521
523
|
Oarlock parsers (NK Logbook) may add: ``catch``, ``finish``,
|
|
@@ -524,17 +526,22 @@ Oarlock parsers (NK Logbook) may add: ``catch``, ``finish``,
|
|
|
524
526
|
If imported from TCX, Rowpro, or other tools, some data fields may not contain
|
|
525
527
|
useful information.
|
|
526
528
|
|
|
527
|
-
|
|
528
|
-
CSV
|
|
529
|
-
|
|
529
|
+
=======================
|
|
530
|
+
rowingdata CSV Columns
|
|
531
|
+
=======================
|
|
530
532
|
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
533
|
+
This section describes the dataframe schema used by the ``rowingdata`` class.
|
|
534
|
+
It is this package's own column layout, not a vendor-neutral standard. For a
|
|
535
|
+
cross-vendor interchange format, see the Rowing Data Standard at
|
|
536
|
+
https://github.com/MoveLab-Studio/rowing-data-standard, which rowingdata
|
|
537
|
+
targets when exporting FIT.
|
|
534
538
|
|
|
535
|
-
|
|
539
|
+
Any parser implementation feeding the ``rowingdata`` class should produce at
|
|
540
|
+
least the columns described below.
|
|
541
|
+
|
|
542
|
+
Please send to me any CSV file that follows the layout described here
|
|
536
543
|
but does not parse well in the "rowingdata" module. I will update the module
|
|
537
|
-
and add the file to
|
|
544
|
+
and add the file to regression testing.
|
|
538
545
|
|
|
539
546
|
Field Names (Columns)
|
|
540
547
|
----------------------
|
|
@@ -551,14 +558,23 @@ The standard field names are:
|
|
|
551
558
|
* ' StrokeDistance (meters)'
|
|
552
559
|
* ' DriveTime (ms)'
|
|
553
560
|
* ' StrokeRecoveryTime (ms)'
|
|
554
|
-
* ' AverageDriveForce (
|
|
555
|
-
* ' PeakDriveForce (
|
|
561
|
+
* ' AverageDriveForce (N)' (preferred; SI units)
|
|
562
|
+
* ' PeakDriveForce (N)' (preferred; SI units)
|
|
563
|
+
* ' AverageDriveForce (lbs)' (legacy; still supported)
|
|
564
|
+
* ' PeakDriveForce (lbs)' (legacy; still supported)
|
|
556
565
|
* ' lapIdx'
|
|
557
566
|
* ' ElapsedTime (sec)'
|
|
558
567
|
|
|
559
568
|
Optional (Oarlock/NK Logbook): ``catch``/``catchAngle``, ``finish``/``finishAngle``,
|
|
560
569
|
``slip``, ``wash``, ``peakforceangle``, ``effectiveLength``.
|
|
561
570
|
|
|
571
|
+
Planned for dual oarlock (port/starboard symmetry): ``catch_port``, ``catch_starboard``,
|
|
572
|
+
``finish_port``, ``finish_starboard``, ``slip_port``, ``slip_starboard``, ``wash_port``,
|
|
573
|
+
``wash_starboard``, ``peakforceangle_port``, ``peakforceangle_starboard``,
|
|
574
|
+
``effectiveLength_port``, ``effectiveLength_starboard``. See *Dual oarlock
|
|
575
|
+
(port/starboard)* below. **Note:** rowingdata does not yet implement parsing or
|
|
576
|
+
export for these per-side columns.
|
|
577
|
+
|
|
562
578
|
The CSV file adheres to the US conventions, with fields
|
|
563
579
|
separated by a comma (',')
|
|
564
580
|
and using the dot '.' as the decimal symbol.
|
|
@@ -760,14 +776,12 @@ The duration of the recovery part. See Drive Time for the definition. Drive Time
|
|
|
760
776
|
Average Drive Force
|
|
761
777
|
--------------------
|
|
762
778
|
|
|
763
|
-
Field name: ' AverageDriveForce (
|
|
779
|
+
Field name: ' AverageDriveForce (N)' (preferred) or ' AverageDriveForce (lbs)' (legacy)
|
|
764
780
|
|
|
765
|
-
Unit:
|
|
781
|
+
Unit: newtons (N), or pounds (lb) for older files and tools
|
|
766
782
|
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
This should be the part of the handle force that does actual work.
|
|
783
|
+
Use **Newtons** for new data and integrations. **Pounds** remain supported for
|
|
784
|
+
backward compatibility. This should be the part of the handle force that does actual work.
|
|
771
785
|
|
|
772
786
|
For dynamic ergs and OTW rowing this is not sufficient to describe the
|
|
773
787
|
complete stroke dynamics, so additional fields can be defined, for example
|
|
@@ -790,9 +804,9 @@ as opposed to an average over time or oar angles.
|
|
|
790
804
|
Peak Drive Force
|
|
791
805
|
------------------
|
|
792
806
|
|
|
793
|
-
Field name: ' PeakDriveForce (
|
|
807
|
+
Field name: ' PeakDriveForce (N)' (preferred) or ' PeakDriveForce (lbs)' (legacy)
|
|
794
808
|
|
|
795
|
-
Unit:
|
|
809
|
+
Unit: newtons (N), or pounds (lb) for older files and tools
|
|
796
810
|
|
|
797
811
|
See discussion about measuring forces under Average Drive Force.
|
|
798
812
|
|
|
@@ -808,11 +822,14 @@ source: NK Logbook uses these columns).
|
|
|
808
822
|
These fields come from NK Logbook (Oarlock) and similar OTW
|
|
809
823
|
measurement systems. They describe rigging geometry and blade angles:
|
|
810
824
|
|
|
811
|
-
* **catch**, **finish** – oar angles at catch and finish (degrees)
|
|
812
|
-
|
|
825
|
+
* **catch**, **finish** – oar angles at catch and finish (degrees),
|
|
826
|
+
using the rowing convention where **0° = oar perpendicular to the boat's
|
|
827
|
+
longitudinal axis**. Negative values indicate the catch direction (oar blade
|
|
828
|
+
toward bow, handle toward stern); positive values indicate the finish direction
|
|
829
|
+
(oar blade toward stern, handle toward bow). NK uses catchAngle, finishAngle.
|
|
813
830
|
* **slip** – blade slip angle.
|
|
814
831
|
* **wash** – wash/backwash angle.
|
|
815
|
-
* **peakforceangle** – oar angle at peak force.
|
|
832
|
+
* **peakforceangle** – oar angle at peak force (same 0° = perpendicular convention).
|
|
816
833
|
* **effectiveLength** – effective lever length (rigging geometry). *Not*
|
|
817
834
|
the same as Drive Length: Effective Length is the horizontal component
|
|
818
835
|
from pin to handle (a rigging/setup measure, often in cm), whereas
|
|
@@ -820,6 +837,16 @@ measurement systems. They describe rigging geometry and blade angles:
|
|
|
820
837
|
stroke (typically 1.2–1.5 m). Both may appear in the same dataset;
|
|
821
838
|
they serve different purposes.
|
|
822
839
|
|
|
840
|
+
Dual oarlock (port/starboard)
|
|
841
|
+
..............................
|
|
842
|
+
|
|
843
|
+
When a rower uses two smart oarlocks, oarlock metrics can be reported per side:
|
|
844
|
+
port (left) and starboard (right). Each metric may appear as a per-side column
|
|
845
|
+
(e.g. ``catch_port``, ``catch_starboard``); the unsuffixed summary column
|
|
846
|
+
(``catch``) is the average of the two sides when both exist, and the value of
|
|
847
|
+
whichever side is present otherwise. **Note:** rowingdata does not yet
|
|
848
|
+
implement parsing or FIT export for these per-side columns.
|
|
849
|
+
|
|
823
850
|
Lap Identifier
|
|
824
851
|
-------------------
|
|
825
852
|
|
|
@@ -908,6 +935,26 @@ Boat bearing.
|
|
|
908
935
|
Release Notes:
|
|
909
936
|
================
|
|
910
937
|
|
|
938
|
+
Unreleased
|
|
939
|
+
----------
|
|
940
|
+
|
|
941
|
+
- **Breaking change to exported FIT file contents.** FIT export now follows the
|
|
942
|
+
Rowing Data Standard (https://github.com/MoveLab-Studio/rowing-data-standard,
|
|
943
|
+
Draft v0.1). The ``exporttofit`` API is unchanged, but the bytes it writes are
|
|
944
|
+
not: the developer application ID is now the standard UUID, ``DriveLength``
|
|
945
|
+
and ``EffectiveLength`` are encoded in millimetres rather than metres,
|
|
946
|
+
``AverageBoatSpeed`` uses scale 255, stroke rate moves to field ID 93, and
|
|
947
|
+
stroke work to field ID 19. Consumers that hardcoded the previous rowingdata
|
|
948
|
+
application ID or the old metre-based scales must be updated. ``FITParser``
|
|
949
|
+
still reads files written by rowingdata 3.7.3 and earlier.
|
|
950
|
+
- In-stroke curve fields are emitted under a separate, private application ID,
|
|
951
|
+
because those field IDs are not allocated in the standard's registry and so
|
|
952
|
+
carry no interoperable meaning.
|
|
953
|
+
- Removed ``docs/FIT_STANDARD.md`` and ``docs/FIT_STANDARD.pdf``. The standard is
|
|
954
|
+
maintained by a committee at
|
|
955
|
+
https://github.com/MoveLab-Studio/rowing-data-standard, which is the single
|
|
956
|
+
source of truth; this repository no longer ships a copy.
|
|
957
|
+
|
|
911
958
|
0.97.x
|
|
912
959
|
------
|
|
913
960
|
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 2,
|
|
3
|
+
"_comment": "Authoritative FIT developer field definitions for rowingdata fitwrite. Field IDs, scales and units must match the Rowing Data Standard registry at https://github.com/MoveLab-Studio/rowing-data-standard (registry/field-ids.md); that repository is the source of truth, this file is only rowingdata's machine-readable copy of the subset it emits. v2: mm precision for DriveLength/PeakForcePositionAbs (scale 1000); StrokeRate dev field (93); instroke curve Y-scale registry.",
|
|
4
|
+
"instroke_dynamic": {
|
|
5
|
+
"summary_start": 20,
|
|
6
|
+
"summary_id_padding": "ceil_to_10",
|
|
7
|
+
"curve_start": 60
|
|
8
|
+
},
|
|
9
|
+
"instroke_curve_types": {
|
|
10
|
+
"HandleForceCurve": {
|
|
11
|
+
"y_scale": 10,
|
|
12
|
+
"y_units": "N",
|
|
13
|
+
"default_abscissa": "HANDLE_DISTANCE_UNIFORM_M"
|
|
14
|
+
},
|
|
15
|
+
"BoatAcceleratorCurve": {
|
|
16
|
+
"y_scale": 100,
|
|
17
|
+
"y_units": "m/s^2",
|
|
18
|
+
"default_abscissa": "TIME_UNIFORM_MS"
|
|
19
|
+
},
|
|
20
|
+
"OarAngleVelocityCurve": {
|
|
21
|
+
"y_scale": 10,
|
|
22
|
+
"y_units": "deg/s",
|
|
23
|
+
"default_abscissa": "TIME_UNIFORM_MS"
|
|
24
|
+
},
|
|
25
|
+
"SeatCurve": {
|
|
26
|
+
"y_scale": 255,
|
|
27
|
+
"y_units": "m",
|
|
28
|
+
"default_abscissa": "HANDLE_DISTANCE_UNIFORM_M"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"abscissa_enum": {
|
|
32
|
+
"UNKNOWN": 0,
|
|
33
|
+
"TIME_UNIFORM_MS": 1,
|
|
34
|
+
"HANDLE_DISTANCE_UNIFORM_M": 2,
|
|
35
|
+
"OAR_ANGLE_UNIFORM_DEG": 3,
|
|
36
|
+
"NORMALIZED_DRIVE_0_1": 4
|
|
37
|
+
},
|
|
38
|
+
"instroke_axis_field_ids": [90, 91, 92],
|
|
39
|
+
"always_emit_field_ids": [9, 90, 91, 92],
|
|
40
|
+
"instroke_column_map": {
|
|
41
|
+
"curve_data": "HandleForceCurve",
|
|
42
|
+
"boat accelerator curve": "BoatAcceleratorCurve",
|
|
43
|
+
"oar angle velocity curve": "OarAngleVelocityCurve",
|
|
44
|
+
"seat curve": "SeatCurve"
|
|
45
|
+
},
|
|
46
|
+
"developer_fields": [
|
|
47
|
+
{"field_id": 0, "group": "rowing", "fit_name": "DriveLength", "base_type": "UINT16", "size": 2, "scale": 1, "units": "mm", "df_columns": [" DriveLength (meters)"]},
|
|
48
|
+
{"field_id": 1, "group": "rowing", "fit_name": "StrokeDriveTime", "base_type": "UINT16", "size": 2, "scale": 1, "units": "ms", "df_columns": [" DriveTime (ms)"]},
|
|
49
|
+
{"field_id": 2, "group": "rowing", "fit_name": "DragFactor", "base_type": "UINT16", "size": 2, "scale": 1, "units": "", "df_columns": [" DragFactor"]},
|
|
50
|
+
{"field_id": 3, "group": "rowing", "fit_name": "StrokeRecoveryTime", "base_type": "UINT16", "size": 2, "scale": 1, "units": "ms", "df_columns": [" StrokeRecoveryTime (ms)"]},
|
|
51
|
+
{"field_id": 4, "group": "rowing", "fit_name": "AverageDriveForceLbs", "base_type": "UINT16", "size": 2, "scale": 10, "units": "lbs", "df_columns": [" AverageDriveForce (lbs)"]},
|
|
52
|
+
{"field_id": 5, "group": "rowing", "fit_name": "PeakDriveForceLbs", "base_type": "UINT16", "size": 2, "scale": 10, "units": "lbs", "df_columns": [" PeakDriveForce (lbs)"]},
|
|
53
|
+
{"field_id": 6, "group": "rowing", "fit_name": "AverageDriveForceN", "base_type": "UINT16", "size": 2, "scale": 10, "units": "N", "df_columns": [" AverageDriveForce (N)"]},
|
|
54
|
+
{"field_id": 7, "group": "rowing", "fit_name": "PeakDriveForceN", "base_type": "UINT16", "size": 2, "scale": 10, "units": "N", "df_columns": [" PeakDriveForce (N)"]},
|
|
55
|
+
{"field_id": 8, "group": "rowing", "fit_name": "AverageBoatSpeed", "base_type": "UINT16", "size": 2, "scale": 255, "units": "m/s", "df_columns": [" AverageBoatSpeed (m/s)"]},
|
|
56
|
+
{"field_id": 9, "group": "rowing", "fit_name": "WorkoutState", "base_type": "UINT8", "size": 1, "scale": 1, "units": "", "df_columns": [" WorkoutState"]},
|
|
57
|
+
{"field_id": 10, "group": "metadata", "fit_name": "RecordingStrategy", "base_type": "UINT8", "size": 1, "scale": 1, "units": "", "df_columns": [], "message_type": "session"},
|
|
58
|
+
{"field_id": 19, "group": "rowing", "fit_name": "StrokeWork", "base_type": "UINT16", "size": 2, "scale": 1, "units": "J", "df_columns": [" WorkPerStroke (joules)", "driveenergy"]},
|
|
59
|
+
{"field_id": 93, "group": "rowing", "fit_name": "StrokeRate", "base_type": "UINT16", "size": 2, "scale": 100, "units": "spm", "df_columns": [" Cadence (stokes/min)"]},
|
|
60
|
+
|
|
61
|
+
{"field_id": 11, "group": "oarlock", "fit_name": "Catch", "base_type": "SINT16", "size": 2, "scale": 10, "units": "deg", "df_columns": ["catch", " catch", "catchAngle"]},
|
|
62
|
+
{"field_id": 12, "group": "oarlock", "fit_name": "Finish", "base_type": "SINT16", "size": 2, "scale": 10, "units": "deg", "df_columns": ["finish", " finish", "finishAngle"]},
|
|
63
|
+
{"field_id": 13, "group": "oarlock", "fit_name": "Slip", "base_type": "SINT16", "size": 2, "scale": 10, "units": "deg", "df_columns": ["slip", " slip"]},
|
|
64
|
+
{"field_id": 14, "group": "oarlock", "fit_name": "Wash", "base_type": "SINT16", "size": 2, "scale": 10, "units": "deg", "df_columns": ["wash", " wash"]},
|
|
65
|
+
{"field_id": 15, "group": "oarlock", "fit_name": "PeakForceAngle", "base_type": "SINT16", "size": 2, "scale": 10, "units": "deg", "df_columns": ["peakforceangle", " peakforceangle"]},
|
|
66
|
+
{"field_id": 16, "group": "oarlock", "fit_name": "EffectiveLength", "base_type": "UINT16", "size": 2, "scale": 1, "units": "mm", "df_columns": ["effectiveLength", " effectiveLength", "effective length"]},
|
|
67
|
+
|
|
68
|
+
{"field_id": 200, "group": "oarlock_dual", "dual_pair": "catch", "side": "port", "fit_name": "CatchPort", "base_type": "SINT16", "size": 2, "scale": 10, "units": "deg", "df_columns": ["catch_port", "catchAngle_port"]},
|
|
69
|
+
{"field_id": 201, "group": "oarlock_dual", "dual_pair": "catch", "side": "starboard", "fit_name": "CatchStarboard", "base_type": "SINT16", "size": 2, "scale": 10, "units": "deg", "df_columns": ["catch_starboard", "catchAngle_starboard"]},
|
|
70
|
+
{"field_id": 202, "group": "oarlock_dual", "dual_pair": "finish", "side": "port", "fit_name": "FinishPort", "base_type": "SINT16", "size": 2, "scale": 10, "units": "deg", "df_columns": ["finish_port", "finishAngle_port"]},
|
|
71
|
+
{"field_id": 203, "group": "oarlock_dual", "dual_pair": "finish", "side": "starboard", "fit_name": "FinishStarboard", "base_type": "SINT16", "size": 2, "scale": 10, "units": "deg", "df_columns": ["finish_starboard", "finishAngle_starboard"]},
|
|
72
|
+
{"field_id": 204, "group": "oarlock_dual", "dual_pair": "slip", "side": "port", "fit_name": "SlipPort", "base_type": "SINT16", "size": 2, "scale": 10, "units": "deg", "df_columns": ["slip_port"]},
|
|
73
|
+
{"field_id": 205, "group": "oarlock_dual", "dual_pair": "slip", "side": "starboard", "fit_name": "SlipStarboard", "base_type": "SINT16", "size": 2, "scale": 10, "units": "deg", "df_columns": ["slip_starboard"]},
|
|
74
|
+
{"field_id": 206, "group": "oarlock_dual", "dual_pair": "wash", "side": "port", "fit_name": "WashPort", "base_type": "SINT16", "size": 2, "scale": 10, "units": "deg", "df_columns": ["wash_port"]},
|
|
75
|
+
{"field_id": 207, "group": "oarlock_dual", "dual_pair": "wash", "side": "starboard", "fit_name": "WashStarboard", "base_type": "SINT16", "size": 2, "scale": 10, "units": "deg", "df_columns": ["wash_starboard"]},
|
|
76
|
+
{"field_id": 208, "group": "oarlock_dual", "dual_pair": "peakforceangle", "side": "port", "fit_name": "PeakForceAnglePort", "base_type": "SINT16", "size": 2, "scale": 10, "units": "deg", "df_columns": ["peakforceangle_port"]},
|
|
77
|
+
{"field_id": 209, "group": "oarlock_dual", "dual_pair": "peakforceangle", "side": "starboard", "fit_name": "PeakForceAngleStarboard", "base_type": "SINT16", "size": 2, "scale": 10, "units": "deg", "df_columns": ["peakforceangle_starboard"]},
|
|
78
|
+
{"field_id": 210, "group": "oarlock_dual", "dual_pair": "effectiveLength", "side": "port", "fit_name": "EffectiveLengthPort", "base_type": "UINT16", "size": 2, "scale": 1, "units": "mm", "df_columns": ["effectiveLength_port"]},
|
|
79
|
+
{"field_id": 211, "group": "oarlock_dual", "dual_pair": "effectiveLength", "side": "starboard", "fit_name": "EffectiveLengthStarboard", "base_type": "UINT16", "size": 2, "scale": 1, "units": "mm", "df_columns": ["effectiveLength_starboard"]},
|
|
80
|
+
|
|
81
|
+
{"field_id": 17, "group": "peak_position", "fit_name": "PeakForcePositionNorm", "base_type": "UINT16", "size": 2, "scale": 1, "units": "", "df_columns": ["rel_peak_force_pos", "PeakForcePositionNorm", "% of Stroke Complete When Peak Force Is Reached"], "transformer": "peak_norm", "clip_uint16_max": 10000},
|
|
82
|
+
{"field_id": 18, "group": "peak_position", "fit_name": "PeakForcePositionAbs", "base_type": "UINT16", "size": 2, "scale": 1, "units": "mm", "df_columns": ["peak_force_pos", "PeakForcePositionAbs"], "transformer": "peak_abs"},
|
|
83
|
+
|
|
84
|
+
{"field_id": 90, "group": "instroke_axis", "fit_name": "InstrokeAbscissaType", "base_type": "UINT8", "size": 1, "scale": 1, "units": "", "df_columns": []},
|
|
85
|
+
{"field_id": 91, "group": "instroke_axis", "fit_name": "InstrokeSampleInterval", "base_type": "UINT16", "size": 2, "scale": 1, "units": "", "df_columns": []},
|
|
86
|
+
{"field_id": 92, "group": "instroke_axis", "fit_name": "InstrokePointCount", "base_type": "UINT8", "size": 1, "scale": 1, "units": "", "df_columns": []}
|
|
87
|
+
]
|
|
88
|
+
}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
Bridge Garmin / OpenRowingMonitor FIT messages (Split, SplitSummary, Workout, WorkoutStep)
|
|
4
|
+
from fitparse into fit_tool GenericMessage for re-emission with rowingdata exports.
|
|
5
|
+
|
|
6
|
+
Global message numbers 312 and 313 are not in fitparse's profile (shown as unknown_312 / unknown_313);
|
|
7
|
+
they correspond to Split and SplitSummary in current Garmin FIT profiles.
|
|
8
|
+
"""
|
|
9
|
+
from __future__ import absolute_import
|
|
10
|
+
|
|
11
|
+
from fit_tool.base_type import BaseType
|
|
12
|
+
from fit_tool.definition_message import DefinitionMessage
|
|
13
|
+
from fit_tool.endian import Endian
|
|
14
|
+
from fit_tool.field import Field
|
|
15
|
+
from fit_tool.field_definition import FieldDefinition
|
|
16
|
+
from fit_tool.generic_message import GenericMessage
|
|
17
|
+
|
|
18
|
+
from fitparse.base import FitFile as FitparseFitFile
|
|
19
|
+
# Garmin FIT profile (extended): Split / SplitSummary message numbers
|
|
20
|
+
MESG_SPLIT = 312
|
|
21
|
+
MESG_SPLIT_SUMMARY = 313
|
|
22
|
+
MESG_WORKOUT = 26
|
|
23
|
+
MESG_WORKOUT_STEP = 27
|
|
24
|
+
|
|
25
|
+
_DEFAULT_PRESERVE = (MESG_WORKOUT, MESG_WORKOUT_STEP, MESG_SPLIT_SUMMARY, MESG_SPLIT)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _fitparse_base_type_to_fit_tool(fp_bt):
|
|
29
|
+
"""Map fitparse records.BaseType name to fit_tool BaseType."""
|
|
30
|
+
name = fp_bt.name.lower()
|
|
31
|
+
mapping = {
|
|
32
|
+
'enum': BaseType.ENUM,
|
|
33
|
+
'sint8': BaseType.SINT8,
|
|
34
|
+
'uint8': BaseType.UINT8,
|
|
35
|
+
'string': BaseType.STRING,
|
|
36
|
+
'sint16': BaseType.SINT16,
|
|
37
|
+
'uint16': BaseType.UINT16,
|
|
38
|
+
'sint32': BaseType.SINT32,
|
|
39
|
+
'uint32': BaseType.UINT32,
|
|
40
|
+
'float32': BaseType.FLOAT32,
|
|
41
|
+
'float64': BaseType.FLOAT64,
|
|
42
|
+
'byte': BaseType.BYTE,
|
|
43
|
+
'uint8z': BaseType.UINT8Z,
|
|
44
|
+
'uint16z': BaseType.UINT16Z,
|
|
45
|
+
'uint32z': BaseType.UINT32Z,
|
|
46
|
+
'uint64': BaseType.UINT64,
|
|
47
|
+
'sint64': BaseType.SINT64,
|
|
48
|
+
}
|
|
49
|
+
return mapping.get(name, BaseType.UINT8)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def _field_definition_from_fitparse(fd):
|
|
53
|
+
bt = _fitparse_base_type_to_fit_tool(fd.base_type)
|
|
54
|
+
return FieldDefinition(field_id=fd.def_num, size=fd.size, base_type=bt)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def _set_field_from_raw(fit_field, raw_value):
|
|
58
|
+
"""Copy raw decoded value from fitparse into fit_tool Field.encoded_values."""
|
|
59
|
+
bt = fit_field.base_type
|
|
60
|
+
if raw_value is None:
|
|
61
|
+
inv = bt.invalid_raw_value() if hasattr(bt, 'invalid_raw_value') else 0
|
|
62
|
+
fit_field.set_encoded_value(0, inv, check_validity=False)
|
|
63
|
+
return
|
|
64
|
+
if isinstance(raw_value, tuple):
|
|
65
|
+
for i, rv in enumerate(raw_value):
|
|
66
|
+
fit_field.set_encoded_value(i, int(rv) & 0xFFFFFFFF, check_validity=False)
|
|
67
|
+
return
|
|
68
|
+
if bt == BaseType.STRING:
|
|
69
|
+
fit_field.growable = True
|
|
70
|
+
s = raw_value if isinstance(raw_value, str) else str(raw_value)
|
|
71
|
+
fit_field.set_value(0, s[: fit_field.size] if fit_field.size else s)
|
|
72
|
+
return
|
|
73
|
+
n = len(fit_field.encoded_values)
|
|
74
|
+
if n == 1:
|
|
75
|
+
fit_field.set_encoded_value(0, int(raw_value), check_validity=False)
|
|
76
|
+
else:
|
|
77
|
+
fit_field.set_encoded_value(0, int(raw_value), check_validity=False)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def _generic_from_fitparse_data(def_mesg, data_msg, local_id):
|
|
81
|
+
"""Build fit_tool DefinitionMessage + GenericMessage from fitparse messages."""
|
|
82
|
+
endian = Endian.LITTLE if def_mesg.endian == '<' else Endian.BIG
|
|
83
|
+
field_defs = [_field_definition_from_fitparse(fd) for fd in def_mesg.field_defs]
|
|
84
|
+
definition = DefinitionMessage(
|
|
85
|
+
local_id=local_id,
|
|
86
|
+
global_id=def_mesg.mesg_num,
|
|
87
|
+
endian=endian,
|
|
88
|
+
field_definitions=field_defs,
|
|
89
|
+
developer_field_definitions=[],
|
|
90
|
+
)
|
|
91
|
+
gen = GenericMessage(definition_message=definition, developer_fields=None)
|
|
92
|
+
# Zip field data: fitparse DataMessage.fields order matches def field_defs + dev
|
|
93
|
+
fp_fields = list(data_msg.fields)
|
|
94
|
+
for i, fd in enumerate(def_mesg.field_defs):
|
|
95
|
+
if i >= len(fp_fields):
|
|
96
|
+
break
|
|
97
|
+
fld = gen.get_field(fd.def_num)
|
|
98
|
+
if fld is None and i < len(gen.fields):
|
|
99
|
+
fld = gen.fields[i]
|
|
100
|
+
if fld is None:
|
|
101
|
+
continue
|
|
102
|
+
fv = fp_fields[i]
|
|
103
|
+
raw = fv.raw_value if fv.raw_value is not None else fv.value
|
|
104
|
+
_set_field_from_raw(fld, raw)
|
|
105
|
+
return definition, gen
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def iter_preserved_generic_messages(fit_path, mesg_nums=None):
|
|
109
|
+
"""
|
|
110
|
+
Parse FIT with fitparse low-level API; yield (definition, GenericMessage) pairs
|
|
111
|
+
for each data message whose global mesg_num is in mesg_nums, in file order.
|
|
112
|
+
Local message IDs are reassigned uniquely for fit_tool (starting at 8 to avoid
|
|
113
|
+
clashing with common record/lap local IDs).
|
|
114
|
+
"""
|
|
115
|
+
if mesg_nums is None:
|
|
116
|
+
mesg_nums = _DEFAULT_PRESERVE
|
|
117
|
+
mesg_set = set(mesg_nums)
|
|
118
|
+
f = FitparseFitFile(fit_path)
|
|
119
|
+
while f._parse_message():
|
|
120
|
+
pass
|
|
121
|
+
# Map (mesg_num, tuple of field def signatures) -> next local_id
|
|
122
|
+
# Use local_id >= 8 to avoid clashing with fit_tool defaults (record/lap/event often use 0–3).
|
|
123
|
+
def_key_to_local = {}
|
|
124
|
+
next_local = 8
|
|
125
|
+
for m in f._messages:
|
|
126
|
+
if getattr(m, 'type', None) != 'data':
|
|
127
|
+
continue
|
|
128
|
+
if m.mesg_num not in mesg_set:
|
|
129
|
+
continue
|
|
130
|
+
def_mesg = m.def_mesg
|
|
131
|
+
key = (m.mesg_num, tuple((fd.def_num, fd.size, fd.base_type.name) for fd in def_mesg.field_defs))
|
|
132
|
+
if key not in def_key_to_local:
|
|
133
|
+
def_key_to_local[key] = next_local
|
|
134
|
+
next_local += 1
|
|
135
|
+
local_id = def_key_to_local[key]
|
|
136
|
+
definition, gen = _generic_from_fitparse_data(def_mesg, m, local_id)
|
|
137
|
+
yield definition, gen
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def add_preserved_messages_to_builder(builder, fit_path, mesg_nums=None):
|
|
141
|
+
"""
|
|
142
|
+
Add preserved native messages to a FitFileBuilder.
|
|
143
|
+
|
|
144
|
+
Emits each DefinitionMessage once (required by FIT), then each data message with
|
|
145
|
+
``definition_message`` cleared so FitFileBuilder binds the message to the stored
|
|
146
|
+
definition (see fit_tool FitFileBuilder.add).
|
|
147
|
+
"""
|
|
148
|
+
seen_def = set()
|
|
149
|
+
for definition, gen in iter_preserved_generic_messages(fit_path, mesg_nums=mesg_nums):
|
|
150
|
+
key = (definition.global_id, definition.local_id, tuple((fd.field_id, fd.size, fd.base_type) for fd in definition.field_definitions))
|
|
151
|
+
if key not in seen_def:
|
|
152
|
+
builder.add(definition)
|
|
153
|
+
seen_def.add(key)
|
|
154
|
+
gen.definition_message = None
|
|
155
|
+
builder.add(gen)
|