1

I am currently doing a practical project at university (MSc in GIS).

I have to develop a python script and the functionality of this script has been left very open other than we have to use Python only and with ArcMap.

I’m have use ArcMap and Python which I am very new to. I want to create a popup tool\form that uses python – the tool\form would allow allow me to enter an Address in a text field. When I press a Go button the python script uses GeoPy (Python Geocoding Toolbox) to query google for the coordaintes of this address. These coordinates and the address details are shown in the tool\form and the point is added to my active layer.

Is a Python Toolbox the correct functionality within ArcMap to use? Is it possible to import the GeoPy scripts into the Python tool script using the ‘import GeoPy’ command (should I have the GeoPy scripts in the same folder as the Toolbox file) What if multiple addresses are returned from Google – does the Python Toolbox allow me to view the array of address and select one – i.e. does the python toolbox allow user interaction or should I be using some other functionality of ArcMap to do this with python?

  • 2
    What have you tried? Python only or a wrapper with python? It is unclear with the question as it is how someone could help you. Be sure to edit the original question (not comments) and see help for how to ask a good question. – Brad Nesom Jun 15 '15 at 21:53
  • You seem to be trying to ask several new questions here after receiving answers to your original broad one. I suggest that you take the Tour where it says that there should only be one question per question. I also recommend that you review the advice here about how to structure a question: meta.gis.stackexchange.com/a/3353 – PolyGeo Jun 16 '15 at 9:29
5

I have used this code below in the past. It works pretty well.

#http://stackoverflow.com/questions/14580540/get-location-coordinates-using-bing-or-google-api-in-python
import urllib
import json
import arcpy
import time
import os
arcpy.env.overwriteOutput = True

GOOGLE = 'http://maps.googleapis.com/maps/api/geocode/json?'

def Message(msg):
    print str(msg)
    arcpy.AddMessage(str(msg))

def googleGeocoder(new_fc, addresses=[]):
    """
    Quick and dirty geocode. 

    Required:
    new_fc -- new point feature class for geocoded addresses
    addresses -- dictionary of address and feature name {'address' : 'feature description',..}
                 or a list of addresses ['address, city, state, zip'...]

    Addresses can be in one of the below formats.

    # example: pass addresses with description as dictionary
    addresses = {"400 N 1st Ave W, Hartley, IA, 51346" : "Prins Laundromat",
                 "120 S 8th Ave W, Hartley, IA, 51346" : "Hengeveld Construction",
                 "173 S Central Ave, Hartley, IA, 51346" : "Legal Eyes"}

    # example: pass addresses in as a list
    addresses = ["901 N Broadway, Saint Louis, Missouri, 63102",
                 "10701 Lambert International Blvd, Saint Louis",
                 "15193 Olive Blvd, Chesterfield, Missouri, 63"]
    """
    # check to see if addresses are provided as dict
    hasFeature = True
    if isinstance(addresses, basestring):
        addresses = [addresses]
    if not isinstance(addresses, dict):
        addresses = dict((a, '') for a in addresses)
        hasFeature = False

    # version info
    # sets projection to WGS 1984 GCS
    prj = arcpy.SpatialReference(4326)

    # dictionary to store addresses and points
    addr = {}
    bad = []
    for address, name in addresses.iteritems():
        try:
            pt = google_getCoordinates(address)
            addr[(address, name)] = arcpy.PointGeometry(arcpy.Point(*pt), prj)
        except:
            Message("Could not geocode address \"{0}\"".format(address))
            bad.append(address)

    # create new feature class
    f_length = max(len(a) for a in addresses) + 5
    if f_length > 255:
        f_length = 255
    if arcpy.Exists(new_fc):
        arcpy.Delete_management(new_fc)
    arcpy.CreateFeatureclass_management(os.path.dirname(new_fc),
                                        os.path.basename(new_fc),
                                        'POINT', spatial_reference=prj)
    arcpy.AddField_management(new_fc, 'Address', 'TEXT', field_length=f_length)
    arcpy.AddField_management(new_fc, 'Feature', 'TEXT', field_length=100)
    arcpy.management.AddField(new_fc, 'X_COORD', 'DOUBLE')
    arcpy.management.AddField(new_fc, 'Y_COORD', 'DOUBLE')


    # Insert rows
    fields = ['SHAPE@', 'Address', 'Feature', 'X_COORD', 'Y_COORD']
    with arcpy.da.InsertCursor(new_fc, fields) as irows:
        for attributes, pt in addr.iteritems():
            point = pt.centroid
            irows.insertRow((pt,) + attributes + (point.X, point.Y))
            Message('Geocoded address: {0}'.format(attributes[0]))
    del irows

    # Delete feature field if no feature names supplied
    if not hasFeature:
        arcpy.DeleteField_management(new_fc, ['Feature'])

    # if bad records
    if bad:
        date = time.strftime('_%m_%d_%Y')
        txt = r'C:\Users\{0}\Desktop\Geocode_fail_{1}.txt'.format(os.environ['USERNAME'], date)
        with open(txt, 'w') as f:
            f.writelines('\n'.join(bad))
        os.startfile(txt)
    return new_fc

