Okanagan Marathon

I ran the Okanagan Marathon in Kelowna last weekend… with a time of 2:56:23 which finally puts me under the 3 hour mark. It was an interesting race, in that I was as strong as the the top runners, and actually had a chance of winning. But although I was in second place for most of it, I ended in seventh, and I can chalk that up to a lack of experience rather than a lack of training. In other words, I made a whole bunch of rookie mistakes (even though this was my third marathon!)

First mistake: not having a clear goal. My goal was to run better than 2:50, ideally somewhere around 2:40. While 2:50 was a reasonable goal, 2:40 was not.

Second mistake: starting too fast. I was eager to establish my position, so I grabbed the 2nd position and stayed well ahead of 3rd. It would have made more sense to run beside the 3rd place runner, especially since he had a GPS. Instead, I wore myself out in the first half. In particular I felt a nice little kick of adrenaline at the half and sped up for a bit, but suffered a slow-down soon afterwards.

Fourth mistake: not drinking enough. I missed two water stations that were overcrowded by people coming the other way, but it was a cool, rainy day and I should have had enough water in reserve… if I had been drinking enough before I missed those stations! Gotta grab two cups per station just in case, especially since the cups are often half-full.

In the end, it was the runner who was 6th at the halfway point who won the race. He had a very impressive negative split, running the 2nd half two minutes faster than the first half. The runner in first at the halfway point ended in 5th. So indeed, winning the race is all about having a strong second half.

Training for Kelowna

I've scheduled one more marathon before the winter hits: Kelowna on Oct 9. This will be a real test for me, since it is my last chance this year to finish in under 3hrs. It also marks a new phase in my training; my speedy recovery after the Edmonton marathon encouraged me to attempt 40km+ distances on my Sunday runs. Last weekend I ran the full 42km distance, and suffered nothing worse than sore calf muscles. This morning I ran 46km, next week I'm shooting for 50km. Amazingly, my joints haven't been complaining at all, so I'll knock on wood and hope that they don't start. The purpose of these runs is to avoid the slow-down that hit me at the 30km mark in my previous two marathons. I have to make my body understand that it is capable of sticking to my race pace for the full 42km.

Today was the Terry Fox Run, so I had plenty of company during the downtown portion of my run. It was nice to see all those smiling faces, and to be reminded that running is not just about competition. It's also about inspiration. Terry Fox is not a hero because he ran 40+km per day for months on end — and on just one leg — regardless of how amazing that feat was. He is a hero because he inspired hundreds of millions of people. He taught us that if we are audacious enough, and persistent enough, that anything is possible.

One other short addition to my post: I was saddened to read on Ellie Greenwood's blog that she DNF'd at the world 100km championships, due to an upset stomach. Her blog is a real inspiration to me, it amazes me that one of the best ultrarunners in the world is in my own backyard (Banff) — she won last year's 100km world championship and has also won many other races at 100km, 125km, and even 100 miles. Without people like Ellie, I wouldn't even consider attempting a 50km run.

Abstract interpolator interface

Ten years ago I wrote a filter for VTK called vtkImageReslice. Its purpose was simple: to resample an image volume through a 4×4 matrix transformation using interpolation. For my PhD work I also required deformable transformations, so I coded some. In order to connect these to my vtkImageReslice class, I included a vtkAbstractTransform class that described an abstract interface for a coordinate transformation operations in VTK. This work was sufficiently well-developed that I managed to publish a paper on it.

The interpolation code was not as well-developed, it was tightly integrated into vtkImageReslice and not modular at all. It did its job, certainly, and very efficiently, but as I added more interpolators the size of vtkImageReslice gradually expanded to over 5000 lines of source code, code that was becoming increasingly difficult to manage. I have finally completed a long overdue project that saw the creation of a vtkAbstractImageInterpolator class, providing an abstract interpolation interface and allowing me to move all the interpolation code from vtkImageReslice into several tidy little classes.

So far I provide two concrete interpolators. The first is a basic, default interpolator that provides nearest-neighbor, linear and cubic interpolation. The second is a sinc interpolator that provides high-quality interpolation and optionally performs antialiasing. Soon, I hope to also add some b-spline interpolation code that I have lying around. More information can be found at the VTK wiki page that I wrote for these classes: http://www.vtk.org/Wiki/VTK/Image_Interpolators.

First win!

Last weekend I returned to my home town of Prince George and participated in the 17-mile Labour Day Classic, a small local run that is as old as I am. Going into it I knew that there was a chance that I could win, and win I did! For the first half, I kept to a fast but comfortable pace of just under 4:00 min/km and took the lead early on. For the second half, my goal was just to keep my lead. I slowed down just a bit because my legs were getting tired, but just two miles before the finish I heard some rapid footfalls coming up behind me and had to build up my speed until they gradually faded away. I finished with a 17 second lead at 1:50:20.

