Uptonian Thoughts

The Year in Music — Honorable Mentions, Part One

· ·

Many outstanding end-of-year top album lists have been out there for a few weeks. I took it upon myself to come up with a list of my favorite music of the past year. 2009 was such a great year for music, and it was tough for me to come up with a list of just ten albums to share.

There were many great releases that didn’t make my own cut, and I want to highlight them here. Here’s part one of my list.

The Empyrean by John Frusciante

The Empyrean by John Frusciante

I knew I had hit come upon something special from the moment I heard its nine minute opener, Before the Beginning, but it was Frusciante’s cover of Tim Buckley’s Song to the Siren that made me fall in love with The Empyrean. Other highlights include the cheesy synthesized drums, groovy bassline, and ooh-ing chorus line of Dark/Light and Frusciate’s warbled but earnest vocals on Enough of Me.

Hospice by The Antlers

Hospice by The Antlers

I haven’t had a chance to listen to any of Peter Silberman’s solo work (also released under the name The Antlers), but if the full-band concept album Hospice is any indication, I need to get right on that. This album contains some of the saddest lyrics that I have ever heard, but, paired with some excellent song-writing, that’s a good thing.

Constellations by August Burns Red

Constellations by August Burns Red

Matt Greiner’s drumming skills are the first thing that strike you when opener Thirty and Seven first pounds through your head. Of course, every member of this band is a talented musician, as showcased on such standout tracks as Ocean of Apathy and Meddler. I must have listened to this album a thousand times while on my way to work over the summer, and it got me pumped every single day.

Act III: Life and Death by The Dear Hunter

Act III: Life and Death by The Dear Hunter

Part three of a continuing saga, Life and Death sees The Dear Hunter’s mixture of baroque pop and progressive rock flesh out into something even more grandiose than the previous two chapters. I only found out about Casey Crescenzo’s project a few weeks before the release of this album, but I quickly caught up on Acts I and II. This album has such an epic feeling, and that’s something that they bring to their live show, too. When I saw them in Raleigh, they opened with a rendition of Writing on a Wall that was indistinguishable from the album version, and later had The Fall of Troy vocalist and guitarist Thomas Erak join them for Red Hands (a track from Act II).

In the Unlikely Event by The Fall of Troy

In the Unlikely Event by The Fall of Troy

The Fall of Troy have one of the most intense and insane live shows around. Vocalist and guitarist Thomas Erak seems to enter his own world on stage, and you can’t help but be sucked into it. In the Unlikely Event does a pretty good job of capturing that energy. There are few more sections of clean vocals on this album than on previous efforts, and one can certainly detect an overall effort to broaden the group’s musical horizons. Panic Attack! and slower-than-usual Webs are two favorites.

Last.fm Milestones

· ·

I recorded my fifty thousandth scrobble to Last.fm at the beginning of this past August. I recently found a site that can generate the dates on which you reached certain “milestones” in your scrobbling history. Since I have a rather large data set, I thought it would be neat to visualize my listening over the past four years.

This first image is a graph of the number of days it took me to listen to one thousand tracks. Looking at the chart, I can tell that I have been taking longer to listen to the same amount of music, but I have no idea why. It also seems that I have recently started going through phases of listening to a relatively large amount of music and then stopping, rinsing, and repeating.

Last.fm Milestones — Differences

The next image just corroborates what the other chart implicated: I don’t listen to music as much as I used to. It shows a graph of the moving average of the number of days it takes me to listen to my next one thousand tracks. I bet that a graph that charts when and how much music is added to my iTunes library would both match up with these charts and show a significant slowdown over the past few months and years.

Last.fm Milestones — Average

There are fifty one milestones in these charts represented by forty five different artists. Four different artists appear more than once. There are no individual songs that appear more than once. My top three overall artists appear on the list, as do five of my top ten.

I Love Weather

· ·

UPDATE: It seems that Yahoo! has changed their weather URL formats, which breaks the script that fetches the weather image. In order to fix it, go to Yahoo! Weather and enter your desired location. Once you have the correct page loaded, replace the URL in the script with this new one. The script should start working again.

