def dataset_avg_elevation_diff(dataset, overlap, savgol_window, polynom=2): sqr_elev_diff = 0.0 elev_diff = 0.0 for entry in dataset: dists = entry['dists'] alts1 = entry['alts_orig'] if savgol_window is None: alts2 = entry['alts_srtm_raw'] else: alts2 = elefix.set_altitudes(entry['lats'], entry['lons'], True, savgol_window, polynom) entry_elev_diff = track_avg_elevation_diff(dists, alts1, alts2, overlap) sqr_elev_diff += (entry_elev_diff**2) elev_diff += entry_elev_diff return (math.sqrt(sqr_elev_diff / len(dataset)), (elev_diff / len(dataset)))
def calculate_acc_deviation(dataset, savgol_window, vertical_threshold=DEFAULT_VERT_THRESHOLD, polynom=2): sqr_deviation = 0.0 deviation = 0.0 for entry in dataset: totaldist = entry['dists'][-1] eg_orig = elevation_gain(entry['alts_orig'], totaldist, DEFAULT_VERT_THRESHOLD) if savgol_window is None and vertical_threshold is None: eg_srtm = elevation_gain(entry['alts_srtm_raw'], totaldist, DEFAULT_VERT_THRESHOLD) else: alts_srtm = elefix.set_altitudes(entry['lats'], entry['lons'], True, savgol_window, polynom) eg_srtm = elevation_gain(alts_srtm, totaldist, vertical_threshold) current_deviation = abs(eg_srtm - eg_orig) sqr_deviation += (current_deviation**2) deviation += current_deviation return (math.sqrt(sqr_deviation / len(dataset)), (deviation / len(dataset)))
def main(dataset_dir, window, grade): # validate input directory if not os.path.isdir(dataset_dir): raise ValueError('"dataset_dir" is not a valid directory path') # prepare dataset # each dataset entry: {'lats', 'lons', 'dists', 'alts_orig', 'alts_srtm_raw'} dataset = [] for fname in os.listdir(dataset_dir): # validate file _, ext = os.path.splitext(fname) fpath = os.path.join(dataset_dir, fname) if not os.path.isfile(fpath) or ext not in ['.gpx', '.tcx']: continue # parse input file with open(fpath, 'r') as f: track_content = f.read() if ext.lower() == '.gpx': wpts = elefix.gpx_parse(track_content) else: # ext.lower() == '.tcx' wpts = elefix.tcx_parse(track_content) # remove waypoints for which the distance to the next one is 0 i = 0 while i < len(wpts) - 1: if elefix.wpt_distance(wpts[i], wpts[i + 1]) == 0.0: del wpts[i] else: i += 1 # original latitudes, longitudes and altitudes latitudes = [wpt.lat for wpt in wpts] longitudes = [wpt.lon for wpt in wpts] altitudes = [wpt.alt for wpt in wpts] # accumulated distance on each waypoint dists = [ elefix.wpt_distance(wpair[0], wpair[1]) for wpair in zip(wpts[:-1], wpts[1:]) ] dists_acc = [sum(dists[:i]) for i in range(len(wpts))] # SRTM raw altitudes alts_srtm_raw = elefix.set_altitudes(latitudes, longitudes, smooth=False) dataset_entry = { 'lats': latitudes, 'lons': longitudes, 'dists': dists_acc, 'alts_orig': altitudes, 'alts_srtm_raw': alts_srtm_raw, } dataset.append(dataset_entry) # SRTM raw altitudes (baseline) sqr_avg_acc_dev, avg_acc_dev = calculate_acc_deviation( dataset, None, None, None) sqr_avg_ele_diff, avg_ele_diff = dataset_avg_elevation_diff( dataset, True, None, None) print( 'N\tG\tEGD (quadratic mean)\tEGD (mean)\tAPD (quadratic mean)\tAPD (mean)' .format(sqr_avg_acc_dev, avg_acc_dev, sqr_avg_ele_diff, avg_ele_diff)) print('-\t-\t{:.2f}\t{:.2f}\t{:.2f}\t{:.2f}'.format( sqr_avg_acc_dev, avg_acc_dev, sqr_avg_ele_diff, avg_ele_diff)) # SRTM smoothed altitudes after applying Savitzky-Golay filter best_acc = [None, None, 999999, None] # window, sqr_avg_acc_dev, avg_acc_dev best_elediff = [None, None, 999999, None] # window, sqr_avg_ele_diff, avg_ele_diff sqr_avg_acc_dev, avg_acc_dev = calculate_acc_deviation( dataset, window, DEFAULT_VERT_THRESHOLD, grade) sqr_avg_ele_diff, avg_ele_diff = dataset_avg_elevation_diff( dataset, True, window, grade) print('{}\t{}\t{:.2f}\t{:.2f}\t{:.2f}\t{:.2f}'.format( window, grade, sqr_avg_acc_dev, avg_acc_dev, sqr_avg_ele_diff, avg_ele_diff))
def main(track_fpath, window, grade): # validate input fname, ext = os.path.splitext(track_fpath) if ext.lower() not in ['.gpx', '.tcx']: raise ValueError("Input file's format must be GPX or TCX") # parse input file with open(track_fpath, 'r') as f: track_content = f.read() if ext.lower() == '.gpx': wpts = elefix.gpx_parse(track_content) else: # ext.lower() == '.tcx' wpts = elefix.tcx_parse(track_content) # remove waypoints for which the distance to the next one is 0 i = 0 while i < len(wpts) - 1: if elefix.wpt_distance(wpts[i], wpts[i + 1]) == 0.0: del wpts[i] else: i += 1 # parsed original latitudes, longitudes and altitudes latitudes = [wpt.lat for wpt in wpts] longitudes = [wpt.lon for wpt in wpts] altitudes_orig = [wpt.alt for wpt in wpts] # accumulated distance on each waypoint dists = [ elefix.wpt_distance(wpair[0], wpair[1]) for wpair in zip(wpts[:-1], wpts[1:]) ] dists_acc = [sum(dists[:i]) for i in range(len(wpts))] totaldist = dists_acc[-1] # original accumulated elevation gain eg_orig = elevation_gain(altitudes_orig, totaldist, DEFAULT_VERT_THRESHOLD) # SRTM raw altitudes altitudes_srtm_raw = elefix.set_altitudes(latitudes, longitudes, smooth=False) eg_srtm_raw = elevation_gain(altitudes_srtm_raw, totaldist, DEFAULT_VERT_THRESHOLD) diff_srtm_raw = track_avg_elevation_diff(dists_acc, altitudes_orig, altitudes_srtm_raw, True) # SRTM smoothed altitudes altitudes_srtm = elefix.set_altitudes(latitudes, longitudes, True, window, grade) eg_srtm = elevation_gain(altitudes_srtm, totaldist, DEFAULT_VERT_THRESHOLD) diff_srtm = track_avg_elevation_diff(dists_acc, altitudes_orig, altitudes_srtm, True) # print elevation gain values print("Elevation gain (original): {:.2f}".format(eg_orig * (totaldist / 1000))) print("Elevation gain (SRTM + smoothing): {:.2f}".format( eg_srtm * (totaldist / 1000))) print("Elevation gain (raw SRTM): {:.2f}".format(eg_srtm_raw * (totaldist / 1000))) print("Avg elevation diff (SRTM + smoothing): {:.2f}".format(diff_srtm)) print("Avg elevation diff (raw SRTM): {:.2f}".format(diff_srtm_raw)) # draw diagram wpts = [] for w in zip(dists_acc, altitudes_orig, altitudes_srtm_raw, altitudes_srtm): wpts.append({'dist': w[0], 'type': 'Original', 'alt': w[1]}) wpts.append({'dist': w[0], 'type': 'SRTM', 'alt': w[2]}) wpts.append({ 'dist': w[0], 'type': 'SRTM + Savitzky-Golay', 'alt': w[3] }) fig = px.line(wpts, x='dist', y='alt', color='type', template='simple_white', labels={ 'dist': 'Distance', 'alt': 'Altitude', 'type': 'Data source', }) fig.update_traces(patch={"line": { "color": "blue", "width": 1 }}, selector={"legendgroup": "Original"}) fig.update_traces(patch={"line": { "color": "red", "width": 1 }}, selector={"legendgroup": "SRTM"}) fig.update_traces(patch={"line": { "color": "green", "width": 1 }}, selector={"legendgroup": "SRTM + Savitzky-Golay"}) fig.show()