示例#1
0
 def wrapper(*args, **kwargs):
     self.write("Started: {}".format(func.__name__), debug_level)
     timer = Timer()
     res = func(*args, **kwargs)
     exec_time = timer.stop()
     self.write("Finished: {}, execution time: {} seconds".format(func.__name__, round(exec_time, 2)), debug_level)
     return res
示例#2
0
class MainView(View):
    MVG_AVG_SIZE = 3
    __frame_timer: Timer
    __frame_count: int
    __frame_mvg_average: int
    __fps: int
    """
    Draws the model state onto the screen.
    """
    def __init__(self, services: Services, model: Model,
                 root_view: Optional[View]) -> None:
        super().__init__(services, model, root_view)
        self._services.ev_manager.register_tick_listener(self)
        self.__frame_timer = Timer()
        self.__frame_count = 0
        self.__frame_mvg_average = 0
        self.__fps = 0
        self.__screen = None
        self._initialised = False

    def notify(self, event: Event) -> None:
        """
        Receive events posted to the message queue.
        """

        super().notify(event)
        if isinstance(event, QuitEvent):
            self._initialised = False
            self._services.graphics.window.quit()

    def initialise(self) -> None:
        self.__frame_timer = Timer()

    def tick(self) -> None:
        if not self._initialised:
            return
        self.update()

    def update(self) -> None:
        if self.__frame_timer.stop() >= 1:
            if self.__frame_mvg_average == 0:
                self.__fps = self.__frame_count
            else:
                self.__fps += (self.__frame_count -
                               self.__fps) / self.__frame_mvg_average
            self.__frame_mvg_average = min(self.__frame_mvg_average + 1,
                                           self.MVG_AVG_SIZE)
            self.__frame_count = 0
            self.__frame_timer = Timer()
            self._services.debug.write("FPS: " + str(self.__fps),
                                       DebugLevel.MEDIUM)

        for child in self._children:
            child.update()

        # update window
        self._services.graphics.window.update()
        self.__frame_count += 1
示例#3
0
class SelectorManager(object):
    def __init__(self):
        self._selector = None
        self._timer = Timer()

    def set_selector(self, selector):
        self._selector = selector

    def apply(self, event):
        self._timer.start()

        result = self._selector.apply(event) if self._selector else True

        self._timer.stop()

        return result

    def __str__(self):
        return str(self._timer)
示例#4
0
class BasicTesting:
    """
    Basic class used to assess the performance of an algorithms
    All tests must inherit from this class
    """

    timer: Timer
    display_info: List[MapDisplay]
    key_frame: Callable[[List, Dict], None]
    cv: Condition
    key_frame_skip_count: int
    total_time: int

    def __init__(self, services: Services) -> None:
        self._services = services
        self.timer = None
        self.display_info = []
        self.key_frame = lambda *args, **kwargs: None
        self.cv = None
        self.key_frame_skip_count = 0
        self.total_time = 0
        self.last_frame_time = 0
        self.requires_key_frame = False
        self.reset()

    def reset(self) -> None:
        """
        This method resets the testing state
        """
        self.display_info = []
        self.cv = None
        self.key_frame_skip_count = 0
        self.total_time = 0
        self.last_frame_time = 0
        if self._services.settings.simulator_key_frame_speed == 0 or not self._services.settings.simulator_graphics:
            self.key_frame = lambda *args, **kwargs: None
        else:
            self.key_frame = self.key_frame_internal

    def set_condition(self, cv: Condition) -> None:
        """
        Setter for condition
        :param cv:  The condition is used to synchronize key frames
        """
        self.cv = cv

    def algorithm_start(self) -> None:
        """
        Marks the start of the algorithms
        """
        self._services.debug.write(
            "Algorithm " + str(self._services.algorithm.algorithm_type) +
            " started..", DebugLevel.BASIC)
        self.timer = Timer()

    def is_terminated(self) -> bool:
        return self._services.algorithm.instance.testing != self

    def key_frame_internal(self,
                           ignore_key_frame_skip: bool = False,
                           only_render: List[int] = None,
                           root_key_frame=None) -> None:
        """
        Internal key frame handler
        """
        if self.timer is None:
            self._services.debug.write_error(
                "Algorithm " + str(self._services.algorithm.algorithm_type) +
                " hasn't started yet!")
            return
        self.timer.pause()

        if root_key_frame:
            root_key_frame.instance.testing.key_frame(
                ignore_key_frame_skip=ignore_key_frame_skip,
                only_render=only_render)

        def sleep_pred():
            return not self.requires_key_frame or self.is_terminated()

        # skip render frame
        if ignore_key_frame_skip or self.key_frame_skip_count >= self._services.settings.simulator_key_frame_skip:
            self.display_info = self._services.algorithm.instance.set_display_info(
            )

            if only_render:
                self.display_info = [self.display_info[i] for i in only_render]

            if self.cv is not None:
                with self.cv:
                    self.requires_key_frame = True
                    self.cv.notify()
                    cond_var_wait_for(self.cv, sleep_pred)
            self.key_frame_skip_count = 0
        else:
            self.key_frame_skip_count += 1

        # limit key frame speed
        if self.cv is not None:
            t = time.time()
            sleep_dt = self._services.settings.simulator_key_frame_speed - (
                t - self.last_frame_time)
            self.last_frame_time = t

            while sleep_dt > 0:
                with self.cv:
                    self.requires_key_frame = True
                    self.cv.notify()
                    cond_var_wait_for(self.cv, sleep_pred)
                nt = time.time()
                sleep_dt = sleep_dt - nt + t
                t = nt

        if self.is_terminated():
            from simulator.models.map_model import AlgorithmTerminated
            raise AlgorithmTerminated()

        self.timer.resume()

    def algorithm_done(self) -> None:
        """
        Marks the end of the algorithms
        """
        if self.timer is None:
            self._services.debug.write_error(
                "Algorithm " + str(self._services.algorithm.algorithm_type) +
                "did not start!")
            return
        self.total_time = self.timer.stop()

        if self._services.settings.simulator_graphics:
            self.display_info = self._services.algorithm.instance.set_display_info(
            )
        self.print_results()
        self._services.debug.write("", DebugLevel.BASIC, timestamp=False)

    def get_results(self) -> Dict[str, Any]:
        """
        Returns the test results
        :return: The test results
        """
        trace: List[Trace] = self._services.algorithm.map.trace

        grid: Optional[DenseMap] = self._services.algorithm.map
        if isinstance(grid, SparseMap):
            grid: DenseMap = grid.convert_to_dense_map()

        return {
            "map":
            self._services.algorithm.map,
            "map_obstacles_percentage":
            self.get_occupancy_percentage_grid(grid.grid, DenseMap.WALL_ID),
            "goal_found":
            self._services.algorithm.map.is_goal_reached(grid.agent.position),
            "distance_to_goal":
            self.distance_from_agent_to_goal(grid),
            "original_distance_to_goal":
            self.get_original_distance(grid),
            "trace":
            trace,
            "total_steps":
            len(trace),
            "total_distance":
            self.get_euclidean_distance_traveled(trace, grid.agent),
            "smoothness_of_trajectory":
            self.get_smoothness(trace, grid.agent),
            "obstacle_clearance":
            self.get_average_clearance(trace, self._services.algorithm.map),
            "total_time":
            self.total_time,
            "algorithm_type":
            self._services.algorithm.algorithm_type,
        }

    def print_results(self) -> None:
        """
        Prints the test results
        """
        results: Dict[str, Any] = self.get_results()
        self._services.debug.write("Map: " + str(results["map"]),
                                   DebugLevel.MEDIUM)
        self._services.debug.write(
            "Original distance: {0:.2f}".format(
                results["original_distance_to_goal"]), DebugLevel.BASIC)
        self._services.debug.write(
            "Occupancy percentage: {0:.2f}%".format(
                results["map_obstacles_percentage"]), DebugLevel.BASIC)
        self._services.debug.write(
            "Goal was " + ("FOUND" if results["goal_found"] else "NOT FOUND"),
            DebugLevel.BASIC)
        if not results["goal_found"]:
            self._services.debug.write(
                "Distance to goal: " + str(results["distance_to_goal"]) +
                " (Original: {})".format(results["original_distance_to_goal"]))
        self._services.debug.write(
            "Total steps: " + str(results["total_steps"]), DebugLevel.BASIC)
        self._services.debug.write(
            "Total distance: {0:.2f}".format(results["total_distance"]),
            DebugLevel.BASIC)
        self._services.debug.write(
            "Trajectory Smoothness: {0:.2f}".format(
                results["smoothness_of_trajectory"]), DebugLevel.BASIC)
        self._services.debug.write(
            "Total time: " + str(results["total_time"]) + " seconds",
            DebugLevel.BASIC)
        self._services.debug.write("Trace: " + str(results["trace"]),
                                   DebugLevel.MEDIUM)

    @staticmethod
    def get_occupancy_percentage_grid(grid: np.array, token: int) -> float:
        """
        Searches for token in grid and returns the occupancy percentage of the token
        :param grid: The grid
        :param token: The search token
        :return: The percentage
        """
        tokens: int = np.sum(grid == token)

        return BasicTesting.get_occupancy_percentage_size(
            Size(*grid.shape), tokens)

    @staticmethod
    def get_original_distance(mp: Map):
        agent_pos = mp.trace[0].position if mp.trace else None
        return BasicTesting.distance_from_agent_to_goal(mp, agent_pos)

    @staticmethod
    def distance_from_agent_to_goal(mp: Map, agent_pos: Point = None):
        if agent_pos is None:
            agent_pos = mp.agent.position
        dist = np.linalg.norm(np.array(agent_pos) - np.array(mp.goal.position))
        return dist

    @staticmethod
    def get_occupancy_percentage_size(size: Size, items_nr: int) -> float:
        """
        Returns the percentage of present items given the size
        :param size: The size
        :param items_nr:  The number of items
        :return: The percentage
        """
        return (items_nr / reduce(mul, size, 1)) * 100

    @staticmethod
    def get_euclidean_distance_traveled(trace: List[Trace],
                                        agent: Agent) -> float:
        if (not trace) or trace[-1].position != agent.position:
            trace.append(Trace(agent.position))
        dist = 0
        for i in range(1, len(trace)):
            dist += np.linalg.norm(
                np.array(trace[i - 1].position) - np.array(trace[i].position))
        return dist

    @staticmethod
    def get_smoothness(trace: List[Trace], agent: Agent) -> float:
        if (not trace) or trace[-1].position != agent.position:
            trace.append(Trace(agent.position))
        angle = 0
        prev_angle = None

        for i in range(1, len(trace)):

            if (not trace[i - 1].position == trace[i].position):

                unit_vector1 = np.array(trace[i - 1].position -
                                        trace[i].position) / np.linalg.norm(
                                            np.array(trace[i - 1].position -
                                                     trace[i].position))
                t = [0] * (len(agent.position) - 1)
                t = tuple([1] + t)
                dot_product = np.dot(unit_vector1, t)
                if prev_angle is None:
                    prev_angle = np.arccos(dot_product)
                    continue

                angle += abs(prev_angle - np.arccos(dot_product))
                prev_angle = np.arccos(dot_product)

        return (angle / len(trace))

    @staticmethod
    def get_average_clearance(trace: List[Trace], grid: Map) -> float:
        if isinstance(grid, DenseMap):
            obstacles = np.transpose(np.where(grid.grid == grid.WALL_ID))
        else:
            obstacles = np.full(grid.size, grid.CLEAR_ID, dtype=np.uint8)
            for o in grid.obstacles:
                if type(o) is Obstacle:  # we don't want extended wall
                    obstacles[o.position.values] = grid.WALL_ID
            obstacles = np.transpose(np.where(obstacles == grid.WALL_ID))

        if len(grid.obstacles) == 0:
            return 0

        obstacle_dists = []
        for t in trace:
            pos = np.array(t.position.values)
            obstacles_shifted = obstacles - pos
            norms = np.linalg.norm(obstacles_shifted, axis=1)
            min_dist = np.min(norms)
            obstacle_dists.append(min_dist)
        return sum(obstacle_dists) / len(obstacle_dists)

    @property
    def map(self) -> str:
        return "map"

    @map.getter
    def map(self) -> Map:
        return self._services.algorithm.map
