Coincidentally, I had been thinking about maps for a while when it came time to think about fleshing out an idea for this project. So, the idea really started with a picture of a map in my head. That naturally led to the idea of ‘place poems’. Basically, could I capture the essence of a geographical location in a computer generated poem? What would that even look like? Who knows. But I did know that if I was going to create poems based on geographical locations, I’d need to gather data. As much of it as I could.
First steps – a map
Before even starting thinking about text, I got a map up and running using leaflet. Turns out it’s really easy to get a simple map working. Just a few lines of code, really.
gives pretty much this:
With a bit of extra styling, I could get the map full screen and add some title text. The great thing about working with leaflet was that it handles basically everything – clicks, panning, zooming, loading map tiles.
I set up the skeleton of a Flask app to handle the incoming location data. I’d use this data to query API’s to try to gather location based information.
Getting warmer – API’s
With the map sending data to a flask application running server side, it was time to dig into API’s. API’s are a pain mainly because they are all different. They all have different methods of interacting with them, and they all give responses in different structures. So it was really tedious to work through getting data from a bunch of API’s, but alas, I did as much as I could.
Ultimately I gathered data from the following sources
New York Public Library Digital Collections -> which I downloaded images from, then piped those images to ->
Google Cloud Vision API to get keywords from the images.
NYTimes article search API -> to gather news articles related to the name of the location
UNData -> to gather some specific data on a country
Open Weather Map -> to get realtime weather information
Factual -> to get landmarks (i.e. restaurants, etc) based on coordinates
Wikipedia -> grab pages related to place
Oh, and on the front end I used Google’s reverse geocoding API to convert coordinates obtained from clicking the map to an address that I could break down into city, country, etc.
I ended up creating a class (a really, really messy class) called api_requests, that would hide all of the sloppy API code, and from my main flask file, I could query all the API’s, as well as access their results simply like this:
Another module, called compose is responsible for taking all the data gathered from the API’s, and arranging it into a paragraph of text. The nice thing about creating a class for the api requests was that I could save all the results to properties on the class and keep all that information self contained and easily accessible.
To make my life a bit easier, Api_Requests has a property dev that I can flip to True to load a local file so I didn’t have to constantly call the API’s. Within Api_Requests I also used the shelve module to save google cloud vision results to NYPL images, so that if an image came up again, it wouldn’t have to download the image from NYPL or go to google to get keywords. Eventually, this database will grow and grow so that the program will barely ever have to go to NYPL or google cloud vision, as it’s creating it’s own database. Shelve also came in handy to save UN Data, since for some odd reason it return 503’s seemingly randomly. The same request will sometimes work perfectly, but then suddenly return a 503. No idea why, so I started cataloging data as it’s downloaded and only go back to the UN Api when the data isn’t already present.
As this class is super messy, I won’t post it here, but it’s all viewable here on github
Now the hard part. I had all this data, but what do I do with it? A short poem?
I first tried constructing short, poem like lines inputting random data grabbed from all the API information I had. So put a random article headline here, a random wiki line there, make up some lines that I could put the weather info into, etc.
Not so great. I was clipping the article lines and wiki lines so they were nice and short. Otherwise it felt even weirder having alternating short and long lines. But if you look through this poem you can see what kind of data I’m pulling. map, document, a area are keywords generated by running the NYPL photos through Google cloud vision. The weather data is mapped to keywords based on wind speed, temperature, and weather status (i.e. clear, rainy, etc). 46 social’s refers to the catagories of places that are immediately near where the user clicked. Socials refers to social type places, I guess. Then there’s the == stuff, which is how Wikipedia outputs headers to sections when pulling entire page content. So, a decent first attempt, but I wasn’t satisfied.
That’s when I learned about Tracery.
Rethink that whole poem thing
I was thinking about poems too literally. So much of what we talked about this semester is that a poem doesn’t have to be confined to the strict limits that traditionally define it’s structure. The very nature of writing poems with a computer means that poetry is malleable, and thus I shouldn’t bind myself to recreating a seemingly traditional poetic form. So I decided to ditch the poem form. In thinking about what would make sense with a location, well, what came to mind was a wikipedia style opening paragraph mashed up with some travel advice.
Using Tracery, I constructed a very convoluted structure:
The origin of the structure is set based on the current weather conditions. If it’s raining, it’ll print out one sentence structure, if clear, another, etc. Eventually I’d like to have many of these structures. The problem with Tracery is that I still end up structuring the sentences. In effect, I’m still authoring these summaries. Sure there’s an element of randomness, but it’s not exactly what I envisioned. What I’d ideally want to strive for is a completely hands-free generative form. I could have used a Markov chain for this, but it would be very difficult to insert the weather information and data I gathered using a Markov chain. So for now the tracery structure works just fine.
Lastly, I had to hook up the save poem button so that the poems were actually saved. I added a route to the my python app:
I used uuid to generate random strings and shelve save the poem using the randomly generated string as a key. The key would also act as a url parameter, so that a user could pull up that poem again if they felt so inclined.
A Few Examples