<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
   <title>aBlog</title>
   <link rel="alternate" type="text/html" href="http://www.pandamatak.com/people/anand/blog/" />
   <link rel="self" type="application/atom+xml" href="http://www.pandamatak.com/people/anand/blog/atom.xml" />
   <id>tag:www.pandamatak.com,2012:/people/anand/blog/2</id>
   <updated>2011-12-04T03:25:32Z</updated>
   <subtitle>Anand Venkataraman&apos;s Blog</subtitle>
   <generator uri="http://www.sixapart.com/movabletype/">Movable Type 3.35</generator>

<entry>
   <title>Do it with D3 - Lazy Loading Images</title>
   <link rel="alternate" type="text/html" href="http://www.pandamatak.com/people/anand/blog/2011/12/do_it_with_d3_lazy_loading_ima.html" />
   <id>tag:www.pandamatak.com,2011:/people/anand/blog//2.82</id>
   
   <published>2011-12-04T01:52:11Z</published>
   <updated>2011-12-04T03:25:32Z</updated>
   
   <summary>I&apos;m lucky to have stumbled upon Mike Bostock&apos;s excellent D3 library when I was looking for a good implementation of force-directed layouts for certain kinds of graphs. I now use it for many more things than graph rendering. Data Driven...</summary>
   <author>
      <name>&amp;</name>
      <uri>http://pandamatak.com/people/anand</uri>
   </author>
         <category term="Technical" scheme="http://www.sixapart.com/ns/types#category" />
   
   <category term="63" label="d3" scheme="http://www.sixapart.com/ns/types#tag" />
   <category term="52" label="images" scheme="http://www.sixapart.com/ns/types#tag" />
   <category term="64" label="lazyloading" scheme="http://www.sixapart.com/ns/types#tag" />
   
   <content type="html" xml:lang="en" xml:base="http://www.pandamatak.com/people/anand/blog/">
      <![CDATA[I'm lucky to have stumbled upon <a href=http://mbostock.github.com/d3/>Mike Bostock's excellent D3 library</a> when I was looking for a good implementation of force-directed layouts for certain kinds of graphs. I now use it for many more things than graph rendering. Data Driven Documents are indeed the future of the web and HTML5 apps, and d3.js is sure to have an enormous impact.

As an example of how D3 helped me greatly simplify things I'd hitherto put together using plain ol' javascript and jQuery, Here's an adaptation in D3 of a lazy image loader I'd written last year. The old code was over 50 lines long and not as simple as befits an obviously simple task such as lazy loading.

Now, using D3, the code is an awesome 10 lines of pure simplicity.  <a href="http://pandamatak.com/people/anand/demo/lazy">See the demo here</a>. (View Source to copy).

&

]]>
      
   </content>
</entry>
<entry>
   <title>A Google room with two doors</title>
   <link rel="alternate" type="text/html" href="http://www.pandamatak.com/people/anand/blog/2011/10/a_google_room_with_two_doors.html" />
   <id>tag:www.pandamatak.com,2011:/people/anand/blog//2.81</id>
   
   <published>2011-10-16T16:19:13Z</published>
   <updated>2011-10-16T19:41:26Z</updated>
   
   <summary>A room with two doors and scant else. I love Google and its products. Despite some points made in Steve Yegge&apos;s fantastically well-written and enjoyable rant, I&apos;ve always thought its obsessive product focus and extreme emphasis on minimalistic designs a...</summary>
   <author>
      <name>&amp;</name>
      <uri>http://pandamatak.com/people/anand</uri>
   </author>
         <category term="Technical" scheme="http://www.sixapart.com/ns/types#category" />
   
   <category term="60" label="google" scheme="http://www.sixapart.com/ns/types#tag" />
   <category term="62" label="product-design" scheme="http://www.sixapart.com/ns/types#tag" />
   
   <content type="html" xml:lang="en" xml:base="http://www.pandamatak.com/people/anand/blog/">
      <![CDATA[A room with two doors and scant else.  I love Google and its products. Despite some points made in <a href=https://plus.google.com/112678702228711889851/posts/eVeouesvaVX>Steve Yegge's fantastically well-written and enjoyable rant</a>, I've always thought its obsessive product focus and extreme emphasis on minimalistic designs a wise investment. After all, you can always furnish an empty house with furniture of your liking (as long as the doors are wide enough), but you can't reconfigure a home crammed with someone else's favorite furniture that's bolted right down.

But then I recently noticed an alarming misstep in Google's product design - Almost half as bad as LinkedIn's horrible home page that has <strong>'Sign Up'</strong> fields showing by default rather than <strong>'Sign In' fields with an optional link to 'Sign up if not already a member'</strong>. The latter and better design makes it easy for returning visitors (which a CEO should hope to be many). The former makes it one search-and-click harder for loyal users while embarrassingly making this implicit admission - that there is a greater business need for new users than for retaining existing ones. The latter says we'll take good care of you once you're with us. The former says "We love those that don't love us more than those that do - That's natural human psychology, and you better get used to it right now, so there!"
]]>
      <![CDATA[The Google fubar I'm talking about is this:

<a href="http://pandamatak.com/people/anand/blog/gmail-logout.png"><img alt="Gmail logout screen" src="http://www.pandamatak.com/people/anand/blog/gmail-logout.png" width="500" /></a>

If you're anything like me, you have more than one Gmail account (notwithstanding Circles :-). Almost everyone i know has at least one.  As I'm sure even a cursory analysis of the Gmail data will show, the majority of Gmail sessions are logged out only to be logged right back in by the same person or by someone else in the family. Perhaps I'm wrong about what the data shows, but in any case, why even seed doubt in a prospective user's mind that there are many who need to sign up? Isn't it much better to subtly reinforce the sub-conscious message that the whole world is on Gmail?

The above logout page doesn't do justice to the near ubiquity of Gmail. Instead of immediately presenting with a re-login screen (with an optional link to sign up), it takes me to a page, whose purpose, for all I can tell, is purely promotional. It's a room with a door leading in, with nothing else but a door leading out, except for wall papering with marketing material you're invited to admire.

I cannot conceal my mild disappointment (and inconvenience) with this <em>feature</em>. But knowing Google's penchant for rapid parallel testing and iteration cycles, this is something that (a) not the whole world is seeing and (b) will hopefully soon be corrected, especially when folks have pointed it out to them. Please join me in raising this issue on its feedback pages and speaking of it to our Googler friends.

&
]]>
   </content>
</entry>
<entry>
   <title>What&apos;s a Yot?</title>
   <link rel="alternate" type="text/html" href="http://www.pandamatak.com/people/anand/blog/2011/05/whats_a_yot.html" />
   <id>tag:www.pandamatak.com,2011:/people/anand/blog//2.80</id>
   
   <published>2011-05-10T06:32:29Z</published>
   <updated>2011-05-11T14:24:29Z</updated>
   
   <summary>Last week, on the way back from my swim at the Y, I noticed a number of cop cars outside the house opposite the Y. I was consumed with curiosity as any sane person would be, but wouldn&apos;t dare stop...</summary>
   <author>
      <name>&amp;</name>
      <uri>http://pandamatak.com/people/anand</uri>
   </author>
         <category term="Technical" scheme="http://www.sixapart.com/ns/types#category" />
   
   
   <content type="html" xml:lang="en" xml:base="http://www.pandamatak.com/people/anand/blog/">
      Last week, on the way back from my swim at the Y, I noticed a number of cop cars outside the house opposite the Y. I was consumed with curiosity as any sane person would be, but wouldn&apos;t dare stop and ask them what it was all about. We all know how much cops like lookie loos.


      <![CDATA[So I naturally did the next best thing. I Yotted on <a href=http://yatown.com>Yatown</a>. <a href=http://yatown.com>Yatown</a>, started by <a href=http://profiles.google.com/pentagoniac/about>Christopher Nguyen</a>, is a neighborhood social site that aggregates info from locals. It's a place where I could "tweet" but not have my tweet go out to the world, but just to my 'hoodies. To paraphrase Keaton's character in "The Paper". I don't effin live in the effin world. I effin live in effin Palo Alto" (Well almost. I think I have a bit too few f's in there). 

<a href=http://yatown.com>Yatown</a> is a service I can rely upon to bring me the happenings, big and small, in my little town - from earthquake and tsunami warnings, to garage sales and fund raisers. It meshes into the real world by way of locality and real-people connections. A message intended for my family will reach us somehow, since people in our local network know us well enough to call one of us, or leave a post-it note stuck to our door for when we return.

So what's a yot? Honestly, I don't know. But that's the word that popped into my head when I pondered, looking for the right word to describe a unit of thought to share on Yatown. There you go - A "<em>yot is a unit thought you jot down on Yatown</em>". Soon after my little yot, some 'hoodies reached out to me by email and phone - such is the reach of the nascent Yatown already. They didn't have answers either, but some pretty good theories about what was going on :-)

Needless to say, I'm excited for Chris about the prospects of Yatown, and I'm super glad there's something like this out today. I, for one, certainly plan on using it regularly.

&






]]>
   </content>
