Salem Oregon Address Import
Jump to navigation
Jump to search
Current Status
In accordance with the Import/Guidelines:
- We have contacted what local community members we were able to find.
- We have contacted City of Salem GIS to ensure licensing is appropriate. Via email they've confirmed that there is no copyright on this data; it's public domain.
- We have prepared a draft and small test-import of data available as an .OSM file for review. Any and all feedback is appreciated.
- We have added our wiki page to the Import/Catalogue
- We have sought comments, community and import mailing list approval from OSMUS Slack, the Community Forum, and https://lists.openstreetmap.org/pipermail/imports/.
Get involved:
- on GitLab for source code, issues, and official discussion
- OSM US Slack, #imports channel (get an account here)
Background
City of Salem has published address and road datasets on their GIS hub: https://data.cityofsalem.net/datasets/salem::primary-address/explore
Why does this belong in OSM?
Can't navigate a place without roads and addresses!
Interested Parties
- User:Zyphlar
- (add your name here)
Tags, Processing, Quality/Validation, and Workflow
See [1]
# Salem Oregon Address Import See [https://wiki.openstreetmap.org/wiki/Salem_Oregon_Address_Import](https://wiki.openstreetmap.org/wiki/Salem_Oregon_Address_Import) ## Data Source - Salem GIS department's FTP server - Also https://data.cityofsalem.net/datasets/salem::primary-address/explore - No copyright, public domain <img src="Screenshot_2023-10-25_213128.png"/> ## Field Mapping - ADD_NUM -> addr:housenumber (int) - formatstreet(FULL_ST_NAME) -> addr:street (text) - SUB_VAL -> addr:unit (text) - title(CITY) -> addr:city (text) - ZIP -> addr:postcode (text) - addr:state 'OR' (manually added) ## Processing - Get `Primary_Addresses.geojson` from the City GIS server linked above. - Open the file in QGIS and open the layer attribute table - Use the field calculator and the below script to add new virtual fields per the mapping above. - Export the layer to geojson with "EPSG:4326 - WGS 84" projection. Deselect all fields besides those above. - Save as `processed.geojson` ## Import steps - Load processed.geojson into JOSM - Zoom in to the area you wish to work on and Download OSM data to a New Layer - In the geojson layer, select one neighborhood or city block worth of addresses - Click Edit > Merge Selection - Delete the selected items you just merged (so you don't try merging them again later) - Switch to Data Layer 1 and run the JOSM Validator - An easy way to only validate changes is to press the Upload button, but cancel before actually uploading. - We don't need to worry about validation errors that don't involve our changes. - Fix all duplicate housenumber warnings and nearby street not found warnings - An easy way to auto-fix all duplicate housenumbers is to select all duplicates, Search within the selection for `new`, and delete. - Pay special attention to errors like "East Street Northeast" -> "E Street Northeast" which can be mass-corrected. - Search for all `new "addr:housenumber" = "0"` elements and delete them. - Click Upload, verify there are no further warnings or errors in the changeset - Make sure there are no erroneous Relations or other unwanted objects about to be uploaded. - Upload with this changeset comment: ``` comment=Addresses near Salem Oregon #salemimport import=yes website=https://wiki.openstreetmap.org/wiki/Salem_Oregon_Address_Import source=City of Salem GIS source:url=https://data.cityofsalem.net/datasets/salem::primary-address/explore ``` - Review imported data in Achavi or Osmcha to ensure it looks proper. ## QGIS Processing script ``` import qgis.core import qgis.gui import re # # This will keep street names like SR 574A as SR 574A however # will lowercase other number-digit suffixes with <2 or >4 numbers # or >1 suffix-letters, like 12th Street or 243rd Ave. # @qgsfunction(args='auto', group='Custom', referenced_columns=[]) def getstreetfromaddress(value1, feature, parent): parts = value1.split() parts.pop(0) # Ignore the first bit (i.e. "123" in "123 N MAIN ST") parts = map(formatstreetname, parts) return " ".join(parts) @qgsfunction(args='auto', group='Custom', referenced_columns=[]) def formatstreet(value1, feature, parent): parts = value1.split() parts = map(formatstreetname, parts) return " ".join(parts) # Internal function def formatstreetname(name): # Acryonyms if name == "CR": return "County Road" if name == "SR": return "SR" # State Route if name == "NFS": return "NFS" # National Forest Service? if name == "US": return "US" # Directions if name == "N": return "North" if name == "NE": return "Northeast" if name == "E": return "East" if name == "SE": return "Southeast" if name == "S": return "South" if name == "SW": return "Southwest" if name == "W": return "West" if name == "NW": return "Northwest" # Suffixes if name == "AV": return "Avenue" if name == "AVE": return "Avenue" if name == "BLVD": return "Boulevard" if name == "BND": return "Bend" if name == "CIR": return "Circle" if name == "CR": return "Circle" if name == "CT": return "Court" if name == "DR": return "Drive" if name == "FLDS": return "Fields" if name == "GRV": return "Grove" if name == "HL": return "Hill" if name == "HOLW": return "Hollow" if name == "HW": return "Highway" if name == "HWY": return "Highway" if name == "LN": return "Lane" if name == "LOOP": return "Loop" if name == "LP": return "Loop" if name == "PATH": return "Path" if name == "PL": return "Place" if name == "RD": return "Road" if name == "RUN": return "Run" if name == "SQ": return "Square" if name == "ST": return "Street" if name == "TER": return "Terrace" if name == "TRL": return "Trail" if name == "VW": return "View" if name == "WAY": return "Way" if name == "WY": return "Way" if name == "XING": return "Crossing" if re.match('^[0-9]{2,4}[A-Za-z]$', name) != None: return name return name.capitalize() ```