brails.types.asset_inventory module
This module defines classes associated with asset inventories.
A class representing a collection of Assets managed as an inventory.  | 
|
  | 
A spatial asset with geometry coordinates, and attributes.  | 
- class brails.types.asset_inventory.Asset(asset_id, coordinates, features=None)
 Bases:
objectA spatial asset with geometry coordinates, and attributes.
To import the
Assetclass, use:from brails.types.asset_inventory import Asset
- asset_id
 Unique identifier for the asset.
- Type:
 str or int
- coordinates
 Geometry coordinates of the asset, typically as a list of [x, y] pairs.
- Type:
 list[list[float]]
- features
 Additional attributes/features of the asset. Defaults to
None.- Type:
 dict[str, Any], optional
- add_features(additional_features, overwrite=True)
 Update the existing features in the asset.
- Parameters:
 additional_features (dict[str, Any]) – New features to merge into the asset’s features.
overwrite (bool, optional) – Whether to overwrite existing features. Defaults to
True.
- Returns:
 A tuple containing two values:
updated (bool):
Trueif any features were added or updated,Falseotherwise.n_pw (int): Number of possible worlds.
- Return type:
 tuple[bool, int]
Examples
>>> asset = Asset( ... asset_id='123', ... coordinates=[[-122.4194, 37.7749], [-122.4180, 37.7755]] ... ) >>> updated, n_pw = asset.add_features({'roof_type': 'gable'}) >>> print(updated, n_pw) True 1 >>> print(asset.features) {'roof_type': 'gable'}
>>> updated, n_pw = asset.add_features( ... {'possible_heights': [10, 15, 20], 'roof_type': 'hip'}, ... overwrite=True ... ) >>> print(updated, n_pw) True 3 >>> print(asset.features) {'roof_type': 'hip', 'possible_heights': [10, 15, 20]}
>>> # When overwrite=False, existing keys are not updated >>> updated, n_pw = asset.add_features( ... {'roof_type': 'flat', 'color': 'red'}, ... overwrite=False ... ) >>> print(updated, n_pw) True 1 >>> print(asset.features) {'roof_type': 'hip', 'possible_heights': [10, 15, 20], 'color': 'red'}
- get_centroid()
 Get the centroid of the asset geometry.
- Returns:
 [[x, y]]if centroid can be calculated,[[None, None]]otherwise.- Return type:
 list[list[float]]
Examples
>>> asset = Asset( ... asset_id='123', ... coordinates=[[-122.4194, 37.7749], [-122.4190, 37.7750]] ... ) >>> asset.get_centroid() [[-122.41919999999999, 37.774950000000004]]
>>> empty_asset = Asset(asset_id='empty', coordinates=[]) Coordinates input is empty for empty; defaulting to an empty list. >>> empty_asset.get_centroid() [[None, None]]
- hash_asset()
 Generate a unique hash for this asset based on its coordinates and features.
This hash can be used to quickly identify duplicate assets by comparing geometry and attribute data. Both the coordinates and features are serialized as strings and then hashed using MD5.
- Returns:
 A hexadecimal string representing the MD5 hash of the asset.
- Return type:
 str
Example
>>> asset1 = Asset( ... asset_id='123', ... coordinates=[[-122.4194, 37.7749], [-122.4180, 37.7755]], ... features={'roof_type': 'gable'} ... ) >>> asset2 = Asset( ... asset_id='124', ... coordinates=[[-122.4194, 37.7749], [-122.4180, 37.7755]], ... features={'roof_type': 'flat'} ... ) >>> hash1 = asset1.hash_asset() >>> print(hash1) 1e629fc184329ea688c648e7663b439d >>> hash2 = asset2.hash_asset() >>> print(hash2) ac0d104a411f92bffff8cc1398257dd8 >>> hash1 != hash2 True
- print_info()
 Print the asset’s coordinates and feature attributes.
This method outputs the spatial coordinates and all associated feature key-value pairs of the asset to the console.
- Returns:
 None
Example
>>> asset = Asset( ... asset_id='123', ... coordinates=[[-122.4194, 37.7749], [-122.4180, 37.7755]], ... features={'roof_type': 'gable'} ... ) >>> asset.print_info() Coordinates: [[-122.4194, 37.7749], [-122.4180, 37.7755]] Features: {'roof_type': 'gable'}
- remove_features(features_to_remove)
 Remove specified features from the asset.
- Parameters:
 features_to_remove (Iterable[str]) – An iterable of feature keys to remove from the Asset features. Accepts iterable types such as
list,tuple,set, ordict_keys.- Returns:
 Trueif at least one feature was removed;Falseotherwise.- Return type:
 bool
- Raises:
 TypeError – If
features_to_removeis not an iterable of strings.
Example
>>> asset = Asset( ... asset_id='123', ... coordinates=[[-122.4194, 37.7749], [-122.4180, 37.7755]] ... ) >>> asset.features = {'color': 'red', 'height': 10} >>> asset.remove_features(['color']) True >>> asset.features {'height': 10}
- class brails.types.asset_inventory.AssetInventory
 Bases:
objectA class representing a collection of Assets managed as an inventory.
This class provides methods to add, manipulate, join, write and query a collaction of :class:Asset objects.
To import the
AssetInventoryclass, use:from brails.types.asset_inventory import AssetInventory
- add_asset(asset_id, asset)
 Add an Asset to the inventory.
- Parameters:
 asset_id (str or int) – The unique identifier for the asset.
asset (Asset) – The asset to be added.
- Returns:
 Trueif the asset was added successfully,Falseotherwise.- Return type:
 bool
- Raises:
 TypeError – If
assetis not an instance ofAsset.
Examples
>>> asset = Asset( ... asset_id='001', ... coordinates=[[-122.4194, 37.7749]], ... features={'type': 'building'} ... ) >>> inventory = AssetInventory() >>> success = inventory.add_asset('001', asset) >>> print(success) True
>>> # Adding the same asset_id again will fail >>> success = inventory.add_asset('001', asset) >>> print(success) False
- add_asset_coordinates(asset_id, coordinates)
 Add an
Assetto the inventory by adding its coordinate information.- Parameters:
 asset_id (str or int) – The unique identifier for the asset.
coordinates (list[list[float]]) – A two-dimensional list representing the geometry in
[[lon1, lat1], [lon2, lat2], ..., [lonN, latN]]format.
- Returns:
 Trueif the asset was added successfully,Falseotherwise.- Return type:
 bool
Examples
>>> inventory = AssetInventory() >>> coords = [[-122.42, 37.77], [-122.43, 37.78], [-122.44, 37.79]] >>> success = inventory.add_asset_coordinates('A123', coords) >>> print(success) True
>>> # Attempt to add the same asset_id again >>> success = inventory.add_asset_coordinates('A123', coords) >>> print(success) False
- add_asset_features(asset_id, new_features, overwrite=True)
 Add new asset features to the Asset with the specified
asset_id.- Parameters:
 asset_id (str or int) – The unique identifier for the asset.
new_features (dict) – A dictionary of features to add to the asset.
overwrite (bool) – Whether to overwrite existing features with the same keys. Defaults to
True.
- Returns:
 Trueif features were successfully added,Falseif the asset does not exist or the operation fails.- Return type:
 bool
Examples
>>> inventory = AssetInventory() >>> inventory.add_asset_coordinates( ... 'A123', ... [[-122.4194, 37.7749], [-122.4180, 37.7755]] ... ) True >>> features = {'height': 10, 'material': 'concrete'} >>> success = inventory.add_asset_features('A123', features) >>> print(success) True
>>> # Add features without overwriting existing keys >>> more_features = {'material': 'steel', 'color': 'red'} >>> success = inventory.add_asset_features( ... 'A123', ... more_features, ... overwrite=False ... ) >>> print(success) True >>> asset = inventory.inventory['A123'] >>> print(asset.features) {'height': 10, 'material': 'concrete', 'color': 'red'}
- add_asset_features_from_csv(file_path, id_column)
 Read inventory data from a CSV file and add it to the inventory.
- Parameters:
 file_path (str) – The path to the CSV file
id_column (str) – The name of column that contains id values. If
None, new indicies will be assigned
- Returns:
 Trueif assets were addded,Falseotherwise.- Return type:
 bool
- add_model_predictions(predictions, feature_key)
 Add model predictions to the inventory.
This method goes through the inventory and updates each item by adding the corresponding model prediction as a new feature under the specified key. Items without a matching prediction are left unchanged.
- Parameters:
 predictions (dict) – A dictionary where keys correspond to inventory items and values represent the predicted features to be added.
feature_key (str) – The key under which the predictions will be stored as a new feature in each inventory item.
- Returns:
 None
- Raises:
 TypeError – If
predictionsis not a dictionary orfeature_keyis not a string.ValueError – If none of the keys in
predictionsexist in the inventory.
Example
Suppose the inventory contains assets with IDs 1, 3, and 12. To add predicted roof types for these assets:
>>> predictions = {1: 'gable', 3: 'flat', 12: 'hip'} >>> inventory.add_model_predictions( predictions, feature_key='roof_type' )
After this call, each asset with an ID in
predictionswill have a new featureroof_typeset to the corresponding predicted value.
- change_feature_names(feature_name_mapping)
 Rename feature names in
AssetInventoryvia user-specified mapping.- Parameters:
 feature_name_mapping (dict) – A dictionary where keys are the original feature names and values are the new feature names.
- Raises:
 TypeError – If the mapping is not a dictionary or contains invalid key-value pairs.
