NSI Integration
This is an example to demonstrate how BrailsPlusPlus integrates with the National Structures Inventory. There are two ways to integrate:
Create an inventory that does not include footprint information directly from NSI.
Integrate an existing AssetInventory with NSI. For each Asset in the asset inventory, the features from NSI are obtained and merged with the asset’s existing features. This is done by finding an asset in the NSI located in the footprint.
1# written: fmk, bacetiner
2# Last updated: 11-06-2024
3# License: BSD-2
4
5"""
6brails_nsi.py
7=============
8Example demonstrating the use of NSI scraper module .
9
10 Purpose: Testing 1) get_class method of Importer
11 2) get_raw_data_given_boundary and
12 get_filtered_data_given_inventory methods of NSI_Parser
13 3) get_footprints method from scraper
14 4) print_info and write_to_geojson method of AssetInventory
15 objects
16"""
17
18import argparse
19import sys
20import os
21import json
22
23# the following line is not neeeded if brails is imported from pypi
24# .. it is included here as it allows us to test the code on a nightly basis
25sys.path.insert(1, "../../")
26
27import brails
28
29from brails import Importer
30
31def main():
32
33 # Create the argument parser
34 parser = argparse.ArgumentParser(description="Demonstrate Importer.")
35 parser.add_argument('scraper', type=str, help="Footprint Scraper")
36 parser.add_argument('location', type=str, help="Location")
37
38 # Parse the arguments
39 args = parser.parse_args()
40
41 # Create an importer to get the required classes:
42 importer = Importer()
43
44 # Select a region and create its RegionBoundary:
45 region_boundary_class = importer.get_class('RegionBoundary')
46 region_boundary_object = region_boundary_class({'type': 'locationName', 'data': args.location})
47
48 #
49 # Use NSI_Parser to get the NSI raw data for the specified region
50 #
51
52 nsi_class = importer.get_class('NSI_Parser')
53 nsi = nsi_class()
54 nsi_inventory = nsi.get_raw_data_given_boundary(region_boundary_object, 'ft')
55 print(f'Total number of assets detected using NSI is {len(nsi_inventory.inventory)}')
56
57 print('\n******** SMALL NSI INVENTORY *********')
58 nsi_inventory_subset = nsi_inventory.get_random_sample(2, 200)
59 nsi_inventory_subset.print_info()
60
61 #
62 # Now Use the FootprintScraper to get footprints and integrate NSI inventory data
63 # - will integrate on smaller inventory set
64 #
65
66
67 scraper_class = importer.get_class(args.scraper)
68 scraper = scraper_class({'length': 'ft'})
69 scraper_inventory = scraper.get_footprints(region_boundary_object)
70 print(f'Total number of assets detected using {args.scraper} is {len(scraper_inventory.inventory)}')
71 # Create inventories that are a small subset of the obtained footprints & print:
72 inventory_subset1 = scraper_inventory.get_random_sample(5, 200)
73 inventory_subset2 = scraper_inventory.get_random_sample(5, 200)
74
75 print('\n******** SMALL INVENTORY WITH NO NSI_DATA *********')
76 inventory_subset1.print_info()
77
78 # integrate subset with raw and filtered NSI data
79 subset_nsi_raw_data = nsi.get_raw_data_given_inventory(inventory_subset1, 'ft')
80 subset_nsi_processed_data = nsi.get_filtered_data_given_inventory(inventory_subset2, 'ft')
81
82 #
83 # Print the inventories
84 #
85
86 print('\n******** SMALL INVENTORY WITH RAW NSI DATA *********')
87 subset_nsi_raw_data.print_info()
88
89 print('\n******** SMALL INVENTORY WITH PROCESSES NSI DATA*********')
90 subset_nsi_processed_data.print_info()
91
92 #
93 # Write the extracted inventory to a GeoJSON file:
94 #
95
96 FILE_PATH = 'tmp/smallinv.geojson'
97 directory = os.path.dirname(FILE_PATH)
98 os.makedirs(directory, exist_ok=True)
99 geojson = subset_nsi_processed_data.write_to_geojson(FILE_PATH)
100
101
102# Run the main function if this script is executed directly
103if __name__ == "__main__":
104 main()
The script is executed by entering the following command in a terminal window:
python3 brails_nsi.py OSM_FootprintScraper "Berkeley, CA"
As shown in the print_output() of the smaller NSI inventory, the coordinates for such an inventory only contain points instead of the building footprints.
1******** SMALL NSI INVENTORY *********
2AssetInventory
3Inventory stored in: dict
4Key: 474740175 Asset:
5 Coordinates: [[-122.262559, 37.879117]]
6 Features: {'fd_id': 474740175, 'bid': '849VVPHP+JXW-2-1-2-2', 'occtype': 'RES1-2SWB', 'st_damcat': 'RES', 'bldgtype': 'M', 'found_type': 'B', 'cbfips': '060014225001003', 'pop2amu65': 2, 'pop2amo65': 1, 'pop2pmu65': 2, 'pop2pmo65': 1, 'sqft': 1773, 'num_story': 2, 'ftprntid': '06001_559590', 'ftprntsrc': 'NGA', 'students': 0, 'found_ht': 2, 'val_struct': 359933.479, 'val_cont': 179966.739, 'val_vehic': 27000, 'source': 'P', 'med_yr_blt': 1939, 'firmzone': 'NA', 'o65disable': 0.22, 'u65disable': 0.03, 'x': -122.2625592, 'y': 37.879116732, 'ground_elv': 350.8512103598022, 'ground_elv_m': 106.93944549560547, 'type': 'Building'}
7Key: 475206003 Asset:
8 Coordinates: [[-122.279912, 37.894081]]
9 Features: {'fd_id': 475206003, 'bid': '849VVPVC+J2P-4-4-4-3', 'occtype': 'RES1-2SNB', 'st_damcat': 'RES', 'bldgtype': 'W', 'found_type': 'C', 'cbfips': '060014213001020', 'pop2amu65': 2, 'pop2amo65': 0, 'pop2pmu65': 1, 'pop2pmo65': 0, 'sqft': 2341, 'num_story': 2, 'ftprntid': '06001_730116', 'ftprntsrc': 'NGA', 'students': 0, 'found_ht': 1.5, 'val_struct': 378037.886, 'val_cont': 189018.943, 'val_vehic': 27000, 'source': 'P', 'med_yr_blt': 1939, 'firmzone': 'NA', 'o65disable': 0.22, 'u65disable': 0.03, 'x': -122.2799116, 'y': 37.894081399, 'ground_elv': 195.71405070861817, 'ground_elv_m': 59.65364074707031, 'type': 'Building'}
The output also shows that the number of buildings in the two inventories, nsi_inventory and scraper_inventory, are different:
Total number of assets detected using NSI is 27705
Total number of assets detected using OSM_FootprintScraper is 35547
As there are different numbers of buildings in the two inventories, when integrating NSI dataset into the footprint inventory, there will be assets for which no NSI data exists. In the merge performed with the example run, 2 out of the 5 assets in the subset inventories do not have data available in NSI. This is shown in the output lines:
The original and integrated inventories are as shown:
1******** SMALL INVENTORY WITH NO NSI_DATA *********
2AssetInventory
3Inventory stored in: dict
4Key: 2989 Asset:
5 Coordinates: [[-122.2539358, 37.8823889], [-122.2538841, 37.8822577], [-122.2538636, 37.882258], [-122.2538454, 37.8821659], [-122.2540379, 37.8821623], [-122.2540337, 37.8822459], [-122.2539784, 37.882245], [-122.2540264, 37.8823667], [-122.2539358, 37.8823889]]
6 Features: {'type': 'Building', 'buildingheight': 'NA', 'erabuilt': 'NA', 'numstories': 1, 'roofshape': 'NA', 'fpAreas': 2973}
7Key: 13333 Asset:
8 Coordinates: [[-122.2743673, 37.8721826], [-122.2743469, 37.8720391], [-122.2743897, 37.8720353], [-122.2743867, 37.8720143], [-122.2744387, 37.8720097], [-122.2744416, 37.8720305], [-122.2744612, 37.8720287], [-122.2744816, 37.8721725], [-122.2743673, 37.8721826]]
9 Features: {'type': 'Building', 'buildingheight': 'NA', 'erabuilt': 'NA', 'numstories': 'NA', 'roofshape': 'NA', 'fpAreas': 1866}
10Key: 1989 Asset:
11 Coordinates: [[-122.2534638, 37.856443], [-122.2534705, 37.856479], [-122.2535403, 37.8564711], [-122.253547, 37.8564912], [-122.2535946, 37.8565177], [-122.2535993, 37.8565277], [-122.2536127, 37.8565272], [-122.2535939, 37.8564404], [-122.253494, 37.8564531], [-122.2534913, 37.8564399], [-122.2534638, 37.856443]]
12 Features: {'type': 'Building', 'buildingheight': 'NA', 'erabuilt': 'NA', 'numstories': 'NA', 'roofshape': 'NA', 'fpAreas': 625}
13Key: 9361 Asset:
14 Coordinates: [[-122.2654248, 37.8550534], [-122.2654134, 37.854993], [-122.2654737, 37.8549859], [-122.2654851, 37.8550463], [-122.2654248, 37.8550534]]
15 Features: {'type': 'Building', 'buildingheight': 'NA', 'erabuilt': 'NA', 'numstories': 'NA', 'roofshape': 'NA', 'fpAreas': 392}
16Key: 17479 Asset:
17 Coordinates: [[-122.292788, 37.8763201], [-122.2927717, 37.8762696], [-122.2928486, 37.8762541], [-122.2928649, 37.8763047], [-122.292788, 37.8763201]]
18 Features: {'type': 'Building', 'buildingheight': 'NA', 'erabuilt': 'NA', 'numstories': 'NA', 'roofshape': 'NA', 'fpAreas': 435}
19
20Getting National Structure Inventory (NSI) building data for the entered location input...
21Found a total of 3 building points in NSI that are within the entered region of interest
22keys: [2989, 13333, 1989, 9361, 17479] index [0, 1, 2]
23
24Getting National Structure Inventory (NSI) building data for the entered location input...
25Found a total of 3 building points in NSI that match the footprint data.
26keys: [2989, 13333, 1989, 9361, 17479] index [0, 1, 2]
27
28******** SMALL INVENTORY WITH RAW NSI DATA *********
29AssetInventory
30Inventory stored in: dict
31Key: 2989 Asset:
32 Coordinates: [[-122.2539358, 37.8823889], [-122.2538841, 37.8822577], [-122.2538636, 37.882258], [-122.2538454, 37.8821659], [-122.2540379, 37.8821623], [-122.2540337, 37.8822459], [-122.2539784, 37.882245], [-122.2540264, 37.8823667], [-122.2539358, 37.8823889]]
33 Features: {'type': 'Building', 'buildingheight': 'NA', 'erabuilt': 1954, 'numstories': 1, 'roofshape': 'NA', 'fpAreas': 2973, 'fd_id': 475445345, 'bid': '849VVP4W+HHW-2-2-2-2', 'occtype': 'IND6', 'st_damcat': 'IND', 'bldgtype': 'W', 'found_type': 'S', 'cbfips': '060014239021001', 'pop2amu65': 0, 'pop2amo65': 0, 'pop2pmu65': 4, 'pop2pmo65': 0, 'sqft': 6506.02409, 'num_story': 1, 'ftprntid': '06001_548222', 'ftprntsrc': 'NGA', 'students': 0, 'found_ht': 0.5, 'val_struct': 958384.635, 'val_cont': 958384.635, 'val_vehic': 81000, 'source': 'E', 'med_yr_blt': 1939, 'firmzone': 'NA', 'o65disable': 0.22, 'u65disable': 0.03, 'x': -122.2535494, 'y': 37.85648153, 'ground_elv': 239.3753899307251, 'ground_elv_m': 72.96161651611328, 'lon': -122.2539358, 'lat': 37.882252355, 'fparea': 1592, 'repaircost': 389506.045, 'constype': 'RM1', 'occupancy': 'RES1'}
34Key: 13333 Asset:
35 Coordinates: [[-122.2743673, 37.8721826], [-122.2743469, 37.8720391], [-122.2743897, 37.8720353], [-122.2743867, 37.8720143], [-122.2744387, 37.8720097], [-122.2744416, 37.8720305], [-122.2744612, 37.8720287], [-122.2744816, 37.8721725], [-122.2743673, 37.8721826]]
36 Features: {'type': 'Building', 'buildingheight': 'NA', 'erabuilt': 1992, 'numstories': 1, 'roofshape': 'NA', 'fpAreas': 1866, 'fd_id': 473584913, 'bid': '849VVPJW+WC4-6-2-5-3', 'occtype': 'RES1-1SWB', 'st_damcat': 'RES', 'bldgtype': 'M', 'found_type': 'B', 'cbfips': '060014216002007', 'pop2amu65': 2, 'pop2amo65': 1, 'pop2pmu65': 2, 'pop2pmo65': 1, 'sqft': 1592, 'num_story': 1, 'ftprntid': '06001_813170', 'ftprntsrc': 'NGA', 'students': 0, 'found_ht': 2, 'val_struct': 389506.045, 'val_cont': 194753.022, 'val_vehic': 27000, 'source': 'P', 'med_yr_blt': 1954, 'firmzone': 'NA', 'o65disable': 0.22, 'u65disable': 0.03, 'x': -122.2539358, 'y': 37.882252355, 'ground_elv': 1004.1034449096679, 'ground_elv_m': 306.05072021484375, 'lon': -122.2743974, 'lat': 37.872097621, 'fparea': 1539.29, 'repaircost': 320524.48, 'constype': 'W1', 'occupancy': 'RES3A'}
37Key: 1989 Asset:
38 Coordinates: [[-122.2534638, 37.856443], [-122.2534705, 37.856479], [-122.2535403, 37.8564711], [-122.253547, 37.8564912], [-122.2535946, 37.8565177], [-122.2535993, 37.8565277], [-122.2536127, 37.8565272], [-122.2535939, 37.8564404], [-122.253494, 37.8564531], [-122.2534913, 37.8564399], [-122.2534638, 37.856443]]
39 Features: {'type': 'Building', 'buildingheight': 'NA', 'erabuilt': 1939, 'numstories': 1, 'roofshape': 'NA', 'fpAreas': 625, 'fd_id': 474705763, 'bid': '849VVPCG+R6Q-4-2-3-2', 'occtype': 'RES3A', 'st_damcat': 'RES', 'bldgtype': 'W', 'found_type': 'S', 'cbfips': '060014223003010', 'pop2amu65': 1, 'pop2amo65': 0, 'pop2pmu65': 0, 'pop2pmo65': 0, 'sqft': 1539.29, 'num_story': 1, 'ftprntid': '06001_34778', 'ftprntsrc': 'NGA', 'students': 0, 'found_ht': 0.5, 'val_struct': 320524.48, 'val_cont': 160262.24, 'val_vehic': 27000, 'source': 'P', 'med_yr_blt': 1992, 'firmzone': 'NA', 'o65disable': 0.22, 'u65disable': 0.03, 'x': -122.2743974, 'y': 37.872097621, 'ground_elv': 165.9004509815979, 'ground_elv_m': 50.56645584106445, 'lon': -122.2535494, 'lat': 37.85648153, 'fparea': 6506.02409, 'repaircost': 958384.635, 'constype': 'W1', 'occupancy': 'IND6'}
40Key: 9361 Asset:
41 Coordinates: [[-122.2654248, 37.8550534], [-122.2654134, 37.854993], [-122.2654737, 37.8549859], [-122.2654851, 37.8550463], [-122.2654248, 37.8550534]]
42 Features: {'type': 'Building', 'buildingheight': 'NA', 'erabuilt': 'NA', 'numstories': 'NA', 'roofshape': 'NA', 'fpAreas': 392}
43Key: 17479 Asset:
44 Coordinates: [[-122.292788, 37.8763201], [-122.2927717, 37.8762696], [-122.2928486, 37.8762541], [-122.2928649, 37.8763047], [-122.292788, 37.8763201]]
45 Features: {'type': 'Building', 'buildingheight': 'NA', 'erabuilt': 'NA', 'numstories': 'NA', 'roofshape': 'NA', 'fpAreas': 435}
46
47******** SMALL INVENTORY WITH PROCESSES NSI DATA*********
48AssetInventory
49Inventory stored in: dict
50Key: 2989 Asset:
51 Coordinates: [[-122.2539358, 37.8823889], [-122.2538841, 37.8822577], [-122.2538636, 37.882258], [-122.2538454, 37.8821659], [-122.2540379, 37.8821623], [-122.2540337, 37.8822459], [-122.2539784, 37.882245], [-122.2540264, 37.8823667], [-122.2539358, 37.8823889]]
52 Features: {'type': 'Building', 'buildingheight': 'NA', 'erabuilt': 1954, 'numstories': 1, 'roofshape': 'NA', 'fpAreas': 2973, 'fd_id': 475445345, 'bid': '849VVP4W+HHW-2-2-2-2', 'occtype': 'IND6', 'st_damcat': 'IND', 'bldgtype': 'W', 'found_type': 'S', 'cbfips': '060014239021001', 'pop2amu65': 0, 'pop2amo65': 0, 'pop2pmu65': 4, 'pop2pmo65': 0, 'sqft': 6506.02409, 'num_story': 1, 'ftprntid': '06001_548222', 'ftprntsrc': 'NGA', 'students': 0, 'found_ht': 0.5, 'val_struct': 958384.635, 'val_cont': 958384.635, 'val_vehic': 81000, 'source': 'E', 'med_yr_blt': 1939, 'firmzone': 'NA', 'o65disable': 0.22, 'u65disable': 0.03, 'x': -122.2535494, 'y': 37.85648153, 'ground_elv': 239.3753899307251, 'ground_elv_m': 72.96161651611328, 'lon': -122.2539358, 'lat': 37.882252355, 'fparea': 1592, 'repaircost': 389506.045, 'constype': 'RM1', 'occupancy': 'RES1'}
53Key: 13333 Asset:
54 Coordinates: [[-122.2743673, 37.8721826], [-122.2743469, 37.8720391], [-122.2743897, 37.8720353], [-122.2743867, 37.8720143], [-122.2744387, 37.8720097], [-122.2744416, 37.8720305], [-122.2744612, 37.8720287], [-122.2744816, 37.8721725], [-122.2743673, 37.8721826]]
55 Features: {'type': 'Building', 'buildingheight': 'NA', 'erabuilt': 1992, 'numstories': 1, 'roofshape': 'NA', 'fpAreas': 1866, 'fd_id': 473584913, 'bid': '849VVPJW+WC4-6-2-5-3', 'occtype': 'RES1-1SWB', 'st_damcat': 'RES', 'bldgtype': 'M', 'found_type': 'B', 'cbfips': '060014216002007', 'pop2amu65': 2, 'pop2amo65': 1, 'pop2pmu65': 2, 'pop2pmo65': 1, 'sqft': 1592, 'num_story': 1, 'ftprntid': '06001_813170', 'ftprntsrc': 'NGA', 'students': 0, 'found_ht': 2, 'val_struct': 389506.045, 'val_cont': 194753.022, 'val_vehic': 27000, 'source': 'P', 'med_yr_blt': 1954, 'firmzone': 'NA', 'o65disable': 0.22, 'u65disable': 0.03, 'x': -122.2539358, 'y': 37.882252355, 'ground_elv': 1004.1034449096679, 'ground_elv_m': 306.05072021484375, 'lon': -122.2743974, 'lat': 37.872097621, 'fparea': 1539.29, 'repaircost': 320524.48, 'constype': 'W1', 'occupancy': 'RES3A'}
56Key: 1989 Asset:
57 Coordinates: [[-122.2534638, 37.856443], [-122.2534705, 37.856479], [-122.2535403, 37.8564711], [-122.253547, 37.8564912], [-122.2535946, 37.8565177], [-122.2535993, 37.8565277], [-122.2536127, 37.8565272], [-122.2535939, 37.8564404], [-122.253494, 37.8564531], [-122.2534913, 37.8564399], [-122.2534638, 37.856443]]
58 Features: {'type': 'Building', 'buildingheight': 'NA', 'erabuilt': 1939, 'numstories': 1, 'roofshape': 'NA', 'fpAreas': 625, 'fd_id': 474705763, 'bid': '849VVPCG+R6Q-4-2-3-2', 'occtype': 'RES3A', 'st_damcat': 'RES', 'bldgtype': 'W', 'found_type': 'S', 'cbfips': '060014223003010', 'pop2amu65': 1, 'pop2amo65': 0, 'pop2pmu65': 0, 'pop2pmo65': 0, 'sqft': 1539.29, 'num_story': 1, 'ftprntid': '06001_34778', 'ftprntsrc': 'NGA', 'students': 0, 'found_ht': 0.5, 'val_struct': 320524.48, 'val_cont': 160262.24, 'val_vehic': 27000, 'source': 'P', 'med_yr_blt': 1992, 'firmzone': 'NA', 'o65disable': 0.22, 'u65disable': 0.03, 'x': -122.2743974, 'y': 37.872097621, 'ground_elv': 165.9004509815979, 'ground_elv_m': 50.56645584106445, 'lon': -122.2535494, 'lat': 37.85648153, 'fparea': 6506.02409, 'repaircost': 958384.635, 'constype': 'W1', 'occupancy': 'IND6'}
59Key: 9361 Asset:
60 Coordinates: [[-122.2654248, 37.8550534], [-122.2654134, 37.854993], [-122.2654737, 37.8549859], [-122.2654851, 37.8550463], [-122.2654248, 37.8550534]]
61 Features: {'type': 'Building', 'buildingheight': 'NA', 'erabuilt': 'NA', 'numstories': 'NA', 'roofshape': 'NA', 'fpAreas': 392}
62Key: 17479 Asset:
63 Coordinates: [[-122.292788, 37.8763201], [-122.2927717, 37.8762696], [-122.2928486, 37.8762541], [-122.2928649, 37.8763047], [-122.292788, 37.8763201]]
64 Features: {'type': 'Building', 'buildingheight': 'NA', 'erabuilt': 'NA', 'numstories': 'NA', 'roofshape': 'NA', 'fpAreas': 435}
NSI Integration Notebook
Here is a link to a Jupyter Notebook that runs the basic code, accompanied by graphics to better illustrate the output.
Note
Information on the fields output for NSI can be found here
When the number of buildings in the NSI differs from the inventory it is being merged with, imputation may be required during the integration process.
The NSI is new and under development and as a consequence is not perfect.