Dealing with the Maryland Coordinate System


by Drew Bollinger
@drewbo19
20 Oct 2014

If you’re reading this, you’ve likely come across some geo data that you want to use but the coordinates are given in the Maryland Coordinate System and you’d like to have them in a more usable format, like simple latitude/longitude. Well, you’re in luck. For our project mapping gun crimes in DC, we needed to make this same conversion and tried to come up with a more repeatable way to do it in the future. The crime data that DC provides only gives BLOCKCOORDS and we needed lat/lng in order to map it.

Maryland Coordinate System

First, some background. Plenty of geo government data is provided in the Maryland Coordinate System, which shows east/west and north/south distance in meters from a fixed point. While using lat/lng seems obvious to those of us raised on web mapping, there’s a fairly good reason for using a state-specific coordinate system: it makes surveying and intra-state work much simpler. Also, the errors produced by pretending the earth is flat tend to be very small at the state level. But now that we can easily project information on to a map using spherical coordinates, it makes sense to seek an easy way to convert.

DC GIS Developer Tools

The DC government has very functional web tool for converting from Maryland Coordinate System to lat/long on the DC GIS Developer Page.

However the service isn’t very easy to find, could be easier to use, and doesn’t natively handle large batch requests. I recently needed to convert more than 2,000 coordinate sets, so I wrote a small script. I’m not familiar with SOAP requests, so I used a python script to execute multiple HTTP POST requests.

Python

You’ll need two different python modules for this:

import requests
from bs4 import BeautifulSoup

The response will be in XML (not ideal), so we will use Beautiful Soup to convert to a more useable format. Normally I’d use lxml for this because it is fast. However lxml is less accepting of badly formatted XML. As our responses will be small and maybe a little messy, Beautiful Soup is a safer choice.

We use requests to set up the requests. Here’s an annotated mock script:

data = []
url = "http://citizenatlas.dc.gov/usng/getusng.asmx/MD_SPCStoLL"

for d in raw_data:
try:
    value = d[7] + ',' + d[8]            # these are the block coordinates from the raw data
    params = {'SPCSXYSTR': value}        # we need to send a key-value pair with this key name and our coordinates as the value
    r = requests.post(url,data=params)   # make a post request with our data
    soup = BeautifulSoup(r.text)         # construct a BeautifulSoup object out of the XML response
    cs = soup.find('convstr')            # the lat/lng coordinates are given inside this tag
    row = []
    row.append(cs.text.split(',')[0])    # append the lat to our output row
    row.append(cs.text.split(',')[1])    # append the lng to our output row
    print(cs.text)
    data.append(row)                     # append this row to our final data
except:
    print("ERROR")

So about ~20 lines of python to get our final result!

The full code for our project is located here

Thanks to Chris Given, Tobias Shapinsky, Steven Reilly and Tim Abdella for their help with this project and post.