</entry>
<entry>
   <title>Ode to Tech Cooks</title>
   <link rel="alternate" type="text/html" href="http://www.pandamatak.com/people/anand/blog/2011/05/ode_to_tech_cooks.html" />
   <id>tag:www.pandamatak.com,2011:/people/anand/blog//2.79</id>
   
   <published>2011-05-09T06:48:42Z</published>
   <updated>2011-05-11T01:15:55Z</updated>
   
   <summary>I wrote this for my wife&apos;s recipes website a few months ago. But I like it so much that I have decided to share it with everyone :-) :-) Ode to Tech Cooks No potatoes, no carrots, no garlic nor...</summary>
   <author>
      <name>&amp;</name>
      <uri>http://pandamatak.com/people/anand</uri>
   </author>
         <category term="Technical" scheme="http://www.sixapart.com/ns/types#category" />
   
   
   <content type="html" xml:lang="en" xml:base="http://www.pandamatak.com/people/anand/blog/">
      <![CDATA[I wrote this for my wife's recipes website a few months ago. But I like it so much that I have decided to share it with everyone :-) :-)

<div style="text-align:center;">

<h3>Ode to Tech Cooks</h3>

No potatoes, no carrots, no garlic nor leeks
  But algos and APIs, ambrosia for us geeks

No whey, no milk, no butter nor curds
  Just programming poils, to bond with fellow nerds

Not how to make pickle, with dills that are kosher
  But how to get out of one, with clever use of closure

Not how to jazz up that boring curry with spices
  But how to resize in real-time with push, pop and splices

No mention of pesto, pate, or fry-less fwitters
We're itchin' to share how we wall-posts and twitters

You won't find us by the oven, or sweatin' by the stove-top
  We're lounging on that sofa, logged into our lovetop

Not chopping, not dicing, not sifting by the pound
  But hacking, tuning, refining, 'til Zarro boogs found!

</div>

PS. BTW, I know at least one other person (Stewart Alsop of Alsop-Louie) likes this poem. But he's a self-confessed foodie like me.
]]>
      
   </content>
</entry>
<entry>
   <title>A proof from the mouth of a babe</title>
   <link rel="alternate" type="text/html" href="http://www.pandamatak.com/people/anand/blog/2011/05/a_proof_from_the_mouths_of_bab.html" />
   <id>tag:www.pandamatak.com,2011:/people/anand/blog//2.78</id>
   
   <published>2011-05-08T15:49:19Z</published>
   <updated>2011-05-11T01:23:40Z</updated>
   
   <summary>One of the high points of this last academic year has been volunteering in Katya&apos;s 2nd/3rd grade English and Math classes. I was suitably rewarded for this just a few weeks ago with a delicious treat of an elegant mathematical...</summary>
   <author>
      <name>&amp;</name>
      <uri>http://pandamatak.com/people/anand</uri>
   </author>
         <category term="Happenings" scheme="http://www.sixapart.com/ns/types#category" />
   
   
   <content type="html" xml:lang="en" xml:base="http://www.pandamatak.com/people/anand/blog/">
      <![CDATA[One of the high points of this last academic year has been volunteering in Katya's 2nd/3rd grade English and Math classes. I was suitably rewarded for this just a few weeks ago with a delicious treat of an elegant mathematical argument from a 2nd grader (Katya's in 3rd). Here's the puzzle and its solution (names of individuals have been changed).

It all started with the teacher, Judith, posing a seemingly simple problem to the kids. She was teaching fractions that Thursday. In the latter half of Math class, the kids were each given rectangular cards, and asked to imagine they were cookies (or pizzas). Since classes at Ohlone are always mixed between two grades, the problems are always posed in a range of difficulties. With this one, the kids had to divide up their cookies into 2, 4, 8 and 3 equal parts. The more different ways you could slice it up, the more points you get.

The puzzle I want to talk about concerns the division of the rectangle into 4 equal parts. Most kids did it the conventional way, by which I mean folding the rectangle in half, first vertically, then horizontally, and cutting along the creases. Edgar (name changed), however, adopted a different tack. He folded the rectangle along its two diagonals.

The cool thing about this is that it's not immediately obvious that this way of cutting the rectangle produces 4 equal cuts, especially not to 2nd or 3rd graders. See the figure below, for instance:

<div style="text-align:center;">
<img alt="rectangle-1.jpg" src="http://www.pandamatak.com/people/anand/blog/rectangle-1.jpg" width="411" height="160" />
</div>

Can we tell immediately that Slice A is the same size as Slice B? Edgar claimed they were, but wasn't able to explain it - he just felt it in his gut.  Judith, awesome teacher that she is, immediately recognized the opportunity to enrich and picked up on this issue, calling the attention of the entire class to the problem. She wrote it up on the white-board and named it "Edgar's challenge". Anyone who was done with the rest of the problems was welcome to give it a shot. Can they show that the four slices were the same size?

]]>
      <![CDATA[It turns out that a great many of the kids were done with the "rest of the problems" really quickly, and were intrigued by Edgar's challenge. They all tried to prove it, and mostly with what I might call the straightforward and more "boring" proof. It uses the formula for the area of a triangle, which is equal to half its base times its height. The base of triangle A is equal to the width of the rectangle (if you rotate A by 90 degrees). Its height, clearly is half the length of the rectangle. Thus it's area must be one quarter the product of the rectangle's height and width. By a similar argument, you can show that the area of triangle B is also exactly that quantity.

I was checking to see if there were any other interesting arguments and questions, when Mary ran up to me and asked if I could check her answer to Edgar's challenge. What she had was different from everyone else, and so she couldn't tell if it was right or not. So I went, and was suitably impressed. Mary took the 4 triangles and assembled two rhombuses (or is it rhombi?) from them.

<div style="text-align:center;">
<img alt="rhombus-1.gif" src="http://www.pandamatak.com/people/anand/blog/rhombus-1.gif" width="406" height="160" />
</div>

<div style="text-align:center;">
<img alt="rhombus-2.gif" src="http://www.pandamatak.com/people/anand/blog/rhombus-2.gif" width="408" height="164" />
</div>

As you can see from the above pictures, the first rhombus was made with triangles A and C, and the second with triangles B and D. She laid one over the other and said they're the same size. Since each of these is made of two "equal" triangles, she said, the 4 triangles also have to be of the same size each.  No formulas, no equations, just a plain and simple, albeit elegant geometric proof, stated with child-like innocence. Pretty awesome, considering that that's how one comes up with the formula for a triangle's area in the first place! Somewhere along the continuum, one loses sight of the beginnings until teachers like Judith and schools like Ohlone teach us the value of the past!

That weekend, I remember recounting this marvelous experience to <a href="https://profiles.google.com/cactgent/about">Chris Nguyen</a> over a breakfast catchup. And he followed up with an equally interesting tidbit his daughter had just discovered a week ago at a play structure - What single formula gives the area of a rectangle, trapezoid and a triangle? The answer, not so surprisingly (or surprisingly to some) is quite simple - It's the product of the height and the average length of the two parallel sides.

There you go - two nice little rewards in return for volunteering in a child's class, which is rewarding in itself.  Not too shabby.

&




]]>
   </content>
