This semester I took CS 530: Introduction to Scientific Visualization. It was my first graphics course as well as my first graduate-level course. It covered various methods of data processing and visualization of scientific data such as medical scans, physical simulations, or mathematical equations. The best part about the course is that we got to make pretty pictures.
For the first project, we implemented three forms of vector visualization. The vector field we used was the electric field created by a positively charged object at the center of the space surrounded by four negatively charged objects. First, we rendered the streamlines representing the paths of a particles along the field:
Second, we rendered the time surface, which is the expanding (or contracting) surface created by a set of points at a particular point in time:
Third, we rendered the flow volume, which is the "tube" with borders defined by the streamlines. This type of visualization shows the divergence or convergence characteristics of a vector field.
For the second project, we impelemented a surface rendering algorithm called marching tetrahedrons, which is a particular form of marching cubes. We rendered two datasets:
First, the electron density of a methane molecule:
Second, a prepared dataset of someone's head:
We used these same two datasets for the third project, but we rendered them instead using volume rendering with ray casting. The basic idea is that one shoots a ray out of every pixel of the image and accumulates color for each sample point along a ray that passes through the data.
Note that one can see both the brain and the skull in the following renders of the head data.
For the term project, students had to prepare a project proposal, implement the proposed visualization, and then write a 12-page paper on the project.
All in just two weeks.
We were "encouraged" to work in groups for this project, so Marc and I decided to work together. Our project proposal had three parts:
Get some real medical data to visualize. In the previous three projects we had only used calculated data (as in the case of the electrical field and methane molecule) or prepared datasets (as in the case of the head).
Render more than one surface. The surface rendering project only rendered one surface.
Use the view orientation, color, and other parameters from the surface rendering to create a volume rendering. In all the projects, we had to type in parameters by hand or, in the case of my volume rendering project, create an initialization file with the paramters. We wanted to make the process easier.
We initially planned to use the CT or MRI scans of my leg implant. I called up my surgeon, but we found out that my scans had taken place before the hospital went completely digital. My surgeon's assistant— who went above and beyond searching for data for us to use— learned that a man with a soft-tissue tumor was getting an MRI one day last week. She got the technicians to burn a CD of the data, and I traveled to the office the next day to pick it up.
The data was ideal for the project. It was in a standard binary format called DICOM, which stands for Digital Imaging and Communications in Medicine. I read up on the standard, and wrote a reader in about two days. Here are some of the raw MRI slices direct from the machine:
While I was working on the DICOM reader, Marc was working on the user interface. Once those two parts were more or less functional, we started working on the rendering portions of the application. He took care of the surface rendering, greatly extending the project two code such that it could respond better to user input and render up to three translucent surfaces. Rendering three surfaces was more involved than it might appear because the triangles that form the surface must be drawn from front to back for lighting and transparency to work. Also, we needed to calculate the camera position and orientation for the volume rendering to work.
I built the volume rendering section such that it could take the view parameters from the surface section, make some good guesses about the volume rendering parameters, and output a ray cast image. Unlike project three in which rays traveled in parallel, we had to cast diverging rays to make the perspective appear the same as in the surface rendering.
We managed to iron out the last glaring bugs during the final stress-filled day before the due date. We traded off on writing the paper and programming up into the final minutes. Amazingly, we turned in the final CD and paper printout ten minutes before the midnight due date.
Despite having a ridiculously short time to implement the project, I think the final pictures speak for themselves:
Here we used the methane data to test the multiple surfaces. The first image is the GUI with the surface rendering; the second is the volume rendering.
Here is a rendering of one of the MRI data sets. It is looking at the back of the patient's thigh.
I feel that the following images made the project. The first picture is the MRI slice, the second shows the surface rendering, and the final picture shows the volume rendering. The tumor is obvious in the MRI slice and surface rendering. It is a little less visible in the volume rendering, but it is still there.
I have posted the application executable here if anyone would like to try it out. I have disabled the head and MRI data because the data files are so large. You can play with the surfaces of the methane data by adjusting the sliders on the right. Click and drag on the surface render window to rotate the molecule. Right-click and drag to zoom in or out. You can create a volume rendering by clicking the "Render" button.
A word of warning: I am ashamed to admit that the volume rendering leaks memory like crazy, so you may not want to run it more than two or three times before restarting the application. It will very likely crash if you render much more than that. Also, the volume renderings can take anywhere from one to five minutes, depending on your CPU speed and how much memory you have.
It is official: I am going to Illinois in the fall. Everything I have read about UIUC's department and everything I saw last week has convinced me that it is the right place to go. That, and I hate having unresolved decisions hanging over my head. I faxed the acceptance letter after classes today.
I finally got a response from Texas: they regret to inform me that they are not recommending me for admission. I also got confirmation that my UIUC admission acceptance arrived successfully. So, with my curiousity satisfied and my conscience clear that I made the right choice, I close the book on my graduate school admissions saga.
I got rejection emails from MIT, Carnegie Mellon, and, surprisingly, Purdue. I was getting discouraged and a bit scared when I got my first acceptance email from the University of Illinois at Urbana-Champaign. That first line: "It's my pleasure to congratulate you..." eliminated all worry and made me jump out of my chair in excitement. You may remember that UIUC has always been near the top of my list. Soon after receiving UIUC's email, Wisconsin-Madison's arrived. It said I could come, but they would not give me any money if I did. I am still waiting on Texas-Austin.
Last weekend I went to the UIUC CS department's Prospective Graduate Student Weekend. They put 14 other CS students and me up in a hotel and tried to woo us to the department just like we tried to woo them a few months ago.
I arrived in the midafternoon on Saturday and found a fire truck in the hotel parking lot. I learned from the front desk that the sprinklers had gone off, soaking a maid with stagnant water and turning a stairwell into a waterfall. I checked in amidst the excitement, then wandered around campus for a while.
Even though Illinois and Purdue have a comparable number of students, Illinois' campus seemed much larger. The buildings appeared to have more floors (perhaps because half of Purdue is underground) and tree-lined malls seemed to spread them out more. I walked from one end, where all the engineering and technical students spend their time, to the agricultural greenhouses near a large cemetery, then back through the liberal arts section. Oddly, the campus is peppered with random farm houses tucked in between hulking red brick buildings. I forgot to get my camera out of the car before walking around, but you can find other peoples' pictures of the campus here.
In the evening, the other prospective students and I went to a pizza social with current CS grad students. The event was held in the ground floor of UIUC's new CS building, the absolutely beautiful Siebel Center. I networked admirably with a small handful of graduate students and briefly with Darko Marinov, a new professor in the software engineering group with whom I had exchanged a few emails.
My name on the big screen in Siebel Center
Later that evening, a few of the prospective students and I were planning to go to Green Street, the main entertainment strip through the campus, but pelting rain forced us to the restaurant near the hotel instead. The six of us then embarked on the absolute best bull session I have ever had. We made fun of our (and each other's) undergraduate schools, talked about CS, and generally had a merry time for several hours.
The organizers filled Sunday to the brim. In the morning we listened to professors talk briefly about the various areas of study available in the department. Then we had a surprisingly informative question-and-answer session with a panel of professors. After lunch, we split off to go to individual meetings with professors. I talked with Professor Marinov about automated refactoring tools, automated exhaustive unit testing techniques, and programming languages for use in testing, all topics that I can assure you are much more interesting than they may sound.
Lunch in Siebel Center
I had a bit of time to burn after that, so I joined some of the theory group graduate students who were talking with an impromptu group of prospective students in a lounge area. At one point Steve LaValle, the main host of the weekend, brought out a three-wheeled scooter that could travel at about the pace of a relaxed jog when the rider rotated the handlebars correctly. Those of us in the lounge took turns racing it around the second floor with varying degrees of success. Professor LaValle said that he had bought the scooter with research money to find out if its method of propulsion could be applied to his field of robotics.
Steve LaValle with the scooter (apologies for the blurriness)
At around 4:00 the prospective students reconvened for a building and campus tour. My group had an unfortunately shy and reticent guide, but we saw a bit more of Siebel Center and the northern part of campus.
Touring Siebel Center
A memory core from ILLIAC
View from the second floor of Siebel Center
A strange mannequin in the server room that was apparently used for wearable computing applications
The whiteboard in the server room
We finished the evening with dinner at a plush Italian restaurant in Champaign.
I reflected on the weekend during my two hour drive back to Purdue that night. It was difficult last semester and last year to decide that I wanted to pursue graduate school. I have a good deal of work experience from my summer internships, and I would not have had a problem finding a job if I chose. Would I be capitalizing on that experience as much as I could if I went to graduate school? Speaking to professors and current graduate students this weekend gave me a clearer view of what my next few years in graduate school may contain. I am sure I will work harder and longer than I ever have before, but it will be on the bleeding edge of the area I choose. Nowhere will I have the opportunity to expand myself and my chosen craft more than in an institution like UIUC. Whether I end up there or at UT, I am convinced that graduate school is where I need and want to be at this point in my life.
For some context, see parts one and two of my semester project rundown.
In the rare periods during which I was not thinking about the software engineering project, I worked on the semester project for my programming languages course. It was the most unique programming assignment that I think I have ever worked on. I got to play around with finite state machines, environment simulation, programming language design, and functional programming. It was a very interesting and enjoyable project, but I would have enjoyed it more had the software engineering project not consumed all of my time.
The project idea came from the 2004 ICFP programming contest. We had to "design an ant colony that will bring the most food particles back to its anthill, while fending off ants of another species." Ants were finite state machines governed by a simple machine language consisting of eight simple commands. To create a winning ant, we had to write a compiler that would take in a high-level ant language that we designed and output a series of ant commands. The twist was that for the class project we had to write our compiler in Scheme.
I had some experience with functional programming from using XSLT, but I had never used a "real" functional programming language. The majority of the course involved the Lambda Calculus, so the instructor wanted to give us applied experience with both the Lambda Calculus and functional programming by having us write a language compiler in Scheme.
The class had only six students, which made for very intimate lectures. Imagine six people sitting in the first three rows of a 90-person classroom. There were two women in the class. This is an astronomically high percentage for a CS course. The class split into two ant teams. At the end of the semester we would pit our ants against each other and see who won. About halfway through the semester, one of the women dropped the course. This cut our female attendance in half and reduced my team to myself and a guy named Phil who was on one of the software engineering mapping teams. I am glad he was not on the other Del.icio.us team. Having two software engineering students on a team was difficult enough; it would have been worse had we been competing against each other in the other class.
The first draft of our language looked like a normal procedural language containing loops, conditionals, variables, etc. I found out later that this was the direction that the other team as well as the winning ICFP team went. Phil and I, however, felt there had to be a better way to specify ant behavior.
Our second draft abandoned the procedural approach. We instead designed a language that could specify stimulus/response pairs similarly to the way we thought real ants could possibly think. Each stimulus "handler" specified a series of actions to take in response to the ant sensing something such as a wall, food, or other ant. The syntax expanded on the state-based nature of the ant neurology by allowing the programmer to specify superstates that could contain stimulus/response handlers as well as any number of substates. Handlers could jump between states based on certain stimuli. For example, sensing food could jump from the "searching" state to the "found_food" state. A state would loop indefinitely, performing its default actions, until some stimuli caused the ant to jump to a different state.
The following is an example of our final language. It exhibits several features of the language such as macro expansion, marker expansion, default actions, substates, and various stimuli. The syntax looks very Scheme-like, but this was simply to make it easier to read and parse.
The initial default state is executed first. This randomly splits the ants into two main types: soldiers and foragers. Macro and marker definitions, such as the ones that follow the initial default state, are automatically expanded by the compiler when used in the code. The hierarchy of the states also defines the scope of macro and marker definitions. A macro or marker is valid in the current state as well as any substates. Therefore, because the two definitions are in the "root" state, they are valid for the entire program. The forager state contains the searching-for-food and return-home substates. A forager ant will initially fall into the searching-for-food state. The ant will move and mark until it senses either a rock or food. If it senses a rock, it will turn left and resume searching. If it senses food, it will execute the code in SEE-FOOD, then jump to the return-home state. The marker in this case does not do anything. A more complex program like the one we used in the competition could use markers to create trails and send messages to other ants.
This is a very stupid ant and far less complex than the ant we ran against the other team at the end of the semester. However, one can easily see how the state hierarchy and stimulus/response design can be used to define very complex and useful behavior.
Phil and I had our language design pretty early in the semester, but as software engineering picked up, our compiler and ant fell further and further down in the priority list. I am sorry to say we finished the last 75% of the project in the three days before the final presentation and competition. We put the finishing touches on our ant program during the hour before the class started.
Our final ant had forager and guard states. We made it so that there were three foragers for every guard. Foragers wandered around looking for food. Whenever one found food, it would carry its food along a directed path back to the home anthill. Other foragers, when they found a food trail would follow it in the opposite direction to the food. Guards stayed on the home anthill and guarded the food that the foragers brought back.
The competition took place on a very nice visual ant simulator that a classmate found. We lost, but I do not feel this is due to any weakness in the language. Given time, we could have created an incredibly powerful ant.
You can find part one of my semester project rundown here.
Purdue's CS307 software engineering course is regarded as one of the most project-intensive courses that an undergraduate can take. Over the course of a semester, a team of students must design and implement a real-world project proposed by a corporate partner. This year Motorola sponsored two projects: a mapping application tailored to building-to-building campus navigation*; and a social networking and data visualization application built on top of Del.icio.us. There were four teams, two competing on each project. I was the team leader for one of the Del.icio.us teams.
As indicated by the length of this post, this project became my primary concern this semester. I could never have foreseen the hours and hours that I willingly poured into my team's application. We spent many evenings, nights and weekends putting together the largest project any of us have ever seen to completion.
My team consisted of myself and six other CS students: Brandon, Brett A., Kai, Han, Jon, and Matt. I knew I wanted to be the team leader before the class even started. I hope to make software engineering my career one day, so I wanted to gain experience leading team through the entire development process.
I am very pleased with how the team performed. Everyone worked hard throughout the semester and contributed positively to the entire project. Once builds got underway, each person adopted a particular part of the application. I was the jack-of-all-trades, laying the groundwork for future builds and helping in current builds wherever I could. This organization worked out incredibly well. We communicated well, and the individual parts of the application came together without too many problems.
It was amazing the project went as smoothly as it did considering...
Three team members had part-time jobs
Two team members were married
One had a daughter and did not have a computer at home
One was in the marching band (which is a huge time commitment)
One was taking compilers (also a huge time commitment)
None but myself had any experience with .NET programming or large application design.
Design and Implementation
The main idea of the project proposal was that Del.icio.us' existing tag and bookmark "space" defines social relationships between users. For example, two users that have many tags or bookmarks in common probably share similar interests. The project needed to make these implicit relationships explicit through more social networking and data mining functionality. The project would need to display these social and data relationships in some form of enhanced visual frontend. Because the project was sponsored by Motorola, we also needed some kind of mobile device interface to the application.
We spent the first half of the semester designing the application. The course required a formal requirements document, user manual, and design specification. The purposefully vague project description gave us a great deal of freedom to design creatively. Even so, it was difficult to know how the application would function before we had written any code.
It was during this design phase that Brandon thought of naming the application "Scrumptious". I thought this name fit perfectly because it implies Del.icio.us-ness, with a little bit extra added on. Brandon even registered the domain sc.rumptio.us** which I thought was a nice touch.
We had seven weeks during the second half of the semester in which to build the application we designed. Unlike most CS classes, we, rather than the teachers, determined exactly what we needed to turn in and when. I planned the sequence and duration of each "build module" before we started developing. Prior to each module, we had to turn in a build plan to specify what we were planning to develop, a test plan to show that the module met the functional requirements, and an inspection plan to verify that the code and tests were correct. We usually had three build modules under development at any given point. I am pleased, as the team leader, to say that we only had to modify our build schedule twice and made only minor changes to our design document.
It was not until we started building that we realized how large the project would be. We managed to meet all of our build plan goals, but it was not without a great deal of hard work and long nights. We had a short status meeting every Tuesday night to plan the week's tasks. Each team member did his part during the week in preparation for the build demo every Monday. Around the fifth build we also started meeting on Saturdays in the lab*** for long team development sessions. These long meetings made it feel like we were a small web startup getting ready to roll out our flagship product.
Despite having just seven builds, our application had a very long list of features. The following is a very short list of the application's core functionality.
Like other social networking applications, Scrumptious users could create personal profiles, form "buddy" links, and send public or private messages to other users. Pretty standard stuff.
Users could do pretty much everything on Scrumptious that they could do in Del.icio.us. When a user added or modified a bookmark in Scrumptious, the changes were automatically mirrored back to Del.icio.us via the Del.icio.us API. Internally we had a DeliciousInterface class that was powerful enough to spin off into a standalone .NET library if we wanted.
The Scrumptious API
We tried to emulate Del.icio.us' open nature by creating a Scrumptious API similar to the Del.icio.us API. Like Del.icio.us, our API accepted HTTP GET requests and returned XML responses. It provided an interface to almost all of the functionality within the core system and drove both the visual and mobile interfaces (see below).
Data Relationships and Visualization
This was probably Scrumptious' killer feature. Internally, we wrote logic to retrieve users related by common tags and tags related by common bookmarks. Externally, we displayed these relationships in an interactive Flash interface.
The visual interface displayed a network of boxes connected by lines. The boxes could represent either users or tags depending on what the user wanted to browse. When a user clicked a box, a cloud of other boxes all related to the clicked box would spring outward and form links to the clicked box as well as related boxes already displayed on the network. When the user clicked the line connecting two boxes, he or she could see what made the two boxes related. For example, while browsing the tag network, clicking a line would display a list of bookmarks on which the two tags were used.
The boxes were positioned dynamically using a spring physics engine that I wrote. Related boxes would attract down to a certain threshold while all nodes would repel when below the threshold. It was engrossing to click a box and watch the network reach a new equilibrium.
Internally, the visual interface just pulled XML from the Scrumptious API and displayed the results.
I really wish the application was still running so I could link to a demo; words do not do the visual interface justice.
Kai became our "mobile guru". He designed and implemented a mobile thin client written in J2ME. Because it was driven completely by the Scrumptious API, the mobile interface only needed to handle the UI, sending the GET requests, and parsing the XML responses. Thanks to the power of the API, the mobile interface supported almost all of the functionality of the core system but on a tiny phone screen. Pretty impressive.
The big selling point of the mobile interface was that it illustrated how a third-party application could piggyback on Scrumptious in the same way that we piggybacked on Del.icio.us. I love how applications are starting to become more open and distributed making architectures like this possible.
In addition to the scheduled builds, the team put together several side projects to help support various parts of the application.
Han became the "database guy" during the course of development. He wrote a quick app that would remove all of our test data from the database and refresh it to a normalized state.
.NET Mobile Interface
Before we had decided on an architecture for the mobile interface, Matt played around with the .NET Compact Framework. We did not get much farther than screen prototypes, but it did give us an indication of what to expect on other mobile architectures. The reasons behind our choice of J2ME are too convoluted to go through here.
To make build plans less painful, I wrote a quick application that generated the required documentation from the .NET documentation XML output after compilation.
In order to have meaningful data for testing and for displaying on the visual interface, I wrote a scraper that spidered across Del.icio.us' RSS feeds and saved the data directly back to our database. It may bend Del.icio.us' terms of service a bit, but it gave us some great data with which to demo the application.
Our test plans for each build module simply consisted of the code for NUnit unit tests. It was a perfect way to demo the functionality of each module; when everything was green, we got the points.
As is the case with any software project, we had our share of problems during the course of development. The most frustrating by far involved our server.
Brandon had a dual-processor, quadruple-RAID, redundant power supply, rackmount server lying unused in his apartment. This was extremely fortunate because Purdue does not offer any way to host .NET applications. He agreed to donate it to the project for the semester and installed everything we needed.
At first we were planning to run the server in my apartment. This proved infeasible because the redundant power supplies produced redundant noise. It sounded like a miniature jet everywhere in the apartment even with all the doors closed. Fortunately, the TA allowed us to run the server in his office, but we soon found this setup had its own problems.
We thought the first crash was a fluke. All of us were in the lab developing at the time, so Jon and I trudged over to TA's office to restart the server. The second crash, not 24 hours later, made us worry a bit more. We were again in the lab, so Brett A. and I dejectedly walked over to the TA's office. To our horror, the door was locked! As it was dawning on me that we might have a serious problem, the door opened and the graduate student that shared the office with the TA ushered us in. With a sigh of relief, I restarted the server. The graduate student, hearing our complaints, gave us his number for if we ever found the door locked again. We copied it down, naively expecting that we would never need to call it.
The third crash was the worst. It was the day before a build module was due and key parts were not yet complete. The server went down at about 10 PM, so I knew as soon as I got the "Unable to connect" error that the office would be locked. I drove over anyway and valiantly jiggled the handle. I reluctantly called the graduate student. By some miracle he was home and thinking about heading into the office anyway. I agreed to pick him up.
The drive over was epic. I drove up and down the street—the very street I live on—several times but was unable to find the grad student's apartment. I stopped at my apartment and sprinted up the stairs to look at an online map. It was no help. I called him again, apologized for the delay, and got better directions. A few minutes later I found him shivering at the entrance to his apartment complex. We drove back to the office, and I restarted the server.
The team and I speculated long and hard about what could be causing the crashes. Perhaps we had too many connections to the database; perhaps we had some critical bug in our application; perhaps Windows was being characteristically flaky... who knows? After Thanksgiving break, Brandon installed a remote power management card and set it to restart the server every night. That prevented further crashes. In the end we fixed the symptom without ever knowing the true cause of the problem.
The Final Presentation
My team gave our final presentation on Saturday, December 3 to the course administrators and a Motorola representative. Each team had to give a 25-minute "sales presentation" followed later in the day by a 45-minute "poster session" in which we demoed the application. Our presentation went very well, but the server had one final laugh during our demo: we got a full-page server error that none of us had seen before while showing the Scrumptious API to the professor. Oh well.
I consider the project a great success. We got an A on our presentation, an A on our documentation and builds, and we won the competition against the other Del.icio.us team. In addition, I learned how to better gauge the scope of projects and how to coordinate a team of developers.
* The winning mapping team's project can be found at BoilerMap.com. They did a superb job.
** Right now http://sc.rumptio.us does not resolve to anything. We had to take down the server after the final presentation.
*** Live webcam pictures of the lab can be found here and here.
I expected this to be a light semester. I knew it might get busy from time to time, but I certainly could not have foreseen the constant, unremitting load of work that I have borne like an overworked pack mule for the entire semester.
In previous semesters, I have been fortunate to have at most two major projects going at any one time. They might overlap for a week or two, but overall, I have had periodic bursts of heavy work separated by lighter—but certainly not empty—spells. This semester has been different. This semester I had three major projects spanning the entire three and a half months since summer ended.
It has been tough, but all three projects are complete, turned in, and/or demoed. I plan to write about each of them in the order they concluded, starting with...
Project One: Graduate School Applications
I have heard it said that applying to medical school is the equivalent of a three credit hour college course. If that is the case, then applying for a Computer Science graduate degree counts for at least a two credit hour seminar. I wish I could have hired a secretary to handle all the papers, requirements, forms, and pages and pages of thorough yet misleading instructions.
Of the three projects, this has lasted the longest. I knew I wanted to go to graduate school around sophomore year. Much of my CS work—such as undergraduate research and the CS honors program—has been to prepare for further study in addition to a career. Last summer I seriously started looking at schools and began researching what I would have to do to apply. I started the online applications about a month into the semester, and I took the GRE in October.
The GRE is a computer-adaptive test, meaning that the questions get harder as one progresses. The increase in difficulty was very noticeable because I started having to guess a lot about halfway through each section of the test. The adaptive nature of the test also makes it very short—only about three hours total—so time plays a large factor in completing the sections. These two things made the test much more stressful than a normal multiple choice test. Taking the test on the computer was beneficial, however, because I got my verbal and math scores as soon as I finished. I did reasonably well.
The application process sped up after I took the GRE. I completed my statement of purpose in an afternoon, and three current and former course instructors agreed to write letters of recommendations around that time.
All are top-20 computer science graduate schools, and I am sure I would be happy wherever I end up. I plan to get my master's degree in computer science, but at the advice of several people, I am applying as a PhD. student. This will help my chances of getting accepted and will probably open up opportunities for working on more interesting projects. It will also make it easier to continue for four years if I decide to get my doctorate.
It was interesting to note the similarities and differences between the schools' application processes. I was pleased to find that every school had an online application. I only had to send my paper transcripts to each school and a paper application to the computer science department at UT.
Purdue and UIUC both used the same software for their applications. This is interesting because the schools are so similar in other respects: both are highly-respected, technological, Midwestern schools. Fittingly, the software was equally bad in both cases.
MIT had the best application. It was easy to use, it gave clear instructions, it did not use popups (UIUC's was three popups deep at one point), and it worked in Firefox. The only downside was that I had to manually type in every CS, math, and science course I have taken as an undergrad.
I submitted each of the applications and mailed the final paperwork about two weeks ago. Now I must leave it up to the faceless application machinery to decide what I am going to do with myself for the next two or more years.
The good news: those on my mother's side of the family who lived in New Orleans got out before Hurricane Katrina hit. They are staying with family in Baton Rouge and elsewhere. Amazingly, NOAA satellite imagery seems to indicate that all of their houses stayed above water. My aunt went back to work at a temporary office in Baton Rouge a few days ago. Her husband, my uncle, works for the Army Corps of Engineers and returned to New Orleans to help rebuild the city.
The bad news: even though it appears that my family may have homes to return to, it does not look like they will ever return to the city they knew. My heart goes out to them and all the other millions of people affected by this catastrophe.
In the long time since I last posted, I finished my summer of programming at the software company, moved into my first apartment, and started the first semester of my senior year of college. I am not going to write about any of those things just yet. Instead, for my return to weblogging, I wanted to write about the project I undertook during my last two days of summer.
My grandmother gave me an old dining table and six chairs to take with me to the apartment. (Thanks again, Grandma, if you are reading this.) It was well-made furniture that had stayed with the family for 50 years. My father remembers sitting around it for dinner in his family's first house. It has filled my grandmother's informal dining room for as long as I can remember. All that history showed in the wood and seats, so when I loaded the first four seats into the trunk of my car, I knew I would need to do something to revitalize them and make them my own.
When I got home I brought one of the chairs and my dad's orbital sander out to the back porch. I turned over the chair, turned on the sander, and gingerly sanded a hidden surface on the bottom of the leg support. The chair did not burst into flames or scream out in pain, so I sanded a little more. Underneath the old varnish and years of use, the wood was still bright and beautiful. I knew then that I would have to go all the way. I retrieved some more supplies from the workshop and dove into sanding.
After I finished with the orbital sander, I rubbed each of the chairs with steel wool and then a wet paper towel to remove any remaining dust. Then, I sprayed each of them a thin layer of acrylic clear coat to protect the wood and bring out the color some more. I think the results are extraordinary.
My next task was to replace the thin and worn vinyl upholstery on the seats. I went to the fabric store and picked out a medium gray suede-ey fabric and some 1½ inch padding. I had never reupholstered a chair before, so I used packing tape to set the fabric and see how it would look. I mangled my first attempt at cutting foam— I now know that it is not necessary to bevel the edges of the foam with one's scissors— but everything went smoothly after that.
I used Dad's electric stapler to attach the fabric to the bottom of the chair. I just pulled as hard as I could to compress the foam into a nice curve and stapled where I was pulling. The corners required a little bit of work to prevent creases from showing. The stapler did not shoot the staples all the way into the wood, so I went back with a small hammer to finish the job.
Finally, I reattached each new cushion to the sanded chairs. It took me two afternoons to complete four of the six chairs. The last two had to wait because I needed to start packing for the move. I plan to finish them and perhaps the table during some vacation.
I love it when a project turns out better than expected.
I invited Wendy and Chelsea to the Indianapolis 500 Festival Parade. Wendy told me they were already planning to go with some other interns from the company where they are working this summer, but she invited me along. All of the interns live downtown in a nice little village of apartments paid for by the company. They are within walking distance of White River, the canal, and the center of downtown. I would love to live so close to everything.
We took advantage of the location and the bright, springlike day by walking to Monument Circle. The crowd was already starting to form, but we got there early enough to grab a seat on the wall surrounding the monument. We were high up and could see the half of the circle, the intersection of Market and Pennsylvania, and the entire route along Meridian Street.
The parade itself was interesting to see. Lots of marching bands. I was pleased they put Purdue's right at the front. We did not stay all the way until the end. With maybe 30 minutes left we walked along the parade route to a side road where we bought sandwiches. We concluded the parade had ended when I flood of people surged down the street in front of the restaurant.
I will let the pictures tell the whole story once Purdue's FTP server decides to let me log in.
Here is a question for Miss Manners: if your coworkers invite you to eat lunch at a pizza place, and you ate almost half a pizza for dinner the night before, is it appropriate to take the bag lunch you had prepared that morning and eat it at the restaraunt?
I did that today. My coworkers and I had a good laugh when I walked up to the group holding a plastic bag containing my lunch. The waitress looked at me strangely when I ordered just a glass of water and no food. I left a good tip: infinite percent of what I paid!
I told my parents about the experience this afternoon. Their responses could not have been greater opposites. Dad felt it was perfectly normal. He said one of his coworkers does it all the time. Sue, meanwhile, said, "That could not be more tacky!" I was right in the middle. It felt strange, but I did not feel that it was particularly rude.
As my junior year drew to a close, I told myself, "I am going to make this an interesting summer. I am going to have fun as much as I can." I did squat last summer. There were a fewinterestingevents, but I feel like I floated through most of those three months. Work, lift, surf, sleep. I want this summer to be a little more memorable.
Three weeks in and I am off to a good start. I still have those four staples: working, lifting, surfing, and sleeping, but these last three weeks have had a light sprinkling of interesting events. Charlie came to town a week ago Tuesday. An old friend's parents cooked a gourmet steak dinner for the group of us that welcomed him to town.
On Friday Eric and I went with two of his female engineering friends, Wendy and Chelsea, to The Slippery Noodle downtown. I did not realize how much I missed seeing such good music. The front stage had an old blues man, while the back stage— which I did not realize existed until two hours into the night— had a rock cover band. They finished on Hendrix. It made my evening.
At one point I tried to be smooth and offered to buy drinks for the girls. Wendy wanted a fuzzy navel, but Chelsea said, "surprise me". My smoothness shattered when I brought her a scotch and soda to go along with the one I bought for myself. Alas, she did not drink much of it. I should have gotten her something more colorful.
And that brings me to what I really wanted to mention: I signed up for bartending classes after work today. Classes start June 6 and run during the evening five days a week for three weeks. By the end I will have a state liquor-serving license and can legally work behind a counter if I so choose. Not only will it be an interesting new experience, but it may lead to a useful part time job to help pay bills while I am in grad school. (That is, if I cannot find a part time programming or research job.)
Enrolling was an interesting experience. Before I could ask about the cost or time commitment, the receptionist sat me down at a counter with a form to fill out. In front of me she proudly presented a photo album full of pictures from previous classes and a binder full of letters from former students. I glanced over the menacing form. It had more questions than most bank applications. I did not bother to fill it out and instead asked some questions about the class. What does it cover? How long does it take? When does it meet? She deftly diverted me to the manager seated in a wood paneled office tucked in the back of the building.
He was built like an ex-football player and had the skills of a used car salesman. He went through a binder containing the "curriculum", pointing out the benefits of various "subjects". When I asked about price he blustered a bit about how easy it is to make money in tips, then wrote a number on a sheet of paper and slid it across the desk. I looked at it and my eyes grew wide. It was about $200 above what I had expected. "oooh. That is a bit out of my league right now," I said. I was ready to leave, secure with the knowlege that I had saved some money by not signing up. To my surprise the manager replied, sounding concerned, "Well, Brett, what is in your league right now?" He assumed I was a poor college student wanting to make some extra money. That is partly true, so I played the part and gave him a low figure. He responded by cutting $150 off the cost. Too bad Purdue does not do stuff like that.
And so I signed up. Sue seemed surprised at the decision. Dad seemed excited for me. He worked at a liquor store during his time at Purdue and now I may work as a bartender during mine. Ironic, no?
I am working for a software design and consulting firm this summer. A new (to me) company, new coworkers, and a new language: I am learning ASP.NET. After all the work I have done with PHP, ASP's "web controls" require a complete shift in thinking. This was to be expected. I have learned something new during every one of my internships, and I am glad this summer is no exception. Armed with the requisite 800-page reference book, I jumped headlong into development when I started last Wednesday. I hope to write a post about ASP once I get more familiar with it.
I bought some new buttondown shirts to replace the old oxfords I have worn for at least four years. One had a hole in the elbow, another I accidentally washed with a black pen, and a third seemed to stay perpetually wrinkled no matter how many times I ironed it. Wearing one of those would not have been a good way to make a good impression on my first day of work. I bought three wrinkle-free, cotton blend, fitted dress shirts. If you have never worn a fitted dress shirt, you should. On a trim guy like myself, fitted shirts fall much more naturally and look O so much better than a wider, billowy cut. I still had a terrible time finding decent colors. Designers, please throw all your pastel, neon striped, paisley print, and above all, pink dress shirts in the dumpster behind your building. The men of the world thank you.
My morning commute is about ten minutes longer than the previous summers'. I am still trying to determine the best route. I am thankful I can still avoid the interstate. Each day I have chosen a different path to work and used an old stopwatch to time how long it takes me to get there and back. I have found the most direct route takes the most time due to traffic. I was inches away from putting together a spreadsheet to average times across several days and determine a day's deviation from the mean.
I was pleased to learn that my employer has a deal with the YMCA, reducing the monthly membership cost by about $15. Today I did some analysis to determine the best YMCA at which to work out this summer. Using Google Maps, I plotted the length of the drive from work, to a YMCA, and back home. The Y to the west requires 16.6 miles for the whole trip; the one to the north requires 14.1; and the one to the southeast requires 15.6. It figures. I could not have chosen a worse location to place work in relation to nearby YMCAs. Fortunately, the one to the north has the most direct path and the nicest equipment. This analysis also led me to send Google a feature request asking for directions through a series of waypoints.
A grocery store near where I live rents out little alcoves at the front of the store to small businesses. One lies empty, but the other contains a small shoe repair shop. It cannot be more than eight feet wide by 15 long. It smells like old leather and melted wax. The shelves lining the walls display all sorts of polishes, laces, and other shoe accessories. Any other free space is piled high with paper bags containing works in progress: boots with no soles, high heels without the heel, scuffed dress shoes, and other strange pieces of leather that I do not recognize. I notice an army green, turn-of-the century buffing wheel in the repair area behind the checkout counter.
I start my summer job tomorrow, so I stopped in to get some black polish to rejuvenate my InternWear™ dress shoes. As I reached for a bottle of liquid polish, the spindly proprietor shook his head in dismay. In a soft, breathy voice he said, "no, no, no. Don't get the liquid. That will ruin your shoes. You need to go with the old-fashioned paste. It will protect the leather and extend the life of your shoes. Down and to your right." I picked up a small tin and looked to him for approval. He nodded. After I paid, he placed the tin carefully in small paper bag, stapled it closed, and handed it to me reverently.
A while back I needed to buy some matte board with which to mount some more celica ads. The only place I found that sold large sheets was a small frame shop in a nondescript strip mall. A bell rang as I entered and a small white terrier came sprinting through the store to see who had arrived. A voice called out from the back, "Just a moment, my friend. I will be right with you." The dog watched me diligently as I looked at the pictures leaning in deep stacks against the walls. "How may I help you, my friend?" said the proprietor as he picked carefully between pictures and a queen bed-sized cutting table. I told him I needed some matte board. He retrieved a sheet from the back room. "You are a student, my friend? We get many students buying matte board from us, don't we [dog's name]."
I get asked that all the time. Is it really that obvious?
The dog jumped up on the counter as I paid, then tailed me to the door as I left.
The Comic Book Guy
It became a ritual for me to go to the comic book store whenever I came home from school for weekends or vacation. The same bearded cashier was working every time. He probably has a strange opinion of me.
Michael's former IM screenname incorporated IG-88, an obscure Star Wars droid that appears for a few seconds in The Empire Strikes Back. George Lucas nevertheless made a 12 inch action figure of it. The comic book store had one displayed prominently on the front counter. I of course had my camera with me and decided to take a picture to send Michael.
I had asked the cashier if it was okay for me to take a picture, but he still looked at me strangely. "That'll be ten dollars," he said when I finished.
It took the entire weekend for me to merge one Standard Dorm Unit (SDU) of stuff into my room at home. I have also learned that a 1990 Celica can hold 0.5 SDUs, minus one Standard Loveseat Volume (SLV). My parents took the couch in Dad's SUV which, amazingly, holds exactly one SLV with the back seats down.
The Variable Relocated Mass Law states that mass is not conserved when one moves one's belongings from one location to another. In other words, the amount of mass entering the system before a move is always more than that which exits the system after the move. Case in point: I seem to have lost my TV remote.