def __init__(
        self,
        idf_file_path,
        unit_registry,
        profiles_files_handler: Optional[ProfileFilesHandler] = None,
        custom_config={},
    ):
        """
        You can only use one construction type at a time. All three constr_xxx callables take a construction object as the first argument.
        Either constr_writer or constr_get_idf_files should point to a method of your construction, you can also assign both method if you wish.

        :param constr_name_lookup: function which returns the name for a given construction object
        :param constr_writer: function which writes the passed construction object to the idf file passed as a second parameter
        :param constr_get_idf_files: function which returns partial idf files for that construction which shall be appended at the end of IDF-Writing process. files are collected
               and before writing duplicated files are removed. this allows that you return the same file several
               times and it will only be appended once, but means that you have to make sure files with different content have different file names.
        :param idf_file_path: file name including full path to write IDF to. file should not exist.
        :param geometry_writer: instance of class to write geometry properties from the model to the IDF
        :param custom_config: dictionary containing configuration entries overwriting package default config
        """
        assert not os.path.exists(idf_file_path), f"Cannot create IDF File {idf_file_path}. Already existing."
        self.logger = logging.getLogger(__name__)
        self._cfg = config_loader.load_config_for_package(_default_config_file, __package__, custom_config)
        self._custom_config = custom_config
        self.unit_registry = unit_registry
        idd_path = get_idd_path(ep_config=self._cfg)
        self.logger.info(f"using IDD {idd_path}")
        IDF.setiddname(idd_path)
        self.idf_file_path = idf_file_path
        self.__create_empty_idf()
        self.zone_data = Optional[Dict[int, Tuple[str, List[EpBunch]]]]
        if profiles_files_handler:
            self.profiles_files_handler_method = profiles_files_handler.add_file
        else:
            self.profiles_files_handler_method = lambda x: x  # do nothing, just return filepath back
Example #2
0
def test_config_subpackage():
    custom_cfg = {"MOM": {"CHILD": {"STATE": "smiling"}}}
    config = config_loader.load_config_for_package(_TEST_SUBPKG_CONFIG_PATH,
                                                   "mom.child", custom_cfg)

    assert config["STATE"] == "smiling"
    assert config["LOCATION"] == "at home"
    def __init__(self,
                 main_bldg_fid,
                 site_bldgs: pd.DataFrame,
                 glazing_ratio: float,
                 custom_config: Dict[str, Any] = {}):
        """
        :param main_bldg_fid: gis_fid of main building which will be simulated. gis_fid must be containted in
                                  site_bldgs

        :param site_bldgs: pandas DataFrame with one row for each building, columns being 'gis_fid', 'height', 'footprint_shape' and main_vertex_x/main_vertex_y
                            for convenience in lookup of reference vertex for a building 'footprint_shape' is a pandas DataFrame[columns=[x,y]] all vertices of one building
        :param flat_site_vertices: pandas DataFrame with columns gis_fid, x, y, height having several rows per gis_fid.
                                    vertex are expected in counter-clockwise sequence
        """
        self.site_bldgs = site_bldgs
        self.bldg_main = self.site_bldgs.loc[main_bldg_fid].to_dict(
        )  # as it contains a nested DF, for pickling we need to convert to dict....
        self.origin_vertex = {
            "x": self.bldg_main["main_vertex_x"],
            "y": self.bldg_main["main_vertex_y"],
            "z": 0
        }
        self.glazing_ratio = glazing_ratio
        self._cfg = config_loader.load_config_for_package(
            _default_config_file, __package__, custom_config)
        self._custom_config = custom_config
        self._neighbours: Optional[pd.DataFrame] = None
        self._logger = logging.getLogger(__name__)
Example #4
0
def test_config_with_custom():
    custom_cfg = {"HELLO": {"SUNSHINE": "warm", "DARKNESS": "cold"}}
    config = config_loader.load_config_for_package(_TEST_CFG_PATH,
                                                   "cesarp.hello", custom_cfg)
    assert isinstance(config["WORLD"], str)
    assert config["WORLD"] == "How are you?"
    assert config["DARKNESS"] == "cold"
    assert config["SUNSHINE"] == "warm"
Example #5
0
def test_config_default():
    config = config_loader.load_config_for_package(_TEST_CFG_PATH,
                                                   "cesarp.hello")
    assert isinstance(config["WORLD"], str)
    assert config == __HELLO_expected_test_config
def get_config(custom_config: Dict[str, Any] = {}):
    return config_loader.load_config_for_package(_default_config_file,
                                                 __package__, custom_config)