示例#5
0
#!/usr/bin/env python

'''
Created by Samvel Khalatyan, May 02, 2012
Copyright 2012, All rights reserved
'''

from __future__ import print_function

import sys
import tempfile

from utility.timer import Timer

if "__main__" == __name__:
    tests = int(sys.argv[1]) if 1 < len(sys.argv) else 1000
    print("run", tests, "tests")

    timer = Timer()

    filename = tempfile.mktemp()
    with open(filename, "w") as output_:
        for test in range(tests):
            timer.start()
            output_.write("this is a test string which should go into file\n")
            timer.stop()

    print(timer)
    print("(outpus is saved in:", filename, ")")
示例#6
0
class MapModel(Model):
    speed: int
    key_frame_is_paused: bool
    last_thread: Thread
    frame_timer: Timer
    condition: Condition
    processing_key_frame: bool

    def __init__(self, services: Services) -> None:
        super().__init__(services)
        self._services.ev_manager.register_tick_listener(self)
        self.last_thread = None
        self.key_frame_is_paused = False
        self.cv = Condition()
        self.processing_key_frame = False
        self.frame_timer = Timer()
        self.speed = 1

        self._services.algorithm.set_root()

    def move_forward(self, e) -> None:
        self.reset()
        if self._services.algorithm.map.size.n_dim == 3:
            p = Point(e.position.x, e.position.y + self.speed, e.position.z)
        else:
            p = Point(e.position.x, e.position.y + self.speed)
        self.move_valid_entity(e, p)

    def move_backwards(self, e) -> None:
        self.reset()
        if self._services.algorithm.map.size.n_dim == 3:
            p = Point(e.position.x, e.position.y - self.speed, e.position.z)
        else:
            p = Point(e.position.x, e.position.y - self.speed)
        self.move_valid_entity(e, p)

    def move_up(self, e) -> None:
        if self._services.algorithm.map.size.n_dim == 3:
            self.reset()
            p = Point(e.position.x, e.position.y, e.position.z + self.speed)
            self.move_valid_entity(e, p)

    def move_down(self, e) -> None:
        if self._services.algorithm.map.size.n_dim == 3:
            self.reset()
            p = Point(e.position.x, e.position.y, e.position.z - self.speed)
            self.move_valid_entity(e, p)

    def move_left(self, e) -> None:
        self.reset()
        if self._services.algorithm.map.size.n_dim == 3:
            p = Point(e.position.x - self.speed, e.position.y, e.position.z)
        else:
            p = Point(e.position.x - self.speed, e.position.y)
        self.move_valid_entity(e, p)

    def move_right(self, e) -> None:
        self.reset()
        if self._services.algorithm.map.size.n_dim == 3:
            p = Point(e.position.x + self.speed, e.position.y, e.position.z)
        else:
            p = Point(e.position.x + self.speed, e.position.y)
        self.move_valid_entity(e, p)

    def move_valid_entity(self, e, p) -> None:
        if self._services.algorithm.map.is_agent_valid_pos(p):
            if self.is_agent(e):
                self.move(p, False)
                self._services.debug.write("Moved agent to: " + str(p),
                                           DebugLevel.MEDIUM)
            else:
                self.move_goal(p, False)
                self._services.debug.write("Moved goal to: " + str(p),
                                           DebugLevel.MEDIUM)

    def is_agent(self, e) -> bool:
        return e is self._services.algorithm.map.agent

    def reset(self) -> None:
        self.stop_algorithm()
        self._services.algorithm.reset_algorithm()
        if self.processing_key_frame:
            self.processing_key_frame = False
            with self.cv:
                self.requires_key_frame = False
                self.cv.notify_all()
        with self.cv:
            cond_var_wait_for(
                self.cv,
                lambda: self.last_thread is None or self.requires_key_frame,
                timeout=0.8)
            if self.last_thread is not None:
                self.requires_key_frame = False
                self.cv.notify_all()
                cond_var_wait_for(self.cv,
                                  lambda: self.last_thread is None,
                                  timeout=0.8)
            self.requires_key_frame = False
            if self.last_thread is None:
                self._services.ev_manager.post(KeyFrameEvent(refresh=True))

    def move(self, to: Point, should_reset: bool = True) -> None:
        if should_reset:
            self.reset()
        self._services.algorithm.map.move_agent(to, True)
        self._services.ev_manager.broadcast(StateEntityUpdateEvent())

    def move_goal(self, to: Point, should_reset: bool = True) -> None:
        if should_reset:
            self.reset()
        self._services.algorithm.map.move(self._services.algorithm.map.goal,
                                          to, True)
        self._services.ev_manager.broadcast(StateEntityUpdateEvent())

    def stop_algorithm(self) -> None:
        self.key_frame_is_paused = True

    def resume_algorithm(self) -> None:
        self.key_frame_is_paused = False

    def toggle_pause_algorithm(self) -> None:
        self.key_frame_is_paused = not self.key_frame_is_paused

    @property
    def requires_key_frame(self) -> bool:
        return self._services.algorithm.instance.testing is not None and self._services.algorithm.instance.testing.requires_key_frame

    @requires_key_frame.setter
    def requires_key_frame(self, value) -> None:
        if self._services.algorithm.instance.testing is not None:
            self._services.algorithm.instance.testing.requires_key_frame = value

    def tick(self) -> None:
        if self.processing_key_frame:
            self.processing_key_frame = False
            with self.cv:
                self.requires_key_frame = False
                self.cv.notify_all()

        if not self.key_frame_is_paused and self.last_thread is not None:
            MAX_FRAME_DT = 1 / 16
            dt = self.frame_timer.stop()
            if self.requires_key_frame or (dt < MAX_FRAME_DT):
                with self.cv:
                    if cond_var_wait_for(self.cv,
                                         lambda: self.requires_key_frame or
                                         self.last_thread is None,
                                         timeout=(MAX_FRAME_DT - dt)):
                        self.processing_key_frame = True
                        self._services.ev_manager.post(KeyFrameEvent())
                self.frame_timer = Timer()

    def compute_trace(self) -> None:
        if self.last_thread:
            return

        self.reset()

        def compute_wrapper() -> None:
            terminated = False
            self.key_frame_is_paused = False
            if self._services.settings.simulator_key_frame_speed > 0:
                self._services.algorithm.instance.set_condition(self.cv)
            self._services.ev_manager.post(KeyFrameEvent(refresh=True))
            try:
                self._services.algorithm.instance.find_path()
            except AlgorithmTerminated:
                self._services.debug.write("Terminated algorithm",
                                           DebugLevel.BASIC)
                self._services.ev_manager.post(KeyFrameEvent(refresh=True))
                terminated = True
            if self._services.settings.simulator_key_frame_speed == 0:
                # no animation hence there hasn't been a chance to render
                # the last state of the algorithm.
                self._services.ev_manager.post(KeyFrameEvent(refresh=True))

            self._services.ev_manager.broadcast(
                StateTerminatedEvent() if terminated else StateDoneEvent())

            with self.cv:
                self.last_thread = None
                self.cv.notify()

        self.last_thread = Thread(target=compute_wrapper, daemon=True)
        self.last_thread.start()

    def toggle_convert_map(self) -> None:
        if isinstance(self._services.algorithm.map, DenseMap):
            self._services.debug.write("Converting map to SparseMap",
                                       DebugLevel.BASIC)
            mp = self._services.algorithm.map.convert_to_sparse_map()
        elif isinstance(self._services.algorithm.map, SparseMap):
            self._services.debug.write("Converting map to DenseMap",
                                       DebugLevel.BASIC)
            mp = self._services.algorithm.map.convert_to_dense_map()
        else:
            self._services.debug.write("Map conversion not applicable",
                                       DebugLevel.BASIC)
            return

        if mp is None:
            self._services.debug.write("Map conversion not applicable",
                                       DebugLevel.BASIC)
            return

        self.reset()
        timer: Timer = Timer()
        self._services.algorithm.map = mp
        self._services.debug.write(
            "Done converting. Total time: " + str(timer.stop()),
            DebugLevel.BASIC)
        self._services.debug.write(self._services.algorithm.map,
                                   DebugLevel.MEDIUM)
        self._services.ev_manager.post(KeyFrameEvent())

    def notify(self, event: Event) -> None:
        """
        Called by an event in the message queue.
        """

        if isinstance(event, ResetEvent):
            self.reset()
