__init__ ist kein Konstruktor, und sondern in Initialisierer. Man prüft nicht explizit auf == True.
Variablen werden klein_mit_unterstrich geschrieben. Npoints ist überflüssig, da man auch mit -1 von hinten her indizieren kann.
Warum benutzt total_distance nicht create_distances?
Es gibt keine privaten Methoden, die doppelten Unterstriche sind damit auch falsch.
In plot_trip gibt es einen NameError, wenn weder has_tracks noch has_routes True sind.
Warum erzeugst Du in `plot_trip` den Dataframe nochmal?
Die ganzen Hilfsklassen sind irgendwie überflüssig. Entweder funktioniert das Lesen, oder es gibt an der passenden Stelle einen Fehler automatisch.
Ungetestet:
Code: Alles auswählen
from __future__ import print_function, division
from glob import glob
import matplotlib.pyplot as plt
import pandas as pd
from geopy import distance
import gpxpy
class Trajectory():
def __init__(self, gpxdata):
"""
initializes dataframe
"""
self.gpx = gpxdata
# initiation of booleans for properties of different types of gpx-files
self.has_tracks = bool(gpxdata.tracks)
self.has_routes = bool(gpxdata.routes)
self.has_elevation = False
self.has_time = False
if self.has_tracks:
self.points = gpxdata.tracks[0].segments[0].points
self.has_elevation = bool(self.points[0].elevation)
self.has_time = bool(self.points[0].time)
else:
self.points = gpxdata.routes[0].points
self.has_elevation = False
self.has_time = False
self.df = pd.DataFrame()
self.df['lon'] = [pt.longitude for pt in self.points]
self.df['lat'] = [pt.latitude for pt in self.points]
# different cases of having altitude- and/or time-information
if self.has_elevation:
self.df['alt'] = [pt.elevation for pt in self.points]
if self.has_time:
self.df['time'] = [pt.time for pt in self.points]
# public methods
@property
def total_distance(self):
"""
Calculates the total distance of a list of geographic points
Input: list of geographic points [(lat1,lon1), (lat2, lon2), ..., (lat_n, lon_n)]
Output: total distance in km, i.e. d(p2,p1) + d(p3,p2) + .... + d(p_n,p_(n-1)), where d(x,y) is
the distance of points x and y
"""
return self.get_distances().sum()
@property
def start_end_elevation(self):
"""
calculates the altitude at the beginning and at the end of a whole trip
"""
alt = self.df['alt']
return alt[0], alt[-1]
@property
def min_max_elevation(self):
"""
calculates the minimum and maximum altitude of a whole trip
"""
alt = self.df['alt']
return alt.min(), alt.max()
@property
def up_down_hill(self):
"""
calculates the total uphill and downhill movement
"""
delta = self.df['alt'].diff()
up_hill = diff.clip_lower(0).sum()
down_hill = diff.clip_upper(0).sum()
return up_hill, down_hill
@property
def total_elapsed_time(self):
"""
calculates the total time elapsed of the track walked
"""
time = self.df['time']
return time[-1] - time[0]
def plot_velocities(self):
"""
creates a graphical plot of all velocities between each of the two trackpoints
"""
distances = self.get_distances()
seconds = self.df['time'].diff()[1:].dt.total_seconds()
velocities = distance/seconds / 3.6
plt.plot(distances.cumsum(), velocities)
plt.xlabel('Distance [km]')
plt.ylabel('Velocity [km/h]')
plt.show()
def plot_trip(self):
"""
creates a graphical plot of the whole trip
"""
plt.plot(self.df['lon'], self.df['lat'])
plt.show()
def print_summary(self):
print('Total distance: {:.3f}'.format(self.total_distance/1000), 'kilometer')
if self.has_time:
print('Total elapsed time:', self.total_elapsed_time, 'hh:mm:ss')
else:
print("time and velocity not available")
if self.has_elevation:
print('start/end elevation m:', self.start_end_elevation)
print('min/max elevation m:', self.min_max_elevation)
print('up/down hill m:', self.up_down_hill)
else:
print("elevation-infos not available")
# private methods
def get_distances(self):
"""
all single distances are calculated in meters, necessary for velocity-calculation
"""
rows = df[['lat','lon']].iterrows()
first = next(rows)
distances = []
for second in rows:
distances.append(
distance.distance(first, second).m
)
first = second
return pd.Series(distances)
def get_velocities(self):
"""
creates a list of all velocities in km/h based on seconds and appropriate distances
"""
distances = self.get_distances()
seconds = self.df['time'].diff()[1:].dt.total_seconds()
return distance/seconds / 3.6
def main():
for filename in glob("data/*.gpx"):
with open(filename) as gpx_file:
gpxdata = gpxpy.parse(gpx_file)
print("results for:", filename)
trajectory = Trajectory(gpxdata)
trajectory.print_summary()
if trajectory.has_time:
trajectory.plot_velocities()
trajectory.plot_trip()
if __name__ == "__main__":
main()