Example
First create an
AssetInventorywith two assets with IDsasset1andasset2.>>> inventory = AssetInventory() >>> asset1 = Asset( ... asset_id='asset1', ... coordinates=[ ... [-122.4194, 37.7749], ... [-122.4194, 37.7849], ... [-122.4094, 37.7849], ... [-122.4094, 37.7749], ... [-122.4194, 37.7749] ... ], ... features={'old_name': 100, 'unchanged': 50} ... ) >>> inventory.add_asset('asset1', asset1) >>> asset2 = Asset( ... asset_id='asset2', ... coordinates=[[-122.4194, 37.7749], [-122.4094, 37.7849]], ... features={'old_name': 200} ... ) >>> inventory.add_asset('asset2', asset2)
Then, change the names of the features of these assets.
>>> inventory.change_feature_names({'old_name': 'new_name'}) >>> inventory.inventory['asset1'].features {'new_name': 100, 'unchanged': 50} >>> inventory.inventory['asset2'].features {'new_name': 200}
- combine(inventory_to_combine, key_map=None)
 Combine with another AssetInventory, avoiding duplicate assets.
Assets are compared using their hashed coordinate and feature data. Duplicate assets (identical geometry and properties) are skipped. Optionally, keys from the inventory to combine can be remapped using
key_map. Any resulting key conflicts are automatically resolved by assigning new unique numeric IDs.- Parameters:
 inventory_to_combine (AssetInventory) – The secondary inventory whose assets will be merged into this one.
key_map (dict, optional) – A mapping of original keys in
inventory_to_combineto new keys in this inventory. For example: {“old_key1”: “new_keyA”, “old_key2”: “new_keyB”}. If not provided, original keys are used as-is unless they already exist in the current inventory.
- Returns:
 A dictionary mapping each original key from
inventory_to_combineto its final key in this inventory (after applyingkey_mapand resolving conflicts).- Return type:
 dict
- Modifies:
 - self.inventory (dict):
 Updates the inventory in-place by adding new, non-duplicate assets from
inventory_to_combine.
- convert_polygons_to_centroids()
 Convert polygon geometries in the inventory to their centroid points.
Iterates through the asset inventory and replaces the coordinates of each polygon or linestring geometry with the coordinates of its centroid. Point geometries are left unchanged.
This function is useful for spatial operations that require point representations of larger geometries(e.g., matching, distance calculations).
Note
Polygon coordinates are wrapped in a list to ensure proper GeoJSON structure.
Linestrings are converted to points at their centroid unless the geometry is invalid or ambiguous.
- Modifies:
 - self.inventory (dict):
 Updates the
