One benefit of using Julia for playing with statistics is that it’s a modern, usable language for general purposes as well. Earlier I built a k-Nearest Neighbor classifier for predicting crime from the data on hbg-crime.org, so I thought it would be fun to build a web service in Julia that could return those results.

using Morsel
using Datetime
import JSON
require("knn_classification")

app = Morsel.app()

Morsel is a small Sinatra-like web framework for Julia that we’re going to be using.

function jsonResponse(res, data)
    res.headers["Content-Type"] = "application/json"
    JSON.json(data)
end

Here’s a quick function to handle building a JSON response out of a hash; we just set the Content-Type header on the response in place, and then write out our response data as JSON.

function parseNearestParams(params)
    lat = parsefloat(Float64, get(params, "lat", "0"))
    lon = parsefloat(Float64, get(params, "lon", "0"))
    k = parseint(get(params, "k", "7"))
    timestring = get(params, "time", nothing)
    time = isdefined(:timestring) ? Datetime.datetime("yyyy-MM-ddTHH:mm:ss", timestring) : Datetime.now()
    lat, lon, k, time
end

This is how we’re going to parse the params for a request, which will look like this: /nearest?lat=40.27258&lon=-76.87438 For lat and lon we just call parsefloat on the string we receive; for k (how many nearest neighbors to use) we use parseint, and for time we either parse a string we receive or use the current time.

get(app, "/nearest") do req, res
    lat, lon, k, time = parseNearestParams(req.state[:url_params])
    if (lat == 0 || lon == 0)
        jsonResponse(res, {:error => "You must supply lat and lon parameters."})
    else
        result = nearest(lat, lon, time, k)
        jsonResponse(res, {"beware-of" => result})
    end
end

Here’s our only route. We are pulling the params out of the req.state hash, and either rendering an error if lat and lon aren’t specified, or returning the result of our prediction.

start(app, 8000)

And then we start the app; once the kNN engine parses the reports data and is ready to go, you’ll see a ready message from Morsel and you can start making requests to http://localhost:8000/nearest.