There’s no question that my post that describes my script to get the current weather conditions with Python and Yahoo! weather feeds is the most popular post on my site. It drives a huge proportion of the (small amount of) traffic that this site gets, and the post has many more comments than the average post.

Many people post images of their desktops in their best GeekTool getup, including ones that feature my weather script. One of these in particular had a lovely image to go along with his weather conditions. The author, Gato’s, was kind enough to share how he retrieved and displayed this image in the comments of the photo post. I love this idea, and tweaked Gato’s’ method. I thought I’d detail what I did in case anyone else is interested.

Partly Cloudy

Gato’s’ method of retrieving Yahoo!’s weather images involves two additional GeekTool entries: one to fetch the image, and one to display the image on the desktop. I knew that there was a better way to do this, and I knew it involved launchd. launchd is a system-wide service for starting and stopping daemons. It replaced init, cron, and many other utilities in OS X 10.4. You can find out a lot more on the previous link and on the Wikipedia page.

I had never used launchd before, but setting up my own entry was fairly straightforward after I read a couple of the related man pages. In particular, launchd.plist and execvp were very useful. In order to get started, you need to use the Property List Editor, found in /Developer/Applications/Utilities/Property List Editor.app. If you do not have Apple’s developer tools installed, you can create an XML file with a .plist extension with the same contents.

Before we start creating a launchd item, we need the script for the item to run. I have provided a bash script version of Gato’s’ image-grabbing command. I added a fifteen second timeout argument to the initial curl call; this prevents long timeouts for those times that you are without a network connection. You will also need to replace the URL at the end of line three of the script with your weather forecast URL. Simply go to the Yahoo! weather page and put in your zip or location code in order to retrieve your weather page, then paste that page’s URL into the script. You can download the script here.

1
2
3
4
5
6
#! /bin/bash

/usr/bin/curl --connect-timeout 15 --silent "http://weather.yahoo.com/united-states/virginia/blacksburg-2365044/" |
/usr/bin/grep "forecast-icon" |
/usr/bin/sed "s/.*background\:url(\'\(.*\)\')\;\ _background.*/\1/" |
/usr/bin/xargs curl --silent -o /tmp/weather.png

Now we can create the property list that will launch our image-grabbing script. launchd works by parsing a particular format of property list file. The man page for launchd.plist is very extensive and contains documentation on the entries that are allowed in a launchd item. If that is all a bit too dense, I will walk through the creation of a simple launchd item with the bare minimum of properties needed to launch our script.

Open Property List Editor.app and create a new item by clicking Add Item in the toolbar. In the Key column, type Label. The default Type is string, so type a label identifier in the Value column. I used com.thomasupton.fetchweatherimage. You can use whatever you like. Next, add another item and this time switch its Type to boolean. Type KeepAlive as the Key and don’t check the check box to leave its value as false. Add another number item called StartInterval and give it a value of 600. Finally, add an array item called ProgramArguments. Add a child to this array (just click the Add Item button with the Program Arguments node selected) and give it a value of /bin/bash. Add a second child and give it a value of /absolute/path/to/script/get_weather_image.sh, with the absolute path to where you saved the script. I have pasted the XML contents of the file here, and you can download the property list file here. You can open the property list with a text editor to edit the contents if you do not have the Property List Editor installed.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.thomasupton.fetchweatherimage</string>
    <key>KeepAlive</key>
    <false/>
    <key>StartInterval</key>
    <integer>600</integer>
    <key>ProgramArguments</key>
    <array>
        <string>/bin/bash</string>
        <string>/Users/thomasupton/code/script/get_weather_image.sh</string>
    </array>
</dict>
</plist>

What we have just created is a launchd item that will only start on demand every 600 seconds and run our script to grab the weather image. Save the property list to ~/Library/LaunchAgents and give it a name like com.thomasupton.fetchweatherimage.plist. Open Terminal.app and type the following command to load our new launchd item, replacing the name of the script with the file name that you saved your property list as.

