Friday, August 28, 2020

Making History | Building a 2000 Year Old Computer

One of the story lines in the novel The Map of Salt and Stars follows an ancient mapping expedition. The only two surveying tools noted in the text are a notebook and an astrolabe. Naturaly I wondered what's the deal with the astrolabe, and could it realistically power this type of endeavor?

I had some vague notion of what an astrolabe was. In my mind's eye it was a sort of primitive sextant. I was mostly, though not completely, wrong. Here's an excellent TED talk on the subject.

In short, the astrolabe is an ancient mechanical computer. Like the slide rule, it consists of various scales that when aligned solve otherwise complex problems. While the slide rule lets you solve math problems, the astrolabe lets you tackle geospatial ones. What direction is North? What time is it? When is sunset? What stars will appear in the sky tonight? What's my latitude? These are just some of the questions the astrolabe can answer; it has a reputation for being quite the information multi-tool.

This explanation suggests that yes, in ancient times an astrolabe may very well have been the primary tool used by map makers and explorers. Consider that it predates the simple magnetic compass by 1,400 years.

Reading about the remarkable prowess of the astrolabe, I naturally decided I had to have one. I figured Amazon would have a cheap knock-off that I could purchase. Alas, that was a dead end. The products that show up when I searched were both pricey and decorative and wouldn't be useful in a field context. Some additional digging, however, turned up another option: I could make my own, for free no less!

I found two projects that allow you to build an impressively detailed and authentic astrolabe:

I found in-the-sky's version first and the assembly process is straightforward. You download the appropriate PDF for your latitude, print it out, cut the pieces out and pin them together to form a rotating disk. The only gotcha is that you need to print one of the pages on a clear sheet of plastic, which you may not having lying around. See below for the supplies I bought to build my own.

The AstrolabeProject is more sophisticated, it requires that you run a Java based program to generate the relevant PostScript files. The reward for putting up with this requirement, however, is that you can customize the finished device in novel ways. I built the in-the-sky version because I found it first, but I can already imagine building v2 using the AstrolabeProject's generator. Another feature of the AstrolabeProject: it has two lengthy documents that describe how to use the finished device, including a 47 page class handout and a 44 page manual.

I purchased a few items to make my in-the-sky version of the astrolabe, including:

  • C-line transparency film - this transparency material worked well with our Canon Laser printer.
  • 1/2" brass paper fasteners - these were ideal for holding the stack of papers that make up the astrolabe.
  • Japanese Screw Punch - this makes punching the required holes a breeze and was a worthwhile investment.
  • OLFA Rotary Circle Cutter - this simplified cutting out the circular parts of the astrolabe. In hindsight I could have lived without it. Like the paper punch, I figured I was investing in a tool that would be useful for future projects.

With the tools in hand, I was able to print and cut out each piece of the astrolabe. I opted to laminate the various paper components to add some heft to the finished product. I used this BIC lighter hack to bend the sights up on the ruler. That worked OK, but I can already envision a better solution for v2.

If paper isn't your thing, you can check out these instructions for a laser cut plastic version, or go crazy and build one by hand from brass (wow!).

I'm now able to hold in my hand the same tool that helped power explorers, astronomers, astrologers and priests over a thousand years ago. This is humbling. I can't wait to get out in the field put the device to use. Move over map, compass, watch and GPS--there's a new player in town.

Monday, August 24, 2020

Review: The Map of Salt and Stars

I try to learn as a little about a book as possible before I start it. Heck, I'll skip the author's introduction just to start chapter one with a blank slate. And yet, the two words I did catch in the description of The Map of Salt and Stars: A Novel by Zeyn Joukhadar were enough to conjure an entire plot. The two words: Syrian and Refugee.

From these two words I envisioned how the story would go: the main character(s) would be living in Syria, get displaced by war and end up in a refugee camp. He/She/They would toil there while the world ignored them.

I realized part way through the book what helped inspire this notion: ads by Patrick Stewart on YouTube. Apparently those ads made quite the impact on me. Between the ads and other stories I've heard, my vision of being a refugee was all about being passive. You remain in limbo, dependent on others, while the word moves on.

I truly enjoyed The Map, and even more so because I went into the text blind. So I don't want to ruin this book for you. But I will say, the plot I imagined above couldn't have been more wrong. Whereas I imagined a static plot, Joukhadar brought the opposite: plenty of heroic action. What a while ride The Map turned out to be.

I found the lyrical nature of the book to be a bit confusing at first, but I'm glad I stuck with it. My suggestion is to go read (or, do as I did and listen to) the book and then come back and read my comments below. They aren't anything Earth shattering, but I can't help but lay out a number of elements of Joukhadar's novel that caught my attention.

Spoilers Below

Joukhadar's use of a 12 year old American girl to serve as the protagonist was inspired. She provided precisely the naive perspective that someone like myself, unfamiliar with Middle East politics and customs, would have. And the decision to give her Synesthesia made not only for a useful poetic device, but was a clever super-power. And the interleaving of modern and historic adventures, that truly made this an outstanding read.

I found myself quite moved by the modern story. The bombing of Nour's family left me stunned. One imagines that residents in a city filled with unrest have a choice; stay or go? And when you do go, you at least have some time to pick which items you'll take with you. But the bombing shows how wrong headed this thinking is. One moment there's a family with a home and possessions, and the next there's nothing but destruction and pain. As I played the scenario over in my head I found myself stuck. What's the right way to respond to this impossible crisis? Nour and her family prove to be inspirational: you take what you can and move towards something better. The situation may be impossible, but giving up is even less of an option.

And that moment on the ferry where time stops; that moment nearly brought me to tears, something I can't recall a book ever doing. Like I said, a wild ride.

Sure, there's a few aspects of the plot I could quibble with. When the family has to separate, why all the secrecy? Wouldn't you want your daughters to know the name of the city and family member they are seeking out? Isn't that everything? The map is clever and full of symbolism, but it seems woefully impractical. And the plot lost a bit of steam at the end when we find Nour busting out of a facility that would let her sister come and go as she pleased. Still, these are minor quirks.

Overall, The Map of Salt and Stars delivers not one, but two epic tales. And while it shows a dark and troubling aspect of our humanity, it also shows  the power hope and moving forward. Perhaps most importantly, the book has inspired me to dig deeper into the subject. Now I'd like to read the true accounts of actual Syrian refugees to see what parts of the story are fanciful and what parts are realistic.

Wednesday, August 19, 2020

The 3P's of Gear Selection