Example #7
0
def create_bldg_shape_detailed(
    bldg: pd.DataFrame,
    glazing_ratio: float,
    get_adjacent_footprint_vertices: Callable[..., pd.DataFrame],
    *args_to_get_adjacent_footprint_vertices,
    custom_config: Dict[
        str,
        Any] = {},  # make sure to pass as a named parameter, otherwise the previous param consumes it...
) -> BldgShapeDetailed:
    """
    Define building shape as cesarp.manager.manager_protocols.BldgShapeDetailed
    Glazing ratio is applied per wall. This means, if a building has walls adjacent to the next building or walls that are too small for windows,
    those walls will be modeled without a window, resulting in a overall building glazing ratio lower than the specified one.

    :param bldg: one row defining the building for which to create the shape data
    :type bldg: DataFrame[columns=['footprint_shape', 'height']] - footprint vertices in counter-clockwise order
    :param glazing_ratio: glazing ratio per wall
    :param get_adjacent_footprint_vertices: function with at least
        1 positional parameter bldg DataFrame[columns=['footprint_shape']]  and
        returning a Series[columns=main_vertices]] with zero to many adjacent vertices as DataFrame[columns=[x,y]]
    :param args_to_get_adjacent_footprint_vertices: additional parameters for function get_adjacent_footprint_vertices
    :param custom_config: dict with custom configuration entries overwriting values from package default config
    :return: dict with keys:


    """

    cfg = config_loader.load_config_for_package(_default_config_file,
                                                __package__, custom_config)

    floors = define_bldg_floors(
        bldg["footprint_shape"],
        bldg["height"],
        min_story_height=cfg["MAIN_BLDG_SHAPE"]["MINIMAL_STORY_HEIGHT"])

    walls = define_bldg_walls_per_floor(floors)
    adj_footprint_vertices = get_adjacent_footprint_vertices(
        *((bldg, ) + args_to_get_adjacent_footprint_vertices))
    adjacent_walls = find_adjacent_walls(walls, adj_footprint_vertices)

    cfg_window = cfg["MAIN_BLDG_SHAPE"]["WINDOW"]

    if cfg["MAIN_BLDG_SHAPE"]["MINIMAL_STORY_HEIGHT"] < cfg_window["HEIGHT"]:
        raise CesarpException(
            f"inconsistent configuration: minimal story height MINIMAL_STORY_HEIGHT {cfg['MAIN_BLDG_SHAPE']['MINIMAL_STORY_HEIGHT']} is smaller than window height WINDOW: HEIGHT {cfg_window['HEIGHT']}"
        )

    all_windows = define_windows_for_walls(
        walls, glazing_ratio, cfg_window["HEIGHT"],
        cfg_window["MIN_WALL_WIDTH_FOR_WINDOW"],
        cfg_window["MIN_WINDOW_WIDTH"], cfg_window["MAX_GLZ_RATIO_WALL_WIDTH"])
    windows = remove_windows_in_adjacent_walls(all_windows, adjacent_walls)

    return BldgShapeDetailed(
        groundfloor=floors[0],
        roof=floors[-1],
        internal_floors=floors[1:-1],
        walls=walls,
        windows=windows,
        adjacent_walls_bool=adjacent_walls,
        window_frame=cfg_window["WINDOW_FRAME"],
    )
 def __init__(self, passive_cooling_op_fact: PassiveCoolingOperationFactoryProtocol, unit_registry, custom_config={}):
     self._unit_registry = unit_registry
     self._custom_config = custom_config
     self._cfg = config_loader.load_config_for_package(_default_config_file, __package__, custom_config)
     self._passive_cooling_op_fact = passive_cooling_op_fact
    def __init__(
        self,
        base_output_path: Union[str, Path],
        main_config: Union[str, Path, Dict[str, Any]],
        unit_reg: pint.UnitRegistry,
        load_from_disk: bool = False,
        fids_to_use: List[int] = None,
        delete_old_logs=True,
    ):
        """
        :param base_output_path: full folder path where idf, eplus output and other cesar-p output and intermediate files are stored.
        :type base_output_path: Union[str, Path]
        :param main_config: either dict with configuration entries or path to custom config yml file.
                            for details about how the configuration works see class description
        :type main_config: Union[str, Path, Dict[str, Any]]
        :param unit_reg: pint Unit Registry application wide instance ()
        :type unit_reg: pint.UnitRegistry
        :param load_from_disk: True if you want to load existing simulation files into memory. cannot be combined with fids_to_use, defaults to False
        :type load_from_disk: bool
        :param fids_to_use: pass list of FID's for which called methods on the manager object should be performed, if not provided all fids defined in the input file are used
        :type fids_to_use: List[int]
        :param delete_old_logs: if true old \\*-cesarp-logs folder are deleted when a new worker pool is created
        :type delete_old_logs: bool
        """
        self.logger = logging.getLogger(__name__)
        assert not (load_from_disk and (fids_to_use is not None)
                    ), "if load_from_disk is True you cannot pass fids_to_use"
        self._unit_reg = unit_reg
        self.delete_old_logs = delete_old_logs

        if not isinstance(main_config, dict):
            self._custom_config = config_loader.load_config_full(main_config)
        else:
            self._custom_config = main_config
        self.__validate_custom_config(self._custom_config)

        self._mgr_config = config_loader.load_config_for_package(
            _default_config_file, __package__, self._custom_config)

        self._storage = FileStorageHandler(base_output_path,
                                           self._custom_config,
                                           reloading=load_from_disk)

        self.failed_fids: Set[int] = set()

        self._worker_pool = None

        if not fids_to_use:
            fids_to_use = self.get_fids_from_config()
        self._fids_to_use = fids_to_use

        self.bldg_containers = self._init_empty_bldg_containers(fids_to_use)
        self.output_folders: Dict[int, str] = {}
        self.idf_pathes: Dict[int, str] = {}
        self.weather_files: Dict[int, str] = {}

        if load_from_disk:
            self.bldg_containers = self._storage.load_existing_bldg_containers(
            )
            self.idf_pathes = self._storage.load_existing_idfs()
            if self.idf_pathes:
                self.weather_files = self._storage.load_existing_weather_mapping(
                )
            self.output_folders = self._storage.load_existing_result_folders()
            self._fids_to_use = list(
                set(
                    list(self.bldg_containers.keys()) +
                    list(self.idf_pathes.keys()) +
                    list(self.output_folders.keys())))