</entry>
<entry>
   <title>Gmail Autologout and Timed Session</title>
   <link rel="alternate" type="text/html" href="http://www.pandamatak.com/people/anand/blog/2011/02/gmail_autologout_and_timed_ses.html" />
   <id>tag:www.pandamatak.com,2011:/people/anand/blog//2.75</id>
   
   <published>2011-02-24T14:53:50Z</published>
   <updated>2011-02-26T16:58:28Z</updated>
   
   <summary> If your family is anything like ours, and your home is anything like ours, then you probably have one laptop per member on average, but everyone seems to prefer to use the &quot;living room laptop&quot; that&apos;s always sitting on...</summary>
   <author>
      <name>&amp;</name>
      <uri>http://pandamatak.com/people/anand</uri>
   </author>
         <category term="Technical" scheme="http://www.sixapart.com/ns/types#category" />
   
   
   <content type="html" xml:lang="en" xml:base="http://www.pandamatak.com/people/anand/blog/">
      <![CDATA[<div style='text-align:center;'>
  <img alt="gm-autologout.png" src="http://www.pandamatak.com/people/anand/blog/gm-autologout.png" width="508" height="189" />
</div>

If your family is anything like ours, and your home is anything like ours, then you probably have one laptop per member on average, but everyone seems to prefer to use the <em>"living room laptop"</em> that's always sitting on the coffee-table. Thank Google for this - We don't really need to live down on earth any more, preferring instead the lofty locale of the clouds wherein most of our data resides.

The upside of this situation is that we are much more tolerant of individual computer crashes, since every machine to us is pretty much the same once we login. But the downside is that we invariably forget to log out of sessions in the common pool of machines we tend to use. This is normally no big deal, but the living room laptop tends to get used by our guests too. I have too often had to log out of private email sessions left open by our guests (as I hope my hosts will do for me in their homes :-)

To save time, worry and potential embarrassment, I've always wished that Gmail provided a configurable Autologout feature that users can turn on in their personal profiles. This would save them the trouble of having to remember whether they logged out of their sessions before they left for home.

Finding no such "Labs" feature and waiting all too patiently for it to appear, I eventually ended up writing my own (based on Chris Nguyen's cool Greasemonkey script for Searching Unread mail in Gmail). Because I have it on good authority from my friends at the big G that a full featured auto-logout will likely make its appearance in Gmail Labs sometime soon, I saved myself the trouble of embellishing the bare-bones functionality of this feature. But I find it useful, and hopefully so will you, until the official feature is released from the plex.

Here are the few really simple instructions on how to get a timed Gmail session with auto-logout within your browser. Oh, BTW, I implemented a Timed Session, rather than auto-logout based on inactivity - it's a quicker hack; I didn't have to listen for events and such.
]]>
      <![CDATA[To install Gmail Autologout, you first need to install the Greasemonkey plugin. I describe how to do it in Mozilla Firefox below. Installation in most other browsers is pretty simple and similar, if not pre-done for you.  

Step 1 of 3:  Install the Greasemonkey Firefox add-on.  Greasemonkey allows you to simplify and automate a great many tasks using free scripts written by folks like us. I recommend that you install it.  Get it from the official Mozilla add-ons page: <a href=https://addons.mozilla.org/en-us/firefox/addon/greasemonkey/>https://addons.mozilla.org/en-us/firefox/addon/greasemonkey</a>.  Visit the page and click on the big green button that says "Add to Firefox":

<div style='text-align:center'>
  <img alt="greasemonkey-ff.png" src="http://www.pandamatak.com/people/anand/blog/greasemonkey-ff.png" width="538" height="239" />
</div>

Follow through with the rest of the steps. When you restart Firefox, you should see that Greasemonkey is active in the FF taskbar at the bottom right. Make sure the add-on is enabled by checking that the monkey is not grayed out.  You can click on the monkey to toggle activation at any time during your Firefox session.

<div style='text-align:center;'>
 <img alt="greasemonkey-status.png" src="http://www.pandamatak.com/people/anand/blog/greasemonkey-status.png" width="187" height="102" />
</div>

You should also see a new menu item called Greasemonkey under "Tools" in the top menu, where you can selectively enable and disable specific scripts under "Manage User Scripts".

Step 2 of 3: Install my Gmail Autologout user script from userscripts.org.  You can get it at <a href=http://userscripts.org/scripts/show/97613>http://userscripts.org/scripts/show/97613</a>. If you forget the URL, search for "gmail autologout" on the userscripts.org site.  Again, installation is a simple matter of clicking on the big green button that says "Install" and following through with the rest of the steps.

<div style="text-align:center;">
  <img alt="gm-us-install.png" src="http://www.pandamatak.com/people/anand/blog/gm-us-install.png" width="500" />
</div>

That's it. If you login to your Gmail account now you should see a timer counting down (every 5 seconds, starting at 5 minutes). When it hits zero, you will be logged out of your gmail session (unless you have something unsaved, in which case you'll get a popup dialog).

Step 3 of 3: There's really no third step.  But if you really want it, please go to 
<a href=http://userscripts.org/scripts/show/97613>http://userscripts.org/scripts/show/97613</a> and become a fan of this script, or review it.

<h2>FAQ</h2>

Q. What if I have unsaved work? Will auto-logout make me lose it?

A. No. If you have unsaved work, Gmail will issue a popup confirmation dialog before logging you out. If you did actually get logged out, then your work was auto-saved and you can get right back to it from Drafts after logging back in. The trick I use when presented with this popup is to hit "Cancel" - telling Gmail that I don't want to logout. This, of course, silences Gmail for the moment, but the user script timer gives you just 5 more seconds before the next popup (if your work isn't auto-saved by then). To get another 5 whole minutes, simply save your work and refresh the Gmail page with Ctrl-R sometime within the 5-second window. It's like totally doable, I do it often :-)

Q. Can I get more than 5 minutes?

A. The short answer is "No." But if you can figure out a way to getElementByID of the text-input box that holds the countdown, inside of the timedSession() function, I'd appreciate knowing about your update to my script 'cos I'll be the first to use it.  Note that you can always hit Ctrl-R in the Gmail window to refresh your 5-minute at any time.

Alternately, download a copy of the script (name it something that ends in .user.js), edit it locally to change the 5 minutes to your desired value and drag the re-saved script from your desktop into FF. The thing to change is the "value=300" attribute for the &lt;input element near the bottom of the gm_autologout() function.

Q. Are there any caveats I should know about?

Yes - The script runs within the scope of Gmail only.  If you login to your Google account outside of Gmail, or login to Gmail but close the tab without logging out, the script will not run and not log you out.  Keep the Gmail session open.

Q. How can I prevent being auto-logged-out when I'm working on a Google Doc and have my Gmail tab open simultaneously?

A. The easiest way is to simply close the Gmail tab and open it if and when you want (you're already logged in, so there's little overhead).  Or you can open a dummy popup chat window within Gmail and leave that open. After 5 minutes Gmail will issue a dialog asking if you want to logout because it will close that chat window, and you can leave that popup untouched until such time as you're really ready to logout.  Hacky, but it works :-)

</ol>

Note that you can remotely sign out of Google sessions from anywhere via the "Last Activity Link at the bottom of your Gmail page (see pic below).

<div style="text-align:center;">
  <img alt="gm-activity.png" src="http://www.pandamatak.com/people/anand/blog/gm-activity.png" width="368" height="73" />
</div>

Thus the feature I have provided is at best to set your mind at ease while on the road home.

Enjoy!

]]>
   </content>
</entry>
<entry>
   <title>Client-side image crop and then upload</title>
   <link rel="alternate" type="text/html" href="http://www.pandamatak.com/people/anand/blog/2010/11/clientside_image_crop_and_then.html" />
   <id>tag:www.pandamatak.com,2010:/people/anand/blog//2.74</id>
   
   <published>2010-11-06T15:44:10Z</published>
   <updated>2011-12-04T01:48:08Z</updated>
   
   <summary>Earlier this week, Mathangi wanted to know if it&apos;s possible to crop an image in the browser and then upload it to the server for her website. I promised I&apos;ll think about it over this weekend. So I got up...</summary>
   <author>
      <name>&amp;</name>
      <uri>http://pandamatak.com/people/anand</uri>
   </author>
         <category term="Technical" scheme="http://www.sixapart.com/ns/types#category" />
   
   <category term="57" label="client-side" scheme="http://www.sixapart.com/ns/types#tag" />
   <category term="59" label="crop and then upload" scheme="http://www.sixapart.com/ns/types#tag" />
   <category term="55" label="html5" scheme="http://www.sixapart.com/ns/types#tag" />
   <category term="52" label="images" scheme="http://www.sixapart.com/ns/types#tag" />
   
   <content type="html" xml:lang="en" xml:base="http://www.pandamatak.com/people/anand/blog/">
      <![CDATA[Earlier this week, Mathangi wanted to know if it's possible to crop an image in the browser and then upload it to the server for her website. I promised I'll think about it over this weekend. So I got up early today and spent a good hour looking around for a solution. There seems to be a ton of code out there that lets you crop an image using JavaScript and PHP, including the excellent JCrop library. However, these all seem to be written for pre-HTML5 days. While you can define the crop area on the client, actual cropping is done on the server. See for example, at the time of writing, the <a href= "http://deepliquid.com/content/Jcrop_Implementation_Theory.html"><em>disclaimer</em></a> in the JCrop manual.

<blockquote>
Jcrop creates an interface to crop an image. However, actually creating a new, cropped image file is obviously beyond the scope of a client-side plugin. It may also be the most challenging part of implementing such a process in your web application (now that you've found Jcrop).
</blockquote>

Unfortunately, this defeats the whole purpose of the upload for my wife. She wants the image cropping to be done on the client because the upload will be much smaller, and only consist of the <em>area of interest</em> that the user <em>wants to upload</em>.  Not the whole 10MB JPEG file.  But fortunately, the task may not be as <em>challenging</em> as the disclaimer suggests.

So I put together a quick and tiny solution using a combination of JCrop, JQuery, HTML5's neat File and Canvas APIs, and a "clever" trick. Here is the full code in its awesome smallness (only about 32 lines for the HTML file and 55 lines for the JS including comments).  Obviously you need to embellish it considerably.

You can see this code in action at <a href="http://pandamatak.com/people/anand/demo/crop"> this demo here</a>.  Of course, it only works in HTML5 compatible modern browsers, such as Chrome, Firefox and Safari.

If you're just interested in the code, feel free to grab it by Viewing Page Source, and then linking through to the JavaScript in the file crop.js.

</ul>]]>
      <![CDATA[<h2>How it works</h2>

Jcrop is fantastic, but I couldn't figure out a way to get it to latch on to the HTML5 canvas object. Apparently it could only crop images directly. To access the individual pixels within the image, we need the image to be in an HTML5 canvas. What we need, therefore, is some way to map the Jcrop-provided crop-coordinates into corresponding canvas coordinates so we can extract the crop region as a data stream (image data).  There's a few different ways to do this, including having a hidden canvas into which the image is secretly loaded. But I just took the easy shortcut and overlaid the canvas directly on top of the raw image in a div of the exact same dimensions :-)

HTML5 drag/drop hooks allow us to drag an image into the div. Using the FILE api, we then read the image contents from the local file system into a data URL and display it in both the div and the canvas. Note that I scale the longer side of the image to fit within the 200 pixel div I use to display it. You may wish to play around with all these settings.

Jcrop is attached to the div, but because the image in the canvas is of the exact same display dimensions, Jcrop's crop coordinates apply exactly to the canvas as well. So we are able to extract the requested slice of the image from the canvas, transfer it to a second "preview" canvas for the user to verify.  When the user is happy with what they see in the second panel, they can click the Upload button, which will then transmit to the server only the contents of the second (cropped) panel.  Oh, I forget to mention, you still need server side code, but it doesn't have to do any image processing.  Even more importantly, you don't have to suffer the overhead of having to receive a whole entire large image, only a small portion of which is actually intended for display by the uploading user!  

Here are the 15 lines of PHP code that receive the image and save it into an image file. Obviously you need to customize it to build in error handling and save the image in a location that your application requires, not /dev/null :-)

<pre>
   &lt;?php
   if (isset($_POST['i'])) {
     $data=$_POST['i'];
     $filteredData=substr($data, strpos($data, ",")+1);
     $decodedData=base64_decode($filteredData);
     $fp = fopen('/dev/null', 'wb');
     fwrite($fp, $decodedData);
     fclose($fp);
     echo "Upload successful\n";
   } else {
     echo "No uploaded data\n";
   }
   ?>

</pre>

<h2>TODO</h2>

This is clearly only a proof of concept. I'm happy to spend a few more cycles on this when I can next manage to tear myself away from my day-job. But in the meantime if you happen to address any issues or make enhancements this basic approach, I'd be interested to hear about it, cohack or use your mods, perhaps for the following:

<ul>
  <li> Progress meter while reading the image file
  <li> Error checks of various kinds
  <li> Bells and whistles as needed
  <li> Better smoothing/interpolation when shrinking a large image into the div and cropping a small part of it.
</ul>

Enjoy!

&

]]>
   </content>
