voxcity.generator.update ======================== .. py:module:: voxcity.generator.update .. autoapi-nested-parse:: Functions for updating VoxCity objects with new grid data. Functions --------- .. autoapisummary:: voxcity.generator.update.update_voxcity voxcity.generator.update.regenerate_voxels Module Contents --------------- .. py:function:: update_voxcity(city: voxcity.models.VoxCity, *, buildings: Optional[voxcity.models.BuildingGrid] = None, building_heights: Optional[numpy.ndarray] = None, building_min_heights: Optional[numpy.ndarray] = None, building_ids: Optional[numpy.ndarray] = None, land_cover: Optional[Union[voxcity.models.LandCoverGrid, numpy.ndarray]] = None, dem: Optional[Union[voxcity.models.DemGrid, numpy.ndarray]] = None, tree_canopy: Optional[Union[voxcity.models.CanopyGrid, numpy.ndarray]] = None, canopy_top: Optional[numpy.ndarray] = None, canopy_bottom: Optional[numpy.ndarray] = None, building_gdf=None, tree_gdf=None, tree_gdf_mode: str = 'replace', land_cover_source: Optional[str] = None, trunk_height_ratio: Optional[float] = None, voxel_dtype=None, max_voxel_ram_mb: Optional[float] = None, inplace: bool = False) -> voxcity.models.VoxCity Update a VoxCity object with new grid data and regenerate the VoxelGrid. This function allows partial updates - only the grids you provide will be updated, while the rest will be taken from the existing VoxCity object. The VoxelGrid is always regenerated from the (updated) component grids. :param city: The existing VoxCity object to update. :type city: VoxCity :param buildings: Complete replacement for the building grid. If provided, takes precedence over individual building_heights/building_min_heights/building_ids. :type buildings: BuildingGrid, optional :param building_heights: 2D array of building heights. If buildings is not provided, this updates only the heights while keeping existing min_heights and ids. :type building_heights: np.ndarray, optional :param building_min_heights: 2D object-dtype array of lists containing [min_height, max_height] pairs for each building segment per cell. :type building_min_heights: np.ndarray, optional :param building_ids: 2D array of building IDs per cell. :type building_ids: np.ndarray, optional :param land_cover: New land cover data. Can be a LandCoverGrid or a raw numpy array. :type land_cover: LandCoverGrid or np.ndarray, optional :param dem: New DEM/elevation data. Can be a DemGrid or a raw numpy array. :type dem: DemGrid or np.ndarray, optional :param tree_canopy: New tree canopy data. Can be a CanopyGrid (with top/bottom) or a raw numpy array (interpreted as canopy top heights). :type tree_canopy: CanopyGrid or np.ndarray, optional :param canopy_top: 2D array of tree canopy top heights. Takes precedence over tree_canopy for top heights if both are provided. :type canopy_top: np.ndarray, optional :param canopy_bottom: 2D array of tree canopy bottom heights (crown base). :type canopy_bottom: np.ndarray, optional :param building_gdf: Updated building GeoDataFrame. If provided without building grids (building_heights, building_min_heights, building_ids), the function will automatically generate the building grids from the GeoDataFrame using create_building_height_grid_from_gdf_polygon. The GeoDataFrame is also stored in city.extras['building_gdf']. :type building_gdf: GeoDataFrame, optional :param tree_gdf: Updated tree GeoDataFrame. If provided without tree canopy data (tree_canopy, canopy_top, canopy_bottom), the function will automatically generate the canopy grids from the GeoDataFrame using create_canopy_grids_from_tree_gdf. The GeoDataFrame must contain 'top_height', 'bottom_height', 'crown_diameter', and 'geometry' columns. The GeoDataFrame is stored in city.extras['tree_gdf']. :type tree_gdf: GeoDataFrame, optional :param tree_gdf_mode: How to combine tree_gdf with existing canopy data. Options: - "replace": Replace the existing canopy grids with new ones from tree_gdf. - "add": Merge the tree_gdf grids with existing (or provided) canopy grids by taking the maximum height at each cell (preserves existing trees). When canopy_top/canopy_bottom are also provided, the tree_gdf grids are merged on top of those arrays instead of the existing city canopy. :type tree_gdf_mode: str, default "replace" :param land_cover_source: The land cover source name for proper voxelization. If not provided, attempts to use the source from city.extras or defaults to 'OpenStreetMap'. :type land_cover_source: str, optional :param trunk_height_ratio: Ratio of trunk height to total tree height for canopy bottom calculation. Default is approximately 0.588 (11.76/19.98). :type trunk_height_ratio: float, optional :param voxel_dtype: NumPy dtype for the voxel grid. Defaults to np.int8. :type voxel_dtype: dtype, optional :param max_voxel_ram_mb: Maximum RAM in MB for voxel grid allocation. Raises MemoryError if exceeded. :type max_voxel_ram_mb: float, optional :param inplace: If True, modifies the input city object directly and returns it. If False, creates and returns a new VoxCity object. :type inplace: bool, default False :returns: The updated VoxCity object with regenerated VoxelGrid. :rtype: VoxCity .. rubric:: Examples Update building heights and regenerate voxels: >>> import numpy as np >>> new_heights = city.buildings.heights.copy() >>> new_heights[10:20, 10:20] = 50.0 # Increase height in a region >>> updated = update_voxcity(city, building_heights=new_heights) Update with a complete new BuildingGrid: >>> from voxcity.models import BuildingGrid >>> new_buildings = BuildingGrid(heights=..., min_heights=..., ids=..., meta=city.buildings.meta) >>> updated = update_voxcity(city, buildings=new_buildings) Update land cover and DEM together: >>> updated = update_voxcity(city, land_cover=new_lc_array, dem=new_dem_array) Update buildings from GeoDataFrame (automatic grid generation): >>> updated = update_voxcity(city, building_gdf=updated_building_gdf) Update trees from GeoDataFrame (replace existing canopy): >>> updated = update_voxcity(city, tree_gdf=updated_tree_gdf) Add trees from GeoDataFrame to existing canopy: >>> updated = update_voxcity(city, tree_gdf=new_tree_gdf, tree_gdf_mode="add") .. py:function:: regenerate_voxels(city: voxcity.models.VoxCity, *, land_cover_source: Optional[str] = None, trunk_height_ratio: Optional[float] = None, voxel_dtype=None, max_voxel_ram_mb: Optional[float] = None, inplace: bool = False) -> voxcity.models.VoxCity Regenerate only the VoxelGrid from existing component grids. This is a convenience function for when you've modified the grids in-place and need to regenerate the voxels without passing all parameters. :param city: The VoxCity object whose voxels should be regenerated. :type city: VoxCity :param land_cover_source: Land cover source for voxelization. Defaults to source from extras. :type land_cover_source: str, optional :param trunk_height_ratio: Trunk height ratio for tree canopy calculation. :type trunk_height_ratio: float, optional :param voxel_dtype: NumPy dtype for voxel grid. :type voxel_dtype: dtype, optional :param max_voxel_ram_mb: Maximum RAM in MB for voxel allocation. :type max_voxel_ram_mb: float, optional :param inplace: If True, modifies city directly; otherwise returns a new object. :type inplace: bool, default False :returns: The VoxCity object with regenerated VoxelGrid. :rtype: VoxCity .. rubric:: Examples >>> # Modify building heights in place >>> city.buildings.heights[50:60, 50:60] = 100.0 >>> # Regenerate voxels to reflect the change >>> city = regenerate_voxels(city, inplace=True)