Over the weekend, this thread was posted over at /r/ultralight:

Calling BS on the 10 essentials (for dayhikes)

I get that they're important, and I get why they are important, but do any of you actually bring all of the 10 essentials on all of your dayhikes and trail runs?
...
Can anyone on this sub, realistically, make a case that I needed a: Paper map and compass. Headlamp with extra batteries. Additional insulating layer (I brought a wind/rain shell). Firestarter. Knife. Emergency shelter.

The top answer is currently:

Hey OP- I’m in search and rescue and while I understand your feelings for sure, a lot of the missions that my search and rescue team get are 100% preventable- day hikers with issues that wouldn’t have been issues if they had the 10 essentials with them (dehydrated, heat exhaustion, injuries, lost, ran out of daylight and had no flashlight, etc). There’s plenty of lightweight versions of the 10 essentials. Even if you are experienced and end up never needing them yourself, it’s nice to have them “just in case” as well as to help anyone else on the trail that might need it.

It's followed up by this terse recap:

This. Because not bringing the ten essentials makes you an asshole. Many SARs are volunteers.

Don’t be an asshole to volunteers.

And while the above is solid reasoning, I'd like to pile on with a bit of my own gear philosophy. Anyone who follows my blog or has spent time with me in person, knows that I often carry a bag, and in that bag is a fairly significant amount of gear  (by /r/ultralight standards, it's massive). Why carry all this gear everywhere? The answer: the Three P's.

P1 - Prepardness

In the context of a day hike, carrying a bit of extra gear gives you a chance to respond to the unexpected. The original poster imagined taking an 8 mile hike on a popular trail. Does he really need to bring a flashlight, emergency shelter and map and compass for this? While unlikely, it is possible that emergencies can stack up--a servely twisted ankle, as the sun is going down, with a dead cell phone--that may call for emergency gear.

Not moved by this argument? Not to worry, let's talk about the other two P's.

P2 - Practice

It's not hard to imagine finding yourself finishing the above well known trail in the dark. Depending on the conditions, you may get by on ambient light or your cell phone's flashlight. But this is also a terrific opportuntity to practice with your gear. If you bust out the flashlight that you rely on when backpacking, even though it's overkill for a day hike, you're getting a free opportunity to test it out in a realistic context.

P3 - Psychology

Still not moved? Let's say you decide to only carry emergency gear on truly adventerous hikes. Imagine, like Shira and myself that you find yourself turned around in a canyon filled landscape. In our case, we backtracked to the car and all was fine. But let's say you got turned around and backtracking isn't an option. Night and a storm of what-ifs are closing in. What if you miss your flight? What if nobody hikes this trail for weeks? What if you can't get cell signal? What if your cell phone dies? What if the vague message you sent your family isn't detailed enough to have them find you? What if temps drop and the shorts and t-shirt you're wearing leave you hypothermic? Now is precisely the wrong time to bust out an emergency kit you're not familiar with. If you always carry the same gear, you can take a deep breath and realize you have the essentials covered. It's hard to quanitfy this mindset bonus, but when an emergency happens every bit of familiarity with your gear is going to help.

I do agree with the original poster that the traditional 10 Essentials may not be the ideal prescription. Rather, you want to head into the wilderness armed with a kit to deal with emergenices the 10 Essentials were developed for. This includes: getting lost, getting injured, getting stuck in the dark, getting hit by unexpected weather and needing to shelter in place for the night.

The 3P's suggest you want compile a kit to deal with these scenerios (bonus: the kit can even be ultra-lightweight) and carry it religously.

Thursday, August 13, 2020

Baby's First Backpacking Trip

At first glance, the Thurston Griggs Trail to Appalachian Trail to Black Rock route hardly looks like a must-do bit of trekking. But this past weekend it served as the setting for an audacious expedition: Baby's First Backpacking Trip.

In a normal year, I'd be itching to take a summer backpacking trip. But this year, with the pandemic keeping us at home, and a 6 month old baby I was eager to share the wonder of nature with, I found the pull of getting out on the trail even stronger. But how to do it?

First off, I'd needed to establish that we could carry the gear to have a proper overnight. I gathered up a tent, a sleeping bag for Shira, inflatable sleeping pads and a few other odds and ends. I shoved them into my 65 liter Gregory Backpack. I eyed the space left over. I'd need to fit in clothes for the Baby and Shira, food for all of us, diapers and plenty of water for making bottles. Yes, I decided it could be done.

But that's not all that needed to be carried. What about the little guy himself? At nearly 25 pounds, we decided that a robust carrier would make all the difference. So we picked up the deluxe Osprey Poco Plus. Like all Osprey packs, this is a thing of beauty. We put the little man it in for a walk through the neighborhood. At first he squirmed, and then got comfortable. We did our walk with him in and it was a success. Hurray, the gear was covered.

Now we needed a route. On one hand, we wanted one close by. On the other, we wanted a location that wouldn't be overrun with people on a weekend. We poured over our options and decided on the Thurston Griggs Trail to Appalachian Trail to Black Rock trip outlined on All Trails. The Thurston Griggs trail was far enough away from the popular Annapolis Rocks trail head, that we hoped it wouldn't be parked up. The trail itself called for an uphill slog that passed by a campsite. That meant that we could hike in, setup camp, and then do some additional hiking on the AT if we felt up to it. On paper, it looked like a solid choice.

The morning of our trip I cataloged the major ways this little project could fail, and possible work-arounds. The weather could take a turn for the worse. The parking lot could be full. The trail could be too technical to safely navigate with a baby in carrier. The campsites could be filled by the time we arrived. And those were just the obvious fail points.

To my amazement and joy, everything went precisely to plan. There was plenty of space to park the car. The schlep up Thurston Griggs trail was relatively steep and rocky, but not at all technical, so we had no problem making our way up the trail. When we arrived at Pogo Memorial Campground we found a couple of campers there. But we also found a half dozen empty sites. We picked one out of the way and setup our tent. Even the weather cooperated, with my Garmin InReach reporting 0% chance of precipitation for the next 24 hours.

After setting up our tent and letting the little guy play around the campsite he started to show signs of being tired. We put him in the carrier and we continued up the trail, this time on the official Appalachian Trail, up to Black Rock overlook. The view was spectacular, the kid fell asleep, and I got to relish in the joy of being in the backcountry.