$ launchctl load ~/Library/LaunchAgents/com.thomasupton.fetchweatherimage.plist

Back in GeekTool, all you need to do is add one new entry. Make it a picture and give it the URL file:///tmp/weather.png. Et voilà, you have a beautiful image of your weather conditions on your desktop.

I took a picture of my current desktop to show you what it looks like. I gave the weather image an opacity of 60% for a more subtle effect.

Snow Leopard Desktop

New Beginnings

· ·

I recently started working at Mailtrust in Blacksburg, VA. Mailtrust is a division of Rackspace, a company that has been experiencing some astounding growth recently. One of the companies that Rackspace recently acquired is Slicehost. Last week, I decided to sign up for Slicehost hosting and move my website to this new server. I also decided to buy a new domain, thomasupton.com. I spent the last week or so setting up my server just how I wanted it.

I followed the excellent Slicehost articles in order to get started. Setup is a breeze because you have total control over your server. When I screwed something up shortly after starting the setup process, I simply rebuilt and re-imaged my slice and started over.

The articles for Ubuntu 8.10 are presented in a useful order and detail how to set up and secure a new slice, install Apache to serve websites, and install MySQL and PHP to start getting things done.

By far the hardest part of setting all of this up was the migration of my Wordpress installation. I spent a lot of time trying to export a MySQL dump of my existing Wordpress database and import onto my slice. It turns out that Wordpress supports an extended XML-based format for importing and exporting almost every bit of user-created content, including posts, comments, and pages. Existing URL structures are preserved, and author data can be changed to an existing author in the new installation. This was much easier to do than my attempt to directly import a MySQL dump.

After I installed and migrated Wordpress, I decided that I wanted to redesign the look of the site. I wanted an article-centric design that took a minimalist approach to the extreme. What I needed was a skeleton Wordpress template that had useful, semantic markup that was easily customizable. Enter Sandbox. After activating the theme, designing a layout purely in CSS was extremely easy, thanks in large part to the clear and concise HTML markup. I’m still tweaking the design here and there, and I want to add a dedicated Archives page, but I’m really happy with how the site has turned out so far.

As I mentioned a couple of weeks ago, my interest was rekindled in Tumblr after the release of version five. Tumblr supports custom domains, so I’ve moved my tumblelog to This Is Thomas.

I’m really hoping to have more time to blog about issues and topics that I care about now that I don’t have class and homework to worry about. The site is continually undergoing changes in design and structure as I learn more about how to write and design more effectively.

Enjoy.

Dell Latitude D800 Pointing Stick Issues

· ·

I recently installed Ubuntu 8.10 on my old Dell Latitude D800. I had not used that machine in a couple of years, and I had forgotten about a few hardware issues that it had. One of the most annoying issues was the “drifting” pointing stick.

According to a number of posts I found when searching for solutions to the problem, the drifting pointing stick issue is a common one on many Dell models. It causes random and erratic mouse movement, making it nigh impossible to operate a graphical interface. I got around the issue when I was using this machine full time by disabling the pointing stick using the Windows driver for the ALPS GlidePoint. Unfortunately, the system preferences offered by Ubuntu do not have an option to disable the pointing stick.

I found a post on the Ubuntu forums from a user who had a similar problem to mine. A responder mentioned that he removed the keyboard and found that the pointing stick had its own leads that could be disconnected. I searched for the Dell support document that matched my model and decided that I, too, could remove my keyboard and disconnect the pointing stick.

Unfortunately, I did not take any pictures of my machine when I had it opened. However, it is very easy to remove the keyboard by following the instructions in the support document. Once the machine was open and the keyboard removed, I just ripped off the leads from the pointing stick where they attached back to the keyboard connector. To be safe, I taped the loose end with electrical tape. After I replaced the keyboard, the trackpad and keyboard both worked fine and were not marred by the erratic mouse movement that was caused by my pointing stick.

Interview Developer Test

· ·

When I interviewed earlier this week, I was given a developer take-home test to complete as part of the application process. The test consists of six short coding problems, any three of which are required to be completed within 48 hours of receiving the test.