</entry>
<entry>
   <title>How much energy does a 100kg human pack?</title>
   <link rel="alternate" type="text/html" href="http://www.pandamatak.com/people/anand/blog/2010/11/on_relating_to_scientific_fact.html" />
   <id>tag:www.pandamatak.com,2010:/people/anand/blog//2.73</id>
   
   <published>2010-11-03T16:02:41Z</published>
   <updated>2010-12-14T22:56:27Z</updated>
   
   <summary>One of the things I absolutely love about dropping Panini off at JLS is to engage in some absolutely refreshing nerdy conversations. These are always interesting, often funny, and frequently educating to both of us. Today, we talked about fusion...</summary>
   <author>
      <name>&amp;</name>
      <uri>http://pandamatak.com/people/anand</uri>
   </author>
   
   
   <content type="html" xml:lang="en" xml:base="http://www.pandamatak.com/people/anand/blog/">
      <![CDATA[One of the things I absolutely love about dropping Panini off at JLS is to engage in some absolutely refreshing nerdy conversations. These are always interesting, often funny, and frequently educating to both of us.

Today, we talked about fusion and energy. It turns out he was just learning about the periodic table and the elements. He asked how a helium atom can be made from hydrogen atoms and enquired why the mass of the helium atom is less than the mass of the "ingredients" that went into it. 

I, of course, took that opportunity to introduce fusion at a high level and said that some of the mass is turned into energy. He was amazed to learn, as we all are at first presentation, that mass is a compact form of energy. So he naturally asked "How much energy is there in a person if we turn them completely into energy?"

I said that's pretty easy to calculate.  Let's make some simplifying assumptions. Take a person that weighs 100 Kilograms so we can work the numbers in our head while still paying attention to the road. Einstein's equation tells us that the mass of this person, if converted entirely into energy is given by E=mc<sup>2</sup>.  If we assume c to be 300,000 kilometers per second, or 3x10<sup>8</sup> meters per second, then c<sup>2</sup> is 9x10<sup>16</sup>. If we multiply this by the mass of the person, we get 9x10<sup>18</sup> Joules.

Here is where the fun really starts. On face value, 9x10<sup>18</sup> Joules is just a number, albeit a pretty large one in energy-speak. When you state a bland fact like "A 100 Kg person can be converted into 9x10<sup>18</sup> Joules of energy if we completely annihiliate them, reactions will be very mixed, ranging from "Wow that's interesting" (meaning actually <b>not</b>) to "that's a huge amount of energy, isn't it?" (meaning, "I have no idea what that means").



]]>
      <![CDATA[To truly appreciate this fact, and "commune" with nature for a few seconds, we must translate that into something tangible. So we went down that path. Just how much energy is 9x10<sup>18</sup> Joules? Winter is soon upon us, and the space heaters will be out. So we took a 1 kilowatt space heater as our reference point.  The amount of energy a 1KW heater emits in one second is 1 kilojoule, or 1000 Joules. So if we took 9x10<sup>18</sup> Joules of energy, which is the same as 9x10<sup>15</sup> KJ, it would take the heater  9x10<sup>15</sup> seconds to dissipate it. If we turn that into hours, we could say that much energy is equivalent to the energy from a 1KW heater over 9x10<sup>15</sup>/3600 = 2.5x10<sup>12</sup> hours.  Hmmm... Assume there's 25 hours in a day (as we often do :-)  Then that's about 10<sup>12</sup> days.  Divide by 365 to get years and we have about 3x10<sup>8</sup> years or 300 million years.

So the amount of energy in a 100Kg person, which we could get if we totally annihilate them, can power a 1KW space heater for 300 million years. Say we switch the space heater to setting 2, which draws 2KW instead of 1KW.  Then we'd still be able to power it for 150 million years.

Now each heater takes up about 1 square foot of space. Consider a side of a reasonably large building, not unlike the NASDAQ building in Manhattan with its Flat-panel lined external wall. If we took a building wall that is 100 feet wide and 30 feet tall (or vice versa), its area is 3000 square feet.  If we stacked and lined up these heaters in a huge array to completely cover this side of the building, we can fit about 3000 space heaters neatly. If they were all running at 1KW, then this wall will radiate heat for 300x10<sup>6</sup>/3000 = 100,000 years.  At 2KW, this wall will still radiate heat continuously for 50,000 years.

The nice thing about translating facts into tangible things like this is that it lets us instantly visualize and appreciate these magnitudes in a way that isn't possible otherwise. Imagine how much different it is to say "A 100 Kg person, if totally annihilated, can power a 1KW space heater (which we can all feel the warmth of) for 300 million years" rather than "The mass in a 100 Kg person is equivalent to 9x10<sup>15</sup> Kilo Joules of energy.  Yuck! WTF is that?




]]>
   </content>
</entry>
<entry>
   <title>Can connect to localhost but not to its IP Address?</title>
   <link rel="alternate" type="text/html" href="http://www.pandamatak.com/people/anand/blog/2010/06/can_connect_to_localhost_but_n.html" />
   <id>tag:www.pandamatak.com,2010:/people/anand/blog//2.71</id>
   
   <published>2010-06-11T14:34:25Z</published>
   <updated>2010-06-11T15:00:37Z</updated>
   
   <summary>Welcome! If you got here, you probably searched for &quot;Could connect to localhost, but not to its IP address&quot; or some variation of that phrase. That&apos;s how I got here. To writing this post, that is. After unsuccessfully trying many...</summary>
   <author>
      <name>&amp;</name>
      <uri>http://pandamatak.com/people/anand</uri>
   </author>
         <category term="Technical" scheme="http://www.sixapart.com/ns/types#category" />
   
   
   <content type="html" xml:lang="en" xml:base="http://www.pandamatak.com/people/anand/blog/">
      Welcome!  If you got here, you probably searched for &quot;Could connect to localhost, but not to its IP address&quot; or some variation of that phrase.

That&apos;s how I got here. To writing this post, that is. After unsuccessfully trying many clever variations of my query theme in finding an answer to this problem, we decided to troubleshoot it ourselves, ended up fixing it, and decided to blog for the benefit of the wider community.

