1

I'm working with PyQgis in version 2.18 and have a number of coordinates in WGS84 (decimal degrees) that I would like to convert to degrees, minutes, seconds (DMS) programmatically. I began by writing a Python function as follows:

from qgis.utils import *
from PyQt4.QtCore import * 
from PyQt4.QtGui import * 
from qgis.core import * 
from qgis.gui import * 
import math


layer = iface.activeLayer()

#creating my new dms fields called 'LONGITUDE' and 'LATITUDE'
myField_1 = QgsField( 'LONGITUDE', QVariant.String)

layer.dataProvider().addAttributes([myField_1])
layer.updateFields()

fed = layer.fieldNameIndex('LONGITUDE')

myField_2 = QgsField( 'LATITUDE', QVariant.String)

layer.dataProvider().addAttributes([myField_2])
layer.updateFields()

det = layer.fieldNameIndex('LATITUDE')

#creating the function
def dd2dms(longitude, latitude):
    layer.commitChanges()
    split_degx = math.modf(longitude)
    degrees_x = int(split_degx[1])
    minutes_x = abs(int(math.modf(split_degx[0] * 60)[1]))
    seconds_x = abs(round(math.modf(split_degx[0] * 60)[0] * 60,2))

    # repeat for latitude
    split_degy = math.modf(latitude)
    degrees_y = int(split_degy[1])
    minutes_y = abs(int(math.modf(split_degy[0] * 60)[1]))
    seconds_y = abs(round(math.modf(split_degy[0] * 60)[0] * 60,2))

    # account for E/W & N/S
    if degrees_x <= 0:
        EorW = "W"
    else:
        EorW = "E"

    if degrees_y <= 0:
        NorS = "S"
    else:
        NorS = "N"

    # abs() remove negative from degrees, was only needed for if-else above
    print "\t" + str(abs(degrees_x)) + u"\u00b0 " + str(minutes_x) + "' " + str(seconds_x) + "\" " + EorW
    print "\t" + str(abs(degrees_y)) + u"\u00b0 " + str(minutes_y) + "' " + str(seconds_y) + "\" " + NorS



features = layer.getFeatures()

layer.startEditing()

#
for feat in features:
    name_1 = feat['LAT']
    name_2 = feat['LONG']
    feat[fed] = dd2dms(name_2, 0)
    feat[det] = dd2dms(0, name_1)
    layer.updateFeature(feat)

layer.commitChanges()
iface.vectorLayerTools().stopEditing(layer)

LAT and LONG are the names of the fields which I'd like to convert to DMS. The problem I'm facing now is that, when I run the script, the changes occur only on the Python console, but not in the attribute table. values not appearing python console results

I would like to know why my attribute table is not getting populated when I run the script.

1

The main problem I see is that the result of your function is two print statements which will just be printed to the console. In order to use those values you need to return them from your function.

I no longer use QGIS 2.18 and I have not tested this, but I would try something like this.

at the end of your function:

x = "\t" + str(abs(degrees_x)) + u"\u00b0 " + str(minutes_x) + "' " + str(seconds_x) + "\" " + EorW
y = "\t" + str(abs(degrees_y)) + u"\u00b0 " + str(minutes_y) + "' " + str(seconds_y) + "\" " + NorS
return x, y

Then:

*Edit 1: Based on comments below- let's try working with the layer data provider.

for feat in features:
    name_1 = feat['LAT']
    name_2 = feat['LONG']
    x_dms, y_dms = dd2dms(name_2, name_1) #unpack return values
    atts = {fed: str(x_dms), det: str(y_dms)}
    layer.dataProvider().changeAttributeValues({feat.id(): atts})

layer.commitChanges()

*Edit 2: You should also remove the layer.commitChanges() call from inside your function. You only need to call it once at the end of the script.

2
  • Thanks Ben for your answer, but after trying it out, it still only populates the console and not the attribute table
    – GeomaSmart
    Oct 22 '19 at 21:32
  • No problem @GeomaSmart, I have updated my answer, using a different method of updating feature attributes. Hopefully this will work.
    – Ben W
    Oct 22 '19 at 22:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.