Yearly Archives: 2014

nonfiction

Let It Marinate

In my first year of college, my dorm was configured as a suite, with five rooms around a common living area. One of my suite mates was a fellow named John whose primary motivation in all activities was to bring ladies to his room to “rub”.

“I’m goin’ out with this lady tonight, then we gonna’ come back to my room an’ rub,” he’d say. Except he never said “rub” as a normal person would say “rub” (fittingly enough). He would always elongate the “u”. Ruuuuuuuuuuuub. As in, We gonna’ ruuuuuuuuub.

John was always a great source of amusement to me. He could easily have crossed the line of creepiness, but he seemed to be able to stay on the right side of that divide (barely) by becoming a sort of caricature of himself.

His term of choice—ruuuuuuuuub—was part of his charm. It’s meaning in the given context was clear. Yet, by itself—rub, without the elongated vowel—it’s a fairly innocuous word. I decided one day that I was interested in learning more about what was involved in John’s favorite pastime.

“I’m goin’ out with this lady tonight, then we gonna’ come back to my room an’ ruuuuuuuuub.”

“John, man,” I said, “how does one ‘ruuuuuuuuub’?”

“C’mere, lemme show you somethin’.” He gestured for me to come to his room. Aside from the lamp draped with a sheer piece of fabric to add a slight red tint to the light of the fluorescent bulbs above, nothing about the room struck me as particularly conducive to what I had interpreted ruuuuuubbing to involve. I looked around the room, then stared at him blankly. He smiled at me. “Hold on,” he said as he walked to the light switch, and flipped off the lights above. We were now staring at each other in the dim, red light of the incandescent lamp. “Check it,” and he pointed at the ceiling.

His ceiling was covered with the sort of adhesive, glow-in-the-dark stars that a fifth-grader might use to decorate his room. But that wasn’t what he was pointing to. He was pointing to the spot directly above the head of his bed. He had taken a sheet of the same material used for the stars, and with the skill and accuracy of a young child, cut out letters to form the word RELAX. I can’t say for certain, but I would imagine that if I were a female, and some fellow had flipped off the lights to reveal a sloppily cut, glow in the dark RELAX on the ceiling, I would do anything but.

Now, like John, I was smiling—but for a different reason. “So this is part of ruuuuuuubbing?”

“First, you set the mood.” He paused and smiled even more broadly. “Then you let it marinate.”

In my entire college experience, I attended many lectures. In each of those lectures, a professor hoped to teach some lesson that would, at least in some small way, shape the minds of the students in the class. Yet I would be hard pressed to provide an example of a lesson that made more of an impact on me than what John taught me that day. First, you set the mood. Then you let it marinate. True, dat.

knitting

Faux Cable Hat

Download the pattern: Faux Cable Hat

The standard technique for moving a column of stitches across a pattern is cabling, in which one or more stitches are passed over one or more other stitches while knitting a row. However, a column of stitches can also be moved across a pattern by balancing increases on one side of the column with decreases on the other side of the column. As an exercise in this technique, I started drawing up a chart with two such columns, criss-crossing is opposite directions.

I ended up with what I call my Faux Cable Hat. It’s a subtle pattern — without the bulk of real, honest-to-goodness cables — that looks best in a single color yarn.

Also, it can be knit with either a foldable brim, or a short, simple brim.

One note about the increases: All increases have either a “left” or “right” lean, specified as M1L and M1R, respectively. M1L is made by lifting the bar between the current two stitches from the front, and knitting through the back loop. M1R is made by lifting the bar between the current two stitches from the back, and knitting through the front loop. Further information about these two techniques can be found at,

http://www.twistcollective.com/collection/component/content/article/92-how-to/1046-make-1-left-or-right-m1-m1l-m1r

I occasionally become bleary-eyed, and forget which type on increase requires lifting the bar from which side. Eventually, I came up with the mnemonic that M1L lifts the bar from the Front, because L and F are similar (both letters are constructed with only horizontal and vertical lines). Likewise, M1R lifts the bar from the Back, because R and B are similar (both letters are constructed with a rounded shapes).

Download the pattern: Faux Cable Hat

programming

Race Progress Visualization Using D3