If you&apos;re lucky, (a) our solution works for you and (b) this post shows up in the first few pages of your Google results saving you much time you might have wasted in following dead-ends.

      <![CDATA[Here is the problem - We discovered it first in our hadoop cluster, which had been set up by a contracted sysadmin no longer with us. The namenocde could not talk to any of the datanodes. The logs would show "Connection refused". Debugging with "telnet -d datanode 54311" would surface a misleading error message with setsockopt complaining about lack of permission.  Funnily enough, when logged on to the datanode directly, we could issue a connection request to localhost, or 127.0.0.1 and it would work perfectly, but all connection requests to datanode, its fully qualified domain name, or even its IP address would fail.

Since we weren't running many other services on the datanodes, this problem didn't manifest in other applications. However, a quick check revealed that the problem was general. We could start up sendmail or an echo server and find the same discrepancy between connecting to localhost and its IP address.

Needless to say, as most people on various forums have tried to do, we too tried the obvious thing first - Perhaps an issue with SELinux or firewalls?  We turned both off. But to no avail. That's when we decided to look a bit deeper.

<div style="color: red; font-family:courier-new; font-weight:bold; margin-left:10px;">
  netstat -an | grep 54311
</div>

showed that a listener was attached to 127.0.0.1:54311, which is to the loopback interface, but not to datanode.xyz.com:54311 or its IP-address:54311. Hmmm... how could that be?  We checked the hadoop configuration and it was clear that it bound to the domain name of the host, not localhost. So what gives? That's when we discovered that /etc/hosts was somehow misconfigured on our machines. The culprit, specifically, was this line:

<div style="color: red; font-family:courier-new; font-weight:bold; margin-left:10px;">
127.0.0.1 localhost.localdomain localhost datanode.xyz.com
</div>

If you don't see the problem, it's the fact that datanode.xyz.com was being locally associated to the loopback IP address in this file. So of course, when a program issues a library call to resolve datanode.xyz.com, it's going to resolve to localhost, rather than its IP address, since the /etc/hosts file takes precedence over DNS queries.

Now the fix was clear.  All we had to do was to restore the /etc/hosts file on all our datanodes. Simply replacing

<div style="color: red; font-family:courier-new; font-weight:bold; margin-left:10px;">
127.0.0.1 localhost.localdomain localhost datanode.xyz.com
</div>

with

<div style="color: red; font-family:courier-new; font-weight:bold; margin-left:10px;">
127.0.0.1 localhost.localdomain localhost
</div>

did the trick. If it doesn't for you, then let me know and we'll have another think about this. I hope this helps.

&


]]>
   </content>
</entry>
<entry>
   <title>From Powerpoint to Profitability</title>
   <link rel="alternate" type="text/html" href="http://www.pandamatak.com/people/anand/blog/2009/12/from_powerpoint_to_profitabili.html" />
   <id>tag:www.pandamatak.com,2009:/people/anand/blog//2.67</id>
   
   <published>2009-12-25T00:36:34Z</published>
   <updated>2011-03-23T18:59:02Z</updated>
   
   <summary>Another fantastic year at 33Across. We have come a long way since our early Power-point days. We have accomplished amazing feats and as Eric said at our recent all-hands, we have continued to hit the ball outta the park. We...</summary>
   <author>
      <name>&amp;</name>
      <uri>http://pandamatak.com/people/anand</uri>
   </author>
         <category term="Happenings" scheme="http://www.sixapart.com/ns/types#category" />
   
   <category term="49" label="33across" scheme="http://www.sixapart.com/ns/types#tag" />
   
   <content type="html" xml:lang="en" xml:base="http://www.pandamatak.com/people/anand/blog/">
      <![CDATA[Another fantastic year at 33Across.  We have come a long way since our early Power-point days. We have accomplished amazing feats and as Eric said at our recent all-hands, we have continued to hit the ball outta the park. We have had our ups and our downs, petty squabbles and grand confluences. But in the end, we've all come to truly appreciate what we have.

So here's to a great year in celebration and anticipation.  John, Mike and Sree - We missed you last night and hope you can make the next one.

<div style="text-align: center;">
  <a href="http://www.pandamatak.com/people/anand/blog/33x_dinner-2009-table-800x.jpg">
    <img alt="33x_dinner-2009-table-480x.jpg" src="http://www.pandamatak.com/people/anand/blog/33x_dinner-2009-table-480x.jpg" width="480" height="360" />
  </a>
</div>

Here's the 4-second video that FRC wanted - as one of us said, ultimate proof that the 33Across engineering team always over-delivers :-)

<div style="text-align:center;">

<object width="425" height="344"><param name="movie" value="http://www.youtube.com/v/C1ht_mNJZ0U&hl=en_US&fs=1&"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/C1ht_mNJZ0U&hl=en_US&fs=1&" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"></embed></object>

</div>

Happy 2010 all!

&
]]>
      
   </content>
</entry>
<entry>
   <title>Unintentional Poetry</title>
   <link rel="alternate" type="text/html" href="http://www.pandamatak.com/people/anand/blog/2009/11/unintentional_poetry.html" />
   <id>tag:www.pandamatak.com,2009:/people/anand/blog//2.65</id>
   
   <published>2009-11-26T18:19:01Z</published>
   <updated>2009-11-27T07:18:16Z</updated>
   
   <summary>Here is the best of totally unintentional communal poetry. It&apos;s written by folk who didn&apos;t have the slightest suspicion that they were contributing to the effort, and shamelessly plagiarised by me. Read on, and sue me if they don&apos;t rival...</summary>
   <author>
      <name>&amp;</name>
      <uri>http://pandamatak.com/people/anand</uri>
   </author>
         <category term="Misc" scheme="http://www.sixapart.com/ns/types#category" />
   
   
   <content type="html" xml:lang="en" xml:base="http://www.pandamatak.com/people/anand/blog/">
      <![CDATA[Here is the best of totally unintentional communal poetry. It's written by folk who didn't have the slightest suspicion that they were contributing to the effort, and shamelessly plagiarised by me.  

Read on, and sue me if they don't rival with the best koans you know.  After you've read the first one, see the picture below to reveal the secret behind the poem, and the names of the authors, themselves unaware of their worthy words.

<div style="color:gold; text-align:center;">
<div style="text-decoration:underline;">Please Tell Me</div><P>

Please tell me it is so
But what will you give me
Such a little firebrand

And I have no mother or father
From that dark day to the present
Far and few, far and few

Look what I pictured on road
At midday
scraped the cupboard
On that little heap of stones

But
You decide, if they die or not
Sorry for your father
Dead or alive

If I were
In the middle of a wood
Reed broke the silence
An inn when he suddenly noticed
You can save more on the goods for solving man's problems

</div>

And here's the secret to the origins of this poem.

]]>
      <![CDATA[<center>
<a href="http://www.pandamatak.com/people/anand/blog/poem-1.jpg"><img alt="poem-1-thumb.jpg" src="http://www.pandamatak.com/people/anand/blog/poem-1-thumb.jpg" width="476" height="411" /></a>
</center>

It's amazing. Don't you agree? And I didn't even have to reorder the lines!

And there's more:

<div style="color:gold; text-align:center;">
<div style="text-decoration:underline;">I Was A Baby</div><P>

I was a baby
Said the Yonghy-Bonghy-Bo

Panic in Atlantic City disco
Please tell me it is so

Quit your day job
Said the Yonghy-Bonghy-Bo

If I had anywhere else to go
In the middle of a wood

Enlarge, expand and strengthen
Said the Yonghy-Bonghy-Bo
</div>

How about this one?

<div style="color:gold; text-align:center;">
<div style="text-decoration:underline;">Is My Card At Yours?</div><P>

Dear
Is my card at yours?
Don't worry
Nor fear the mockery of thy yellow flowers

If I had anywhere else to go
Place where I reside
A good place to make your condition better
I am not deceitful
I shall be one with nature herb and stone
But I knew no one else in the house agreed
And hardly knew what it meant

I was a baby
Arbitrary
Story floor
Toxine destroyer
Have you anything more to add?
If we got nothing lasting in their stead

Now it so happened that on one occasion
Reed had made her promise that she would
Bring electricity back to your love circle!
The voltage will be high
Get a full-mast again
Choose your topic
Become virile like a rabbit!

Bessie came in with a pastry tart for me
Caplet-formed dong-booster
Which they ate with a runcible spoon

When girls fight daily
Bessie will help you pack your things
Indeed she's hot
What else we've got

An inn when he suddenly noticed
It was now late
He set off for home
To thank his generous host
Forget Asking For A Link
Your reply is blocked

</div>

Finally, how about this one?

<div style="color:gold; text-align:center;">
<div style="text-decoration:underline;">I depart as air</div><P>

I depart as air
I shake my locks at the runaway sun
I bequeath myself to the dirt
To grow from the grass I love.
If you want me again
Look for me under your boot soles
You will hardly know
Who I am or what I mean
But I shall be good health to you nevertheless.
Missing me one place?
Search another
I stop somewhere
Waiting for you

</div>

But no - That last real gem was from one of my favourite episodes of Six Feet Under, Season 3, Episode 3, Disc 3 :-)

Feel free to contribute more <em>poetry of dubious value</em>, and wreak havoc on my blog's spam detector!

And on this fine Thanksgiving day of 2009, let me express my heartfelt gratitude to that most unlikely folk of all to receive thanks, those incorrigible spammers, for giving me something rewarm my blog pipe.

&
]]>
   </content>
