Thursday 25 July 2019

DOF_Manager QGIS plugin (1) - introduction

Let's back to the problem of dealing with obstacles coming from Digital Obstacle File (DOF) with GIS. I have covered this issue in following posts so far:
PostGIS database for storing FAA Digital Obstacle File - SQL statements to create database
Challenge: importing FAA digital obstacle file content into PostGIS database - Python script to import data from dat file with obstacle data directly into PostGIS database
QGIS Plugin to convert DOF (Digital Obstacle File) data - QGIS plugin that reads dat file and convert it into CSV, KML or shapefile format.
As you can see, we are already able to import obstacles into spatial database, display it using QGIS and convert data into other formats. But we want to go further - a QGIS plugins that reads data and import it directly to database, updates imported data with data from daily change files, easily search and export data with specified criteria (e.g type, location within circle of specified point) to other formats, manually adding data etc.
You might asking at this point why I am going to write a new plugin that does the same work as the scrips I have got already. Well, the first thing is it is a good idea to have all this functionality in one tools, especially if they will be accessible from QGIS. The second reason is that I am going to use slightly different approach, that will be helpful to deal with features I am going to add in this plugin. And this plugin will be a nice practice before I will develop more generic tool to deal with obstacles.

In this post I will create class that parse line od data in DOF. I want to make it in a different way than previous. This time it will be more generic - in case format of DOF will change (e. g. new column, column will be extended etc.) little will have to be change in source code to parse data. Notice that at this stage I am not going to check if values are correct (e. g. altitude is a number not a strng) or if for example coordinate is missing or is wrong.

DofObstacle class has FIELDS dictionary, which is a class attribute that keeps information how to map line of DOF with obstacle attribute: 


class DofObstacle:

    FIELDS = {'OAS_CODE': [1, 2],
              'OBS_NUMBER': [4, 9],
              'VERIF_STATUS': [11],
              'CTRY_IDENT': [13, 14],
              'STATE_IDENT': [16, 17],
              'CITY_NAME': [19, 34],
              'LAT_DMS': [36, 47],
              'LON_DMS': [49, 61],
              'OBS_TYPE': [63, 88],
              'QAUNTITY': [82],
              'AGL_HT': [84, 88],
              'AMSL_HT': [90, 94],
              'LIGHTING': [96],
              'HOR_ACC': [98],
              'VERT_ACC': [100],
              'MARK_INDICATOR': [102],
              'FAA_STUDY_NR': [104, 117],
              'ACTION': [119],
              'JULIAN_DATE': [121, 127]}

Constructor creates initial state of obstacles - by default all attributes are 'empty'


def __init__(self):
    self.OAS_CODE = ''
    self.OBS_NUMBER = ''
    self.VERIF_STATUS = ''
    self.CTRY_IDENT = ''
    self.STATE_IDENT = ''
    self.CITY_NAME = ''
    self.LAT_DMS = ''
    self.LON_DMS = ''
    self.OBS_TYPE = ''
    self.QAUNTITY = ''
    self.AGL_HT = ''
    self.AMSL_HT = ''
    self.LIGHTING = ''
    self.HOR_ACC = ''
    self.VERT_ACC = ''
    self.MARK_INDICATOR = ''
    self.FAA_STUDY_NR = ''
    self.ACTION = ''
    self.JULIAN_DATE = ''
    self.LAT_DD = ''
    self.LON_DD = ''

Coordinates in data file are in DMSH format, we want to get them in DD format so method that convert is neeeded:


@staticmethod
def dms2dd(dms):
    h = dms[-1]
    dms_m = dms[:-1]
    dms_t = dms_m.split(' ')
    d = float(dms_t[0])
    m = float(dms_t[1])
    s = float(dms_t[2])

    dd = d + m / 60 + s / 3600
    if h in ['W', 'S']:
        dd = - dd
    return dd

Method that reads line of DOF, extracts data and assigns it to attributes is very simple: just iterates through keys of FIELDS class attribute, reads specified part of line defined in the values of FIELDS dictionary. After 'itration' convertion from DMS to DD is performed.

def parse_line(self, line):
    for key in DofObstacle.FIELDS:
        if len(self.FIELDS[key]) == 2:
            self.__dict__[key] = line[int(DofObstacle.FIELDS[key][0]) - 1:int(DofObstacle.FIELDS[key][1])]
        if len(self.FIELDS[key]) == 1:
            self.__dict__[key] = line[int(DofObstacle.FIELDS[key][0] - 1)]

    # Calculate coordinates in DD format
    self.__dict__['LAT_DD'] = self.dms2dd(self.__dict__.get('LAT_DMS'))
    self.__dict__['LON_DD'] = self.dms2dd(self.__dict__.get('LON_DMS'))


No comments:

Post a Comment