[The project referred to in this post can be found at http://vestigial.org/MMT/ ]

I’ve been looking for some better tools to produce interactive, data driven, visually appealing web content. In the past couple of years, I’ve become enamored with R for analysis and visualization, but the graphic results are static. (Sure, there are tricks to create animations, but I’m not looking for workarounds.) I occasionally use Google Charts when I need to put together a quick visualization, but they don’t provide quite the level of flexibility I’d like. I started looking at either working directly with SVG or Canvas DOM elements, or using a Javascript SVG library that would allow me to avoid the low-level details.

The most interesting possibility was the D3 framework. D3 — for Data-Driven Documents — is an entire framework for DOM manipulation in data-driven sites. Browsing through the examples on the D3 site, I recognized several memorable visualizations that have appeared on one of my favorite blogs through the years, Flowing Data. It is possible to use D3 for SVG construction and manipulation while non-data-driven portions of the site are handled by, eg, jQuery or standard Javascript. But as long as you’re already using the bandwidth to load the framework, you might as well drop other frameworks, and use the tools that D3 provides.

I was keen to get some experience with D3. When learning a new technology, I prefer to dive straight in — come up with a short, but non-trivial project that I can build. In this case, I came up with a project that melds technology, data visualization, and ultrarunning. The Massanutten Mountain 100 Mile Trail Run (or MMT) is in a few weeks. In such a long race, runners and crews like to have some idea when they’ll arrive at intermediate points along the course if they’re aiming for some given finish time. Conversely, knowing when they’ve arrived at points along the course can help to predict what sort of finish time to expect. While I’m not the first person to provide a visualization, or some tool to correlate aid station splits with finish times, it’s fun to put together something that’s visually appealing and useful.

Showing data from 2011 and 2013 for finishers who finished between 20:59 and 25:55, race time. The horizontal axis is time and the vertical axis is distance, labeled on the left with mileage at each aid station, and on the right with the aid station name. Each diagonal line represents a single racer. Intermediate times on the graph show first and last racer times of arrival at each aid station (for racers in the result set).

Showing data from 2011 and 2013 for finishers who finished between 20:59 and 25:55, race time. The horizontal axis is time and the vertical axis is distance, labeled on the left with mileage at each aid station, and on the right with the aid station name. Each diagonal line, or “track”, represents a single racer. Intermediate times on the graph show first and last racer times of arrival at each aid station (for racers in the result set). Tufte would be proud.

 

There are several interactive components that I think are noteworthy. First, I provide on-demand data loading. When the page loads, none of the race results is loaded. When a year is selected, the page checks whether the data have been downloaded. If not, it fires an AJAX request, and saves the data so the results can be turned on and off.

The page also provides sliders to limit the result set based on finish time. Each limiter consists of three components: a triangular slider widget (represented by an SVG path element), a time display (represented by an SVG text element), and a vertical guide line (represented by an SVG line element). When the widget is slid, all three elements should move in unison, and the time display should update with the time value at the current point. As a bonus, the vertical guide gets brighter. So I needed to be able to address each element individually, but move them in unison. To build that, first I needed to define the shape for my widget (note that in SVG coordinates, the top left is [0,0]):

var limpolygon = [{x: 0, y: 0}, {x: 10, y: 0}, {x: 5, y: 10}, {x: 0, y: 0}];

I also need to define a function to tell D3 how to interpret the data above. I can use d3.svg.line() to return a function for this purpose. Since I’ve built the object with straight-forward X and Y coordinates, I just need to build a simple function based on those values:

var limline = d3.svg.line()
  .interpolate("linear")
  .x(function(d) { return d.x; })
  .y(function(d) { return d.y; });

Finally, I put the group together. I define a group element (“g”), and append the widget, which I construct in place. I then use the D3 selector to reselect the group, and add the line, then the text:

svg.append("g")  // Create the group, append it to the svg object
  .attr("id", "lim1")
  .attr("transform", "translate("+lim1x+","+limy+")")  // Put it into position
  .append("path")  // Create "path" element for widget, and append it to group
    .attr("id", "lim1_point")
    .attr("d", limline(limpolygon))  // A path has a "d" attribute which gives
                                     // instructions for drawing. Our limline()
                                     // translates raw data into path data
    .attr("fill", "white")
    .on("mousedown", function() {
      capt = "lim1";
      d3.select("#lim1_line").style("stroke-opacity", "1");
    });

d3.select("#lim1").append("svg:line")   // Create line element, append to group
  .attr("x1", limhalfw)
  .attr("y1", ex_pad.top)
  .attr("x2", limhalfw)
  .attr("y2", height - ex_pad.bottom)
  .attr("id", "lim1_line");

d3.select("#lim1").append("svg:text")   // Create text element, append to group
  .attr("id", "lim1_time")
  .text("00:00")
  .style("text-anchor", "end")
  .attr("transform", "translate(-2)");  // Push it 2px to left, for a nice gap

In my view, the coolest trick is making the data respond to the sliders. Whereas showing or hiding the individual years relies on a small number (3) of discrete values, I need to show or hide individual race results based on what is essentially a continuous scale. This involves several steps. First, when adding each track to the graph, I need to attach the finish time to it. Fortunately, HTML5 provides the ability to specify arbitrary data attributes with the data-* construct.

lineset.enter()
  .append("path")
  .attr("data-finish", function(d) {  // Add the data-finish attribute
    return d.finish;
   })
  .style("stroke-opacity", function(d) {
    if (d.finish > finScale(lim2x) || d.finish < finScale(lim1x)) return "0";
    else return ".3";
   })
  .datum(function(d) { return d.splits; })
  .attr("class", "rtrack line " + iden)  // Classes to use later in selectors
  .attr("d", line);

Above is the code to add the tracks. While it might not make much sense if you are not familiar with D3, the key point is the third line. The object has a data object, d, applied to it, and on that line, we set the data-finish attribute to the value of d.finish. (Directly below that, we set the opacity of the line to 0 (making it invisible) if it falls outside of our specified range, or .3 if it is inside the range. But we’re getting ahead of ourselves.)

The next thing we need to a way to translate the location of a slider into a finish time. D3 provides “scales” for just such a purpose. Usually, D3 scales are used to translate some real world value to a pixel position. In this case, we want to do the reverse. I want to build a function that will translate an input domain of a pixel position into the output range of a race time, which in this case is between 0 and 36 hours.

var finScale = d3.scale.linear()
  .domain([lim1x, lim2x])
  .range([0, 36]);

(An astute reader who is familiar with D3 might note that somewhere else, I must have defined a scale to translate from times to pixel values. In that case, someone might wonder why I don’t just use linear.invert() to translate a range value into its corresponding domain value. The answer is that the scale that translates from time to position uses a domain defined by the time of day as a date object, whereas in this case, I want to translate between position and a floating point number representing the finish time in hours (with minutes represented in the fractional portion of the number). Hence the need to define a new scale.)

In this case, lim1x is the initial pixel position of the lower limit slider, and lim2x is the pixel position of the upper limit slider. That produces a function that can be called as finScale(px_pos) to return a corresponding race time. I can then use that in the function that is called when a slider is released.

function updateRange() {
  var fin1 = finScale(lim1x);  // Translate pixel positions to finish times
  var fin2 = finScale(lim2x);
  d3.selectAll(".rtrack").transition(500).style("stroke-opacity", function(d) {
    if (this.getAttribute("data-finish") > fin2 ||
        this.getAttribute("data-finish") < fin1) return "0";
    else return ".3";
  });

  updateAidStationTimes();
}

That function translates the current pixel positions of the sliders into race times (fin1 and fin2). Then it uses d3.selectAll to get every item with the class “rtrack” (which is every race line displayed on the graph), applies a 500ms transition time to the following step, then sets the stroke-opacity style based on a function that checks whether the custom attribute data-finish is in the range defined by the limiters. Finally, it calls updateAidStationTimes(), which I won’t explain in detail here, but it uses d3.extent() with a custom accessor function to find the first and last arrival time of racers in the result set at each aid station. (If you’re particularly interested, you can always dig it out of the source.) It then updates the times displayed on the graph, and moves them into the proper positions.

I started the project on Saturday morning with no experience in D3 (or with SVG graphics), and I finished Sunday evening. I even had time to get out for a bike ride, a run, and a trip to the library to get a movie (which I also watched over the weekend). In the course of this project, I came to appreciate just how massive D3 is. I’m starting to get a feel for it, but this project just scratched the tip of the D3 iceberg (though I’m not sure one would really scratch an iceberg, the tip or otherwise).

[The project referred to in this post can be found at http://vestigial.org/MMT/ ]

music

Traumerei

When I was very young — maybe around second grade — I started taking piano lessons from Mrs. Bickley, who also happened to be my school’s librarian. But I had little patience for practicing. Working through a new song, note by note, making the same mistakes again and again created such visceral frustration that there came a point when I refused to practice at all. Sometime during fourth or fifth grade, my parents allowed me to quit. I felt some shame whenever I would venture into the library and see Mrs. Bickley, but that couldn’t nearly outweigh how much I disliked practicing.

Some years later, when my brother was taking guitar lessons, I tried again. My parents could take us both to the music store with the sound-proof practice rooms in the back, and we could take our lessons. That time around, I lasted perhaps a year before deciding that it wasn’t for me.

In middle school and high school, I was involved in theater (some, of the musical variety) and choral groups. I wasn’t much of a singer, but it turns out that at certain times and places, if you are a male, it’s sufficient just to be willing to show up. I was the beneficiary of just such a situation.

Many, many years later, I found myself regretting that I didn’t stick with music. I’m envious of people who can sit down with an instrument, and play a song. As time went on, my regret grew more and more palpable. I still had a mini Casio keyboard that I received as a gift as a child. I plugged it in, and started to pick out songs on its miniature keys. After several weeks of the tinny, synthesized keyboard sound, I decided that it was time to commit. I bought a full-sized keyboard, and I started to play again. Whereas I had been an impatient child, I have become an adult who is quite content to spend an hour or two working through a troublesome section of a song.

I can’t claim that I’ve become a very good piano player. But I can pick through a song, and repeat it enough that it eventually starts to sound coherent. One of my favorites is Traumerei by Schumann. It’s short and melancholy and open to oh-so-much expression. Here, I play it too fast, and I’m sort of distracted by the concerns of self-recording. I hammer the keys too hard and unevenly in many places, and I continually turn even eighth notes into dotted eighth notes and sixteenth notes.

But it brings me joy to be able to sit down at an instrument, and play a song.

 

 

(I should note that the C above middle C on my keyboard is busted. The key itself is loose and most of the time, it doesn’t play when struck. So if you are paying close attention, you’ll notice that that note is almost entirely absent from the song. Also, I recorded the sound on Garageband on my iPad. For some reason, that app has recently decided that my songs really need occasional, randomly placed gong sounds. So again, if you are paying close attention, you’ll hear a couple of Garageband gongs.)

life

Grandma

Grandma passed away four years ago. The following is the eulogy I gave at her memorial service.


Grandma moved in with us when I was very young. She was a part of the family, and she helped my mother and my father raise me and my brother. I suppose that the prime directive of raising two boys is to get them through adolescence without allowing them to cause excessive harm to themselves or others. And as a testament to their success in that endeavor, my brother, Mark, and I are here today.

But if I were to claim that grandma only kept me out of harm’s way, I would be failing to recognize the deep impact she had on my life—on making me the person I am today. And while she influenced me in many ways, there was one lesson she taught me that stands above all others. It’s a lesson that she repeated throughout her life—to me and to everyone who came in contact with her. She never forced it on anyone, and most of the time you might not have recognized that she was offering a lesson at all. I didn’t. I didn’t realize it until many years after she started teaching it to me.

When I was young, I realized that grandma had a unique way of seeing the world. While other adults would talk about difficulties, she would talk about joys. When other adults would talk about how cold and rainy it was outside, she would talk about how warm and cozy it was inside. I thought that she just didn’t see somethings that other people saw—that she had some sort of blind spot for those things that most people dwell on.

Years passed, and I grew older. Eventually, I could talk to her as an adult. And as an adult, I realized something: I had been naive. She wasn’t missing anything. She could see the difficulties and travails of life just as well as anyone else. The difference between her and everyone else was that she had an amazing ability to put the bad aside, and focus on the good. She wasn’t an optimist because she couldn’t see the down side of a situation. She was an optimist because she chose to embrace the up side of all situations. Her optimism was intentional.

Grandma never tried to convince me that I should practice her brand of intentional optimism. No, she was content to let me become my own person, to find my own way. All the while—through my childhood and beyond—she was a presence, offering herself as an example of one way to see the world.

None of us can go through life without affecting, and being affected by, the people around us. Grandma lived for 96 years. Many people loved her, and she loved many people. In one way or another, she touched every one of us. When someone like Grandma passes on, those of us who loved her struggle to find a way to honor her and everything that she gave to us. I’m glad that we could all come here today to remember and honor her. But after we leave here, and return home, she will still be with us. Each of us has the opportunity to continue honoring her by embracing that most important lesson that she taught all of us: that we can choose to see the joy, the up side, the good in any situation. I know that every time I practice intentional optimism, a part of her carries on. And in that way, she will always be with me.

knitting

A Sweater

While in Iceland for the Laugavegur Ultra Marathon, Martha and I came across the storefront for the Handknitting Association of Iceland. I took the opportunity to stock up on yarn. The Álafoss Lopi was ridiculously inexpensive, so I got a sweater’s worth of it.

sweater_detail

After a bit of consideration, and consultation with Martha, we decided on a forest green main color, with some yellow and white for contrasting colors. I didn’t really know what I was going to do with it.

sweater_front

I ended up working the standard seamless design from Elizabeth Zimmerman’s Knitting Without Tears.  I started with a provisional cast on, and reversed it with a perl round after a few inches to give me a straight, hemmed edge. I did the same around the sleeves. The touch of color on the inside makes me happy.

sweater_hem

I made up the yoke as I went along. You put in so much work for something like that, and you have no idea whether it’ll fit until it’s pretty much done. So you need to enjoy the process, and accept that in the end you might walk away with something that sucks. If it comes out right, well, that’s just a bonus.

sweater_seated

 

music

Music From Long Ago

I recently came across some old tapes from high school, when I sang with a madrigal group. Twenty years ago? Really?

I dug up an old Walkman™, put in some fresh batteries, plugged it into a computer, pulled the songs into an audio editing program to clean them up (most noticeably by getting rid of a loud hiss at around 8kHz), and put them on the interwebs so that the digital archeologists of the future might someday take note.

 

electronics

Blinking LED Circuit

As part of a larger project, I needed a circuit to blink an LED. It’s a simple task, and there are plenty of existing designs. But having almost no experience with circuit design, I wanted to make my own. Further, I wanted to make it with basic components — no ICs. An integrated circuit, like a 555, would take the fun out of it!

As is the case with most oscillators of this sort, the charge/discharge cycle of a capacitor acts as a switch to turn the LED on and off. I sketched out a few ideas, and eventually arrived at this:

Blinking LED Circuit

The blinking happens because the circuit oscillates between several states:

  1. Current goes through PNP transistor Q2 to the anode side of capacitor C1. As C1 charges, the cathode side drains through resistor R1 to ground. In doing so, it also puts “pressure” on the base of PNP transistor Q1, preventing current from flowing through it.
  2. After C1 is fully charged, its cathode side will no longer be draining, so there will be nothing preventing flow from the base of Q1 through R1 to ground. At that point, Q1 will start to conduct to the big loop, which will cause three things to happen.
    1. Current will flow to the base of NPN transistor Q3, which will allow C1 to slowly discharge through resistor R3. Also, once Q3 is conducting, the drain on the base of Q1 will increase as current flows to the cathode side of C1.
    2. Current will flow through diode D1, to put “pressure” on the base of Q2, thereby preventing further charging of C1 from the voltage source.
    3. Current will flow through light emitting diode D2, causing it to light up.
  3. Once C1 is fully drained, the base of Q1 will only drain through R1. If R1 has a high enough value, the output of the collector of Q1 will fall below the threshold to block the base of Q2. When that happens, current will once again flow through Q2, C1 will start charging again, Q1 will stop conducting, the LED will turn off, and we return to step 1.

So that was my theory. My next step was to build it, and figure out the right values for all the components. I breadboarded it like this:

Blinking LED Circuit

Voltage: +5
Q1: (PNP) 9015
Q2: (PNP) 9015
Q3: (NPN) PN2222
R1: 10KΩ
R2: 10KΩ
R3: 680Ω
R4: 68Ω
C1: 470µF
D1: 1N4148
D2: Blue, 3.7V, 20mA

That resulted in a flash rate of 1.3Hz. The blinking speed can be adjusted by changing the capacitor and/or changing the values of R1 and R2. I swapped C1 for a 22µF cap, and the flash rate increased dramatically, perhaps to something between 20 and 30Hz. So I swapped R1 and R2 for 100KΩ, and the flash rate returned to something around 1.6Hz. Ideally, the capacitor should be very small, since it is essentially charging, then dumping its charge in every cycle. I’d like to try to use a much smaller capacitor (with larger R1 and R2 values) to see if I can maintain enough current in that part of the circuit to control the functioning of the transistors. I used a blue, 3.7V LED on a 5V circuit. The LED can be changed, as long as R4 is changed as well to ensure the proper current for the LED’s voltage.

It’s not the simplest circuit of this sort, and I’m sure that I’ve screwed up at least part of the analysis. But as someone who only knows as much about circuit design as he could find on the internet, and a couple of books (namely, Getting Started in Electronics by Forrest Mims, and Starting Electronics by Keith Brindley), I was fairly pleased with myself for making this work.

knitting

Diamonds on the Mind

Download the pattern: Diamonds on the Mind PDF

When knitting, I like colorwork and I like hats. It should come as no surprise, then, that I doubly like colorwork hats.

This one has a hemmed brim, and a repeating, overlapping pattern that is made “jogless” by a bit of special trickery at the end of each round. The only special skill (aside from knit, purl, ssk, k2tog and basic stranding) that’s required is a provisional cast-on. Usually, before I begin a project with a provisional cast-on, I’ll look up a little refresher.

After you get past the provisional cast-on, you’ll knit the inside of the brim, do a perl round for the turn then knit the outside of the brim. To avoid sewing, at the top of the brim, you’ll pick up one of the provisionally cast-on stitches, and k2tog with a live stitch from the body—and repeat that all the way around.

The pattern calls for three yarns: a main color #1 (MC1), a main color #2 (MC2) that is in the same color family as MC1 and a contrast color (CC) that is white or off-white. If you are so inclined you can skip MC2, and just use MC1 for the entire hat. And, of course, if you go crazy and use something wild for the CC, small children won’t die.

Note that several people who have knit this pattern have said that it ends up too big. Between my propensity for knitting tight, and the lack of a forgiving ribbed brim, you would be well advised to pay attention to gauge, and perhaps use smaller needles or modify the pattern if you knit loosely.

Overall, it’s a fairly simple hat that, if I may say so myself, looks pretty nice. Enjoy!

Download the pattern: Diamonds on the Mind PDF

life

A Recovery

“You HAVE to go to a doctor!”

“Yeah, I guess.”

“Seriously… I’ll make an appointment for you. Your fever was 101 yesterday, and it’s 102 today. A 102 fever is a legitimate, doctor-worthy fever.”

“Alright.”

Martha was right. I needed to see a doctor. It had been several days since Highland Sky 40 Miler. Martha and I started the race together. After 10 miles, I was struggling to match her pace. After 20 miles, I told her that there was no way I could keep up with her, so she should go ahead. After 40 miles, I dragged my feet across the finish line, spent, as exhausted as I’ve been after 100 milers. And while I should have started to feel better in the following the race, my condition declined day by day as my fever rose. By Wednesday, I hit 102. I was able to get an appointment for Thursday afternoon.


“Are you going to be able to make it to your doctor’s appointment this afternoon? I think my mom can take you if you can’t drive yourself.”

“No, I can make it.” I was starting to feel better. I even considered cancelling the appointment. “I’ve been thinking, though… This illness… I’m not snotty or coughing, and my stomach feels fine. There’s no respiratory or gastrointestinal component. That’s sort of odd, right?”

“Yeah, it is,” she agreed.

I was looking for some validation for a wild theory. Since she is an infectious disease researcher, I could defer to her judgement. “I was thinking about the last few months. Remember a couple of weeks ago, when we did that long run? Remember how much I struggled? You could hardly run slow enough for me to keep up. All of our runs have been like that recently.”

“I don’t know why. It’s so weird!” It was a sentiment that she had expressed many times in the past, as I had found it harder and harder to keep up with her.

“And not just recently,” I continued. “The last few months have been really bad, but I’ve been struggling for longer than that. I really haven’t been able to run long for a couple years. Everything over an hour reduces me to a shuffle.”

“Right.”

“What if this fever is related to all of that? I mean, the obvious assumption is that I’m just sick because I was immunocompromised from the hard effort of the race last weekend. But what if I was sick before that? All of the difficulty and fatigue I’ve had over the last couple of years could be the real thing, and maybe this fever is just a new symptom.”

“That could be,” she agreed.

“So I looked at my race result, you know, for my entire race history — all the marathons and ultramarathon and everything over the last decade. Every year, I was getting faster and faster, winning and placing in more races every year through 2009. Then, I ran well in the Spring of 2010, and had a good race at Massanutten 100 Miler. I remember pulling a few ticks off of me at the end of the race. And I remember some other racers did the same. That was the turning point. After that, I had a couple of good races, but overall, that was a turning point. After the Spring of 2010, I was nowhere near the runner I was before then. Maybe I have Lyme disease, and it’s been progressing slowly over the last three years.” It made sense to me, but Lyme is a hypochondriac’s delight. It can present as a wide variety of symptoms; any sort of malaise or general achiness could be falsely flagged as Lyme. If Martha was skeptical, I’d drop it, and leave the diagnostics to the professionals.

“Hmm… That’s interesting… You should definitely ask the doctor to test you for Lyme.”


My fever broke an hour before the appointment. I arrived at the doctor’s office feeling like the trip and my concerns had all been wasted effort. Despite feeling like it was a long shot, I did request that the doctor test me for Lyme. She declined, dismissing my self-diagnosis with barely a second thought. As it seemed that I had made an abrupt recovery, there wasn’t much to do, other than send me on my way. I did try to get some conjecture about what sort of illness I might have had — what could have made me so sick, with no respiratory or gastrointestinal symptoms. I knew that aside from my own curiosity, Martha would be interested in a firm diagnosis. But the doctor was unable or unwilling to provide an answer. So drove myself home, where I promptly started shivering, and my temperature returned to 101.

The doctor called me the following day. “Hi, I know that you wanted a diagnosis. I was thinking about your case last night. I think I know what the problem was.”

“Great!” I was thoroughly sick once again, and I was happy that the doctor was giving me some attention. “What is it?”

“I think you are suffering from heat exhaustion from the race you did last weekend.”

“Heat exhaustion?”

“Yes,” she explained, “when you work very hard, you body’s ability to cool itself sometimes…”

“No, I know what heat exhaustion is. I’m just not sure that that’s the case. The weather during the race was fine. It was overcast, and in the 60s for the whole day.”

“That may be,” she continued, “but it was 40 miles. That’s an extremely long distance to run. Even on a cool days, it is a tremendous stress to your body.”

“I mean… You know… I know it sounds like a long way. But in the grand scheme of things… You know… The big picture… Like, I’ve done a lot of races that long. And longer! I don’t think that that’s anywhere near my limit.”

“What you need to remember, though, is that now you’re 36, not 16. I’m not saying that you’re ‘old’ by any means. However, you are at an age where perhaps you need to dial back your expectations of what you can do. People just aren’t made to run long distances like that.”

There was only one possible response. “Thank you,” I told her, “I’ll keep that in mind.” I needed to find a new doctor.


The next doctor was an infectious diseases specialist. Due to factors out of my control, it was a week before I was able to get an appointment. By then, my fever had mostly subsided (though on any day, I might be running a slight temperature). Unfortunately, an array of new symptoms started to present. I was extremely tired and occasionally dizzy, I developed severe skin sensitivity and I would drench the sheets with sweat every night. Martha wanted to come to the doctor with me. I was happy to have her as an advocate who could talk to the doctor with more authority than I could.

The infectious diseases doctor performed a routine examination, and ordered some standard blood work. He confidently declared that I would be better within a week. Martha pushed for a specific diagnosis. “Enterovirus,” he said. But Martha didn’t buy it. She tried to debate him, explaining why she didn’t think that was a likely diagnosis. She asked him to test for Lyme. We brought a copy of my race results in the hopes that we could quantify my decline. The doctor glanced through them, and declared that while my times are a little slower than they once were, I’m still faster than most people. “If you had Lyme, you wouldn’t be able to run a three hour marathon!” We tried to explain that a three hour marathon is a world away from the 2:35 marathons I had been running fairly regularly before 2010. Still, though, he refused. “It’s an enterovirus. You’ll feel better in a week.”

As we left the office, Martha ranted, “He doesn’t know! He has no idea! We’re supposed to respect the doctors, like they have all the answers. But he just felt your lymph nodes and made a guess! It’s… It’s… I’ll tell you what it is: It’s medieval! He might as well set some leeches on you! He might as well say that your humors are out of balance! We need to make an appointment with Dr. H!”

“You think we’ll get a different answer? I’m not sure it’s worth making an appointment with yet another doctor.”

“Dr. H will listen to you. You’ll need to be assertive, but he’ll listen.”


Dr. H was on vacation, so it was yet another week of fatigue and illness before I could get an appointment. At some point, I started tracking my symptoms. Each day was a different set of symptoms: fatigue, night sweats, rashes, skin sensitivity, dizziness, nausea, and most concerning, arrhythmia. Some days were better than others, but even on my best days, I was in a constant fog, napping several times a day to stay functional.

When the time for my appointment arrived, Martha briefed me on Dr. H. “You need to be assertive. He’ll listen to you, but you need to be assertive.”

“Assertive. Got it.” But I didn’t have it. I wasn’t entirely prepared for his line of questioning.

I happened to be having one of my better days when I saw him. He started the consultation by asking, “What symptoms of the illness you called about are you experiencing right now?”

“Right now? Right now I’m not experiencing any symptoms.”

“Okay, then what symptoms were you experiencing on the day that you called to make the appointment?”

“Well, on that day, I believe that I was a little bit fatigued, but I was generally alright.” I spoke from the perspective of someone who had spent the previous month waking up in the morning not knowing whether I would be able to get out of bed during the day, and grateful for the days when I felt relatively normal.

Dr. H, however, was approaching the problem systematically, with the assumption that I was a patient looking for a diagnosis of an illness that was proceeding in an arc of several days or weeks. Growing impatient, he sighed. “When you called to make the appointment, there was some reason, right?”

“Yes. Absolutely. Maybe I should just describe the situation from the beginning…”

“No, no, no,” he cut me off. “I think I know how to get the information I need. Let me ask you several questions, and we’ll figure this out.” He proceeded to ask me a series of questions that did allow me to describe the range of symptoms I had experienced in the preceding month. I described my progression from what seemed like a standard, febrile illness to one that involved a strange array of ever-shifting symptoms that might present or not on any given day. By the end of the interview, he had received a fairly thorough picture of the month since I first started experiencing acute symptoms. “So,” he was ready to conclude, “at this point your primary symptom is the extreme fatigue you described. You are starting to feel better than you have, but you want to know of there is any treatment that can help your recovery. Is that a fair statement of the problem?”

I took the opportunity to respond to the first open-ended question he had posed. “No! The real problem is that for the past decade I’ve been a fast, competitive long distance runner. I was getting faster and faster every year until the Spring of 2010. I had several good races in the Spring of that year, then I did a long trail race. At the end of the race, I pulled several ticks off of me. I thought I got all of them, but ever since then, I’ve been struggling with my running. My race standings dropped precipitously. I’ve been getting slower and slower. By this summer, every run would leave me exhausted. It was only due to this past month of severe, acute illness that I finally took a look at the larger picture to put everything together. I think I got Lyme disease at that race in 2010. I want you to test me for it.” It had all come out in a single breath, blurted without a pause or break.

Dr. H paused for a moment, in case I had any more to say. “Well why didn’t you tell me that earlier? We’ll test you for Lyme and babesiosis, for Epstein-Barr and Cytomegalovirus…” He probably listed a few others, but I don’t recall what they were.


A week later, the doctor’s office called. “Your test results came back. Everything was negative except for the Lyme test. Dr. H wants to start you on three weeks of doxycycline as soon as possible.” (In a follow-up visit with Dr. H a few weeks later, he insisted on showing me my lab results. He assured me that while the raw results aren’t of interest to most patients — they require a bit of interpretation — mine were noteworthy because they, “lit up like a Christmas tree.” Apparently, according to the test, I was as clearly and thoroughly infected as someone could be.)

Many people who receive delayed treatment for Lyme experience prolonged or chronic symptoms. I was tremendously fortunate in that the antibiotics had an immediate effect. Within two days, the acute symptoms had disappeared. Within 10 days, I was feeling better than I had in at least a year. Within a month, I was an entirely new person.

By the Spring of 2013, before my symptoms had become acute, I had come to accept that I could no longer run competitively, that at the end of the work day I would only have the energy to make it to the couch to collapse with exhaustion, that every morning, no matter how much sleep I got the night before, I would wake up dizzy and exhausted and never feel fully rested. Over three years, I had aged three decades. The process was so steady and gradual that I never quite noticed it. Then I took three weeks of antibiotics, and then another three weeks (which I requested after hearing the consensus among many long-term Lyme sufferers that three weeks is not enough), and in the following three months — from the middle of August to the middle of November, I gained back those three decades.

As I write this, in the first few days of 2014, I’m excited about the future. If there are lingering effects of the Lyme, they are small. I have run one race post-Lyme — a 100km race I run every year. I felt better at mile 60 this year than I felt at mile 10 last year. Looking back, it’s hard to believe I dragged myself through that distance last year in the state I was in. I haven’t yet regained all the fitness I lost, but I’m on my way. And now that I’m healthy again, everything feels just so much easier.