Skip to content

Commit

Permalink
[5.1.0] Remove Height profile (#455)
Browse files Browse the repository at this point in the history
* Remove obsolete code in AutomaticWalkTimeTableGenerator

* remove obsolete docker-compose.yml version field

* remove heightprofile

* run linter

* bump version, update docs, drop obsolete requirement

* change version to minor update

* remove user chosen map/excel generation, always generate both
  • Loading branch information
maede97 authored Aug 4, 2024
1 parent 6b98879 commit 23894aa
Show file tree
Hide file tree
Showing 13 changed files with 61 additions and 224 deletions.
3 changes: 1 addition & 2 deletions backend/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -294,13 +294,12 @@ def create_export(options, uuid):
options["print_api_base_url"] = os.environ["PRINT_API_BASE_URL"]
options["output_directory"] = output_directory

options["settings"]["create_elevation_profile"] = True
if "name_points_in_export" not in options["settings"]:
options["settings"]["name_points_in_export"] = True

logger.info("OPTIONS:" + str(options))

generator = AutomatedWalkTableGenerator(uuid, options, manual_mode=True)
generator = AutomatedWalkTableGenerator(uuid, options)
generator.set_data(path, way_points, pois)
generator.run()

Expand Down
163 changes: 55 additions & 108 deletions backend/automatic_walk_time_tables/generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,13 @@
from automatic_walk_time_tables.path_transformers.pois_transfomer import POIsTransformer
from automatic_walk_time_tables.utils import path
from automatic_walk_time_tables.utils.file_parser import GeoFileParser
from automatic_walk_time_tables.walk_time_table.walk_table import (
plot_elevation_profile,
create_walk_table,
)
from automatic_walk_time_tables.walk_time_table.walk_table import create_walk_table
from server_logging.status_handler import ExportStateLogger
from automatic_walk_time_tables.utils.error import UserException


class AutomatedWalkTableGenerator:
def __init__(
self, uuid: str, options: dict, file_content: str = "", manual_mode=False
):
def __init__(self, uuid: str, options: dict):
self.__path: path.Path | None = None
self.__pois: path.Path | None = None
self.__way_points: path.Path | None = None
Expand All @@ -45,24 +40,6 @@ def __init__(
)
pathlib.Path(self.__output_directory).mkdir(parents=True, exist_ok=True)

# Do nothing in manual mode
if manual_mode:
return

# TODO: drop the next few lines, as we are only supporting calling this Generator from within the backend app.
# and there, we hardcoded manual_mode = True

if "file_type" not in options or options["file_type"] is None:
raise Exception("No file ending provided.")

if file_content is None:
raise Exception("No GPX/KML file provided with the POST request.")

geo_file_parser = GeoFileParser(fetch_elevation=False)
self.__path = geo_file_parser.parse(
file_content=file_content, extension=options["file_type"]
)

def run(self):
self.__log_runtime(self.__create_files, "Benötigte Zeit für Export")

Expand All @@ -74,12 +51,12 @@ def run(self):
)

def __create_files(self):
gpx_rout_name = self.__path.route_name
gpx_route_name = self.__path.route_name

name = (
self.__output_directory + "Route"
if gpx_rout_name == ""
else self.__output_directory + gpx_rout_name
if gpx_route_name == ""
else self.__output_directory + gpx_route_name
)

# calc POIs for the path
Expand Down Expand Up @@ -113,90 +90,60 @@ def __create_files(self):
},
)

# name points of walk-time table
if (
self.options["settings"]["create_excel"]
or self.options["settings"]["create_map_pdfs"]
):
naming_fetcher = NamingTransformer()
self.__way_points = naming_fetcher.transform(self.__way_points)

if self.options["settings"]["create_elevation_profile"]:
self.__logger.debug(
"Boolean indicates that we should create the elevation profile."
)
self.__log_runtime(
plot_elevation_profile,
"Benötigte Zeit zum Zeichnen des Höhenprofils",
self.__path,
self.__way_points,
self.__pois,
file_name=name,
legend_position=self.options["settings"]["legend_position"],
)
self.__logger.log(
ExportStateLogger.REQUESTABLE,
"Höhenprofil wurde erstellt.",
{"uuid": self.uuid, "status": GeneratorStatus.RUNNING},
)
naming_fetcher = NamingTransformer()
self.__way_points = naming_fetcher.transform(self.__way_points)

if self.options["settings"]["create_excel"]:
# We use fetch map numbers only for the selected way points,
# this is much faster that for every point in the original path. As the swiss_TML_api uses a tolerance
# of 2_000m anyway the chance to miss a map number is very small.
# We use fetch map numbers only for the selected way points,
# this is much faster that for every point in the original path. As the swiss_TML_api uses a tolerance
# of 2_000m anyway the chance to miss a map number is very small.

map_numbers = self.__log_runtime(
fetch_map_numbers,
"Benötigte Zeit um die Karten-Nummern zu berechnen",
self.__way_points,
)
self.__logger.debug("Input File Name: %s", name)
self.__logger.debug("Map Numbers: %s", map_numbers)

self.__logger.debug(
"Boolean indicates that we should create walk-time table as Excel file"
)
self.__log_runtime(
create_walk_table,
"Benötigte Zeit zum Erstellen der Excel-Tabelle",
self.options["settings"]["departure_time"],
self.options["settings"]["velocity"],
self.__way_points,
route_name=gpx_rout_name,
file_name=name,
creator_name=self.options["settings"]["creator_name"],
map_numbers=map_numbers,
)
map_numbers = self.__log_runtime(
fetch_map_numbers,
"Benötigte Zeit um die Karten-Nummern zu berechnen",
self.__way_points,
)
self.__logger.debug("Input File Name: %s", name)
self.__logger.debug("Map Numbers: %s", map_numbers)

self.__log_runtime(
create_walk_table,
"Benötigte Zeit zum Erstellen der Excel-Tabelle",
self.options["settings"]["departure_time"],
self.options["settings"]["velocity"],
self.__way_points,
route_name=gpx_route_name,
file_name=name,
creator_name=self.options["settings"]["creator_name"],
map_numbers=map_numbers,
)

self.__logger.log(
ExportStateLogger.REQUESTABLE,
"Marschzeittabelle wurde erstellt.",
{"uuid": self.uuid, "status": GeneratorStatus.RUNNING},
)
self.__logger.log(
ExportStateLogger.REQUESTABLE,
"Marschzeittabelle wurde erstellt.",
{"uuid": self.uuid, "status": GeneratorStatus.RUNNING},
)

if self.options["settings"]["create_map_pdfs"]:
self.__logger.debug("Boolean indicates that we should create map PDFs.")
self.__logger.log(
ExportStateLogger.REQUESTABLE,
"Karten werden erstellt...",
{"uuid": self.uuid, "status": GeneratorStatus.RUNNING},
)
map_creator = MapCreator(self.__path, self.uuid, self.options["settings"])
self.__log_runtime(
map_creator.plot_route_on_map,
"Benötigte Zeit zum Erstellen der Karten-PDFs",
self.__way_points,
pois=self.__pois,
file_name=name,
map_scaling=self.options["settings"]["map_scaling"],
map_layers=list(
map(
lambda layer: layer.strip(),
self.options["settings"]["map_layers"].split(","),
)
),
print_api_base_url=self.options["print_api_base_url"],
)
self.__logger.log(
ExportStateLogger.REQUESTABLE,
"Karten werden erstellt...",
{"uuid": self.uuid, "status": GeneratorStatus.RUNNING},
)
map_creator = MapCreator(self.__path, self.uuid, self.options["settings"])
self.__log_runtime(
map_creator.plot_route_on_map,
"Benötigte Zeit zum Erstellen der Karten-PDFs",
self.__way_points,
pois=self.__pois,
file_name=name,
map_scaling=self.options["settings"]["map_scaling"],
map_layers=list(
map(
lambda layer: layer.strip(),
self.options["settings"]["map_layers"].split(","),
)
),
print_api_base_url=self.options["print_api_base_url"],
)