When we returned to the campsite, I made a fire and Shira perfectly roasted hot dogs and marshmallows. Our little one sat in the grass playing. By the time dinner was cleaned up, it was time to put the little one to bed. I did this by putting him in the Moby wrap and taking him on a stroll along the AT. Rather than listen to music, I droned on about the joy of backpacking and he was asleep in no time.

By 8:30pm we were all asleep in the tent, we'd closed out an amazing day.

We'd stay in our little bubble of bliss for all of 4 hours. At around midnight the little guy awoke for a snack. Shira fed him by the red light of her headlamp, which was a bit surreal. I then put him back in the Moby and we roamed the pitch black campground as I put him to sleep. He eventually drifted off to bed. I made my way back to the tent, took him out of the Moby and put him on his sleeping pad. Moments later, he was awake. Ugh. It took us about 3 hours and 3 more attempts to actually get him fully back to sleep.

What I remember most was the look of wonder on his face as he stared up at the night sky. It was dark, but against the pitch black sky you could clearly make out the trees. I could see the little gears in his spinning as he tried to make sense of the scene.

Between attempts to put him sleep, I managed to experiment with some cellphone night-sky photography. While the photos may not appear like much, I'm impressed at how they came out. All told, it was actually quite nice to be up and exploring the area in the middle of the night.

After getting him back to sleep, we all slept in until 7am. We packed up our campsite and slowly trudged down the mountain back to our car. We met some locals on the way who confirmed what we suspected: the nearby Annapolis Rocks parking area fills up by mid-day, but the Thurston Griggs Trail Head always has parking. Keep that little tip in mind if you want to explore the area.

Before I knew it, we were back at the car and within spitting distance of DC. My little backpacking adventure was complete. I couldn't be happier with how it turned out. If anything it went too well. Now I'm itching to get out for two nights!











Wednesday, August 05, 2020

Review: Middle Passage

I tried to describe Middle Passage by Charles Johnson, the current book I was listening to Shira, but got stuck. Finally I explained, it's the type of book we'd read in English class. That is the subtext of the book seems to be just as important, if not more so, then the actual story. Below are some ramblings on this novel, beware, there are spoilers.

Since I finished Middle Passage I've been trying wrap my head around what I just heard. Yes, the book is a coming of age story of the main character, Rutherford Calhoun. And it's clearly an opportunity to ask the question: who's truly free and who's truly a slave? But it does all of this in a fairly novel way.

As I've thought through the book, I noticed an interesting clue: the sailors on the ship that Calhoun stows away on are too nice. He's a stowaway who impersonated another sailor to get on board, and yet the crew fairly quickly welcomes him. Even the captain who's feared by all and openly declares he "doesn't like negros" befriends Calhoun. This got me thinking of another story where the sailors are too nice, the Book of Jonah. Recall that in the Book of Jonah the sailors do everything they can to avoid throwing Jonah overboard.

As I thought about it, there are other similarities about Calhoun and Jonah. In the midst of the storm that forces the sailors to throw Jonah overboard, Jonah can be initially found sleeping below. When Calhoun stows away on the Republic his first act: going to sleep. Both stories involve vivid scenes where the crew offers sacrifices on deck to try to persuade the power's that be to rescue them. Far less esoteric is the fact that both Calhoun and Jonah are running from responsibility, and both encounter forces that show how powerless they are to do so. And of course, both ultimately find themselves back at where they started, now prepared to complete their missions.

To me, these similarities underscore that Calhoun's journey is meant to be taken, like Jonah's, as an allegory. This isn't meant to be historic fiction, accurate down to the last detail. In this context, Middle Passage makes more sense to me.

With the latest attention given to racism in our country, there's a trend of being cautious of how minorities are represented. Aunt Jemima is out of a job, tech companies are revisiting the terms the use and Arlington County is reconsidering its logo. In this environment, I was curious how Middle Passage would handle its subject matter. The author isn't just writing about a slave ship, he's writing about a slave ship with an African American crew mate, who also happens to be a thief and philanderer.

And while I'm no expert on these matters, I think Johnson manages to cover the material in a racially intelligent way. I say this not because of how he describes the sailors, but because of how he describes the captured slaves. They aren't pitiful, faceless men. They are a proud tribe, named and elevated. This isn't merely the story of moving slaves across the Atlantic, but the kidnapping of a distinct people with distinct personalities.

Incidentally, there is one group that doesn't fair so well in the book: women. Put bluntly, the main female character is fat and therefore ugly. When Calhoun reunites with the leading female character he finds her beautiful. Is this because he's learn to see her for all her positive qualities? No, it's because she's lost weight. Sorry ladies, better lose some weight if you want to be pretty.

My Grandpa Irv used to say: why ruin a good story with the truth? I think that may be one of Johnson's strategies in the Middle Passage. This isn't just a story on a slave ship, this is a story on a slave ship post 1808 when the slave trade was technically outlawed. This is evil on top of evil. And yet, Johnson risks humanizing the crew and their endeavor to give us the space to appreciate Calhoun's journey and ultimate redemption. I think it works.

Tuesday, July 28, 2020

Perspective on Covid-19 from an Unexpected Source

Growing up in the 1980's, the virus making headlines was HIV/AIDS. An audio book I recently listened to mentioned how early treatments to this virus were developed. This inspired me to look at how the AIDS epidemic unfolded and I was surprised to see similarities with our battle against Covid-19.

Consider these milestones:

Milestone AIDS/HIV Covid-19
#1 The virus is identified. A rare lung infection is noticed in a cluster of previously healthy gay men. Reports of a 'viral pnuemonia' are detected in Wuhan China.
#2 The virus is named, with some false starts. AIDS, acquired immune deficiency syndrome, is used to describe the disease. The name 'Gay-related immune deficiency' is used, but quickly discarded. Covid-19 is named, though phrases like the 'Chinese Flu' are also used and discarded.
#3 Develop an early understanding of how the disease is transmitted. It's understood that AIDS can be transmitted through sex. More importantly, fears that AIDS could be transmitted through casual contact are debunked. Covid is thought to be transmitted primarily through respiratory droplets. Concerns that Covid can be transmitted through mail and other common touch surfaces are shown to be unlikely.
#4 Develop early public health measures to combat the disease. The first needle exchange programs are setup and businesses with high-risk sex activity are shuttered. We get our first mantra: Stay home, wash your hands, socially distance.
#5 A celebrity contracts the virus and makes headlines. Rock Hudson dies of AIDS, being the first celebrity fatality Tom Hanks and his wife contract Covid-19.
...
#10 The virus claims the lives of over 100,000 Americans