def google_getCoordinates(query, from_sensor=False, googleGeocodeUrl=GOOGLE):
    """use google geocoder to get coordinates from adddress

    query -- address to geocode
    """
    query = query.encode('utf-8')
    params = {
        'address': query,
        'sensor': "true" if from_sensor else "false"
    }
    url = googleGeocodeUrl + urllib.urlencode(params)
    json_response = urllib.urlopen(url)
    response = json.loads(json_response.read())
    if response['results']:
        location = response['results'][0]['geometry']['location']
        latitude, longitude = location['lat'], location['lng']
    else:
        latitude, longitude = None, None
        print query, "<no results>"
    return (longitude, latitude) # as x,y tuple

if __name__ == '__main__':

    # example 1: pass addresses in with description as dictionary
    addresses = {"400 N 1st Ave W, Hartley, IA, 51346" : "Prins Laundromat",
                 "120 S 8th Ave W, Hartley, IA, 51346" : "Hengeveld Construction",
                 "173 S Central Ave, Hartley, IA, 51346" : "Legal Eyes"}

    test = os.path.join(os.environ['USERPROFILE'], r'Desktop\test_gc.shp')
    googleGeocoder(test, addresses)

    # example 2: pass addresses in as a simple list
    addresses = ["901 N Broadway, Saint Louis, Missouri, 63102",
                 "10701 Lambert International Blvd, Saint Louis",
                 "15193 Olive Blvd, Chesterfield, Missouri, 63"]
    test = os.path.join(os.environ['USERPROFILE'], r'Desktop\test_gc_list.shp')
    googleGeocoder(test, addresses)
  • 3
    Homework ... done. – ianbroad Jun 15 '15 at 22:14
  • 4
    If you are going to use this excellent answer in getting your degree you should in the very least credit crmackey and GIS.SE in your header and comments - lecturers read this site too so it's best to be up-front about it rather than getting accused of plagiarism. – Michael Stimson Jun 15 '15 at 23:35
  • 1
    What'd mean homework done? This isn't wrapped up nicely in an actual PYT so it can be run as a tool. ;) – KHibma Jun 16 '15 at 14:40
  • 1
    Haha, in @ian's defense, an edit was made to this question after he posted that asking how to get it into a toolbox. – crmackey Jun 16 '15 at 15:00
  • 3
    "homework scope creep" – KHibma Jun 16 '15 at 15:08
4

Since this is for your university work, you should really research on your own how to do this, as much as possible. If you get stuck, of course you can come here and ask your (specific) question. Going to university is about learning to learn, think and work independently.

Yes of course it is possible (see @crmackey's answer), but presumably the point of the project is to actually learn something, not just solicit code examples.

Some research starting points include the Google Maps geocoding API, the ArcGIS Python help, and the Python tutorial/standard library reference pages. The questions What are some resources for learning ArcPy? and Resources for learning Python programming with generic GIS goals in mind? also have a wealth of relevant learning resources.

And if you want to make your tool interactive via a graphical user interface rather than just a script, you'll also want to learn about Python script tools, Python toolboxes, and Python add-ins in ArcGIS to determine what kind of customization you want to create.

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.