def __log_runtime(
self,
Expand Down
82 changes: 0 additions & 82 deletions backend/automatic_walk_time_tables/walk_time_table/walk_table.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
from multiprocessing import Process

import openpyxl
from matplotlib import pyplot as plt

from automatic_walk_time_tables.utils import path, error
from automatic_walk_time_tables.utils.path import Path
Expand All @@ -14,87 +13,6 @@
logger = logging.getLogger(__name__)


def plot_elevation_profile(
path_: path.Path,
way_points: path.Path,
pois: path.Path,
file_name: str,
legend_position: str,
):
"""
Plots the elevation profile of the path contained in the GPX-file. In addition, the
plot contains the approximated elevation profile by the way_points.
Saves the plot as an image in the ./output directory as an image called {{file_name}}<.png
"""

p = Process(
target=_plot_elevation_profile,
args=(file_name, legend_position, path_, pois, way_points),
)
p.start()
p.join()


def _plot_elevation_profile(file_name, legend_position, path_, pois, way_points):
# clear the plot, plot heights of exported data from SchweizMobil
plt.clf()
distances = [p.accumulated_distance for p in path_.way_points]
heights = [p.point.h for p in path_.way_points]
plt.plot([d / 1_000.0 for d in distances], heights, label="Wanderweg", zorder=1)
# resize plot area
additional_space = log(max(heights) - min(heights)) * 25
plt.ylim(ymax=max(heights) + additional_space, ymin=min(heights) - additional_space)
# add way_points to plot
plt.plot(
[p.accumulated_distance / 1_000.0 for p in way_points.way_points],
[p.point.h for p in way_points.way_points],
label="Marschzeittabelle",
zorder=2,
)
plt.scatter(
[p.accumulated_distance / 1_000.0 for p in pois.way_points],
[p.point.h for p in pois.way_points],
c="lightblue",
zorder=1,
label="Points of Interest",
)
plt.scatter(
[p.accumulated_distance / 1_000.0 for p in way_points.way_points],
[p.point.h for p in way_points.way_points],
c="orange",
s=15,
zorder=4,
label="Wegpunkte",
)
# Check difference between the length of the original path and the length of the way points
logger.info(
"way_points = {} | distances = {}".format(
way_points.way_points[-1].accumulated_distance, distances[-1]
)
)
assert (
abs(way_points.way_points[-1].accumulated_distance - distances[-1]) <= 250
) # max diff 250 meters
# labels
plt.ylabel("Höhe [m ü. M.]")
plt.xlabel("Distanz [km]")
plt.title("Höhenprofil", fontsize=20)
plt.legend(loc=legend_position, frameon=False)
# Grid
plt.grid(color="gray", linestyle="dashed", linewidth=0.5)
# Check if output directory exists, if not, create it.
if not os.path.exists("output"):
os.mkdir("output")
# show the plot and save image
plt.savefig(file_name + "_elevation_profile.png", dpi=750)
logger.info(
"Elevation profile plot saved as " + file_name + "_elevation_profile.png"
)


def create_walk_table(
time_stamp_iso,
speed,
Expand Down
1 change: 0 additions & 1 deletion backend/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ gpxpy==1.6.2
numpy==2.0.1
geopy==2.4.1
openpyxl==3.1.5
matplotlib==3.9.1
grequests==0.7.0
pyclustering==0.10.1.2
polyline==2.0.2
Expand Down
1 change: 0 additions & 1 deletion docker-compose.local-dev.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
version: "3.9"

# Empty as this mode is the default and already specified in docker-compose.yml
services: {}
2 changes: 0 additions & 2 deletions docker-compose.prod-dev.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
version: "3.9"

services:

awt-docs:
Expand Down
2 changes: 0 additions & 2 deletions docker-compose.prod-latest.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
version: "3.9"

services:

awt-docs:
Expand Down
3 changes: 3 additions & 0 deletions docs/changelog/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ A complete, technical changelog is available at [GitHub](https://github.com/cevi
- Fixes a bug where the generated Excel file was buggy (5.0.0)
- Add 1:5'000 scale to the PDF export (5.0.0)
- Dependency updates
- Bug fixes
- Do not create height profile anymore (5.1.0)
- Always create map pdf and excel (5.1.0)

## Version 4 - Improved Error handling & drop CLI support
- Add option to delete waypoints (4.1.0)
Expand Down
2 changes: 1 addition & 1 deletion e2e/cypress/e2e/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export function export_with_interaction(file) {
cy.wait(500)

cy.get('#goto-step-3').click();
cy.get('[formControlName="create_map_pdfs"]').click(); // no map
cy.get('[formControlName="auto_scale"]').click(); // auto scale of map

cy.get('#goto-step-4').click();
cy.get('#goto-step-5').click();
Expand Down
2 changes: 1 addition & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "automatic-walk-time-tables",
"version": "5.0.4",
"version": "5.1.0",
"scripts": {
"ng": "ng",
"start": "tsc set-env.ts && BACKEND_DOMAIN=http://localhost:5000 node set-env.js && angular-build-info && ng serve",
Expand Down
Loading

0 comments on commit 23894aa

Please sign in to comment.