The real winner, as far as I am concerned, was Brian Nemethy who ran the 8.5 mile race in 51:05. That time is impressive, yes, and even more so when you consider that 51 minutes means a speed of 10 miles per hour. He must have set that pace for himself, I'm sure that in his mind he wasn't racing against anyone else. I'm only able to keep that pace for half that distance, and he's my senior by more than a decade.

On my way back to Calgary, I stopped at Mt. Robson Provincial Park to do a trail run to the far end of Kinney Lake and back again. This was a necessary break to stretch my legs, which do not particularly like long drives after a hard run. Running through the forest is absolutely the best kind of running. I really should add trail races to my schedule, so far I haven't participated in any because it is necessary to register for them so far in advance (they always have strict caps, and they are insanely popular around here).

This particular trail run at Mt Robson had a huge payoff. I usually feel best running at my 4:00 pace, and on this day running slower than that aggravated my knee a bit (after all, I had just raced 17 miles the day before). So I wondered, what was the difference between running fast and running slow? I must be landing differently if my knee reacts differently. I tried a little experiment, and landed with my foot a little bit behind its usual landing position — suddenly the twinge in my knee disappeared. Now I know how to run at any pace, slow or fast, without straining my joints! The experts always say that a toe landing is ideal, but in truth that advice is such a gross simplification of running mechanics that, on its own, it is nearly useless. My advice is to run for a couple years, listen to your legs, and experiment a little bit. When you find your perfect footstrike, you will feel it. Then change your pace and find it again. Change the terrain and find it yet again. Try it again with an old, worn-out pair of shoes. Uphill and downhill. You see where I'm going with this? My heavens, thinking about it makes me want to go for a run right now…

Running without injury

So far I have been very lucky: I have been running for two and a half years, and have never suffered a serious injury. As a runner, a serious injury would be one that keeps me from running, anything that does not keep me from running is minor. In the "minor" category I have suffered from mild shin splints, a pulled calf muscle, and iliotibial band inflammation, all during my first year. Since then, the worst that I have had to suffer through are minor aches and pains, i.e. soreness in the muscles and joints that goes away on its own with a bit of ice to help it along.

Why have I been so lucky? Clearly my low weight (160lb) is a major factor (three years ago I was over 180lb, and in case you are wondering, running is not what caused me to lose weight, the not-so-big secret was eating less). Shoes are a help, my early bout of shin splints was undoubtedly because I started out running with an old pair of well-worn cross trainers that weren't up to the job. But still, there are lots of low-weight runners out there with decent shoes who injure themselves. Am I just lucky?

No, it isn't just luck. I think that I am a better runner than most. A lot of that has to do with the fact that while I am running, I am thinking about running. I prefer to run alone, it allows me to concentrate on what my legs are doing. How do they feel? If I lengthen my stride a bit, do they feel better? Am I still in the warmup stage? Am I ready to cut loose and push hard? Do I have any minor aches that I can reduce by adjusting my gait?

I believe that my biggest improvement in running came when I had iliotibial syndrome a year and a half ago. This syndrome results from an inflamed tendon at the side of the knee, it is not especially serious but it can be painful. Since it is the kind of problem that a person can generally run through (unlike, say, shin splints), that is what I did in addition to some stretching and strength exercises. I experimented a lot with adjusting my takeoff and landing, this was all with a very cheap pair of runners that didn't fit very well and provided poor support. Eventually I could run virtually pain-free, even though going up or down stairs, and even ordinary walking, were painful.

The three tools in my "recovery kit" are cold water/ice, short runs (2 to 4km) followed by stretching, and concentration while running. The first two are excellent ways to relieve soreness, the latter is to ensure that I do not aggravate any inflammation or overly strain my muscles and joints. Paradoxically, the thing that I have to concentrate on most is staying relaxed. My legs know what to do, and while I'm running my main job is to listen to them.

Edmonton Marathon: Three PBs in one day

It turns out that I can't attend the Mad Moose Marathon because of a conference that weekend. So I decided to run the Edmonton Derby Marathon instead. It's a lovely course, almost perfectly flat, and I definitely want to do it again.

At this point in the season, I have been training continuously for seven months. So I shouldn't be surprised that my times keep getting better. But my performance during this race was beyond my expectations: on my way to getting a personal marathon best (3hr 2min), I also ran a personal best in the first 10k (38 min) and the first 21.1k (1hr 22min). My average pace up to the 30k mark was 4:00 min per km, something that I had not known I was capable of. In the end, however, the mileage and the heat (25 degrees C) caught up to me and I had to slow down. Still, I managed to finish in just over 3 hrs!

Heat is definitely an issue for me. For the last 10k of the race, I was getting goosebumps and shivers, definitely not a good sign on a warm and sunny day. After the race I could only eat half of the free lunch, and ten minutes later, I tossed that half down the toilet. Like all my little bouts of heat sickness, I was feeling right as rain a couple hours later. The puking is new, though: I haven't done that in a long time!

So, I need to do more afternoon runs in my training. My usual morning runs do not exercise my cooling systems hard enough. If I can find a way to beat the heat, then it is altogether possible that I could knock another ten minutes off of my marathon time.

