diff --git a/rowers/dataprep.py b/rowers/dataprep.py index 50397ff7..ef153533 100644 --- a/rowers/dataprep.py +++ b/rowers/dataprep.py @@ -172,6 +172,36 @@ def get_latlon(id): return [pd.Series([]), pd.Series([])] +def get_latlon_time(id): + try: + w = Workout.objects.get(id=id) + except Workout.DoesNotExist: + return False + + + rowdata = rdata(w.csvfilename) + + if rowdata.df.empty: + return [pd.Series([]), pd.Series([])] + + try: + try: + latitude = rowdata.df.loc[:, ' latitude'] + longitude = rowdata.df.loc[:, ' longitude'] + except KeyError: + latitude = 0 * rowdata.df.loc[:, 'TimeStamp (sec)'] + longitude = 0 * rowdata.df.loc[:, 'TimeStamp (sec)'] + except AttributeError: + return pd.DataFrame() + + df = pd.DataFrame({ + 'time': rowdata.df[' ElapsedTime (sec)'], + 'latitude': rowdata.df[' latitude'], + 'longitude': rowdata.df[' longitude'] + }) + + return df + def workout_summary_to_df( rower, startdate=datetime.datetime(1970,1,1), diff --git a/rowers/interactiveplots.py b/rowers/interactiveplots.py index c4ab7eb1..3673ded8 100644 --- a/rowers/interactiveplots.py +++ b/rowers/interactiveplots.py @@ -1809,6 +1809,124 @@ def leaflet_chart2(lat,lon,name=""): return script,div +def leaflet_chart_video(lat,lon,name=""): + if lat.empty or lon.empty: + return [0,"invalid coordinate data"] + + + # Throw out 0,0 + df = pd.DataFrame({ + 'lat':lat, + 'lon':lon + }) + + df = df.replace(0,np.nan) + df = df.loc[(df!=0).any(axis=1)] + df.fillna(method='bfill',axis=0,inplace=True) + df.fillna(method='ffill',axis=0,inplace=True) + lat = df['lat'] + lon = df['lon'] + if lat.empty or lon.empty: + return [0,"invalid coordinate data"] + + latmean = lat.mean() + lonmean = lon.mean() + latbegin = lat[lat.index[0]] + longbegin = lon[lon.index[0]] + latend = lat[lat.index[-1]] + longend = lon[lon.index[-1]] + + coordinates = zip(lat,lon) + + scoordinates = "[" + + for x,y in coordinates: + scoordinates += """[{x},{y}], + """.format( + x=x, + y=y + ) + + scoordinates += "]" + + script = """ + + + var streets = L.tileLayer('https://api.tiles.mapbox.com/v4/{{id}}/{{z}}/{{x}}/{{y}}.png?access_token=pk.eyJ1Ijoic2FuZGVycm9vc2VuZGFhbCIsImEiOiJjajY3aTRkeWQwNmx6MzJvMTN3andlcnBlIn0.MFG8Xt0kDeSA9j7puZQ9hA', {{ + maxZoom: 18, + id: 'mapbox.streets' + }}), + + satellite = L.tileLayer('https://api.tiles.mapbox.com/v4/{{id}}/{{z}}/{{x}}/{{y}}.png?access_token=pk.eyJ1Ijoic2FuZGVycm9vc2VuZGFhbCIsImEiOiJjajY3aTRkeWQwNmx6MzJvMTN3andlcnBlIn0.MFG8Xt0kDeSA9j7puZQ9hA', {{ + maxZoom: 18, + id: 'mapbox.satellite' + }}), + + outdoors = L.tileLayer('https://api.tiles.mapbox.com/v4/{{id}}/{{z}}/{{x}}/{{y}}.png?access_token=pk.eyJ1Ijoic2FuZGVycm9vc2VuZGFhbCIsImEiOiJjajY3aTRkeWQwNmx6MzJvMTN3andlcnBlIn0.MFG8Xt0kDeSA9j7puZQ9hA', {{ + maxZoom: 18, + id: 'mapbox.outdoors' + }}); + + + + var mymap = L.map('map_canvas', {{ + center: [{latmean}, {lonmean}], + zoom: 13, + layers: [streets, satellite] + }}).setView([{latmean},{lonmean}], 13); + + var navionics = new JNC.Leaflet.NavionicsOverlay({{ + navKey: 'Navionics_webapi_03205', + chartType: JNC.NAVIONICS_CHARTS.NAUTICAL, + isTransparent: true, + zIndex: 1 + }}); + + + var osmUrl2='http://tiles.openseamap.org/seamark/{{z}}/{{x}}/{{y}}.png'; + var osmUrl='http://{{s}}.tile.openstreetmap.org/{{z}}/{{x}}/{{y}}.png'; + + + //create two TileLayer + var nautical=new L.TileLayer(osmUrl,{{ + maxZoom:18}}); + + + L.control.layers({{ + "Streets": streets, + "Satellite": satellite, + "Outdoors": outdoors, + "Nautical": nautical, + }},{{ + "Navionics":navionics, + }}).addTo(mymap); + + var marker = L.marker([{latbegin}, {longbegin}]).addTo(mymap); + marker.bindPopup("Start"); + + var latlongs = {scoordinates} + var polyline = L.polyline(latlongs, {{color:'red'}}).addTo(mymap) + mymap.fitBounds(polyline.getBounds()) + + """.format( + latmean=latmean, + lonmean=lonmean, + latbegin = latbegin, + latend=latend, + longbegin=longbegin, + longend=longend, + scoordinates=scoordinates, + ) + + div = """ +

 

+ """ + + + + return script,div + + def interactive_agegroupcpchart(age,normalized=False): durations = [1,4,30,60] distances = [100,500,1000,2000,5000,6000,10000,21097,42195] diff --git a/rowers/templates/embedded_video.html b/rowers/templates/embedded_video.html index ebd0de5e..5751495a 100644 --- a/rowers/templates/embedded_video.html +++ b/rowers/templates/embedded_video.html @@ -2,10 +2,19 @@ {% load staticfiles %} {% load rowerfilters %} {% load i18n %} +{% load leaflet_tags %} + + {% block title %}Workout Video{% endblock %} +{% block meta %} +{% leaflet_js %} +{% leaflet_css %} +{% endblock %} + {% block main %} +

{% if workout|previousworkout:rower.user %} +

  • +
    + {{ mapdiv | safe}} + +
    +
  • Video Time @@ -37,8 +52,9 @@
  • -
  • - - {% endlanguage %} diff --git a/rowers/views/workoutviews.py b/rowers/views/workoutviews.py index e3557d3b..4fcd1d07 100644 --- a/rowers/views/workoutviews.py +++ b/rowers/views/workoutviews.py @@ -19,6 +19,20 @@ def workout_video_view(request,id=0): df2 = df.resample('1s').mean().interpolate() boatspeed = df2['velo'] + coordinates = dataprep.get_latlon_time(w.id) + coordinates.set_index(pd.to_timedelta(coordinates['time'],unit='s'),inplace=True) + coordinates = coordinates.resample('1s').mean().interpolate() + latitude = coordinates['latitude'] + longitude = coordinates['longitude'] + + # create map + mapscript, mapdiv = leaflet_chart_video(latitude,longitude, + w.name) + + # bundle data + data = {'boatspeed':boatspeed.values, + 'latitude':latitude.values, + 'longitude':longitude.values} return render(request, 'embedded_video.html', @@ -26,6 +40,10 @@ def workout_video_view(request,id=0): 'workout':w, 'rower':request.user.rower, 'boatspeed': boatspeed.values, + 'latitude': latitude.values, + 'longitude': longitude.values, + 'mapscript': mapscript, + 'mapdiv': mapdiv, }) # Show the EMpower Oarlock generated Stroke Profile