I do not think there are any issues with me posting the problems here, and I want to share my solutions. Just to be safe, I’ll only post the three problems that I answered along with only some of my solution and methodology.

The problems could be answered in any of Java, C#, C/C++, Python, or PHP. I answered all three in Python. I wrote 227 lines of code for this test, including comments.

Problem 1

Write a program that justifies a given line of text to the specified width. The width is given on the first line of the input file, and the text in on the second.

Sample input:

20
The quick brown fox jumps over the lazy dog.

Sample output:

The quick  brown fox
jumps  over the lazy
dog.

The algorithm I came up with split the input into a list of words. Then, I keep popping those words off of that list and into a new list until no more words can fit within the specified width. Using the length of each word in the list plus a space between each word (len(" ".join(to_justify))), one can figure out the number of required spaces.

I decided that I would distribute the required spaces one by one into each “slot” that requires spaces until there are no more remaining spaces. This means that for the first x slots, there would be n spaces, and for the remaining number_of_slots - x slots, there would be n - 1 spaces. number_of_slots here is really just len(to_justify) - 1.

The formulas for coming up with n and x are related and fairly straightforward. In terms of modulo arithmetic, think of the slots as your modulo, adding a space to each slot as you traverse the slots. We can use an example to illustrate this. If you have a desired text width of 20 characters, and a current word length of 13 characters, you need 7 spaces. For the first 7 % 4 = 3 slots, you need ceil(7 / 4) = 2 spaces, and for the last slot, you need 1 (which is also floor(7 /4) or just 7 / 4 in Python) space. You need to import the math module in order to access the math.ceil function.

A problem that arises with this method is words that are longer than a line. I got around this by printing the word in chunks of the maximum width until its length was less than that text width. words_printed is just a count of the number of words that have been printed on the line thus far. It was used instead of len(to_justify) for use in another section of the code.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Take care of words that are longer than our desired text width.
while len(word) > text_width:
  if words_printed == 0:
    print word[:text_width]
    word = word[text_width:]

  else:
    # Here we fill the rest of the line with as much of the word as
    # we can, given that there is already text on the current line.
    print " ".join(to_justify) + " " + word[:(text_width -
      len(" ".join(to_justify)) - 1)]
    word = word[(text_width - len(to_justify) - 1):]
    to_justify = []
    words_printed = 0

Problem 2

Write a program that compacts a string in place. It should remove all whitespace and replace duplicate characters with only the first character.

Sample input:

abb cddpddef gh

Sample output:

abcdpdefgh

The re module made this one extremely easy. After grabbing the line from the input file, my entire solution consisted of one line.

print re.compile(r'(.)1+', re.IGNORECASE).sub(r'g<1>', "".join(text.split()))

split() defaults to a whitespace delimiter and join() pushes an array into a string with the given delimiter. This removes all the whitespace in a string.

re.compile() takes a regular expression string as its argument and returns an re object instance. This object instance can then utilize a great many methods related to regular expressions. A lot more information can be found on the Python docs site. Building a string with r' ' tells Python to treat the string literally, e.g. the string r'\n' is two characters long (\ then n). I passed the re.IGNORECASE flag to, well, ignore the case of the searched string.

We can break down the regular expression into three segments. First, (.) creates a character group that matches nearly any non-whitespace character. This lets me match both numbers and letters. 1 lets me match that first character group exactly. (..) or (.){2,} or something similar would not work, as that would match any two characters in a row and not just duplicates. Lastly, + lets me match the previous group 1 or more times. In English, this regular expression says “match any character, then match that exact character 1 or more times directly after it.”

The sub method allows me to substitute using regular expressions. I passed it our string that has gone through split() and join(), and tell it to replace any matches with the first group (1). Since this group only matches single characters, I am done. Regular expressions are powerful.

Problem 3

Print a 2D array in a clockwise spiral fashion.

Sample input:

1 2 3
4 5 6
7 8 9

Sample output:

1 2 3 6 9 8 7 4 5