Today was a scorcher, glad I’m in Alberta

The high was 29C today, and even though I finished my run before it reached that high, it was still painful. Right now I'm working on marathon distances for my Sunday runs, and today's was 39km. After it was over I had to crawl into bed for an hour before my stomach settled enough for me to have lunch, similar to last year when I first started doing long runs in July and August. I can definitely say that I'm glad to live in a city that rarely sees temperatures like this. Or maybe it's the opposite: if I lived somewhere warmer, I might have a chance to adapt.

Stampede Road Race Number 2

My second time at the Stampede Road Race! I love this race, it is small enough to feel comfortable (just 1500 participants), but large enough to be competitive. And both years, the weather has been beautiful!

This year, I did the half-marathon. My time was 1:24:50, a personal best by just over a minute. As always, I was hoping for better, but I can't say that I'm dissatisfied, either. I managed to stick to a 4 min/km pace throughout, and still had enough in me to do a sprint at the finish line.

The next race will probably be the Mad Moose Marathon, which is a 42 km trail run. It's about time that I gave my legs a break by running on dirt instead of asphalt.

New image display classes for VTK

Finally, I've finished a big and rather important project that I started in December (though I was interrupted a few times): a complete re-write of the image display classes for VTK. In brief, these classes replace vtkImageActor and provide a much higher level of functionality. Whereas image display used to be a clunky add-on feature in VTK, it is now a central feature just like geometry and volume display.

The main additions are three new classes:

  • vtkImageSlice – the new actor class for images
  • vtkImageResliceMapper – mapper for drawing images for MPR viewers
  • vtkImageProperty – for controlling lookup tables, window/level, opacity, etc

These are meant to mirror the vtkActor, vtkMapper, and vtkProperty classes used for geometry. The vtkImageSlice and vtkImageProperty classes are very simple, they are just information containers: the vtkImageSlice controls the position and orientation of the data with respect to the world coordinate system, and vtkImageProperty controls the color table, interpolation, and other display-related properties. The vtkImageResliceMapper (and its associated classes vtkImageMapper3D, vtkImageSliceMapper, and vtkOpenGLImageSliceMapper) are where all the work gets done.

My primary goal was to simplify user interaction with the image display, and I decided that the easiest way to do this, since most VTK interaction occurs via the scene "camera", was to make the camera control both the position and orientation of the slice that is displayed, via the camera focal point and view point. This turned out to be a very intuitive way of doing things, and also allowed the VTK interactor classes to be used for image viewing with very little modification.

A brief run-down of the features:

  1. oblique views (obviously!)
  2. nearest-neighbor, linear, and cubic interpolation
  3. easy modification of image transformation via prop's UserTransform
  4. fully multi-threaded reslicing and color mapping operations
  5. streaming, i.e. only pulls the data needed for rendering
  6. works well with very large images (as long as they fit in memory)
  7. LOD-style interaction (switches to faster rendering for interaction)
  8. blend images by adding multiple vtkImageSlice objects to a vtkImageStack
  9. checkerboard images for easy comparison after registration
  10. thick-slab views (see vtkImageResliceMapper for details)
  11. works with vtkCellPicker for picking image voxels as points or cells

For large image viewing, on a 4GB computer (64-bit OS X) I’ve displayed images up to 3GB in size with full interactivity, but YMMV. As long as the mapper’s ResampleToScreenPixels option is On, the mapper will never try to load the full image onto the GPU (which is what causes the vtkImageActor to be slow for large images). The size of the images that you can display is limited only by main memory, I have displayed stacks of RGB images that are 10000×10000 pixels in size.

Template wrapping

Finally, I've achieved one of my long-term goals for the VTK python wrappers: automatic wrapping of templated types! And if I had know how much work it would entail, I probably never would have started, but still, I'm glad that I did it.

The first part, parsing the templates from the C++ header files, is something that I did about a year ago. Templates are one thing that my own parser handles very differently from gccxml. Whereas gccxml spits out information only for the templates that are instantiated in the code, my parser spits out descriptions of the generic templates prior to instantiation. So the biggest part of my current project was creating subroutines that could take the info about generic templates, and generate info for instantiated templates that could then be wrapped. A big advantage of doing things this way is that the wrappers can produce any instantiations that are desired, whether or not they appeared in the original header files. Another advantage is that my wrappers can provide documentation for both the generic and the instantiated class templates.

In python, the templates are a class generator of sorts. They look kind of like a class, and kind of like a dict. They are used as follows:

v = vtkVector[float,3]([1.0, 2.5, 10.2])

The template args are provided in square brackets. Given the template args, the template "vtkVector" instantiates the template to produce a class. The class is then given arguments in parentheses, which it uses to construct an object. Other than the use of square brackets instead of angle brackets, the main difference from C++ template instantiation is that only a limited selection of template args are supported. Calling help( ) on the template will list all the available args.