Looking at the above chart you could be forgiven for being unimpressed. Those milestones would match up with countless diseases. What's the big deal?

The mind blowing part for me: in the case of HIV/AIDS each milestone above represents one year. In about half the time it took name AIDS, Covid-19 has killed nearly 150,000 Americans.

Put another way: AIDS killed 100,00 Americans in 10 years; Covid-19 did this in 5 months.

I was a kid in the 1980s, but even I understood how scary AIDS was. In the early days, to contract the disease was to be given a death sentence. And yet, despite experts understanding and reacting to Covid-19 at comparably breakneck speed, the disease is killing at rate that far exceeds AIDS. Amazing.

Wednesday, July 22, 2020

Gonna Be a Hot One

From two recent at-dawn runs:

Our heatwave continues with another crazy day:

Perhaps there's no better description of the heat than this screen capture of the DC Panda Cam:

That's all of us: Ugh. I give up. I'm so done with this heat.

Friday, July 17, 2020

Review: In the Hurricane's Eye: The Genius of George Washington and the Victory at Yorktown

It seems that nearly everything I know about the American Revolution is either incomplete or flat out wrong.

Take militias. Yes, this common man force had its moments of glory. But it had more than its fair share of failures and was often an ineffective fighting force. The Continental Army that I pictured in rags was indeed under staffed and underfunded. But that wasn't solely because the country was poor or lacked fighting age individuals. At the time, Congress didn't have the power to raise taxes and there were large swaths of Americans who simply didn't want to fund, much less fight, in the war.

The fighting force that did help win the day: the French. And it wasn't just land troops that made the difference, but the French Navy played a key role as well.

And that image in my head of soldiers facing off in straight lines opposite each other is only part of the story. Creative battle tactics were employed, including massive sieges where armies deployed engineers to help strategically strangle a city.

My understanding of how black soldiers participated in the war was also incomplete. On a positive note, there were black soldiers who served with distinction. On the troubling side of things was George Washington's relationship with slavery. His behavior goes beyond ignorance or being blinded by the time he lived in. He saw black troops performing well and knew of proposals that would add much needed soldiers to his ranks by allowing slaves to earn their freedom by serving their country. He had none of it. He was a slave owner through and through, working hard to track down his own runaway slaves and insuring others could do the same. His opinions apparently softened later in life.

Before you write off Washington, however, it's worth noting that one long held fact of mine does continue to hold true. It really was suggested that Washington take on the role of king, and he really did vehemently oppose the idea. Washington was a true believer in the idea of self governance long before anyone imagined such a scheme could work. In that respect, he was a man far ahead of his time.

Perhaps the greatest bit of misinformation I carried with me has to do with the state of our Union after the war. Ready for this: at the time the war ended the constitution hadn't been written, much less ratified. We were a collection of states winging it. The fact that 13 states constructed and agreed to the constitution before the American experimented fizzled out due to infighting is nothing short of miraculous.

So why am I bubbling over with American Revolution trivia? I listened to In the Hurricane's Eye: The Genius of George Washington and the Victory at Yorktown by Nathaniel Philbrick and was blown away by both how little I know about this pivotal war, as well as how interesting it all is. Given the local history and my own research I've come to appreciate that the Civil War was packed with courageous fighting, unlikely victories and riveting tails of history hanging in the balance. Philbrick shows that the same can be said about the Revolutionary War.

A big part of my blindspot associated with this war is the fact that I've often studied the opening chapters. Philbrick's book skips all of this and focuses on the build up and execution of the final pivotal battle: Yorktown. There's no Paul Revere and Minutemen. Instead, there's a beloved, but exhausted General Washington wheeling and dealing to try keep the fight and his very country alive. Though perseverance and more than a good bit of luck, spoiler alert, he pulls it off.

The fact that I happened to read Philbrick's book on the end of the war was a happy accident. From the looks of it, he's written other books that when combined provide a complete narrative of the war.

I'm thankful that Philbrick's book was so well written. Not just because I enjoyed his recounting of this pivotal time in American history, but because he opened my eyes to a topic I know so little about. I look forward to fixing that.

Friday, July 10, 2020

Review: Infinite Powers: How Calculus Reveals the Secrets of the Universe

You wouldn't think that an audio book on calculus would be a page turner, or whatever the audio equivallent of a page turner is. And yet, I found Steven Strogatz's Infinite Powers: How Calculus Reveals the Secrets of the Universe to precisely this. Stogatz's text is blend of history, math concepts, and novel case studies.

On the history side, Stogatz adds real dimension to characters like Galileo, Newton and other classic names. He manages to both humanize these individuals as well as show them as the mathematic uber geniuses they were. I also learned about new folks like Sofia Kovalevsky, who holds a number of firsts for women in mathmatics.

And then there are the interesting case studies. Strogatz shows how calculus was deployed in topics ranging from GPS development to facial reconstruction surgery. With Covid-19 pandemic as context, I found the case study relating to AIDS drug therapies to be especially fascinating. But <insert name of teacher>, am I ever going to need to use <insert advanced math concept> in the real world? Strogatz makes the case, yes, yes you will.

The part of the text that I truly relished was when Strogatz switched into math-teacher mode. From his demonstration of using infinity as a problem solving tool, to his explanation of euler's number and countless topics in between, I loved how clearly he could break down complex material. I was blown away when he effortlessly explained why we can't divide by 0, something I'd taken as gospel but never considered the underlying reason. Being an audio book, however, some topics went beyond my ability to mentally visualize them.

Consider integration. Prior to listening to Infinite Powers I could have told you that one used integration to find the area under a curve. What I couldn't tell was: (a) how to perform an integration and (b) why finding the area under a curve is so useful. I still can't do (a) but thanks to Strogatz, I can explain (b). And in some respects the why is even more imporant than the how.

If you're still on the fence about Infinite Powers, here's another factor to consider: it makes a powerful sleep aid. Our 5 month old and I listened to this book, and on many occasions, it helped deliver him to dream land. And if the kid grows up to be a mathmetical genius, we'll be able to trace his first exposure to advanced mathematical topics to this book.

I'm telling you, stepping a back into 'math class' with Strogatz is a worthwhile endevor. You'll walk away fresh ideas percolating in your head and no pesky tests or homework to stress you out.

Wednesday, July 08, 2020

That's So Covid

That's us picking blueberries for our 22nd wedding anniversary. In masks. Cause, you know, Covid.