I decided that this problem could be attacked using recursion. I quickly looked online for an example of what others had done, but they all seemed sloppy and inefficient. If I could write a function that printed the borders of an array in the desired order, I could recursively process the entire array.

I constructed the array by using split() on each each line of the input file, one by one. If the array passed to print_borders() has one row or one column, it prints it. If it has two rows, it prints the first row in order, and the second row backwards. Otherwise, it prints the top row in order, the right column in order, the bottom row in reverse, and the left column in reverse.

The reversed() top-level method produces an iterator on a list in reverse. This was very useful for the bottom row and left column. This is how I addressed the bottom row of the array:

1
2
for item in reversed(array[-1]):
  "".join(item)

Using array[-1] also came in handy for the right column of the array:

1
2
for item in array[1:-1]:
  print "".join(item[-1])

And also for extracting the part of the array that still needs to be processed:

1
2
3
new_array = []
for row in array[1:-1]:
  new_array.append(row[1:-1])

I think the idea of a developer test is great. It allows the interviewers a brief glimpse into what kind of worker or programmer you are, and it gives the applicant a sense of accomplishment. The fact that I knew how to attack and solve these problems also gave me some confidence in my own programming skills. Being a recent college graduate and not having much professional programming experience meant that I had no idea what to expect. Now I do, and I’m excited. I got the job, and I very much look forward to starting work.

Tumblr

· ·

I recently started using my Tumblr tumblelog a lot more.

I created my Tumblr account some time last year, like everyone else. I linked my Delicious feed and this blog to it and promptly forgot about it. I recently realized that there are photos that I favorite on Flickr, and videos that I favorite on YouTube or like on Vimeo, and quotes that I see on many different web pages, and chats that I have with my friends that I think other friends would enjoy, but I can’t share them in one central place and oh my goodness I’ve just described the entire reason for Tumblr’s being.

So I added the Tumblr bookmarklet to my browser’s bookmark bar, and now my favorite things that I come across on the web are all located in one place.

One of the greatest features of Tumblr is the fact that each tumblelog is connected. I can favorite a post right from its permalink, and I can follow those who I find interesting.

I spent a lot of time over the past two days tweaking Danny Garcia’s LightGrid theme to my liking and in the general look and feel of my tumblelog.

The Cities I’ve Been to, 2008

· ·

Inspired by Jason Kottke, a list of the cities I visited in 2008.

  • Columbia, MD
  • Madrid, Spain
  • Vera, Spain
  • Seville, Spain
  • Granada, Spain
  • Frederick, MD
  • Fall’s Church, VA
  • Harrogate, England
  • Kitty Hawk, NC
  • Brick, NJ
  • Oak Ridge, NC
  • Blacksburg, VA

I spent one or more nights in each of these cities. I went to Spain for spring break, and visited family in England over the summer. I stayed at a friend’s house in Columbia before the Spain trip and in Frederick after. I saw Kate Nash in Washington, DC and stayed with a friend in Fall’s Church, after which I visited a friend in Brick just for fun. My family and I went on a vacation to the beach in Kitty Hawk. My family lives in Oak Ridge, and I live in Blacksburg.

Shelfari

· ·

My Shelfari profile

I recently joined Shelfari, which my dad described to me as Last.fm for books. Your profile consists of your shelf, to which you can add books that you have read, are currently reading, or plan to read. You can search for any book by title, author, ISBN, and other attributes.

The site has a slick design that allows easy manipulation of your bookshelf. It even offers an option to import a tab-delimited list from Delicious Library. I only recently joined, but I am impressed with what I see.

Shelfari offers a widget that can be pasted into a blog, but I did not like the restrictions on the styling that it gave me. I searched, and lo and behold, there is already a WordPress plugin called BookList that can display certain items on your shelf. I have added this plugin to the bottom of my site, under my Last.fm tracks, where you can see what books I am currently reading.

UPDATE: The BookList plugin seems to be broken, so I have disabled it for now.

If you visit my Shelfari profile and decide that you want to join, don’t forget to add me as a friend on the site!