Skip to content

Instantly share code, notes, and snippets.

@rhewitt22
Last active November 6, 2017 22:17
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save rhewitt22/9141903 to your computer and use it in GitHub Desktop.
Save rhewitt22/9141903 to your computer and use it in GitHub Desktop.
Script for converting FAA Digital Obstacle File from .Dat to .csv
##################################################################################################################
#
# Author: Roy Hewitt, US Fish & Wildlife Service
# Location: Southeast Regional Office
# Address: 1875 Century Blvd, Suite 200, Atlanta, GA 30345
# Phone: 404-679-7306
# Email: roy_hewitt@fws.gov
#
# Purpose: To process the FAA Digital Obstacle Files for use with GIS. Converts Degree Minutes Seconds to
# Decimal Degrees; outputs .csv file.
#
##################################################################################################################
import csv, os
# The folder containing all of the .Dat FAA Obstacle files from: https://nfdc.faa.gov/tod/public/TOD_DOF.html
root = r'C:\Users\rhewitt\Desktop\DOF'
counter = 0
# Convert every .Dat file to a .csv; Convert DMS to Decimal Degrees for mapping
for eachFile in os.listdir( root ):
if eachFile.endswith(".Dat"):
dat = open(os.path.join(root, eachFile), 'r')
csvOut = os.path.join(root, dat.name[:-4] + ".csv")
f = open(csvOut, 'wb')
wr = csv.writer(f, quoting=csv.QUOTE_ALL)
# Create a header row in the CSV file containing all field names
header = ["ObstacleNo", "ver_status", "Country", "State", "City", "latdeg", "latmin", "latsec", "N_S", "latitude", "londeg", "lonmin", "lonsec", "E_W", "longitude", "Type", "QTY", "AGL_HT", "AMSL_HT", "Lighting", "horz_acc", "vert_acc", "marking", "FAA_no", "Action", "Julian_dt"]
wr.writerow(header)
print dat.name[:-4]
i=-1
for line in dat:
i+=1
# Skip the first 4 rows (they include poorly formatted header information)
if i < 5:
continue
# .Dat files have fixed-width columns; the data is always in the same position within a row
else:
counter += 1
ORS = line[:9] # The first 9 characters of the row represent the Obstacle number
v = line[9:11]
country = line[11:14]
state = line[14:17]
city = line[17:35]
latDeg = line[35:37]
latMin = line[37:40]
latSec = line[40:46]
latHem = line[46:47]
lonDeg = line[47:51]
lonMin = line[51:54]
lonSec = line[54:60]
lonHem = line[60:61]
obType = line[61:75]
uknown = line[75:76]
agl = line[76:82]
amsl = line[82:88]
lt = line[88:90]
ah = line[90:92]
ccv = line[92:94]
MIN = line[94:96]
study = line[96:111]
action = line[111:113]
jDate = line[113:]
# Convert DMS to Decimal Degrees (N vs. S determines if the value is positive or negative)
if latHem == "N":
latitude = (float(latDeg)+(float(latMin)/60)+(float(latSec)/3600))
else:
latitude = -1*(float(latDeg)+(float(latMin)/60)+(float(latSec)/3600))
# Convert DMS to Decimal Degrees (E vs. W determines if the value is positive or negative)
if lonHem == "E":
longitude = (float(lonDeg)+(float(lonMin)/60)+(float(lonSec)/3600))
else:
longitude = -1*(float(lonDeg)+(float(lonMin)/60)+(float(lonSec)/3600))
csvLine = [ORS, v, country, state, city, latDeg, latMin, latSec, latHem, latitude, lonDeg, lonMin, lonSec, lonHem, longitude, obType, uknown, agl, amsl, lt, ah, ccv, MIN, study, action, jDate.rstrip("\n")]
wr.writerow(csvLine)
f.close()
dat.close()
print "Finished! Converted " + str(counter) + " rows!"
@rhewitt22
Copy link
Author

To Do:

  • Create a VRT file for each .dat file for easy shapefile creation
  • Add Python bindings for ogr2ogr
  • Create a shapefile for each .csv using ogr2ogr

VRT format:

<OGRVRTDataSource>
    <OGRVRTLayer name="01-AL">
        <SrcDataSource>01-AL.csv</SrcDataSource>
        <GeometryType>wkbPoint</GeometryType>
        <LayerSRS>WGS84</LayerSRS>
        <GeometryField encoding="PointFromColumns" x="longitude" y="latitude"/>
    </OGRVRTLayer>
</OGRVRTDataSource>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment