Mount Rose

Had a nice hike partway up Mount Rose today, and snapped a few shots along the way.  Enjoy!

Root system

Five+ Lakes

Sanjiva and I spent a couple of days last weekend knocking around the Five Lakes Basin near Yuba Gap in the northern Sierra Nevada mountains.  Photoset here.  Primary goal was to test our equipment and techniques for potentially more strenuous adventures.  Crooked Lakes Basin is a high-reward area, with most trails having a lakes per mile ratio of greater than one.

TridentWe started off however quickly traversing the Crooked Lakes Basin and Sand Ridge on our way to the Five Lakes Basin that lies beyond – new territory for me.  We had great views of Downey Lake and the terrain between the Grouse Ridge Lookout and Lake Spaulding.  The mule ears were prolific and covered the exposed hillsides with yellow.

We cooled off at the first of the Five Lakes, and continued up the trail towards the granite cliffs hoping to find more of the Five at the base – but it turned out the pristine lake wasn’t one of the Five and was named Glacier Lake.  Although there were a few parties camped around the lake, the prospect of watching night fall over the lake and the Black Buttes beyond was too tempting and we also pitched camp there.

Glacier Lake in the morning

The rising sun found us climbing the ridge and scaling the Black Buttes, from which we had some amazing panoramic views, and a look into the basin on the south side, including Beyers Lakes and Baltimore Lake. Looks like another cool place to explore.  Here’s a map.

ClimbingBetween the climbing the mountain, traversing scree and snow fields, and some short stretches of vertical, I hope Sanjiva got a good sense of the joys and challenges of being off-trail.

Sanjiva the trekkerAfter a long descent, with a bit of boot skiing, we had breakfast and broke camp, heading cross country back towards the Five Lakes Basin, and skirting the cliffs looking for more alpine lakes.  Near the lakes we encountered more streams, waterfalls, and meadows, and followed them down past several of the Five Lakes before retracing our path along Sand Ridge and cutting cross country once more through the Crooked Lakes basin to my favorite one.  We camped on top of the rock outcropping – the “eagle’s nest”, warmed ourselves by a tiny fire and watched the satellites and shooting stars before turning in again.

The morning brought a quick hike out and home so Sanjiva could catch his flight back to Sri Lanka. All in all an excellent trip – about 15 miles almost half of which was strenuous cross country work.  Within that short span we saw a microcosm of the Sierra high country and discovered that even this remote edge of the Sierra holds many charms.

Rural Life: Bears & Bobcats, oh my.

Bear and cubsI hardly can leave home without seeing a deer, or a turkey, or a crowd of the other critters that inhabit our bit of wilderness – fox, bobcat, skunk, coyote, possum, raccoon.  But although my neighbors see the occasional bear I’ve never seen one till our return from school this afternoon.  Momma and her three cuddly cubs hastily scooted up a tree and we were able to inch close enough to get a decent snapshot from the wide angle iPhone camera.

Another advantage of the Prius – it’s a good car for Bobcatstalking wildlife when on battery power. I practically ran over a red-tailed hawk devouring a woodpecker in the middle of the road the other day; only rolling down the window and sticking the iPhone out for a snap excited him enough to take his lunch elsewhere.

While I’m at it I don’t think I ever posted my pic of the small bobcat that peeked in through a window at me before enjoying some r&r poolside a couple of months ago.

Sri Pada: Stairway to the Heavens

[Photoset here.]

Our adventure started as all adventures do in Sri Lanka, with a long drive on progressively smaller roads.  Until the roads give out completely. Sights spin by at a Three elephants on a truckbreakneck speed - elephants on a flatbed, chaotic towns and open-air markets, lazy cattle wandering free – too fast to comprehend let alone photograph well.  At a couple of points the ride was so steep and bumpy that the rear hatch of the van failed and a couple of packs tumbled into the road to the alarm quickly turning to amusement of all.

The end of the road in this case was the tiny village of Palabathgala, near Ratnapura, and the eleven of us, plus guide, were deposited at the bottom of a staircase into the rain forest, leading up up and up into a misty escarpment. Already the grey skies were dripping on us.

StairsThis is the long way up to Adams Peak and the temple of Sri Pada, a pilgrimage popular I suspect not only because it is said to have Buddha’s footprint, but because it’s just so dang hard to get to. Our path starts with unremitting steps up into the forest. Every hundred the count is etched into the concrete - 1000, 2300, 3900. The humidity is intense and I adopt an old man pace to keep from overheating. Stair #4000Step, breath, step, breath. It works pretty well and although I’m towards the back of the pack my heart rate stays low and my legs still feel strong. However my strategy for keeping dry fails. Not only am I drenched in my own sweat, buy when a drizzle starts I throw my windbreaker over my head and drape it over my pack, leaving my arms cool. But any moisture on the pack quickly transfers to the inside of my windbreaker, and mixing with my copious body moisture my windbreaker is quickly thoroughly soaked inside and out.

Monsoon downpourAfter an hour or two, we arrive at a small army base just as a monsoon downpour starts, and take brief refuge as it turns our stairway into a temporary torrential waterfall and then disappears just as quickly as it came.

"Stairs"Finally somewhere near step number 5000, the cement ends and the original rock steps begin. Still unremitting, but somehow the uneven steps are easier to navigate. Maybe it’s because you have more choices than a fixed stairway provides.  Or maybe it just occupies your mind more.

After hours of this we reach a rocky river, spanned by a spiderweb of white threads. It is apparently a custom for new visitors, to weave a thread into the web. All of us newbies partake in this custom (photo courtesy of Udeshika). This is a good spot for lunch and we break out out lunch packets - rice, curry, cal, sambol, all wrapped in plastic and then newspaper - a traditional lunch favorite here.

Then hours more of stairs, as we climb right up into the clouds. The temperature drops to a pleasantly chilly range, but the humidity remains so high everything remains soaked. At last we reach a few nondescript buildings, vendor shacks deserted now on the off season, and dry out a little.

We engage the sole visible resident for some hot water and relish in a hot beverage as only the perpetually wet and cold can.

In the cloudsWe’ve been climbing stairs straight for about 5 hours now, and I am rather surprised that this village represents not the end, but the official start of the Adams Peak Climb! Three more hours to go and it’s already after 4PM when we leave. I stride out, glad to have saved my strength for this part. But it’s not long before I’m taking a short rest after every 20th step, then every 5th, and then at times after each one. After approx 20,000 steps (a nearly 2000m climb), I’m in summiting mode - don’t think about the rest of the trail, think about the next step.

Tired?This section again has concrete steps, and even rails begin to appear, as the stair grade gradually increases from 40 degrees up to 70. The wind is whipping the clouds against the mountain, and although the wind is fairly dry, as we ascend the wind strengthens and blasts us with more and more rain. The vegetation has changed from jungle to cloud forest, eerie twisted shapes draped with moss in the blowing mist. Sometimes Adams Peak is above the cloud layer and while my hopes were never strong that we might emerge into sunshine, it became clear that the summit was being blasted by 40-50 mph winds. We climbed, clinging to the rail, as the stairs wound between granite outcroppings and sheer cliffs whose true extent remained hidden in the mist.

Sri Pada in the cloudAt last a structure emerged from the mist at the top of the near- vertical ascent and as the wind tried one last time to part us, or at least any gear not tied firmly down, from the mountain, we entered an alleyway between two buildings. A man emerged from a tiny cell and showed us to a small cold monastic cell where we could spend the night. A change of dry clothes raised everyone’s spirits and shortly we all moved up into the caretaker’s cell to squeeze onto his bunkbeds, drink another round of hot tea, and chatter away with him animatedly in Singhalese. I just sipped happily as the singsong swirled around the warm cell and mixed with my exhausted daze.

Now we’ve had our dinner packets - despite being tasty my post-extreme appetite is small and I can’t do much more than sample. With another round of animated chatter we laid mats in our cell and have lined up like sleepy sardines to await the morning.

Monastic life[Morning]

Well, that night felt like Survivor – with each person having a share of the floor approximately two feet by five, cramping legs, whistling wind and rain, chilly enough to cause shivering, bumping into each other as you turn, occasional snores, and someone scraping through the door to use the bathroom every 45 minutes or so.  I listened to music on my iPhone almost all night, but dozed off a few times for a total of maybe two hours of sleep.  The whole experience felt like something from a 19th century Himalayan explorer’s tale.

The traditional climax of a Sri Pada trip – viewing the sunrise – fell victim to the continued mist and increasing rain.  But after some bread and jam for breakfast we visited the temple.  My preparation for the elements – a complete poncho over clothes and pack – disintegrated in seconds in the howling wind – but I dutifully rang the bell once representing my first visit, and fled.

SwitchbacksGuess what came next?  Yes!  More stairs!  We took a different (shorter) route down, leading us down the other side of the mountain.  After coming off of the peak and emerging from the cloud, the steps moderated into a broad trail, and we followed a narrow valley filled with manicured hedgerows of tea.  Dozens of waterfalls sprang from the escarpment, and the rain started to ease at times to provide us broader views.  At last we returned to motorized civilization at the village of Nallathanniya, had another hot syrupy tea.

Waterfalls & TeaAnd as all Sri Lankan adventures ended, so did this.  Hours of the most jolting, harrowing driving on narrow, steep, windy roads, leading us inexorably back to Colombo, a shower, dinner, and late that night to the airport, and eventually home.

Dropping into Hong Kong

If you happen to find yourself travelling half way around the world, and have a few extra hours to burn in the middle, what could be nicer than Hong Kong?  The landscape is conveniently compressed into a vertical form that makes it photogenic and easy to get around.

Dry goodsI landed at around 7AM from SFO and the express train deposited me in central Hong Kong shortly after 8. While my mission was to find something local to eat, I decided first to visit the small market area and see if it was buzzing early.  It was, with seafood, butcher, grocers, eateries, and more packed into alleyways covering a few blocks of the neighborhood.  I wandered around admiring some of the exotic offerings, but the stifling heat and humidity combined with the steep streets to put me into an overheated state pretty quickly.  I made my way back down towards downtown and lost my bearings for a remarkably long time in a maze of air-conditioned upscale shopping malls.  By the time I found myself I was cooled off and decided a ferry ride was more sensible in the heat.

Opera houseI travelled the short hop across the harbor to Kowloon and investigated another air-conditioned attraction – the Hong Kong Museum of Art.  Three progressively more exciting exhibits – pottery antiquities, showing the gradual refinement from Neolithic pots to Ming dynasty vases.  Amazing to see a pitcher thousands of years old with a form that modern Italian designers would envy, and how the conventions, techniques, and designs subsequently developed in many cases only detract.

Next was an exhibit of painted scrolls, which although ancient capture an expressionism and spontaneity that the European tradition took centuries to reach.  And the juxtaposition of text and image seemed quite trendy!

The final exhibition was contemporary paintings – all of similar aesthetic to the ancient scrolls, but with modern subjects, colors, and compositions.  Although some came across as fairly flat and cartoony, there were quite a number of amazing pieces from both the point of graphical composition and expressionistic brush artistry.  Well worth the visit!

There is a street under all those signsI hopped a ferry back across to downtown and made my way up the series of outdoor escalators that helps bride the downtown to the trendy SoHo neighborhood.  Searching among the dozens of trendy looking eateries featuring cuisines from all over the world, I finally found a simple Chinese eatery, packed with locals, and with very little Arabic lettering in evidence.

Dim SumI was placed across a tiny table from a man just finishing his meal, and ordered a few items from the minimal English menu they provided – steamed pork buns, squid and garlic, steamed spareribs with black bean sauce.  Solid but simple choices.

Then back to the train, quickly to the airport by about 3PM to await my final flight leg to Sri Lanka.  A report of my adventures there coming soon!

Full Flickr set here.

Our own backyard

Waterfall and fernsSanjiva and I went on a hike yesterday, from the confluence to home, and despite this being my own backyard, we discovered some new things – especially doing some cross-country and bouldering around the abandoned Auburn Dam footings and the newly restored river and kayak park at the former China Bar Rapids.  And after the rain of the past couple of weeks there are quite a few full-fledged waterfalls along the route.  Very cool!

Flickr set here.

Weekly Chatter: “Genetic” renderings

A couple of weeks ago I ran across a fun little program that evolves to recreate an image out of overlapping transparent algorithms.  Although not IMO really genetic, it mutates it’s “DNA” over many generations to reproduce a source image.  I’m still having fun with it, trying to figure out if it could be adapted to glass.  Here are a couple of samples:

Orchid

OldCarGen

 

Orchids 7     CIMG0809

Check out Roger’s gallery too.

Photo Backlog – Donner Peak Hike

Rock slices

It’s been a busy fall – not much time for taking pictures.  Or uploading them promptly!  Now that we’re in vacation mode, I’m looking through some of this falls photos.  Here’s a small set from a hike with family members up to Donner Peak in early September.  Some amazing rock formations…

Layers

 

Loch Leven Lakes

Cross countryJust posted a few snapshots from a Saturday day hike to Loch Leven Lakes, a wonderful and fairly accessible bit of the High Sierras.  Haven’t been there in a while, despite it being a fantastic place for some bouldering with the kids.  It was good to get above California’s persistent smoky haze for a few hours (though later in the afternoon even the high country took on a smoky hue.)

Happy Independence Day

CIMG3510Wishing everyone a last minute happy 4th of July, and for those of you who missed fireworks this year, here’s a couple of photos to hold you till next year.  Full Flickr set here.

CIMG3521

Tamales bay, sky views

Pulled upHad a great though brief visit from Paul, during which we toodled around the north end of Tamales Bay, bordering the Point Reyes National Seashore, the site of one of our successful backpacking trip a couple of years ago.  My primary goal, the Drake Estero, was closed for Harbor Seal pupping season, but we had good fun anyway.  Flickr set here.

Circuit Board?Also uploaded and organized some existing shots from plane windows.  Looking out the window is by far the best part of flying!  Flickr set here.

Christmas in Singapore

See the photos here.

We had a great time exploring Singapore over the last few days.  Here are just a few of the highlights:

  • Raffle's Landing spotArriving at the hotel well after midnight and reuniting with our German friends as we were checking in.
  • The Shangri-La hotel breakfast buffet.  Each morning we power up for the day with a buffet the includes a build-your-own noodle soup section, Indian fare, dim sum, Japanese and Korean fare, fruits and pastries in abundance in addition to the full western buffet.  Three plates each usually fattens us up enough to skip lunch, not to mention discourage an early dinner, but not enough to taste everything that looks delicious.
  • Double-decker hop-on-hop-off bus tour of central Singapore, introducing us to the city, a mix of colonial buildings, traditional two-story storefronts with upper-story shutters in a rainbow of colors, and glass and steel skyscrapers.  Laced through with impeccably maintained greenery.  I didn’t expect Singapore to feel so spacious and gracious.  It doesn’t have that intensely urban feel like Hong Kong or New York.
  • ShuttersWandering through Little India, a maze of shops and eateries heady with burning incense.
  • Dinner at the home of a colleague of our friends, getting a picture of home life and how east meets west.
  • Trawling the many malls on Orchard Road.  A little of that goes a long way for me, unless followed by…
  • A daily afternoon dip in the pool, before, during or after the brief but sometimes heavy daily rainstorm.  An hour with a good book under a beach umbrella, listening to children in the pool or the patter of rain just beyond the shelter.
  • The Night Safari - a cross between a zoo and a wild animal park, but in a dark and rain-glistening tropical jungle lit by a full moon and artistically placed lighting not much brighter than the moon itself.  Never though have I seen such an active and alert a collection of animals - Malaysian tigers, jackals, tapirs, capybaras, elephants, barbarosas (a lumpy wild pig with upturned tusks sticking right through the roof of it’s snout), giant anteaters, sloth bears, bat-eared foxes, giraffes, hippos, water buffalo, antelope…
  • Boat QuayA boat loop on the Singapore river, starting at Boat Quay, a quaint strip of eateries tucked up next to the polished spires of the financial district.
  • Chinatown - a section of quaint and colorful storefronts and street vendors - though very few hawking cheap Chinese merchandise.  For some reason Indian trinkets dominate.  The Hindu temple is festooned with a layer cake of blue characters and a menagerie of animals, and the courtyard walls are topped with images of lounging sacred white cows.
  • Christmas serenadeMeeting with our friends in the vaulted lobby for Christmas eve present sharing, at the foot of a 30 foot tree, as a live choir performs intricately harmonized Christmas songs nearby.
  • A new iPod touch ;-).
  • Indochine, a trendy southeast Asian eatery housed in a wing of the Singapore Asian Civilization Museum on the waterfront looking towards Boat Quay and the financial district, provided the perfect Christmas Eve dinner venue.  My top choices - a beef and prawn salad, steamed cod in lemon sauce, green mussels in coconut curry, lemongrass creme brule, mango and sticky rice.  Wow!
  • The Singapore Art Museum, housed in a colonial former school, boasts an interesting collection of Asian contemporary art, some of which seems rather primitive to me, others quite sophisticated.
  • Orchids 4Perfectly manicured botanical gardens brimming with more kinds of palm tree than you had ever imagined existed.  The fantastic orchid garden.  My favorite specimen is the spindly and bizarrely twisting brownish-purple "Margaret Thatcher".
  • Club Chinois on Orchard Road for Christmas dinner - upscale, trendy, light oriental.  Featured scallops on a slab of silken tofu, fois gras on crispy duck skin, chicken drumstick on a Chinese sweet radish salsa, minced 5-spice chicken on a disk of silken tofu, cod braised in a clay pot with baby bok choy, and cubes of tenderloin stir-fired with ginger and green onion in a crispy noodle basket.  Chased down with apple pie, chocolate lava, peanut-encrusted rice balls filled with bean paste with a honey-ginseng tea, and a warm creamy almond "soup" in a new coconut shell.  One of the best dinners ever!
  • Angels 2Strolling through Christmas street party on Orchard Drive, with elaborate lights and decorations, bizarre floats (my favorite - the jumbo sliced pannatone loaf with fern-like shoots springing from its top and dotted with bread loaves in case you didn’t get the "Jesus is the bread of life" theme), a concert.  But mostly filled with shutterbugs milling around.  At any one time, 1/3 were taking photos, 1/3 were posing for photos, and 1/3 were waiting to take a photo or pose in one.  I’m not exaggerating!
  • Sentosa CableTaking a cable car to Mount Haber (only a 100 meters high or so), and back down to Sentosa Island, which is gradually turning from a beach resort and golf course into an island-sized theme park.  We caught a computer-rendered 3D chair-hurtling "log ride" down a mountain.  Then strolled through Undersea World which held a number of interesting specimens such as the tiny red hearted but otherwise translucent sea angels, giant Japanese Spider crabs, and a long underwater tunnel where we could watch scuba divers feeding the manta rays and hordes of other fish.  Even a dugong.
  • The Pink Dolphin show in the lagoon - standard fare with tricks and petting from volunteers.  With quite a jostling crowd and corny tourist patter, it was remarkable only in that we actually saw the pink dolphins.
  • Dinner at The Banana Leaf Apolo in Little India, where dinner is served on a banana leaf mat that acts both as a placemat and plate.  Gen was the only one who ate the whole meal of samosas, Tandoori chicken, chicken tikka masala, paneer in a creamy tumeric sauce, and a paneer/potato kofta in saag.  Chased down with mugs of limeade.

Mashing up a National Geographic Photo of the Day Feed

(This article first appeared a few days ago on the WSO2 Oxygen Tank.)

I recently wrote a neat little mashup which demonstrates a little of the power of the WSO2 Mashup Server to flow information from one place to another, and from one format to another.  I had a simple set of requirements:

  1. I use the Google Photos Screensaver to show a slideshow of interesting photographs when the family-room computer isn’t being used.  Since the family room computer includes the 37-inch LCD screen as a separate monitor, high quality photos come out really clear and make for a nice, constantly changing design element for the room.  It works best if the set of photographs changes before it gets old.
  2. I recently found the National Geographic site’s “photo of the day” section as an interesting source of high-quality photographs that updates on a daily basis.  However, National Geographic doesn’t provide a feed for the photo of the day.

Essentially then the task was to scrape the URLs from the photo of the day, and package them into a feed.  The complication comes from the fact that there doesn’t seem to be a list of photos of the day available on the National Geographic web site – just links from a particular photo to the one for the previous (or next) day.  Because a feed of 30 photos requires 30 different pages to be scraped, some caching really becomes necessary to improve performance, especially since feed readers can be expected to bombard the service if it proves popular.

I initially broke down the task into three parts:

  1. Scraping a photo of the day page to extract the useful metadata, including the date, title, photographer’s credit, and description of the photo, a set of links to the actual image in various sizes, and links to the page being scraped (so one can return there easily) and to the previous page in the photo stream.  Since this metadata shouldn’t vary, cache it locally for faster retrieval.
  2. Searching the cache or going to the web site (and thus populate the cache) to acquire the metadata for a particular date.
  3. Formatting the metadata for a particular range of dates into a feed.

Here’s how I approached each of these tasks.

Scraping a photo of the day page

The first order of business for scraping a page like this is simply to fetch the page, tidy it into XML so we can navigate it using tools like XPath.  The WSO2 Mashup Server provides a “Scraper” object that accepts an XML language describing the steps involved in scraping.  This configuration language is defined by the Web Harvest component that we use for scraping.  I usually start with a scraping mashup using a simple function that configures and performs the scrape, and returns the results:

 
function scrape_picture_page() {
  var config =
    <config>
      <var-def name='response'>
        <html-to-xml>
          <http method='get'
              url="http://photography.nationalgeographic.com/photography/ ¬
                   photo-of-the-day" />
        </html-to-xml>
      </var-def>
    </config>;

  var scraper = new Scraper(config);

  var bodyWithoutXMLDecl =
      scraper.response.substring(scraper.response.indexOf('?>') + 2);
  var result = new XML(bodyWithoutXMLDecl);

  return result;
}

The config language itself is pretty straightforward, once you learn to read it inside out – the <http> element fetches the requested URL, the <html-to-xml> does just what it sounds like and tidies the result, which is put into a variable named “response”.  The scrape is performed by initializing a new “Scraper” object with the config, and the result is made available through the “response” property on the result – corresponding to the “response” variable we defined within the config file.  One trick though – the result is a stream of XML text, including an XML declaration.  The E4X extensions can parse this into XML (new XML()), but can’t handle the XML declaration.  We have to strip off the declaration ourselves using string manipulation.

By placing the above function in a file named “nationalgeographic.js” in the “scripts” directory of the Mashup Server, a Web service with a scrape_picture_page operation will be deployed.  We can get to it through the try-it page (http://localhost:7762/services/jonathan/nationalgeographic?tryit) and see what the tidied HTML looks like for the page.

Extracting the data from the page can be a tedious process, involving looking at HTTP request-response pairs and trolling through the HTML source of a page.  Fortunately the National Geographic site’s HTML is simple and straightforwardly structured, with a number of well-placed identifiers to help us zero in on the interesting content.  I usually end up using Firebug (Firefox debugging extension) to navigate the live HTML of the page and develop some XPath expressions that extract the desired metadata for the page.  I’ve also found that, since Web Harvest communicates between components using strings rather than parsed XML, that defining a lot of XPath filters to extract information one element at a time during a scrape can perform poorly.  Instead it seems much faster to wrap a series of XPath expressions into a simple XSLT stylesheet so the XML can be parsed once, queried as much as needed, and an XML structure containing the results returned in one action.  To do that, I added an XSLT stylesheet to the above configuration:

  var config =
    <config>
      <var-def name='response'>
        <xslt>
          <xml>
            <html-to-xml>
              <http method='get' url={url} />
            </html-to-xml>
          </xml>
          <stylesheet><![CDATA[
           <xsl:stylesheet version="1.0"
                            xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
              <xsl:output method="xml" omit-xml-declaration="yes"/>
              <xsl:template match="/">
               <photo>
                  <xsl:for-each select="//*[@id='content-center-well']">
                    <date><xsl:value-of select="div[@class='date']"/></date>
                    <previous>http://photography.nationalgeographic.com ¬
                      <xsl:value-of
                          select="div[@class='slide-navigation'][1]/p/a/@href"/>
                    </previous>
                    <xsl:for-each select="div[@class='image-viewer clearfix']">
                      <xsl:for-each select="table/tbody/tr[1]/td/a">
                        <page>http://photography.nationalgeographic.com/photography/¬
                          photo-of-the-day/<xsl:value-of
                          select="substring-before(substring-after(@href,'enlarge/'),
                          '_pod_image.html')"/>.html</page>
                        <xsl:variable name="href"
                          select="concat('http://photography.nationalgeographic.com',
                                substring-before(img/@src, '-ga.jpg'))"/>
                        <location type='small'>
                          <xsl:value-of select="$href"/>-ga.jpg</location>
                        <location type='medium'>
                          <xsl:value-of select="$href"/>-sw.jpg</location>
                        <location type='large'>
                          <xsl:value-of select="$href"/>-lw.jpg</location>
                        <location type='wide'>
                          <xsl:value-of select="$href"/>-xl.jpg</location>
                      </xsl:for-each>

                      <xsl:for-each select="div[@class='summary']">
                        <title><xsl:value-of select="h3"/></title>
                        <credit><xsl:value-of select="p[@class='credit']"/></credit>
                        <description>
                          <xsl:copy-of select="div[@class='description']/node()"/>
                        </description>
                      </xsl:for-each>
                    </xsl:for-each>
                  </xsl:for-each>
                </photo>
            </xsl:template>
            </xsl:stylesheet>
          ]]></stylesheet>
        </xslt>
      </var-def>
    </config>;

Again, fairly straightforward – the <xslt> task has two inputs, <xml> and <stylesheet>.  The stylesheet unfortunately has to be enclosed in a CDATA section rather than as straight XML.  One other nice trick though – when the output is an XSLT template, the “omit-xml-declaration” flag can be used to strip off the XML declaration so we don’t have to do it through text manipulation, simplifying and accelerating our Javascript code.

So we’re almost there with this capability.  Some minor improvements and adding caching are all we need:

  1. Add an optional  “url” parameter to allow this page to work on any photo-of-the-day page URL.  Using E4X’s curly braces we can substitute this value right into the config file.
  2. If the result was successful (e.g. the <photo/> element has children), calculate the date in yyyy-mm-dd format and use the storexml service to cache it – choosing a path unlikely to conflict with other users of the storexml service.  To make the storexml service easy to call, we import it’s stub, which I got from http://localhost:7762/services/system/storexml?stub&lang=e4x&localhost=true and saved into the nationalgeographic.resources folder which serves as the sandbox for this service.  It’s important to save a copy because when the Mashup Server boots up the nationalgeographic service might be deployed before the storexml service – attempts to generate the stub at that time will fail and cause the nationalgeographic service to fail too.  The Mashup Server doesn’t yet track these dependencies (and we’re still thinking about whether this is a tractable problem or not.)
  3. Since this operation isn’t really supposed to be called by end-users of the feed, I could make it private using scrape_picture_page.visible = “false”, but instead I’ve just used the “operationName” property to rename it, indicating to users that it really is just for test purposes.
  4. Add type annotations.
  5. Add documentation annotations (not shown below.)
system.include("storexml.stub.js");
var cachePath = "nationalgeographic/cache/";

scrape_picture_page.operationName = "test_scrape_picture_page";
scrape_picture_page.inputTypes = {"url" : "xs:string?"};
scrape_picture_page.outputType = "xml";
function scrape_picture_page(url) {
  if (url == null)
    url = "http://photography.nationalgeographic.com/photography/photo-of-the-day";
  var config =
    <config>
      <var-def name='response'>
        <xslt>
          <xml>
            <html-to-xml>
            <http method='get' url={url} />
            </html-to-xml>
          </xml>
         <stylesheet>
            ...
          </stylesheet>
        </xslt>
      </var-def>
    </config>;

  var scraper = new Scraper(config);

  var result = new XML(scraper.response);

  if (result.hasComplexContent()) {
    var date = xsDate(new Date(result.date));
    storexml.store(cachePath + date, result);
  }

  return result;
}
xsDate.visible = false;
function xsDate(d)
{
  return d.getUTCFullYear() + "-" +
       (d.getUTCMonth() < 9 ? "0": "" ) + (d.getUTCMonth() + 1) + "-" +
         (d.getUTCDate() < 10 ? "0": "" ) + d.getUTCDate();
}

As an aside, this shows a couple of my wishes:

  1. <xml> is a reserved tag name in XML, it’s unfortunate that Web Harvest doesn’t use something else.
  2. Web Harvest’s requirement that the stylesheet be enclosed in a CDATA section is unfortunate – it means well-formedness errors can’t be caught at Javascript/E4X compile time, but at runtime.  This slows down the development process.  I could put the stylesheet in a separate file, but that just makes it harder to share the service and see what’s going on.
  3. I’d prefer a way to get E4X XML back from Web Harvest directly so I wouldn’t have to parse it myself, worry about the XML Declaration, and so forth.  Maybe we can do something about this in a future release.
  4. Managing date formats becomes a bit of a chore.  I prefer the operations and cache to work on xs:date format (yyyy-mm-dd), but the page metadata is in the form “Month day, year” (directly from the scraped page).  And Javascript prefers to manipulate dates in its own Date object.  Soon we’ll see that the RSS profile defines a subset of the Javascript serialization that means a fourth conversion.

Finding a picture for a particular date

Now that we have a function that can scrape a page given a URL, and given that the data returned and cached by that function contains a link to the page for the previous day’s page, we can do some walking around in the cache to find data for a particular date.  That’s what this function does.

First, we look in the cache for a photo’s metadata.  If it’s there, we can simply return it – we’re done.  Otherwise we need to find the URL for the page representing that date and call the scrape_picture_page operation.

If I can’t find the requested date in the cache, I look for the next earlier date, and so on, until I do find a photo in the cache (or I reach today’s date).  That’s the first while loop.  Then, using the <previous> page url, I work backward again, incidentally populating the cache as I go, until I’m back to the date I was looking for.  The couple of “if” statements look for exceptional conditions: the first one handles the case where I’ve looked all the way forward till today but still haven’t found anything in the cache, and the second makes sure that if a page can’t be scraped for some reason that we give up and return what little we have before we dig ourselves any deeper.

picture_for_date.inputTypes = {"date" : "xs:string"};
picture_for_date.outputType = "xml";
function picture_for_date(date) {
  try {
    return storexml.retrieve(cachePath + date);
  } catch (e) {
    print("failed to find cached photo for date " + date);
    var photo;
    var startDate = parseDate(date);
    var today = new Date();
    // work forwards in the cache until we find something (or hit today)
    while (startDate <= today) {
      try {
        photo = storexml.retrieve(cachePath + xsDate(startDate));
        break;
      } catch (e) {
        startDate.setUTCDate(startDate.getUTCDate() + 1);
      }
    }
    // start with the most current thing in the cache (if any) an work
    // backwards to the requested date, filling in the cache as we go...
    var targetDate = parseDate(date);
    while (startDate > targetDate) {
      var previousPageUrl;
        if (photo == null) previousPageUrl = null;
        else previousPageUrl = photo.previous;

        print("fetching photo for " + startDate);
        photo = scrape_picture_page(previousPageUrl);
        if (!photo.hasComplexContent())
          break;
        startDate.setUTCDate(startDate.getUTCDate() - 1);
    }

    return photo;
  }
}

Generating the feed

Now we have all the pieces in place to aggregate the data and generate a list of some kind as output.  The picture_of_the_day operation does that for us.

The function has some parameters controlling aspects of the feed – whether to link to the small, medium, large, or wide aspect ratio images, and how many items to include.  If no number is specified, we generate a feed of the latest 30 photos – just long enough to enjoy the photo but not so long we get tired of it.

The WSO2 Mashup Server has a Feed object to help construct feeds, but because I’m targeting this feed at the Google Photos Screensaver I need to include some feed extensions that aren’t supported in the 0.2 release (though they’ve just been added to the nightly build!).  It’s not hard to create an RSS by hand though, so that’s what I chose to do.  First I prepopulate the channel with title, links, and description, and then loop through the photos adding an item for each of them.  The first time through the loop, I also add in a <pubDate> reflecting the date of today’s photo.

Again, this isn’t rocket science – the hardest thing is simply to format the dates appropriately.  During the loop I use Javascript Date objects to increment days and tick over at the end of the month.  I convert that to an xs:date to access the cache, to an RSS Profile-conformant string for the <pubDate>, and to an xs:dateTime for use in the <atom:published/> element, which seems useful for the subscription page displayed in Internet Explorer 7.

picture_of_the_day.inputTypes =
     {"size" : "small | medium | large | wide", "numPhotos" : "number?"};