Here's before and after pics from my first haircut during the pandemic. I got my hair cut right before July 4th, thinking there may be a spike in cases due to folks not social distancing during the holiday. Hopefully I'm wrong. Man, that was some special hair.

Thursday, July 02, 2020

A Local Guide to the Hazards of Covid-19

I love the seemingly endless ways to access and visualize Covid-19 data. Making sense of this data, however, is a different matter. That I've yet to crack. One of the best resources I've found to helps make sense of what's going on locally is Dr. Mike Silverman's Friday Night Facebook Update.

Dr. Silverman is the head of Arlington's Virginia Hospital Center's ER. Every Friday for the past couple of months he's been writing a summary of what he's seeing both in terms of local activity as well as national trends. It's become a tradition in our household for Shira to read the latest update aloud on Friday evening.

To get his take on the current status of the virus is to get hyperlocal information from an expert who's on the front lines. It doesn't hurt that he's a solid writer, too.

If you're an Arlingtonian, he's a must follow. If you're not, then you owe it to yourself to search out your own local Dr. Silverman.

My take away from recent updates: wear a mask, keep up the social distancing, don't panic, don't get cocky with the progress we've made and wear a mask.

Tuesday, June 30, 2020

A Programmer's Understanding Of e

Imagine I get a request from a bank to program the function that calculates money earned from one of their accounts. This seems too easy, but here's the code:

(define ($ amt)
  (inexact amt))


(define (grow/1 balance rate)
  (let ((interest (* balance (/ rate 100))))
    ($ (+ balance interest))))

;; Starting balance is $37 and growing by 8%
> (grow/1 37 8)
39.96

;; Confirm an edge case. 0% means no growth.
> (grow/1 37 0)
37.0

;; Another edge case. Growing 100% means doubling your money.
> (grow/1 37 100)
74.0
> 

"Close," the bank replies, "but not quite." The issue: we need to support growing the money in multiple increments. My imaginary contact explains:

Along with promising our customers 8% interest, we also tell them that their money will grow quarterly. So rather than one 8% increase at the end of the year, we give four 2% increases throughout the year.

That's not too tricky to program. Now my growth function takes in an additional frequency argument:

(define (grow/2 balance rate frequency)
  (let ((r (if (or (= 0 rate) (= 0 frequency))  0
               (/ (/ rate frequency) 100))))
    (let loop ((balance balance) 
               (frequency frequency))
      (cond ((= frequency 0) ($ balance))
            (else
             (let* ((interest (* balance r)))
               (loop ($ (+ balance interest))
                     (- frequency 1))))))))
;; The same $37 at 8%, but now grown quarterly
(grow/2 37 8 4)
40.04998992000001

;; The 0% interest edge case still produces no growth. Good.
> (grow/2 37 0 4)
37.0

;; Growing by 100% now *more* than doubles your money. Nice!
> (grow/2 37 100 4)
90.33203125

Growing the money 4 times a year at 8% gives a slightly better return. But check out that 100% edge case: that now more than doubles the money in the account. Looking at these examples one wonders if we can get a better return just by having the bank grow the money more often. Let's try it:

;; Quarterly - good.
> (grow/2 37 100 4)
90.33203125

;; Monthly - better.
> (grow/2 37 100 12)
96.68230573831309

;; Daily - best!
> (grow/2 37 100 365)
100.43899683480936

;; 1000 times per year
> (grow/2 37 100 1000)
100.52618549272809

;; 5000 times per year
> (grow/2 37 100 5000)
100.56637185376789

This strategy of incrementing the balance more often starts off promising. If we can get the bank to increment our money every day for a year we'll make a little over $100, versus the $90 we'll make growing the money quarterly. However, there's a limit to this strategy. Growing the money 1000 or 5000 times doesn't get us past the $100 return.

This makes sense: we may be able to convince the bank to grow our money 5000 times a year instead of 4--which sounds good--but each increase is using an itty bitty (a technical math term) interest rate.

So this is intereting, but what does this have to do with the math constant e.

Check this out: if you look up e you'll see that its value is approximiately:

  e = 2.718281828459045

Now let's say we run our growth/2 function on the simplest possible arguments: $1 grown at 100%. We get:

> (grow/2 1 100 100000)
2.718268237174493

That number is pretty close to e. Coincidence? Nope. An Intuitive Guide To Exponential Functions & e explains:

The number e (2.718…) is the maximum possible result when compounding 100% growth for one time period. Sure, you started out expecting to grow from 1 to 2 (that’s a 100% increase, right?). But with each tiny step forward you create a little dividend that starts growing on its own. When all is said and done, you end up with e (2.718…) at the end of 1 time period, not 2. e is the maximum, what happens when we compound 100% as much as possible.

So e isn't some mysterious number. It's the result of (grow/2 1 100 x) where x is very large number. So large that it's just about infinity. As we suspected, e is a limit:

e is like a speed limit (like c, the speed of light) saying how fast you can possibly grow using a continuous process. You might not always reach the speed limit, but it’s a reference point: you can write every rate of growth in terms of this universal constant.

While it's novel that we can discover this limit ourselves, that's not the whole story.