coordinatesfield of each asset in-place by replacing polygons and linestrings with their centroid.
Example
>>> inventory = AssetInventory() >>> inventory.add_asset_coordinates( ... 'asset1', ... [ ... [-122.4194, 37.7749], ... [-122.4194, 37.7849], ... [-122.4094, 37.7849], ... [-122.4094, 37.7749], ... [-122.4194, 37.7749] ... ] # Polygon ... ) >>> inventory.add_asset_coordinates( ... 'asset2', ... [ ... [-122.4194, 37.7749], ... [-122.4094, 37.7849] ... ] # LineString ... ) >>> inventory.convert_polygons_to_centroids() >>> inventory.get_asset_coordiates('asset1') [[-122.4144, 37.7799]] >>> inventory.get_asset_coordiates('asset2') [[-122.4144, 37.7799]]
- get_asset_coordinates(asset_id)
 Get the coordinates of a particular asset.
- Parameters:
 asset_id (str or int) – The unique identifier for the asset.
- Returns:
 bool – Indicates whether the asset was found.
list – A list of coordinate pairs in the format
[[lon1, lat1], [lon2, lat2], ..., [lonN, latN]]if found, or an empty list if the asset does not exist.
- Return type:
 tuple[bool, list]
Example
>>> inventory = AssetInventory({ ... "A101": Asset( ... coordinates=[[30.123, -97.456], [30.124, -97.457]] ... ), ... "B202": Asset( ... coordinates=[[40.789, -74.123], [40.790, -74.124]] ... ) ... }) >>> inventory.get_asset_coordinates("A101") (True, [[30.123, -97.456], [30.124, -97.457]]) >>> inventory.get_asset_coordinates("Z999") (False, [])
- get_asset_features(asset_id)
 Get features of a particular asset.
- Parameters:
 asset_id (str or int) – The unique identifier for the asset.
- Returns:
 A tuple where the first element is a boolean indicating whether the asset was found, and the second element is a dictionary containing the asset’s features if the asset is present. Returns an empty dictionary if the asset is not found.
- Return type:
 tuple[bool, Dict]
Examples
>>> inventory = AssetInventory() >>> asset = Asset( ... asset_id='001', ... coordinates=[[-122.4194, 37.7749]], ... features={'height': 10, 'material': 'concrete'} ... ) >>> inventory.add_asset('001', asset) True >>> found, features = inventory.get_asset_features('001') >>> found True >>> features {'height': 10, 'material': 'concrete'}
>>> found, features = inventory.get_asset_features('nonexistent') >>> found False >>> features {}
- get_asset_ids()
 Retrieve the IDs of all assets in the inventory.
- Returns:
 A list of asset IDs, which may be strings or integers.
- Return type:
 list[str or int]
Example
>>> inventory = AssetInventory() >>> _ = inventory.add_asset_coordinates( ... 'asset1', ... [[-122.4194, 37.7749], [-122.4180, 37.7750]] ... ) >>> _ = inventory.add_asset_coordinates( ... 2, ... [[-74.0060, 40.7128], [-74.0055, 40.7130]] ... ) >>> inventory.get_asset_ids() ['asset1', 2]
- get_assets_intersecting_polygon(bpoly)
 Get assets with geometries intersecting a bounding polygon.
This method performs a spatial intersection check between each asset’s geometry in the inventory and a provided bounding polygon (or multipolygon). Assets that intersect the polygon are identified and retained. All non-intersecting assets are removed from the inventory.
- Parameters:
 bpoly (shapely.geometry.base.BaseGeometry) – The bounding polygon or multipolygon used to determine spatial intersections.
- Raises:
 TypeError – If
bpolyis not aPolygonorMultiPolygon.
Example
>>> from shapely.geometry import Polygon >>> inventory = AssetInventory() >>> # A LineString in Dallas, TX (will intersect the Dallas bpoly): >>> _ = inventory.add_asset_coordinates( ... 'bridge_A', ... [[-96.8003, 32.7767], [-96.7998, 32.7770]] ... ) >>> # A Polygon in Los Angeles, CA (will NOT intersect the bpoly): >>> _ = inventory.add_asset_coordinates( ... 'tower_B', ... [ ... [-118.2450, 34.0537], ... [-118.2450, 34.0540], ... [-118.2445, 34.0540], ... [-118.2445, 34.0537], ... [-118.2450, 34.0537], ... ] ... ) >>> # A bounding polygon roughly around downtown Dallas: >>> bpoly = Polygon([ ... (-96.81, 32.77), ... (-96.81, 32.78), ... (-96.79, 32.78), ... (-96.79, 32.77), ... (-96.81, 32.77) ... ]) >>> >>> inventory.get_assets_intersecting_polygon(bpoly) >>> 'bridge_A' in inventory.inventory True >>> 'tower_B' in inventory.inventory False
- get_coordinates()
 Get geometry(coordinates) and keys of all assets in the inventory.
- Returns:
 A tuple containing:
A list of coordinates for each asset, where each coordinate is represented as a list of [longitude, latitude] pairs.
A list of asset keys corresponding to each asset.
- Return type:
 tuple[list[list[list[float, float]]], list[str or int]]
Example
>>> inventory = AssetInventory() >>> _ = inventory.add_asset_coordinates( ... 'asset1', ... [[-122.4194, 37.7749], [-122.4180, 37.7750]] ... ) >>> _ = inventory.add_asset_coordinates( ... 'asset2', ... [[-74.0060, 40.7128], [-74.0055, 40.7130]] ... ) >>> coords, keys = inventory.get_coordinates() >>> coords [[[-122.4194, 37.7749], [-122.4180, 37.7750]], [[-74.0060, 40.7128], [-74.0055, 40.7130]]] >>> keys ['asset1', 'asset2']
- get_dataframe()
 Convert the asset inventory into two structured DataFrames and count.
This method processes the internal asset inventory and returns:
A
DataFramecontaining the features of each asset, with support for multiple possible worlds(realizations).A
DataFramecontaining centroid coordinates(longitude and latitude) for spatial operations.The total number of assets in the inventory.
The method flattens feature lists into separate columns if multiple possible worlds exist. It also derives centroid coordinates from the GeoJSON geometry for each asset.
- Returns:
 Asset feature
DataFrame(indexed by asset ID).Asset geometry
DataFramewith ‘Lat’ and ‘Lon’ columns.Total number of assets (int).
- Return type:
 Tuple[pd.DataFrame, pd.DataFrame, int]
- Raises:
 ValueError – If a feature list’s length does not match the expected number of possible worlds.
- get_extent(buffer='default')
 Calculate the geographical extent of the inventory.
- Parameters:
 buffer (str or list[float]) –
A string or a list of 4 floats.
'default'applies preset buffer values.'none'applies zero buffer values.A list of 4 floats defines custom buffer values for each edge of the bounding box in the order: [minlon buffer, minlat buffer, maxlon buffer, maxlat buffer].
- Returns:
 A Shapely polygon representing the extent of the inventory, with buffer applied.
- Return type:
 shapely.geometry.box
- Raises:
 ValueError – If the
bufferinput is invalid.
Example
>>> inventory = AssetInventory() >>> _ = inventory.add_asset('asset1', Asset( ... asset_id='asset1', ... coordinates=[[-122.4194, 37.7749]], ... features={'type': 'building'} ... )) >>> _ = inventory.add_asset('asset2', Asset( ... asset_id='asset2', ... coordinates=[[-74.0060, 40.7128]], ... features={'type': 'bridge'} ... ))
>>> # Get extent with default buffer: >>> extent_default = inventory.get_extent(buffer='default') >>> print(extent_default.bounds) (-122.4196, 37.7748, -74.0058, 40.712900000000005)
>>> # Get extent with no buffer: >>> extent_none = inventory.get_extent(buffer='none') >>> print(extent_none.bounds) (-122.4194, 37.7749, -74.006, 40.7128)
>>> # Get extent with a custom buffer: >>> extent_custom = inventory.get_extent( ... buffer=[0.1, 0.1, 0.1, 0.1] ... ) >>> print(extent_custom.bounds) (-122.51939999999999, 37.6749, -73.906, 40.8128)
- get_geojson()
 Generate a GeoJSON representation of the assets in the inventory.
The function constructs a valid GeoJSON
FeatureCollection, where each asset is represented as aFeature. Each feature contains:A
geometryfield defining aPoint,LineString, orPolygonbased on the asset’s coordinates.A
propertiesfield containing asset-specific metadata.
Additionally, the GeoJSON output includes:
A timestamp indicating when the data was created.
The
BRAILSpackage version (if available).A Coordinate Reference System (
crs) definition set toCRS84.
- Returns:
 A dictionary formatted as a GeoJSON
FeatureCollectioncontaining all assets in the inventory.- Return type:
 dict
Note
Assets without geometry are excluded from the generated GeoJSON representation.
Example
>>> inventory = AssetInventory() >>> _ = inventory.add_asset_coordinates( ... 'asset1', ... coordinates=[[-122.4194, 37.7749]] ... ) >>> _ = inventory.add_asset_coordinates( ... 'asset2', ... coordinates=[[-74.0060, 40.7128], [-73.935242, 40.730610]] ... ) >>> inventory_geojson = inventory.get_geojson() >>> print(inventory_geojson) {'type': 'FeatureCollection', 'generated': '2025-08-11 02:49:47.520953', 'brails_version': '4.0', 'crs': {'type': 'name', 'properties': {'name': 'urn:ogc:def:crs:OGC:1.3:CRS84'}}, 'features': [{'type': 'Feature', 'properties': {}, 'geometry': {'type': 'Point', 'coordinates': [-122.4194, 37.7749]}}, {'type': 'Feature', 'properties': {}, 'geometry': { 'type': 'LineString', 'coordinates': [[-74.006, 40.7128], [-73.935242, 40.73061]] } } ] }
- get_multi_keys()
 Identify features that contain multiple realizations across assets.
Iterates through all assets and returns two lists:
Keys associated with multi-valued features(i.e., lists).
All unique feature keys present in the inventory.
- Returns:
 A list of keys corresponding to multi-realization features.
A complete list of all unique feature keys in the inventory.
- Return type:
 Tuple[List[str], List[str]]
- get_n_pw()
 Get the number of possible worlds (realizations) in the inventory.
- Returns:
 The number of possible worlds stored in the inventory.
- Return type:
 int
- get_random_sample(nsamples, seed=None)
 Generate a smaller asset inventory with a random selection of assets.
This method randomly selects
nsamplesassets from the existing inventory and returns a newAssetInventoryinstance containing only these sampled assets. The randomness can be controlled using an optionalseedfor reproducibility.- Parameters:
 nsamples (int) – The number of assets to randomly sample from the inventory. Must be a positive integer not exceeding the total number of assets.
seed (int or float or str or bytes or bytearray or None, optional) – A seed value for the random generator to ensure reproducibility. If None, the system default (current system time) is used.
- Returns:
 A new
AssetInventoryinstance containing the randomly selected subset of assets.- Return type:
 - Raises:
 ValueError – If
nsamplesis not a positive integer or exceeds the number of assets in the inventory.
Example
>>> inventory = AssetInventory() >>> _ = inventory.add_asset('asset1', Asset( ... asset_id='asset1', ... coordinates=[[-122.4194, 37.7749]], ... features={'type': 'building'} ... )) >>> _ = inventory.add_asset('asset2', Asset( ... asset_id='asset2', ... coordinates=[[-74.0060, 40.7128]], ... features={'type': 'bridge'} ... )) >>> _ = inventory.add_asset('asset3', Asset( ... asset_id='asset3', ... coordinates=[[2.3522, 48.8566]], ... features={'type': 'tower'} ... )) >>> sample_inventory = inventory.get_random_sample( ... nsamples=2, ... seed=42 ... ) >>> sorted(sample_inventory.get_asset_ids()) ['asset1', 'asset3']
- get_world_realization(id=0)
 Extract a single realization(possible world) from an inventory.
This method generates a new
AssetInventoryinstance where all features containing multiple possible worlds are reduced to a single realization specified by id. Features that are not lists are copied as-is .- Parameters:
 id (int, default=0) – The index of the realization to extract. Must be within the range of available possible worlds(0-based indexing).
- Returns:
 A new inventory object representing the selected realization.
- Return type:
 - Raises:
 Exception – If
id > 0but the inventory only contains a single realization.Exception – If any feature has fewer realizations than the specified
id.
- join(inventory_to_join, method='GetPointsInPolygons')
 Merge with another AssetInventory using specified spatial join method.
- Parameters:
 inventory_to_join (AssetInventory) – The inventory to be joined with the current one.
method (str) – The spatial join method to use. Defaults to
GetPointsInPolygons. Themethoddefines how the join operation is executed between inventories.
- Raises:
 TypeError – If
inventory_to_joinis not an instance ofAssetInventoryor ifmethodis not a string.- Returns:
 This method modifies the
AssetInventoryinstance in place.- Return type:
 None
Example
>>> polygon1_asset = Asset('polygon1', [ ... [-122.40, 37.75], ... [-122.40, 37.76], ... [-122.39, 37.76], ... [-122.39, 37.75], ... [-122.40, 37.75] ... ]) >>> polygon2_asset = Asset('polygon2', [ ... [-122.38, 37.77], ... [-122.38, 37.78], ... [-122.37, 37.78], ... [-122.37, 37.77], ... [-122.38, 37.77] ... ]) >>> poly_inventory = AssetInventory() >>> _ = poly_inventory.add_asset( ... asset_id='polygon1', ... asset=polygon1_asset ... ) >>> _ = poly_inventory.add_asset( ... asset_id='polygon2', ... asset=polygon2_asset ... ) >>> poly_inventory.print_info() AssetInventory Inventory stored in: dict Key: polygon1 Asset: Coordinates: [[-122.4, 37.75], [-122.4, 37.76], [-122.39, 37.76], [-122.39, 37.75], [-122.4, 37.75]] Features: {} Key: polygon2 Asset: Coordinates: [[-122.38, 37.77], [-122.38, 37.78], [-122.37, 37.78], [-122.37, 37.77], [-122.38, 37.77]] Features: {} >>> # This point lies within polygon1's boundaries: >>> point_inventory = AssetInventory() >>> _ = point_inventory.add_asset( ... asset_id = 'point1', ... asset = Asset( ... 'point1', ... [[-122.395, 37.755]], ... features={'FFE':6.8} ... ) ... ) >>> poly_inventory.join(point_inventory) Joining inventories using GetPointsInPolygons method... Identified a total of 1 matched points. Inventories successfully joined. >>> poly_inventory.print_info() AssetInventory Inventory stored in: dict Key: polygon1 Asset: Coordinates: [[-122.4, 37.75], [-122.4, 37.76], [-122.39, 37.76], [-122.39, 37.75], [-122.4, 37.75]] Features: {'FFE': 6.8} Key: polygon2 Asset: Coordinates: [[-122.38, 37.77], [-122.38, 37.78], [-122.37, 37.78], [-122.37, 37.77], [-122.38, 37.77]] Features: {}
- print_info()
 Print summary information about the AssetInventory.
This method outputs the name of the class , the type of data structure used to store the inventory, and basic information about each asset in the inventory, including its
keyandfeatures.- Returns:
 None
Example
>>> inventory = AssetInventory() >>> _ = inventory.add_asset( ... asset_id='building1', ... asset=Asset( ... 'building1', ... [[-122.40, 37.75], [-122.40, 37.76], ... [-122.39, 37.76], [-122.39, 37.75], ... [-122.40, 37.75]], ... features={'height': 12.5} ... ) ... ) >>> _ = inventory.add_asset( ... asset_id='building2', ... asset=Asset( ... 'building2', ... [[-122.38, 37.77], [-122.38, 37.78], ... [-122.37, 37.78], [-122.37, 37.77], ... [-122.38, 37.77]], ... features={'height': 8.0} ... ) ... ) >>> inventory.print_info() AssetInventory Inventory stored in: dict Key: building1 Asset: Coordinates: [[-122.4, 37.75], [-122.4, 37.76], [-122.39, 37.76], [-122.39, 37.75], [-122.4, 37.75]] Features: {'height': 12.5} Key: building2 Asset: Coordinates: [[-122.38, 37.77], [-122.38, 37.78], [-122.37, 37.78], [-122.37, 37.77], [-122.38, 37.77]] Features: {'height': 8.0}
- read_from_csv(file_path, keep_existing, str_type='building', id_column=None)
 Read inventory data from a CSV file and add it to the inventory.
- Parameters:
 file_path (str) – The path to the CSV file
keep_existing (bool) – If
False, the inventory will be initializedstr_type (str) –
buildingorbridgeid_column (str) – The name of column that contains id values. If
None, new indices will be assigned
- Returns:
 Trueif assets were addded,Falseotherwise.- Return type:
 bool
- read_from_geojson(file_path, asset_type='building')
 Reads a GeoJSON file and imports assets into a BRAILS asset inventory.
This method loads a GeoJSON file, validates its structure, checks that geometries contain valid [longitude, latitude] coordinates, and converts each feature into a BRAILS Asset object. Each asset is assigned a unique numeric identifier and stored in the class inventory.
- Parameters:
 file_path (str) – Path to the GeoJSON file to be read. Must represent a valid GeoJSON FeatureCollection.
asset_type (str, optional) – The type assigned to all imported assets. Defaults to ‘building’.
- Returns:
 Trueif the GeoJSON file is successfully read and assets are added to the inventory.- Return type:
 bool
- Raises:
 FileNotFoundError – If the specified file path does not exist or is not a file.
ValueError – If the file is invalid JSON, not a valid GeoJSON FeatureCollection, contains no features, or has out-of-range coordinates.
NotImplementedError – If one or more geometries include unsupported types.
KeyError – If a feature is missing required keys (geometry or attributes).
Example
Example GeoJSON file (seattle_buildings.geojson):
{ "type": "FeatureCollection", "features": [ { "type": "Feature", "geometry": { "type": "Polygon", "coordinates": [ [ [-122.3355, 47.6080], [-122.3350, 47.6080], [-122.3350, 47.6085], [-122.3355, 47.6085], [-122.3355, 47.6080] ] ] }, "attributes": { "name": "Building A", "height_m": 18.7 } }, { "type": "Feature", "geometry": { "type": "Point", "coordinates": [-122.3321, 47.6062] }, "attributes": { "name": "Building B", "height_m": 12.4 } } ] }
Example usage:
>>> inv = AssetInventory() >>> inv.read_from_geojson('seattle_buildings.geojson', ... asset_type='building') True >>> inv.print_info() AssetInventory Inventory stored in: dict Key: 0 Asset: Coordinates: [[-122.3355, 47.608], [-122.335, 47.608], [-122.335, 47.6085], [-122.3355, 47.6085], [-122.3355, 47.608]] Features: {'name': 'Building A', 'height_m': 18.7, 'type': 'building'} Key: 1 Asset: Coordinates: [[-122.3321, 47.6062]] Features: {'name': 'Building B', 'height_m': 12.4, 'type': 'building'}
Note
All coordinates are expected to follow the GeoJSON standard
[longitude, latitude]order and use the WGS-84 geographic coordinate reference system (EPSG:4326).
- remove_asset(asset_id)
 Remove an asset from the inventory.
- Parameters:
 asset_id (str or int) – The unique identifier for the asset.
- Returns:
 Trueif asset was removed,Falseotherwise.- Return type:
 bool
Example
>>> inventory = AssetInventory() >>> _ = inventory.add_asset( ... asset_id='building1', ... asset=Asset( ... 'building1', ... [[-122.40, 37.75], [-122.40, 37.76], ... [-122.39, 37.76], [-122.39, 37.75], ... [-122.40, 37.75]], ... features={'height': 12.5} ... ) ... ) >>> inventory.remove_asset('building1') True >>> inventory.print_info() AssetInventory Inventory stored in: dict
- remove_features(features_to_remove)
 Remove specified features from all assets in the inventory.
- Parameters:
 features_to_remove (Iterable[str]) – An iterable of feature keys to remove from each
Asset. Accepts types such aslist,tuple,dict_keys, etc.- Returns:
 Trueif at least one feature was removed from any asset,Falseotherwise.- Return type:
 bool
- Raises:
 TypeError – If
features_to_removeis not an iterable of strings.
Example
>>> inventory = AssetInventory() >>> _ = inventory.add_asset( ... asset_id='building1', ... asset=Asset( ... 'building1', ... [[-122.40, 37.75], [-122.40, 37.76], ... [-122.39, 37.76], [-122.39, 37.75], ... [-122.40, 37.75]], ... features={'height': 12.5, 'floors': 3} ... ) ... ) >>> _ = inventory.add_asset( ... asset_id='building2', ... asset=Asset( ... 'building2', ... [[-122.38, 37.77], [-122.38, 37.78], ... [-122.37, 37.78], [-122.37, 37.77], ... [-122.38, 37.77]], ... features={'height': 8.0, 'floors': 2} ... ) ... ) >>> inventory.remove_features(['floors']) True >>> inventory.print_info() AssetInventory Inventory stored in: dict Key: building1 Asset: Coordinates: [[-122.4, 37.75], [-122.4, 37.76], [-122.39, 37.76], [-122.39, 37.75], [-122.4, 37.75]] Features: {'height': 12.5} Key: building2 Asset: Coordinates: [[-122.38, 37.77], [-122.38, 37.78], [-122.37, 37.78], [-122.37, 37.77], [-122.38, 37.77]] Features: {'height': 8.0}
- remove_nonmatching_assets(image_set, verbose=False)
 Remove assets that do not have corresponding entries in image set.
This method compares asset keys in the inventory with those in the provided ImageSet and removes any asset whose key does not exist in the ImageSet.
- Parameters:
 image_set (ImageSet) – The image set containing valid image keys.
verbose (bool, optional) – If
True, prints a summary of removed keys. Default isFalse.
- Modifies:
 - self.inventory(dict):
 Removes nonmatching asset entries directly from the inventory. The object is updated in-place.
Example
>>> inventory = AssetInventory() >>> _ = inventory.add_asset( ... asset_id='house_A', ... asset=Asset( ... 'house_A', ... [[-118.5123, 34.0451], [-118.5120, 34.0454], ... [-118.5117, 34.0452], [-118.5121, 34.0449], ... [-118.5123, 34.0451]], ... features={'type': 'residential', 'floors': 2} ... ) ... ) >>> _ = inventory.add_asset( ... asset_id='warehouse_B', ... asset=Asset( ... 'warehouse_B', ... [[-118.5105, 34.0467], [-118.5102, 34.0471], ... [-118.5099, 34.0468], [-118.5103, 34.0464], ... [-118.5105, 34.0467]], ... features={'type': 'commercial', 'floors': 1} ... ) ... ) >>> inventory.print_info() AssetInventory Inventory stored in: dict Key: house_A Asset: Coordinates: [[-118.5123, 34.0451], [-118.512, 34.0454], [-118.5117, 34.0452], [-118.5121, 34.0449], [-118.5123, 34.0451]] Features: {'type': 'residential', 'floors': 2} Key: warehouse_B Asset: Coordinates: [[-118.5105, 34.0467], [-118.5102, 34.0471], [-118.5099, 34.0468], [-118.5103, 34.0464], [-118.5105, 34.0467]] Features: {'type': 'commercial', 'floors': 1} >>> img_set = ImageSet() >>> img1 = Image('bldg1.jpg') >>> img2 = Image('bldg2.jpg') >>> _ = img_set.add_image('house_A', img1) >>> _ = img_set.add_image('house_B', img2) >>> inventory.remove_nonmatching_assets(img_set, verbose=True) Removed 1 nonmatching assets: ['warehouse_B']
- update_world_realization(id, world_realization)
 Update the current AssetInventory with a specific world realization.
This method integrates feature values from a single-world
world_realizationinventory into the current multi-world inventory by updating the realization at the specified indexid.- Parameters:
 id (int) – The index of the world(realization) to update. Must be less than
self.n_pw.world_realization (AssetInventory) – An
AssetInventoryinstance representing a single realization of the world. All features in this inventory must be scalar (i.e., not lists).
- Raises:
 Exception –
If the specified
idis not within the valid range of realizations. - Ifworld_realizationcontains features with multiple realizations.
- write_to_geojson(output_file='')
 Write inventory to a GeoJSON file and return the GeoJSON dictionary.
This method generates a GeoJSON representation of the asset inventory, writes it to the specified file path (if provided), and returns the GeoJSON object.
- Parameters:
 output_file (str, optional) – Path to the output GeoJSON file. If empty, no file is written.
- Returns:
 A dictionary containing the GeoJSON
FeatureCollection.- Return type:
 Dict
Examples
Define an AssetInventory consisting of a single asset.
>>> inventory = AssetInventory() >>> inventory.add_asset( ... asset_id='asset1', ... asset=Asset( ... 'asset1', ... [ ... [-122.40, 37.75], ... [-122.40, 37.76], ... [-122.39, 37.76], ... [-122.39, 37.75], ... [-122.40, 37.75] ... ], ... features={'name': 'Building A', 'roofHeight': 22.6} ... ) ... )
Write the AssetInventory data into a GeoJSON dictionary.
>>> geojson_dict = inventory.write_to_geojson() >>> print(geojson_dict['features']) [{'type': 'Feature', 'properties': {'name': 'Building A', 'roofHeight': 22.6}, 'geometry': {'type': 'Polygon', 'coordinates': [[[-122.4, 37.75], [-122.4, 37.76], [-122.39, 37.76], [-122.39, 37.75], [-122.4, 37.75]]]}, 'id': '0'}]
Write the AssetInventory data in a GeoJSON dictionary and a file named
output.geojson.>>> geojson_written = inventory.write_to_geojson('output.geojson') Wrote 1 asset to {../output.geojson}
- brails.types.asset_inventory.clean_floats(obj)
 Recursively convert float values that are mathematically integers to int.
This function traverses a nested structure (e.g., dict, list, JSON-like object) and converts any float that is numerically equivalent to an integer into an int, improving the readability and cleanliness of the output, especially for serialization.
- Parameters:
 obj (Any) – A JSON-like object (dict, list, or primitive value) to process.
- Returns:
 The input object with eligible floats converted to integers.
- Return type:
 Any