picture_of_the_day.outputType = "#raw";
function picture_of_the_day(size, numPhotos) {
  if (numPhotos == null) numPhotos = 30;

  var feed =
    <rss version="2.0">
      <channel>
        <title>National Geographic Picture-of-the-day (from WSO2 Mashup Server)</title>
        <link>http://mashups.wso2.org/services/nationalgeographic/¬
              picture_of_the_day?size={size}</link>
        <description>WSO2 Mashup Server mashup acquiring and caching links to the ¬
          National Geographic Picture of the Day
          (http://photography.nationalgeographic.com/photography/picture-of-the-day),
          and exposing them as a feed.  Sizes of "small", "medium", "large", and "wide"
          are available. A max number of photos can be specified with the "numPhotos"
          parameter.</description>
      </channel>
    </rss>;

  var startDate = new Date();
  var photo, photoDate, url, urlsmall, entry;
  for (var i = 0; i < numPhotos; i++) {
    photo = picture_for_date(xsDate(startDate));
    if (photo.hasComplexContent()) {
      url = photo.location.(@type == size).toString();
      urlsmall = photo.location.(@type == 'small').toString();
      photoDate = new Date(photo.date.toString());
      if (i == 0) {
        feed.channel.appendChild(<pubDate>{rssDate(photoDate)}</pubDate>);
      }
      entry = <item xmlns:media="http://search.yahoo.com/mrss/">
          {photo.title}
                <description>
                  &lt;a href='{url}'>&lt;img src='{urlsmall}'/>&lt;/a>
                  {photo.description.*.toXMLString()}
                </description>
                <pubDate>{rssDate(photoDate)}</pubDate>
                <link>{photo.page.toString()}</link>
                <guid isPermaLink='false'>{photo.page.toString()}</guid>
                <media:content url={url} type="image/jpeg" />
                <media:thumbnail url={urlsmall} />
                <atom:published xmlns:atom="http://www.w3.org/2005/Atom"
                    >{xsDate(photoDate)}T00:00:00Z</atom:published>
              </item>;
      feed.channel.appendChild(entry);
    }
    startDate.setUTCDate(startDate.getUTCDate() - 1);
  }
  return feed;
}

You can access this operation through the try-it page at http://localhost:7762/services/jonathan/nationalgeographic?tryit and see that the operation returns a feed.  However, the try-it uses SOAP by default under the covers, which isn’t terribly friendly to feed readers like the Google Photos Screensaver.  No problem – the Mashup Server also exposes it’s operation through a REST interface.  By accessing the URL http://localhost:7762/services/jonathan/nationalgeographic/photo_of_the_day?size=wide, you can see the feed directly in the browser, point the screen saver at it, subscribe to it, etc.  By adjusting the “size” and “numPhotos” parameters you can generate variants of the feed that suit your purpose.

Publishing the feed

Once I had the service written, tried it for a day or two to ensure it was stable (and fixed a couple of edge cases as a result), I used the administrative UI in the Mashup Server to publish it to http://mooshup.com, which hosts the service live on the internet for others to use.  The publishing process is simple – click the share button, confirm that http://mooshup.com is the destination, and click OK.  While we have lots to do to make this site an attractive and useful place for members of the mashup community to hang out, it does give me a stable internet URL for the feed (for example http://mooshup.com/services/jonathan/nationalgeographic/picture_of_the_day?size=wide) so others can enjoy it.  You can exercise the try-it page live from there, look at the metadata, or download the service to your local installation of the Mashup Server and run it there.

Last Word

Hopefully this helps you get a feel for the Mashup Server in action.  We did some screen scraping, fairly sophisticated caching by invoking an external storexml Web service, formulated an RSS feed, and made it (and intermediate functions) available through a Web service including SOAP 1.2, SOAP 1.1, and HTTP bindings, including an HTTP GET binding amenable to RSS agents.  Although we didn’t look at them in detail in this article, the Mashup Server generated a try-it page for debugging and exercising the service, WSDL, Schema, stubs for accessing the service simply from Javascript or E4X environments, even generated some human-readable documentation for the mashup.  We ran the service locally, then published it live onto the internet.   It also would not be hard to generate a custom HTML interface providing (for example) a slideshow of these photos, but in this case I wanted to show that user interfaces can go beyond just HTML pages by using Google Photos Screensaver as my ultimate user interface.

So what’s next for this service?  The main improvement I can think of is rewriting the code to use the Feed object when it becomes capable of handling the images.  It took me a while to figure out which RSS extensions were necessary and it would be nice not to worry about the representation of dates.  Maybe I could even offer an Atom feed in parallel.  Another idea related to performance would be to experiment with a different, perhaps additional, caching strategy – which is to cache the entire feed to disk and periodically refresh it using the recurrence capabilities of the mashup server.  But those are perhaps good topics for future articles!

Until then, enjoy the great photos available from National Geographic!

[Updated 6 Feb 2008 - added "jonathan" user to endpoint urls as required by the Mashup Server 1.0 release, and changed the online links to point to http://mooshup.com.]

Crooked Lakes Basin reprise

For an end-of-summer blast, an elite selection of Marsh family members returned to the Crooked Lakes Basin for an overnight backpacking trip.  Photos are now online here, joining the set from our last visit a couple of years ago.  The air was a little smoky from recent California wildfires, but it was fun to revisit a place and to dig up new subjects and try to do better on some shots I’d done before.

Penner Lake

Shi Shi Beach trip: Day 4

[Pictures here.  Now geotagged.]

We arose early on our final day - we needed to attain Shi Shi Beach and a water source there before we could rehydrate our breakfast.  The tide was again low so we had little trouble navigating the final gateway to the smooth wide sands of Shi Shi Beach.  As the driftwood at the high-water line was deep in shade at the forest’s edge, and would be for hours, we spread a small tarp on the damp flat sand, made stools of our bear canisters, and tucked into a random array of our remaining food.  My policy is never to pack food for your final lunch - by then you’d rather just hold out for the first cheeseburger.

I discovered that my camera had enough power to take a shot - but not to save it on the SD card - so I used the miniscule internal memory to take one final shot of Gen and Anna on the beach (sorry, marked friends/family only in flickr as are all my shots of friends/family - yes, you’re missing about 30 pictures out of the set if you’re not on my list.)

Rugged trailWhat can I say about Shi Shi?  It protected its secrets well, and who am I to tattle?  I’ll just confirm that it was a worthy destination, though attaining it was strenuous enough that it didn’t leave much time to enjoy its charms.  In the end the journey is always the greatest reward, and Shi Shi can be celebrated as the catalyst of a remarkable and magical expedition.

Along the length of Shi Shi we passed a number of tent encampments starting breakfast fires tucked up against the forest. Shi Shi wasn’t as deserted as the previous two days had been.  Already we were returning to civilization.  At the end of the beach one final steep climb up a cliff led to a couple of miles of forest trail, gradually straightening, widening and becoming less muddy, and eventually developing into a quite civilized set of boardwalks and bridges before depositing us in a car day-park a mile of paved road from our car.  This trail took us from the wild where time is marked by stride after stride, by tides, shadows, sunsets, and the song of the soul, and returned us again to the precise increments of omnipresent second-counting LCDs, per-minute roaming charges, miles per hour, ferry schedules.  We will learn to appreciate these things again, and ease gently into that world of objective time with a dinner reservation for a seafood extravaganza.

But part of us will always remain in that narrow strip of land between the flat sea and the towering stone along this extraordinary piece of wilderness.

Gateway to the arches