示例#7
0
    def generate_map_from_image(self,
                                image_name: str,
                                rand_entities: bool = False,
                                entity_radius: int = None,
                                house_expo_flag: bool = False) -> Map:
        """
        Generate a map from an image
        Load the image from the default location and save the map in the default location
        :param image_name: The image name
        :return: The map
        """
        self.__services.debug.write(
            "Started map generation from image: " + str(image_name) +
            " With House_expo = " + str(house_expo_flag), DebugLevel.BASIC)
        timer: Timer = Timer()

        # loading image
        if house_expo_flag:
            surface: np.ndarray = self.__services.resources.house_expo_dir.load(
                image_name)
        else:
            surface: np.ndarray = self.__services.resources.images_dir.load(
                image_name)
        height, width, _ = surface.shape
        self.__services.debug.write(
            "Image loaded with Resolution:" + str(width) + " x " + str(height),
            DebugLevel.HIGH)

        grid = np.full(surface.shape[:-1], Map.CLEAR_ID, dtype=np.uint8)
        agent_avg_location: np.ndarray = np.array([.0, .0])
        agent_avg_count: int = 1
        goal_avg_location: np.ndarray = np.array([.0, .0])

        if house_expo_flag:
            '''
            We can optimize for house_expo dataset by skipping the check for the goal and agent at each pixel,
            instead, we can only identify obstacles
            '''
            self.__services.debug.write("Begin iteration through map",
                                        DebugLevel.HIGH)
            for idx in np.ndindex(surface.shape[:-1]):
                if Generator.is_in_color_range(surface[idx],
                                               Generator.WALL_COLOR):
                    grid[idx] = DenseMap.WALL_ID
        else:
            for idx in np.ndindex(surface.shape[:-1]):
                if Generator.is_in_color_range(surface[idx],
                                               Generator.AGENT_COLOR, 5):
                    agent_avg_location, agent_avg_count = \
                        Generator.increment_moving_average(agent_avg_location, agent_avg_count, np.array(idx[::-1]))
                elif Generator.is_in_color_range(surface[idx],
                                                 Generator.GOAL_COLOR, 5):
                    goal_avg_location, goal_avg_count = \
                        Generator.increment_moving_average(goal_avg_location, goal_avg_count, np.array(idx[::-1]))
                if Generator.is_in_color_range(surface[idx],
                                               Generator.WALL_COLOR):
                    grid[idx] = DenseMap.WALL_ID

        agent_avg_location = np.array(agent_avg_location, dtype=int)
        goal_avg_location = np.array(goal_avg_location, dtype=int)
        agent_radius: float = 0

        if rand_entities:
            self.__place_random_agent_and_goal(grid, Size(height, width))
            self.__services.debug.write("Placed random agent and goal ",
                                        DebugLevel.HIGH)
        else:
            grid[tuple(agent_avg_location[::-1])] = DenseMap.AGENT_ID
            grid[tuple(goal_avg_location[::-1])] = DenseMap.GOAL_ID

        if not house_expo_flag:
            '''
            We can optimize the house_expo generation by skipping this step, 
            as we have already defined the agent radius
            '''
            self.__services.debug.write(
                "Skipped agent_radius change checking ", DebugLevel.HIGH)

            for idx in np.ndindex(surface.shape[:-1]):
                if Generator.is_in_color_range(surface[idx],
                                               Generator.AGENT_COLOR, 5):
                    '''
                    If color at x y is red (agent) then change the radius of the agent to the max 
                    Change the agent radius to the max between the old radius (from previous iteration )
                    and the magnitude of the agent location - the point 
                        and the magnitude of the agent location - the point 
                    and the magnitude of the agent location - the point 
                    This basically defines the agent radius as the largest red size. But we don't need to do
                    this as we are supplying our own radius
                    '''
                    agent_radius = max(
                        agent_radius,
                        np.linalg.norm(agent_avg_location -
                                       np.array(idx[::-1])))

        agent_radius = int(agent_radius)

        if entity_radius:
            agent_radius = entity_radius

        res_map: DenseMap = DenseMap(grid)
        res_map.agent.radius = agent_radius
        res_map.goal.radius = agent_radius

        self.__services.debug.write(
            "Generated initial dense map in " + str(timer.stop()) + " seconds",
            DebugLevel.BASIC)
        timer = Timer()
        res_map.extend_walls()
        self.__services.debug.write(
            "Extended walls in " + str(timer.stop()) + " seconds",
            DebugLevel.BASIC)
        map_name: str = str(image_name.split('.')[0]) + ".pickle"
        if house_expo_flag:
            path = os.path.join(os.path.join(DATA_PATH, "maps"), "house_expo")
            self.__services.resources.house_expo_dir.save(
                map_name, res_map, path)
        else:
            self.__services.resources.maps_dir.save(map_name, res_map)
        self.__services.debug.write(
            "Finished generation. Map is in resources folder",
            DebugLevel.BASIC)
        return res_map