</entry>
<entry>
   <title>Map-reduce, Hadoop and Clouds - When and When Not</title>
   <link rel="alternate" type="text/html" href="http://www.pandamatak.com/people/anand/blog/2009/04/mapreduce_hadoop_and_clouds_wh.html" />
   <id>tag:www.pandamatak.com,2009:/people/anand/blog//2.63</id>
   
   <published>2009-04-21T04:10:52Z</published>
   <updated>2012-01-27T00:45:46Z</updated>
   
   <summary>What does it take to store Facebook&apos;s entire graph in memory on a computer in your garage? </summary>
   <author>
      <name>&amp;</name>
      <uri>http://pandamatak.com/people/anand</uri>
   </author>
         <category term="Technical" scheme="http://www.sixapart.com/ns/types#category" />
   
   <category term="50" label="33Across" scheme="http://www.sixapart.com/ns/types#tag" />
   <category term="44" label="cloud computing" scheme="http://www.sixapart.com/ns/types#tag" />
   <category term="46" label="facebook graph" scheme="http://www.sixapart.com/ns/types#tag" />
   <category term="48" label="map-reduce" scheme="http://www.sixapart.com/ns/types#tag" />
   
   <content type="html" xml:lang="en" xml:base="http://www.pandamatak.com/people/anand/blog/">
      <![CDATA[<h4>Can you process the entire Facebook network from a PC in your garage?</h4>

Over a decade ago, before I started my graduate work, my then-to-be
advisor gave me a little book and asked that I don't return to him
until after I've read it cover-to-cover.  This
book, <a href="http://www.guardian.co.uk/education/2002/nov/08/highereducation.books">How not to get a PhD</a> (apparently re-published on
a <a href="http://www.amazon.co.uk/How-Get-PhD-Handbook-Supervisors/dp/0335216846">more positive note</a> since 2002), was an invaluable source of wisdom and
advice to me not only before I started my grad work, but even during
it. It enumerated all the wrong reasons why one would want to do a
PhD.  Now, a decade since my degree was granted, rolled up and
squirilled away, I still find the wisdom in that little book
relevant. Not so much in making decisions about matters to do with
formal education, but in real life.<p>

In today's agile world, software projects typically demand strategic
choices over a plethora of possible solutions to most problems.  Some
solutions are appropriate for some problems and some aren't.  It's
important to choose a solution for all the right reasons, and it's
doubly important to not choose it for all the wrong reasons.  Human
factors complicate this issue because inappropriate solutions to some
problems are appropriate and good solutions to other problems.  And
these "other" problems are sometimes faced by reputed technology
companies, who lend "celebrity" status to the solutions.  This leads
the young engineer astray, and coerces them into thinking that just
because Google or Microsoft have found great success with a particular
paradigm, they ought to as well.  Further, within most companies,
there are bound to be a number of non-engineering execs whose
bandwidth is almost completely soaked up by non-engineering matters.
It is consequently easy to get their buy-in for adopting such
technologies using that unfortunately untrue magic phrase, an
<span style="color:orange;font-weight:bold;">egregiously extant engineering enchantment</span> and the mother of all modus ponens if I can
call it that: <span style="color:orange;font-weight:bold;"><em>If it is good enough for Google, it ought to be
good enough for us"</em></span>.  It behooves every company to have at least
one theoretically and practically savvy engineer to protect precisely
against this kind of thing happening.  And to support decisions that
are data-driven, rather than driven by subjective matters such as
<em>coolness</em> and esthetics.  At worst, data-driven decisions are
at least likely to prevent general resentment among staff - one
person's sense of beauty may not always be another's.  On the other
hand, a truly creative idea or proposal is bound to bubble up and find general
support in the numbers.  Those that shirk experimentation,
calculation and testing are the <em>prophets of faith</em> that every
organization should strive to avoid hiring into engineering, in
preference to those that support the <em>voice of empirical
reason</em>.<p>

In this article, I want to focus on two specific <em>cool</em>
technologies that frequently go hand-in-hand: Google's Map-reduce
(e.g. Hadoop), and Cloud Computing (e.g. EC2). For whatever 
reasons possibly including those I've mentioned above, temptation is high among
many engineers today to use these sledge hammers to crack nuts.  As an
illustrative case in point, I'd like to take one of our typical
problems and talk about how we address it
at <a href="http://33across.com/">33Across</a>. Our customers often
express amazement at how we manage to process their gargantuan data
sets and produce results in short order, seemingly with ease.  We are
often asked probing questions that try to get us to divulge our core
data-processing techniques.  Needless to say, I won't be describing
any of our proprietary procedures or secret sauces here.  But a great
deal can be said without going into such matters.  Most of what we
have done to get where we are at is simply to follow published
information you can find in any decent computing journal on occasion,
but most of the time in good Computing-101 texts.  Before we dive into
using a framework that has any overhead associated with it, we always
do quick back-of-the-envelope calculations (not unlike Rapleaf's
<a href="http://blog.rapleaf.com/dev/wp-trackback.php?p=38">nice analysis of whether
to host or cloud</a>) to determine if it will really be worth it.<p>
]]>
      <![CDATA[So without much more ado, here is the sample problem.
At <a href="http://33Across.com">33Across</a>, we analyze graphs -
massive graphs that encode link information from social networks. One
can immediately imagine the scale of the problem.  Take Facebook as an
example.  <a href="//finance.yahoo.com/news/Fastgrowing-Facebooks-user-apf-14884108.html">By last count</a>, Facebook has about 200 million users, with an average of 120 friends per user.  But temper this observation with some business
sense and practicality - the more sane observation
<a href="http://www.techcrunch.com/2009/04/08/facebooks-sheryl-sandberg-preaches-that-the-stream-will-bring-us-closer-together/trackback/">according
to Sheryl Sandberg</a> is that the average number of connections that
actually matter is more likely about 20.  Say we want to perform
calculations on this graph of 200 million persons with about 20
friends per person on averge. People will be represented as nodes in
the graph and connections between people will be represented as the
edges between the nodes. In the context of Facebook, we're talking
about a graph with 200M nodes and about 20 edges per node.  I don't
think there is any doubt that such a graph would be
considered <em>reasonably large</em> by most standards.  And when we
tell folk that our team routinely processes graphs of this magnitude,
the first reaction is almost inevitably one of awe, followed by an
enquiry as to whether we process it using Hadoop.  The answer is no.
In truth, although most people consider our graph to
be <em>large</em>, it is nowhere even near as large as a truly large
graph, by which I mean something like the Internet or the human brain.
And so, as it turns out, our problem is very different in scale from,
say, computing ranks on every document on the web.  In fact, our graph
is <em>small</em> by comparison, and we can afford to do most of our
calculations on this graph in memory and in <em>real-time</em>.  We
are often able to get away with efficiently processing, within each of
many simultaneous threads, the edges of any particular node in
sequence.  To be sure, one can indeed Hadoop this process by clever
definitions of functions that will do the kind of recursive
aggregation for the quantities that interest us.  But we want to see
if it is necessary at all, and for the foreseeable future at least.<p>

What does it take to store the entire useful Facebook graph in memory
on a single machine?  And what would the specifications of such a
machine be?  Obviously we aren't talking super-computers here, but
something you can buy off the shelf from Dell, or your local Fry's.
Here's how we do our back-of-the-envelope calculations - Say that you
want to store the graph as a vector of nodes, where the <em>i</em>'th
element of your vector is actually node <em>i</em>. Having the luxury
of being able to scan and compute on edges sequentially in our
algorithms means that we can simply store the edge-lists for our nodes
as singly linked lists of destination nodes.  Actually we use a map rather than 
a singly linked list, but to keep the argument simple, assume this data structure to be a list for now. Also  ignore, for now, the
quantities we compute on the edges and the nodes themselves.  Consider
only the graph, which consists of nodes, edges and the normalized
weight of each edge.  How much space does it take to store the
Facebook graph in RAM?  Well, 200 million is an order of magnitude
less than 4 billion, which is approximately the largest value storable
in a long (four-byte) integer data type (32 bits means 2<sup>32</sup>
bit patterns), so we can comfortably assume that our graph nodes can
be indexed by an unsigned long integer.  This means that each element
of our singly linked list, which ought to contain a destination node,
a weight on the edge, and a pointer to its sibling will occupy exactly
16 bytes (pointers on a 64-bit Dell PowerEdge are 8 bytes in length,
and we use a single floating point number (4 bytes) to store an edge's
weight.  We're talking about 200M × 20 edges = 4B edges in all.  At 16
bytes per edge, we're looking at approximately 64 billion bytes
(that's 64 GB of RAM). Even if you add in the overhead of a sentinel
node to each of our linked lists, and the constant cost of storing
200M start pointers in a vector, you're still looking at a maximum of
under 70G to store the entire graph in memory.<p>

Now, I want to point out that today, computers with this much main
memory are not only available, they're even relatively inexpensive.
While companies like <a href=http://virident.com>Virident</a> pride
themselves in building eco-friendly green machines with gigantic
amounts (over 256GB per blade) of solid-state RAM having comparable
read-latencies as DIMMs, for only slightly more modest tasks than
processing Facebook's entire graph, one can even get away with far
cheaper solutions.  A dual-Xeon Quad-core Dell PowerEdge 1950 III,
which comes in a slim 1U form factor, complete with cable management
cages and rack-mount rails can be purchased for under about $3K,
especially if you're on good terms with the company rep :-).  Quoting
from Dell's website, a "2-processor Quad Core Intel® Xeon® X5470,
2X6MB Cache, 3.33GHz, 1333MHz FSB" PowerEdge 1950 III (1U form factor)
costs about $4K, and adding in 32G of RAM from Kingston still
prices the machine at just slightly over $5K.  There you have it -
8 computing cores, and 32G of RAM - allowing for the OS and other house-keeping programs, that's still enough juice to load a graph with
almost two billion edges (just under half the size of
Facebook). Finally, if you really need it, you can, for not a whole
lot more money, actually buy 2U servers with up to 192G of RAM
and 16 cores, allowing you to store the entire Facebook graph and
still leave much room to spare.<p>

Now, it's all well and good that you can store such graph in memory on
a single machine in your garage, but how efficiently can you process it?  Evidently
very efficiently. Let's take edge weight normalization as an example.
I pick this because it's an operation that needs to touch every edge
on the graph, and touch each edge twice. It is not an operation that
can be optimized much by most compilers. While you can calculate the
number of nanoseconds it will take to perform each <em>touch and
go</em> from published FLOPS specs on the hardware, we
resort to extrapolating results from simple empirical tests. On the
Dell we cited above, it takes about 25 nanoseconds for a single <em>touch
and go</em> (accumulating the edge weight into a normalizer).  A
second <em>touch and go</em> will be required to divide by this
normalizer, and so we're talking approximately 50 nanoseconds per
edge. At this rate, normalizing a graph of 1B edges ought to take 50 ×
10<sup>-9</sup> × 1B = 50 seconds (less than a minute).  Normalization
can be efficiently parallelized over the nodes in the graph, and so if
you run 8 concurrent threads, you're only looking at slightly over 6
seconds to normalize the entire graph. And that's less time than spent
waiting for some social network pages to load!<p>

Lest this article be misinterpreted as an advocacy against using the
cloud or map-reduce, let me clarify by explicitly stating that's not
the case.  As Don Knuth observes piercingly, <span style="color:orange;font-weight:bold;"><em>premature
optimization is the root of all evil</em></span>.  Map-reduce is an
optimization technique that buys efficiency using a clever
divide-and-conquer approach.  But to know what to divide, and how, and
whether at all, one needs to first measure, estimate and calculate
using tried and trusted techniques. Most of the time, a bigger home is
not the right answer to clutter in a small one. An engineer who cannot
write efficient code on a single computer most likely won't be able to
write efficient code in the cloud.  Only, it will be much harder to
tell.  And so in summary, let me leave you with these parting thoughts
- <span style="color:orange;font-weight:bold;"><em>One must first learn to walk properly on the ground before
trying to fly in the clouds.</em></span>
]]>
   </content>
</entry>
<entry>
   <title>The Four Fours</title>
   <link rel="alternate" type="text/html" href="http://www.pandamatak.com/people/anand/blog/2008/12/the_four_fours.html" />
   <id>tag:www.pandamatak.com,2008:/people/anand/blog//2.60</id>
   
   <published>2008-12-18T03:14:42Z</published>
   <updated>2009-01-15T21:58:03Z</updated>
   
   <summary>This year I&apos;m a volunteer teacher at JLS in Palo Alto to help guide a small number of curious children into the wonders of advanced mathematics over 12 classes in 6 weeks. The program is called &quot;The Number Devil&quot;. It...</summary>
   <author>
      <name>&amp;</name>
      <uri>http://pandamatak.com/people/anand</uri>
   </author>
         <category term="Misc" scheme="http://www.sixapart.com/ns/types#category" />
   
   <category term="40" label="four fours" scheme="http://www.sixapart.com/ns/types#tag" />
   <category term="42" label="math game" scheme="http://www.sixapart.com/ns/types#tag" />
   
   <content type="html" xml:lang="en" xml:base="http://www.pandamatak.com/people/anand/blog/">
      <![CDATA[This year I'm a volunteer teacher at JLS in Palo Alto to help guide a
small number of curious children into the wonders of advanced
mathematics over 12 classes in 6 weeks. The program is called "The
Number Devil".  It uses chapters from the similarly named book by
Hans Magnus Enzensberger as anchor points for discussion during each
class.<p>

Just before the holidays started, the students were to do a warm-up
exercise in preparation for diving into the deeper wonders of Number
Theory in upcoming classes.  Here is the exercise, called the Four
Fours.  Using exactly 4 digits, all of which are fours, and any number
of the arithmetic operators Plus, Minus, Times, Divide,
Exponentiation, Factorial, Square Root, and Parenthesis, derive each
of the numbers from 1 to 50.  E.g. One way you can derive 1 is
obviously 4/4 *4/4.  No doubt there are a number of different ways to
derive each number and the goal is to get students to think about
this, and to come up with expressions that are different from those of
their colleagues.<p>

We, however, decided to turn this little exericse into a game, which
as a matter of fact, also turned out to be a good game to occupy young
minds during the holidays!  Here is how you would play it:<p>

The game has 15 rounds.  Each round lasts 1 minute.  We tried to cover
15 numbers in the game.<p>

Each round consists of:<p>

<ol>
   <li> Host (me): Calling out a different random integer between 1 and 50.
   <li> Players: Each of them has 30 seconds to write an expression
        with exactly 4 4s and the arithmetic operators to get this number.
   <li> We compare answers and points are scored for this round as
        follows:
        <ul>
         <li> Zero points - No expression or invalid expression
              (meaning it doesn't evaluate to the number called)
         <li> M-N points - Otherwise.  M is the number of players and N is the number of other players who have the same expression as you.  If your expression is unique, you get the full M points for the round.
        </ul>
</ol><p>

]]>
      <![CDATA[A great deal of fun though this game was, I was pleasantly surprised
by the number of related meta-issues that we could discuss that laid
the stage for all kinds of advanced concepts one would learn in
grad-school and beyond.  Here is just a sampling of them:<p>

<ul>
 <li> Just how many legal expressions can you ever make (A legal expression 
 is some combination of the 4 fours and the operators that will
 compute correctly, i.e. is syntactically correct)?  What if you
 couldn't use Square Roots, Factorials and Parentheses?  Can you still make
 an infinite number of expressions?  If not exactly how many?<p>

 <li> What is the largest number you can calculate? What if you didn't
 have Factorial?<p>

 <li> How can you tell if two expressions are the same? E.g. If
 John came up with 4*4 * 4/4 = 16 and Mary came up with 4/4 * 4*4 =
 16, how can you tell they were the same?  Notice that it's not always
 this trivial.  This discussion leads to concepts of Normal Forms, how to
 reduce to Normal forms, whether even such reduction is always
 possible, whether unique normal forms exist, and
 how one can algorithmically (and efficiently) compare Normal forms.<p>

 <li> This point, especially, I love because it goes to the root of
 Science, Math, Non-Science and their distinctions! But I've
 completely forgotten the discussion chain that led to this point in
 class!  Suppose John and Mary were to form one expression each as
 above, but instead used a variable for one of the fours.  By
 substituting a value for this variable, each expression would
 evaluate to a certain number. However, it happens to
 be the case that we are unable to reduce
 either expression to Normal form and thus compare them directly.  How
 could we now tell whether the two expressions are in fact the same?
 This brings up all kinds of interesting discussion points -
 Conjectures and Theorems Versus Hypotheses and Theories, Deductive
 and Inductive reasoning, Mathematical Induction, Empirical testing
 and indeed, gives students a real taste of that tantalizing field of
 exploration - Epistemology!<p>

</ul><p>
]]>
   </content>
</entry>
<entry>
   <title>Cool Currency</title>
   <link rel="alternate" type="text/html" href="http://www.pandamatak.com/people/anand/blog/2008/12/a_new_form_of_currency.html" />
   <id>tag:www.pandamatak.com,2008:/people/anand/blog//2.56</id>
   
   <published>2008-12-13T15:52:16Z</published>
   <updated>2009-05-14T16:33:26Z</updated>
   
   <summary> After a long year of Sharon teaching their delightful children, the parents had decided to reward her. On Teacher Appreciation Day, following heart-felt expressions of gratitude and astonishment at what a wonderful job she had done, the head parent,...</summary>
   <author>
      <name>&amp;</name>
      <uri>http://pandamatak.com/people/anand</uri>
   </author>
         <category term="Essays" scheme="http://www.sixapart.com/ns/types#category" />
         <category term="Misc" scheme="http://www.sixapart.com/ns/types#category" />
   
   
   <content type="html" xml:lang="en" xml:base="http://www.pandamatak.com/people/anand/blog/">
      <![CDATA[<div style="padding-left: 10px; padding-right:10px; color:yellow;">

After a long year of Sharon teaching their <em>delightful</em> children, the parents had decided to reward her. On Teacher Appreciation Day, following heart-felt expressions of gratitude and astonishment at what a wonderful job she had done, the head parent, who had coordinated by collecting contributions towards Sharon's gift, presented her with a brightly colored sealed envelope amidst generous applause.  

Sharon opened her gift with great eagerness and found what she would never have spoiled herself with in her wildest dreams - She was now the proud owner of a certificate bestowing upon her the gratitude of a thousand children in Rwanda, who had just been donated $500 on Sharon's behalf.  

Yes - The head parent, in her infinite wisdom, had decided that the best gift for Sharon would not be a couple of sessions at a posh Palo Alto Spa, or a comfy sofa to relax between classes, or even a Bloomingdale's gift card, but rather a donation to a worthy African cause in Sharon's name.  "What could please Sharon more?" would likely have been the most pressing question in her mind, as she tossed around various options for a gift to proudly decide that someone who spends almost every waking hour with children could only ever be pleased by being told that she had benefited yet more children.

</div>
]]>
      <![CDATA[I don't mean to disparage the gift or to belittle the cause.  But as a recipient, would you rather not that the giver had trusted you to make your own decision? Was there a hint of an insinuation there? Might you have spoiled yourself on a trip to Vegas instead of a worthy donation had you been given cash instead?  And is it wrong if you had?

Much as I love this amazing nation of ours, I cannot but help feeling perplexed at how we have let media drive our culture into pathological consumerism, so much so that today, people seem to have absolutely no respect for the worthiest thing of all - the humble dollar bill - unless it was replaced by some other tangible of supposedly equal or better value.

Since the season of gifts is soon upon us, I feel a great compulsion to get these words out sooner than later, lest we suffer yet again the plight of our poor friend and school teacher. What is the best gift you can give someone? Other than your own personal time and effort - An item such as pottery or jewelry you have made yourself, or your time as you offer to massage tired shoulders - I believe the best proxy for your true intention is pure cash.  If I cannot offer something I personally made or propose to make by my own hands, I'd rather present an envelope stuffed with real cash. It is the sincerest form of appreciation and it says "here is a little of my hard-work for you, in return for all of your hard-work for me."

Anything else is a farce, driven into our heads by malicious monopolies and greedy corporations gunning for our hard-earned dollars.  If you're thinking of a gift for someone this holiday season, why not give them an envelope with cash, and a little printout of this article, or a pointer to this URL?

<div style="color:yellow; padding-left: 10px; padding-right:10px; text-align: center;">

A gift of cash is
The best gift of all
It comes from the heart, no
Matter how small

It says that I care
I love the things you do
You made me want to share my
Hard-earned $$$ with you

</div>

Let me leave you with this fictitious and farcical incident that perhaps better captures my thoughts.

<h2>Scene: Safeway at Middlefield, Palo Alto, CA.</h2>

<div style="text-align=center;">
 <center>
   <img src="/people/anand/blog/images/gift-cards-small.jpg" />
 </center>
</div><p>

<div style='padding-left:10px; padding-right: 10px; color: yellow;'>
"Excuse me, can you change a twenty dollar bill for me please?"

"Sure brother. Tens?"

"Err... no..."

"Fives maybe?"

"Uh, no actually..."

"Well, you better tell me then.  Sure as hell can't do nickels and dimes you know?"

"Well, I was kinda thinking another twenty?"

"Excuse me? That bill real man?  Funny money?  Do I need to call the cops or somethin?"

"Hey hey hey, don't freak out.  Yeah, just what I said.  I want another form of $20, you know, something that isn't as flexible as this one?"

"Dude, am like totally lost man... like, not sure what you mean?"

"I'd want something that I can use to buy $20 worth of stuff, but can't use just anywhere you know.  I want to be able to use it at just one place - like Starbucks.  No no make that Pottery Barn... Hey you know what - let's do Mc Donald's.  I mean I want a 20 dollar bill I can only spend at Mc Donald's.  Nowhere else.  I'd like to swap my government issued spend-anywhere-in-this-beautiful-world mint-condition Jackson for a shiny plastic 20-buck-proxy that no would will accept but Mc Donald's.  Actually, it'd be super if you can make that the Mc Donald's on the corner of El Camino and Ravenswood, but I'll take any Mac."

"Now, why would you want that sir?  Why not keep your Twenty?  You realize it's legal tender, and that your favorite McD will take it anyway?"

"Ah, yeah, sure I know that.  But you see it's not for me.  I want to give it to a friend.  It's a gift for her birthday."

"Yeah?"

"I can't give her the $20 now, can I?  I mean, she'll be able to spend it just about anywhere."

"And that's bad?"

"You bet it is. What if she ends up buying herself some granola bars at Whole-Foods like she always does?  Even worse, she might end up buying a book at Kepler's.  I can't have that. Can I? The truth is, [whisper] I don't trust her you know? She doesn't really know to spend wisely.  I gotta help her out."

"Aah..  Then maybe I can introduce you to this nice box of candy?  It's usually $40, but today only it's on sale for $20, and I can peel the price tag off of it..."

...

</div>

]]>
   </content>
</entry>
<entry>
   <title>Deanimizing - A necessary first step to dehumanizing?</title>
   <link rel="alternate" type="text/html" href="http://www.pandamatak.com/people/anand/blog/2008/08/deanimizing_a_necessary_first.html" />
   <id>tag:www.pandamatak.com,2008:/people/anand/blog//2.55</id>
   
   <published>2008-08-09T20:39:43Z</published>
   <updated>2012-02-15T01:23:44Z</updated>
   
   <summary>Last night, I was at a networking social with the Olympic Opening Ceremony on an enormous screen. But I was there strictly to socialize and catch up with good friends. I could not bring myself to enjoy the opening ceremony,...</summary>
   <author>
      <name>&amp;</name>
      <uri>http://pandamatak.com/people/anand</uri>
   </author>
         <category term="Political" scheme="http://www.sixapart.com/ns/types#category" />
   
   
   <content type="html" xml:lang="en" xml:base="http://www.pandamatak.com/people/anand/blog/">
      <![CDATA[Last night, I was at a networking social with the Olympic Opening Ceremony on an enormous screen.  But I was there strictly to socialize and catch up with good friends.  I could not bring myself to enjoy the opening ceremony, flamboyant and ostentatious as it was, in light of the appalling abuses of human and animal rights in a country where, at the very least, all this money could have been put to much worthier use in improving the human condition!  

People might say that it's my loss for missing this magnificent display of oneness and splendor. But I don't see it.  Fortunately for me, there is no dearth of interesting alternatives in today's world that can equally well and guiltlessly take up my time.  Fortunately, I suffer the ancient Chinese curse.  I live in interesting times.  I must boycott the Olympics to protest in what little way I can against such appalling cruelty as <a href=http://www.peta.org>PeTA</a> exposes.

]]>
      <![CDATA[No doubt there is much cruelty elsewhere too.  Even here on American free soil, most would have seen PeTAs shocking expose of KFC's <a href=http://www.kentuckyfriedcruelty.com/u-georges.asp>red bird syndrome</a> that shows millions of birds end up being scalded to death:<p>

<div style="text-align:center;">
<embed src="http://www.kentuckyfriedcruelty.com/swf/pam_kfc_320.swf" quality="high" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" width="335" height="255" allowScriptAccess="always"></embed>
</div>
<br>

But the <a href=http://www.peta.org/feat/ChineseFurFarms/index.asp>anti-fur video</a> took it to a whole new level for me.  I tried not to blog on this topic a second time, but I could not help it. I am still distressed by my memory of the <a href=http://www.pandamatak.com/people/anand/blog/2008/08/skinned_alive_and_tossed_on_to.html>PeTA video</a>.

That a sentient being, much less a human, is even capable of something like this is deeply disturbing.  Despite endless intellectualization that natural variation in neural circuitry is bound to produce innate predispositions to this kind of behavior uncontainable by ethical rationalization, the cold reality of <a href=http://www.pandamatak.com/people/anand/blog/2008/08/skinned_alive_and_tossed_on_to.html>the video</a> scares the shits out of me.  For want of a better word, let me call this deanimization. The way I see it, deanimization, the ability to train oneself to see sentient creatures as unable to feel, is a necessary first step to dehumanization. It is no stretch to the Auschwitz, genocide on a massive scale, to Saddam and his likes, to atrocities of <a href=http://en.wikipedia.org/wiki/Vlad_III_the_Impaler>Vlad the impaler</a> and worse.  One small step to revert to the horrors of the past that we believed were mostly behind us.  Gives me the shits indeed. 

&

<div style="color:yellow; font-size: 80%;">PS. Please excuse the python-long sentences in this article.  Clearly I can't think straight under distress.</div>
]]>
   </content>
</entry>

</feed>

