diff --git a/maps4fs/generator/component.py b/maps4fs/generator/component.py index 77cf994b..97990ede 100644 --- a/maps4fs/generator/component.py +++ b/maps4fs/generator/component.py @@ -2,7 +2,9 @@ from __future__ import annotations +import json import os +from copy import deepcopy from typing import TYPE_CHECKING, Any import osmnx as ox # type: ignore @@ -81,6 +83,57 @@ def previews_directory(self) -> str: """ return os.path.join(self.map_directory, "previews") + @property + def generation_info_path(self) -> str: + """The path to the generation info JSON file. + + Returns: + str: The path to the generation info JSON file. + """ + return os.path.join(self.map_directory, "generation_info.json") + + def info_sequence(self) -> dict[Any, Any]: + """Returns the information sequence for the component. Must be implemented in the child + class. If the component does not have an information sequence, an empty dictionary must be + returned. + + Returns: + dict[Any, Any]: The information sequence for the component. + """ + return {} + + def commit_generation_info(self) -> None: + """Commits the generation info to the generation info JSON file.""" + self.update_generation_info(self.info_sequence()) + + def update_generation_info(self, data: dict[Any, Any]) -> None: + """Updates the generation info with the provided data. + If the generation info file does not exist, it will be created. + + Args: + data (dict[Any, Any]): The data to update the generation info with. + """ + if os.path.isfile(self.generation_info_path): + with open(self.generation_info_path, "r", encoding="utf-8") as file: + generation_info = json.load(file) + self.logger.debug("Loaded generation info from %s", self.generation_info_path) + else: + self.logger.debug( + "Generation info file does not exist, creating a new one in %s", + self.generation_info_path, + ) + generation_info = {} + + updated_generation_info = deepcopy(generation_info) + updated_generation_info[self.__class__.__name__] = data + + self.logger.debug("Updated generation info, now contains %s fields", len(data)) + + with open(self.generation_info_path, "w", encoding="utf-8") as file: + json.dump(updated_generation_info, file, indent=4) + + self.logger.debug("Saved updated generation info to %s", self.generation_info_path) + def get_bbox(self, project_utm: bool = False) -> tuple[int, int, int, int]: """Calculates the bounding box of the map from the coordinates and the height and width of the map. diff --git a/maps4fs/generator/map.py b/maps4fs/generator/map.py index b9099462..3e914fa3 100644 --- a/maps4fs/generator/map.py +++ b/maps4fs/generator/map.py @@ -83,6 +83,16 @@ def generate(self) -> None: e, ) raise e + + try: + component.commit_generation_info() + except Exception as e: # pylint: disable=W0718 + self.logger.error( + "Error committing generation info for component %s: %s", + component.__class__.__name__, + e, + ) + raise e self.components.append(component) pbar.update(1) diff --git a/maps4fs/generator/texture.py b/maps4fs/generator/texture.py index c5ea906e..72801d54 100644 --- a/maps4fs/generator/texture.py +++ b/maps4fs/generator/texture.py @@ -5,7 +5,7 @@ import json import os import warnings -from typing import Callable, Generator, Optional +from typing import Any, Callable, Generator, Optional import cv2 import numpy as np @@ -149,7 +149,6 @@ def process(self): self._prepare_weights() self._read_parameters() self.draw() - self.info_sequence() # pylint: disable=W0201 def _read_parameters(self) -> None: @@ -176,23 +175,8 @@ def _read_parameters(self) -> None: self.width_coef = self.width / self.map_width self.logger.debug("Map coefficients (HxW): %s x %s.", self.height_coef, self.width_coef) - def info_sequence(self) -> None: - """Saves generation info to JSON file "generation_info.json". - - Info sequence contains following attributes: - - coordinates - - bbox - - map_height - - map_width - - minimum_x - - minimum_y - - maximum_x - - maximum_y - - height - - width - - height_coef - - width_coef - """ + def info_sequence(self) -> dict[str, Any]: + """Returns the JSON representation of the generation info for textures.""" useful_attributes = [ "coordinates", "bbox", @@ -207,11 +191,7 @@ def info_sequence(self) -> None: "height_coef", "width_coef", ] - info_sequence = {attr: getattr(self, attr, None) for attr in useful_attributes} - - with open(self.info_save_path, "w") as f: # pylint: disable=W1514 - json.dump(info_sequence, f, indent=4) - self.logger.info("Generation info saved to %s.", self.info_save_path) + return {attr: getattr(self, attr, None) for attr in useful_attributes} def _prepare_weights(self): self.logger.debug("Starting preparing weights from %s layers.", len(self.layers))