Source code for shyft.dashboard.maps.map_axes

from typing import List, Tuple

import numpy as np
from bokeh.models import Range1d

from shyft.dashboard.time_series.bindable import Bindable, BindableError


[docs] class MapAxesRanges(Bindable):
[docs] def __init__(self, width: int, height: int, xmin: float=0, ymin: float=0, xmax: float=1, ymax: float=1, padding: float=0) -> None: """ Class handling axes ranges for map figures. Padding is an extra distance in map units added outside the calculated axes range. Note: All axes bounds are defined as Tuples with x_min, y_min, x_max, y_max, i.e. defined as bbox coordinates """ super().__init__() self._aspect_ration_xy = width/height self._x_min = xmin self._y_min = ymin self._x_max = xmax self._y_max = ymax self._padding = padding self.x_range = Range1d(start=self.x_min, end=self.x_max) self.y_range = Range1d(start=self.y_min, end=self.y_max)
[docs] def on_bind(self, *, parent: 'shyft.dashboard.maps.map_viewer.MapViewer') -> None: """ Function which is call when bound to a figure """ try: parent.bokeh_figure.x_range = self.x_range parent.bokeh_figure.y_range = self.y_range except (RuntimeError, AttributeError) as e: raise BindableError(f"Attempt to bind MapAxes to not MapViewer {parent}: {e}")
[docs] def set_axes_bounds(self, x_min, y_min, x_max, y_max) -> None: """ Sets the ranges from Tuples[x_min, y_min, x_max, y_max], i.e. defined as bbox coordinates """ self._x_min = x_min self._y_min = y_min self._x_max = x_max self._y_max = y_max self.adjust_aspect_ratio() self.update_ranges()
[docs] def set_axes_bounds_from_bounds_list(self, bounds_list: List[Tuple[float, float, float, float]]) -> None: """ Updates the ranges from a List[Tuples[x_min, y_min, x_max, y_max]], i.e. defined as bbox coordinates """ bounds_list = np.array(bounds_list) self._x_min = np.min(bounds_list[:, 0]) self._y_min = np.min(bounds_list[:, 1]) self._x_max = np.max(bounds_list[:, 2]) self._y_max = np.max(bounds_list[:, 3]) self.adjust_aspect_ratio() self.update_ranges()
[docs] def adjust_aspect_ratio(self): """ This function adjusts y and x ranges to get an 1:1 plot axis ratio also dependent on the plot width and height """ range_x = self._x_max - self._x_min range_y = self._y_max - self._y_min if range_x == 0: ratio = self._aspect_ration_xy-1 elif range_y == 0: ratio = self._aspect_ration_xy+1 else: ratio = range_x/range_y if ratio > self._aspect_ration_xy: # adjust y axis y_range_diff = abs(range_x/self._aspect_ration_xy-range_x) self._y_max += y_range_diff/2 self._y_min -= y_range_diff/2 elif ratio < self._aspect_ration_xy: # adjust x axis x_range_diff = abs(range_y*self._aspect_ration_xy - range_x) self._x_max += x_range_diff / 2 self._x_min -= x_range_diff / 2
@property def padding(self) -> float: """ This property of the extra padding """ return self._padding @padding.setter def padding(self, new_padding: float) -> None: """ Setter to set the new padding """ self._padding = new_padding self.update_ranges() @property def x_min(self) -> float: """ This property returns the padded x_min bound """ return self._x_min - self.padding @property def y_min(self) -> float: """ This property returns the padded y_min bound """ return self._y_min - self.padding @property def x_max(self) -> float: """ This property returns the padded x_max bound """ return self._x_max + self.padding @property def y_max(self) -> float: """ This property returns the padded y_max bound """ return self._y_max + self.padding @property def axes_bounds(self) -> Tuple[float, float, float, float]: """ This function returns the axes bounds as Tuples[x_min, y_min, x_max, y_max], i.e. defined as bbox coordinates """ return self.x_min, self.y_min, self.x_max, self.y_max
[docs] def update_ranges(self) -> None: """ This function triggers the update of the data ranges """ self.x_range.start = self.x_min self.x_range.end = self.x_max self.y_range.start = self.y_min self.y_range.end = self.y_max