Source code for fdsreader.evac.evacuation

from typing import List, Tuple, Dict, Sequence, Union

import numpy as np

from fdsreader.fds_classes import Mesh
from fdsreader.utils import Quantity


# class Entrance:
#     def __init__(self):
#         self.id = ""
#         self.extent = Extent(1.0, 1.0, 1.0, 1.0, 1.0, 1.0)
#         self.orientation = 1
#         self.color = (0.0, 0.0, 0.0)


# class Exit:
#     def __init__(self):
#         self.id = ""
#         self.extent = Extent(1.0, 1.0, 1.0, 1.0, 1.0, 1.0)
#         self.xyz = (1.0, 1.0, 1.0)
#         self.orientation = 1
#         self.color = (0.0, 0.0, 0.0)
#         self.count_only = True
#         self.known_door = True


# class Door:
#     def __init__(self):
#         self.id = ""
#         self.extent = Extent(1.0, 1.0, 1.0, 1.0, 1.0, 1.0)
#         self.xyz = (1.0, 1.0, 1.0)
#         self.orientation = 1
#         self.color = (0.0, 0.0, 0.0)
#         self.to_node = Entrance()
#         self.known_door = True
#         self.exit_sign = True


[docs] class Evacuation: """Container to store evac data from evac simulations with FDS. :ivar class_name: Name of the evac class defined in the FDS input-file. :ivar quantities: List of all quantities for which data has been written out. :ivar color: Color assigned to the evac. :ivar n_humans: Number of existing evacs for each timestep per mesh. :ivar lower_bounds: Dictionary with lower bounds for each timestep with quantities as keys. :ivar upper_bounds: Dictionary with upper bounds for each timestep with quantities as keys. """ def __init__(self, class_name: str, quantities: List[Quantity], color: Tuple[float, float, float]): self.class_name = class_name self.quantities = quantities self.color = color self.n_humans: Dict[str, List[int]] = dict() self._positions: List[np.ndarray] = list() self._body_angles: List[np.ndarray] = list() self._semi_major_axis: List[np.ndarray] = list() self._semi_minor_axis: List[np.ndarray] = list() self._agent_heights: List[np.ndarray] = list() self._tags: List[np.ndarray] = list() self._data: Dict[str, List[np.ndarray]] = {q.name: [] for q in self.quantities} self.times: Sequence[float] = list() self.lower_bounds = {q.name: [] for q in self.quantities} self.upper_bounds = {q.name: [] for q in self.quantities} self._init_callback = lambda: None @property def id(self): return self.class_name
[docs] def has_quantity(self, quantity: Union[Quantity, str]): if type(quantity) == Quantity: quantity = quantity.name return any( q.name.lower() == quantity.lower() or q.short_name.lower() == quantity.lower() for q in self.quantities)
[docs] def filter_by_tag(self, tag: int): """Filter all evacs by a single one with the specified tag. """ data = self.data tags = self.tags positions = self.positions evac = Evacuation(self.class_name, self.quantities, self.color) evac._tags = tag evac._data = {quantity: list() for quantity in data.keys()} evac._positions = list() evac.times = list() for t, tags in enumerate(tags): if tag in tags: idx = np.where(tags == tag)[0] for quantity in data.keys(): evac._data[quantity].append(data[quantity][t][idx][0]) evac._positions.append(positions[t][idx][0]) evac.times.append(self.times[t]) evac.lower_bounds = dict() evac.upper_bounds = dict() for q in self.quantities: if len(evac._positions) != 0: evac.lower_bounds[q.name] = np.min(evac._data[q.name]) evac.upper_bounds[q.name] = np.max(evac._data[q.name]) else: evac.lower_bounds[q.name] = 0 evac.upper_bounds[q.name] = 0 return evac
@property def data(self) -> Dict[str, List[np.ndarray]]: """Dictionary with quantities as keys and a list with a numpy array for each timestep which contains data for each person in that timestep. """ if len(self._positions) == 0 and len(self._tags) == 0: self._init_callback() return self._data
[docs] def get_data(self, quantity: Union[Quantity, str]) -> List[np.ndarray]: """Returns a list with a numpy array for each timestep which contains data about the specified quantity for each person in that timestep. """ if self.has_quantity(quantity): if type(quantity) == Quantity: quantity = quantity.name return self.data[quantity] return []
@property def tags(self) -> List[np.ndarray]: """List with a numpy array for each timestep which contains a tag for each evac in that timestep. """ if len(self._positions) == 0 and len(self._tags) == 0: self._init_callback() return self._tags @property def positions(self) -> List[np.ndarray]: """List with a numpy array for each timestep which contains the position of each evac in that timestep. """ if len(self._positions) == 0 and len(self._tags) == 0: self._init_callback() return self._positions @property def body_angles(self) -> List[np.ndarray]: """ """ if len(self._positions) == 0 and len(self._tags) == 0: self._init_callback() return self._body_angles @property def semi_major_axis(self) -> List[np.ndarray]: """ """ if len(self._positions) == 0 and len(self._tags) == 0: self._init_callback() return self._semi_major_axis @property def semi_minor_axis(self) -> List[np.ndarray]: """ """ if len(self._positions) == 0 and len(self._tags) == 0: self._init_callback() return self._semi_minor_axis @property def agent_heights(self) -> List[np.ndarray]: """ """ if len(self._positions) == 0 and len(self._tags) == 0: self._init_callback() return self._agent_heights
[docs] def clear_cache(self): """Remove all data from the internal cache that has been loaded so far to free memory. """ if len(self._positions) != 0: del self._positions self._positions = list() del self._tags self._tags = list() del self._data self._data = {q.name: [] for q in self.quantities}
def __repr__(self): return f"Evacuation(name={self.class_name}, quantities={self.quantities})"