Back in 2018 I experimented with an animation framework with an odd quirk. You could draw exactly one thing: lines from (0,0) to (0,1). You could then scale, rotate and translate these lines. So while you could only draw one type of line, you could transform their size, shape and position in whatever you imagined. You can play a similar game with e. By raising e to a power, you can scale it to calculate any growth rate. Including negative growth (I'm looking at you radioactive half-life).

As a sign of how frequently one raises e to various powers Scheme names this function simply exp. Here's yet another grow function, this time powered by e.

(define (grow/3 balance rate)
  ($ (* balance (exp (/ rate 100)))))

> (grow/3 37 8)
40.08162150397347
> (grow/3 37 0)
37.0
> (grow/3 37 100)
100.57642765298466

So not only do we have a sense of what e is, we now have a new tool in our tool kit: ex. If you find yourself dealing with problems relating to continuous exponential growth, like say an out of control pandemic, e is your friend.

Thursday, June 25, 2020

But the Car Can't Do That | Lessons From a Mercedes A220 UI Glitch

Shira starts up the car and drives away. A few minutes into her drive she looks down to see this:

That's a Mercedes A220 dashboard minus all the gauges. She wasn't stopped for speeding, but had she been the answer would have been: no officer, I have no idea how fast I was going. That's because she had no speedometer on her display.

The A220's fully digital dashboard is sweet. You can switch up themes to change the look and feel. But alas, because it's software, it can also be buggy. And apparently Shira tripped over just such a bug. On 495. Going 60'ish miles per hour.

At a stop light she cut the engine and started up the vehicle again. There was no change. After leaving the car parked for a few hours, it went back to normal.

I recently had a similar, though far less dramatic experience. My ASUS C302 Chromebook wouldn't charge. There were only three explanations I could imagine: the outlet was bad, the cable was bad or the computer was bad. I tried another outlet and found it wasn't at fault. I ordered a new cable from Amazon and found it wasn't at fault. That meant that the charging port on the computer was busted. Or was it?

The first hit of a Google Search turned up an alternative explanation:

Hello all, I got an Asus chromebook flip about a month ago and today I plugged it in to charge and I got no response from the computer or the little indicator on the side.
...
This happened to me even though I was using the stable channel. I found another post on here about holding Refresh while hitting the Power button to perform an EC Reset (Reset charging controller).

Sure enough, holding down refresh and the hitting the power button fixed the problem. Apparently the software handles charging the device ran into an issue.

So is software an awful replacement for hardware and we're all doomed? Uh, no. As a programmer I'm hardly ready to give up on the terrific power and flexibility that software introduces into a system. But also as a programmer, I think it's important to stay humble.

When topics like electronic voting come up it's worth remembering examples like the above. "It'll be foolproof" they tell us. At which point I'll kindly chime in with "let me tell you about the time my wife found herself speeding down the highway without a clue as to her speed."

It boils down to this: Software is awesome. Proceed with caution.

Friday, June 19, 2020

An Ultra-Lightweight PHP Unit Test Framework

A project of mine called for a major DB re-org. The result was going to correct a number of longstanding system issues. It was also going to break the entire application. In theory, once the library code that powers the app was updated to work with the new database structure, the software would be fixed. To insure I addressed all the issues I decided to write a suite of unit tests and watch as they slowly went from all failing to all succeeding.

Given that the application is written in PHP, the obvious choice for a unit test framework was PHPUnit. After reading the docs, however, I couldn't resist putting together my own framework. It had three guiding principles.

First, I wanted tests to be easy to write. The convention I arrived was to have a collection of files nested under a top level tests directory. Each file would contain a variable named $tests that was an array of functions. Each function represents a single test. If the function executes without throwing an exception it is considered passing. That description sounds complex; in pracice the code is pithy:

 $ cd tests/utils/date-and-time
 $ cat time.php
 <?php
   $tests = [
     function() {
       $t1 = strtotime("tomorrow 3:00pm");
       $t2 = strottime("+1 day 3:00pm");
       assert($t1 == $t2);
     },
     
     function() {
       $t1 = time() + (60*60*24*3) + (60*60*3);
       $t2 = strototime("+3 days 3am");
       assert($t1 == $t2);
     }
   ];
 ?>

assert is a standard php function and can be configured to throw an exception. Though any code that throws an exception can be used to fail a test. By catching exceptions, it's possible to confirm that negative paths are working too. For example:

  $tests = [
    function() {
      $name = gen_unique_username();
      $u1 = new_user(['username' => $name]);
      try {
        $u2 = new_user(['username' => $name]);
        assert(false, "Uh, should have failed with duplicate user ex");
      } catch(DuplicateUserException $ex) {
        assert(true, "Hurray, we got a dup user ex");
      }
    }
  ];

Beyond picking the path for the .php file, nothing else is named. That's by design, as it makes composing tests that much simpler.

The next principle I was after was to make the test suite easy to run. Because the framework is so lightweight, it's straightforward to create top level programs that run the tests. For example, here's a test driver that runs from the command line:

<?php
require_once(__DIR__ . '/../lib/siteconfig.php');
(php_sapi_name() == 'cli') || die("I'm a command line tool, thanks.");


function show_outcome($file, $index, $error = false) {
  $path = preg_replace('|^.*?/tests/|', '', $file);
  echo "$path:$index:" . ($error ? $error : "pass") . "\n";
}
$stats = testing_run_all(['fail' => 'show_outcome']);

  
echo "\nPass: {$stats['pass']}, Fail: {$stats['fail']}\n";

And here's a similar version that runs from within the web app itself:

<?php
require_once(__DIR__ . '/../lib/siteconfig.php');
header("Content-Type: text/plain");
(g($_GET,'key') == 'a8a49399f8073e7f26d87a12771b954f') || die("Access Denied");

function show_outcome($file, $index, $error = false) {
  $path = preg_replace('|^.*?/tests/|', '', $file);
  echo "$path:$index:" . ($error ? $error : "pass") . "\n";
}
$stats = testing_run_all(['fail' => 'show_outcome']);

  
echo "\nPass: {$stats['pass']}, Fail: {$stats['fail']}\n";

And here's a version that's intended to run from cron and doesn't output the details of the tests. Instead, it logs the outcomes to AWS's CloudWatch, which make the data trivial to include in a system-wide dashboard.

<?php
require_once(__DIR__ . '/../lib/siteconfig.php');

(php_sapi_name() == 'cli') || die("I'm a command line tool, thanks.");

function show_outcome($file, $index, $error = false) {
  $cloudwatch = get_cloudwatch_instance();
  $cloudwatch->putMetricData([
    'Namespace' => 'app-unit-tests',
    'MetricData' => [
       [ 'MetricName' => $error ? "fail" : "pass",
         'Timestamp'  => time(),
         'Value'      => 1,
         'Unit'       => 'Count' ]
     ]
  ]);
}
testing_run_all(['fail' => 'show_outcome']);

Finally, I wanted make the framework easy to embed into other projects. By keeping the framework lean, I was able to hit this goal. Recently I got to test this out by packaging unit tests with a custom WordPress plugin. The tests directory was out of the way, and a WordPress friendly test running program was easy to write. Here's the test runner's code. Note how I'm using the prefix 'foo', it assumes I'm authoring with 'foo' plugin.

<?p<?php
/*
 * A PHP file for implementing a trivial unit test driver
 */
require_once(__DIR__ . "/../../../../wp-config.php");
header("Cache-Control: no-cache");
header("Expires: 0");
(foo_g($_GET, 'key') == '81b05f7ad603f5d7ae925e44d08ae14b') || wp_die("Permission Denied");
?>
<html>
  <head>
    <style>
     table {
       border-collapse: collapse;
       border: 1px solid #222;
       width: 100%;
     }
     table td {
       border-top: 1px solid #666;
       vertical-align: top;
     }
     td, th {
       padding: 1em;
     }
    </style>

  </head>
  <body>
    <table>
      <tr>
        <th>Test</th>
        <th>Outcome</th>
      </tr>
      <? $stats = foo_testing_run_all(['fail' => 'show_outcome', 'pass' => 'show_outcome']); ?>
    </table>

    <h2>Outcomes</h2>
    <p>
      <b>Pass:</b> <?= $stats['pass'] ?>
    </p>

    <p>
      <b>Fail:</b> <?= $stats['fail'] ?>
    </p>

  </body>
</html>

<?
function show_outcome($file, $index, $error = false) {
  $path = preg_replace('|^.*?/tests/|', '', $file);
  echo "<tr>";
  echo "<td>$path:$index</td>";
  echo "<td><pre>" . ($error ? $error : "pass") . "</pre></td>";
  echo "</tr>";
}

Below is the code for the test framework. Feel free to grab and use it. Remember: tests get easier and more addictive the more you write. Like, say, version control once you've setup your environment and overcome the learning curve you'll wonder how you ever lived without this tool.

<?php
// shared/lib/testing.php -- test framework
function testing_run_all($options = []) {
  return directory_deep_fold(__DIR__ . '/../../tests',
                      function($file, $carry) use($options) {
                        $stats = testing_run($file, $options);
                        return [
                          'pass' => $stats['pass'] + $carry['pass'],
                          'fail' => $stats['fail'] + $carry['fail'],
                        ];
                      }, ['pass' => 0, 'fail' => 0]);
}

function testing_run($file, $options) {
  set_error_handler('exception_error_handler');
  ini_set('zend.assertions', true);
  ini_set('assert.exception', true);

  $pass_handler = g($options, 'pass', function($file, $index) {});
  $fail_handler = g($options, 'fail', function($file, $index, $cause) {});
  require_once($file);
  $stats = ['pass' => 0, 'fail' => 0];
  $ctx = [];
  if(isset($tests)) {
    foreach($tests as $i => $t) {
      try {
        $ctx = $t($ctx);
        $pass_handler($file, $i);
        $stats['pass']++;
      } catch(Throwable $ex) {
        $stats['fail']++;
        $fail_handler($file, $i, $ex);
      } catch(Exception $ex) {
        $stats['fail']++;
        $fail_handler($file, $i, $ex);
      }
    }
  } else {
    $fail_handler($file, 0, new Exception("No variables \$tests defined"));
    $stats['fail']++;
  }
  return $stats;
}

// Utility Functions
function g($array, $key, $default = false) {
  return array_key_exists($key, $array) ? $array[$key] : $default;
}

function directory_deep_fold($root, $fn, $carry) {
  $dh = opendir($root);
  while($file = readdir($dh)) {
    if($file == '.' || $file == '..') {
      continue;
    } else if(is_dir("$root/$file")) {
      $carry = directory_deep_fold("$root/$file", $fn, $carry);
    } else {
      $carry = call_func($fn, "$root/$file", $carry);
    }
  }
  return $carry;
}

// Borrowed from: https://www.php.net/errorexception
function exception_error_handler($severity, $message, $file, $line) {
  if (!(error_reporting() & $severity)) {
    return;
  }
  throw new ErrorException($message, 0, $severity, $file, $line);
}

Thursday, June 11, 2020

The Magic of Plant Snap and The Taste of Honeysuckle Tea

The other day, while strolling through our neighborhood, I came across large swath of greenery dotted with delightful flowers:



My first instinct was to snap pics. Which I did. A lot. Then I turned to new app I've been playing with: Plant Snap. Plant Snap identifies plants from a picture you take within the app.

The concept reminds me of this classic commic:

To my shock, the app works surprisingly well. I tried it on a number of known plants and it properly identified most of them.  On unknown plants, it has served to give me a solid starting point. The app isn't magic and I wouldn't trust it blindly. But as a tool for the amateur botanist, especially one who doesn't want to nag others to learn about plants, the app appears to be a winner.

At $9.99/year, Plant Snap isn't cheap. But it has one notable feature which may justify the price: if automatic plant ID fails you can supposedly get a knowledgeable human to step in and help.

Back in front of the pretty flowers I snapped a pic with PlantSnap:

I was looking at Japenese Honeysuckle. Follow up research showed this to be true. I'm still amazed that the app guessed this from a single picture of a leaf.

Reading up on honeysuckle, it's a wonder  I didn't instantly recognize the plant myself. It's one of those classic plants that was brought to the US with such promise, and then proceeded to wreak utter havoc. While the plant is medicinally promising, pretty and easy to grow, it's fast growth and habit of strangling other plants means it's often considered an invasive weed.

Honeysuckle smells delightful, and a quick Google search revealed that you can make tea from the flowers. Which naturally I had to do. The stand of honeysuckle I found was on public land and plentiful, so I had no qualms about picking a few flowers to give this tea a try.

Preparation was simple: I put the flowers in a small glass jar, added boiling water and waited. I ran the drink through a strainer and found myself with a warm cup of yellow-green tinted liquid. I took a sip: it tasted flowery, woody and leafy. It wasn't love a first sip, but it wasn't bad either. On a backpacking trip, where everything tastes better, I bet having some fresh honeysuckle tea would be a nice treat.



I've always tried to treat my local environment as a sort of treasure hunting grounds: the gems are there, you just need to look past the see-it-everyday blindess that sets in. Plant Snap is the perfect tool for embracing this philosophy. Every random green thing in your neighborhood is now a click away from revealing its identity. So get snapping.

Friday, June 05, 2020

A Most Unusual Bedtime Playlist

Picking music for your baby's bedtime is easy. Fire up Soma FM's Groove Salad and you've got the perfect environment to send your little one off to dream land.

Except our little guy didn't get the memo. When he gets overtired and both desperately needs and fights sleep the ambient beats over at Groove Salad do nothing. Classical Music, Chill and Post Rock all come up equally short.

What he needs, and it's beyond counterinutive, is to rock out to some bang'n tunes. I wouldn't believe it except I witness this on a daily basis. To watch our little one drift off to sleep while Dwight Yokum or Bishop Briggs loudly jams away is to witness a mystery and miracle.

So here it is, the world's most unusual bedtime music list. Kids are weird.

Sweet Dreams!

Monday, June 01, 2020

From Ferocious Meat-Eater to Handsome Acrobat

Meet Ed the Eyed Elater. Ed is a handsome beetle with a passion for acrobatics (he can flip himself off his back, hurling himself four times his body length). But don't let Ed's good looks and clever party trick fool you. In larvae form, he's a beast:

Found under logs and other dark, damp places, the Alaus oculatus larva looks like a stocky, yellowish-brown, segmented worm. It has a flat, dark brown rectangular head that ends in 2 powerful jaws. The jaws, which resemble small crab legs, are used to disable and dismember prey. An individual is about 2 inches long. It looks rather dangerous at the posterior end, too. The 10th segment has 2 anal hooks, 10-12 spines, and setae (hairs) in front of the anus.

Fortunately, Ed puts his powerful jaws, anal hooks and spines to good use eating garden pests. So if you see Ed, a Thank You For Your Service is in order.

Mostly I'm glad Ed stopped by my porch so I could meet a new critter all without leaving the comfort of our quarantine.

Wednesday, May 27, 2020

Skills Inspiration from a Real Life Worst Case Survival Guide

I can't explain it: whenever I pick up big 'ol book on wilderness skills or survival I feel buzz of excitement. Perhaps it's the fixer in me that is eager to synthesize and deploy this new found knowledge. Or maybe I got a kick out of reading these types of book as a kid and this is just a burst of nostalgia. Whatever it is, I love me a survival manual.

Mind you, these texts are often limited in value. The textual descriptions, vague line art, and random pictures often leave a lot to be desired. Ultimately, there's no substitute for experience; even if that experience is in your backyard. Still, these manuals do serve one notable purpose: they offer inspiration for which skills one should investigate and master.

Kicking around on the web, I came across one of these references I hadn't seen before. AF Handbook 10-644 - Survival Evasion Resistance Escape (SERE). This is apparently the Air Force's manual for their SERE program; the course pilots takes to be prepared for ejecting over enemy territory.


The SERE course is legendary stuff and covers everything from basic wilderness survival to evading the enemy to dealing with be a prisoner of war. To even get a glimpse into this world is a treat.

The range of topics covered is impressive. From nuts and bolts of survival to higher level topics such as understanding weather and various types of insulation; from surviving an avalanche to making landfall in raft; the book tries to cover it all. 

Sprinkled throughout the text are accounts of soldiers who deployed  the documented techniques. Consider this tidbit from page 621.

Colonels John Dramesi, a USAF F-105 pilot shot down in April 1967, and Edwin Atterberry, a USAF RF-4C pilot shot down in August 1967, used a disguise as the main focus of their escape attempt from the “Hanoi Hilton”. They used a combination of ground iodine pills and redbrick dust to match the average skin color of the North Vietnamese. Sandals modeled after the shoes of the North Vietnamese peasant. They gathered bits of cloth and string and made white “surgical” masks to disguise facial features. Using thread pulled from towels and needles made of copper wire, they fixed their black prison clothes to look like peasant dress. Out of strips of rice-straw pulled from sleeping mats, the IP wove two conical hats. Originally they had camouflage nets made from three blankets with clumps of rice-straw from brooms sew on them, but were forced to turn them over to the rest of their cell mates, so they used mosquito netting with clumps woven into them. The IP also stole a burlap bag, two baskets, and a carrying pole as props to look like traveling peasants. The Colonels moved through the populated area of Cu Luc North Vietnam without raising suspicion, coming within a yard of policemen and others during their disguised evasion movement. They greeted those that walked with simple nods, while any locals who attempted to talk to them were ignored as the pair cong forward at a constant rate. While their disguised allowed them to get out Hanoi, unfortunately they did not travel far enough before going to a hold-up site and were subsequently captured.

The manual delivers mightily on the inspiration front. Below are 20 skills that I logged as worthy of future investigation and I'm sure I could find more.

If you're looking for a worst case survival guide, AF Handbook 10-644 is where it's at. Master the skills in there and you'll be ready for anything.

  1. Identifying and using 12 common medicinal plants. (page 87)
  2. Crafting an improvised sleeping bag. (page 199)
  3. Crafting improvised footwear, specifically the curiously named Hudson Bay Duffel Bag. (page 192)
  4. Using quartz or pyrite as a spark generator. (page 229)
  5. Using clouds for weather prediction. (page 101)
  6. Using sandstone and other found rocks as an improvised knife sharpener. (page 241)
  7. Learning two common hand sewing stitches. (page 253)
  8. Using the SODIS method of water purification. (page 293)
  9. Understanding improvised methods for determining your current latitude and longitude. (page 410)
  10. Navigating at night using stars. (page 415)
  11. Using an improvised trail marking scheme. (page 430)
  12. Crafting a field expedient oven for baking. (page 365)
  13. Using field expedient methods for preserving food. (page 367)
  14. Constructing an improvised raft. (page 500)
  15. Learning the evasion checklist. (page 530)
  16. Urban navigation: identifying navigational clues from landmarks and local history. (page 623)
  17. Urban navigation: determine direction from weather effects on buildings and infrastructure. (page 625)
  18. Preparing a personal survival kit. (page 278)
  19. Constructing an improvised backpack. (page 450)
  20. Learning basic rock climbing technique and holds. (page 462)

Friday, May 22, 2020

Hiker in Training: Ellanor C Lawrence Park

I'm on a mission to get our 16 week old ready to tackle serious hikes. We've done the prep work and knocked out a short, but nearby trail. Next up was to pick a trail that was longer in distance and drive time.

Our go-to app for finding trails is All Trails. When Shira and I are shopping around for an adventure, we set the difficulty to medium or hard, and the distance to 7+ miles. This time, we looked around for easy trails that would be less than 5 miles. My gosh, there are so many options we'd never heard of!

The one we picked for this adventure was the loop at Ellanor C. Lawrence Park. This 3.8 mile hike is located in a park surrounded by suburbs. Yet, the vibe was that of a real walk in the woods. We caught glimpses of houses only a couple of times and the road noise was minimal.

The trail itself was in great condition and we zipped right through it, stopping only briefly for a snack.

In the age of COVID-19, we wanted solitude not only to enhance the hike but to avoid social distancing issues. At the entrance to the park there's a delightful pond which a few families were congregating around. We slipped by them and on to the trail and from there saw almost nobody else for the rest of the hike.

All in all, our little hiker did great. He endured the 35 minute car ride without an issue and enjoyed the walk in the woods. For our part, we enjoyed discovering a new bit of green space that's perfect for when we need an easy hike. And I even got to snap quiet a few pics of flowers. Ellanor C. Lawrence Park is a winner.