Select discontinuous items or ranges from a Python list

Posted on 02 January 2013 by Joseph

If you need to select several discontinuous items (and/or ranges) from a Python list, you can use the operator module’s itemgetter second-order function. In the realm of lists, it accepts arguments as either integers or slice objects and returns a function object that when called on a list returns the elements specified.

What? Like this:

>>> from operator import itemgetter
>>> get_items = itemgetter(1, 4, 6, slice(8, 12))
>>> get_items
<operator.itemgetter object at 0x02160D70>
>>> get_items(range(20))
(1, 4, 6, [8, 9, 10, 11])

I’ll leave it as an exercise to the reader to figure out how to flatten the resulting tuple. If it proves challenging, I’d suggest trying some or all of the 99 Prolog Problems (but a list ain’t one?), in Python of course :)

Recipe: Tag Photos With Facebook Graph API

Posted on 01 January 2013 by Joseph

The Facebook Graph API presents a powerful, unified view of the myriad resources made available by Facebook. There is only one problem: documentation, particularly for accessing resources from the different SDKs, is lacking. In designing my little Facebook new-profile-creating toy, PRO!(de)file, I came across several fuzzy places in the documentation that I had to clear up with Google, some time spent reading the SDK code, and good ol’ trial and error. Of particular difficulty was tagging uploaded photos, which is a core requirement of PRO!(de)file.

Uploading from the Facebook PHP SDK

There is a published SDK for PHP made available (or at least linked to!) by Facebook. It is basically a handy wrapper for libcurl. Browsing through the source for the SDK and the Graph API documentation for Photos, I managed to work out how to upload photos. Naturally, the photos must first be on the server side, since it wouldn’t do to have PHP magicking them straight off of your hard drive. How to get them there is left as an exercise for the reader. Also left to the reader is how to register your Facebook application and get an application ID (hint: it’s very easy).

All Facebook transactions, whether client-side or server-side, begin with one of the several methods for application authentication. The documentation on auth is pretty good on the Facebook site, though it is spread out over several unlinked pages. After auth, the user has a cookie containing information about the session and the available permissions requested at auth time. Note that in order to publish anything, including photos, you must request the publish_stream permission when authenticating. Creating the Facebook PHP object and getting the session is then very simple:

$fb = new Facebook(array(
    'appId' => 'YOUR_APP_ID',
    'secret' => 'YOUR_APP_SECRET',
    'cookie' => true,
    ));
$session = $fb->getSession();

With these objects, you have everything you need to upload a photo to Facebook:

function post_image($fb, $session, $image_path){
    try{
        $image = array(
            'access_token' => $session['access_token'],
        );
        $fb->setFileUploadSupport(true);
        $image['image'] = '@'.realpath($image_path);
        $fb->api('/me/photos', 'POST', $image);
        echo "Success!";
        return true;
    }catch(FacebookApiException $e){
        echo $e;
        return false;
    }
}

Super easy. And there are all kinds of neat properties you can include in the image array, explained at the Graph API Photo documentation. Of particular interest to me was the “tags” property, described as returning “An array of JSON objects, the x and y coordinates are percentages from the left and top edges of the photo, respectively” when requested in a GET request. But how does one tag users when posting a photo?

Tagging a photo with the Graph API

The trick, it turns out, is to include a “tags” property as it suggests, with the following format: “tags” is an array of associative arrays, each of which contains the fields ‘x’ (x-coordinate of the tag as a percentage), ‘y’ (y-coordinate of the tag as a percentage), and ‘tag_uid’, a user UID. I never did any testing to see if there was any limit to how many tags, but it definitely works for one at least. Here is the updated post_image function from above, now including a tag of the logged-in user in the center of the image:

function post_image($fb, $session, $image_path){
    try{
        $tag = array(
            'tag_uid' => $fb->getUser(),
            'x' => 0,
            'y' => 0
        );
        $tags[] = $tag;
        $image = array(
            'access_token' => $session['access_token'],
            'tags' => $tags,
        );
        $fb->setFileUploadSupport(true);
        $image['image'] = '@'.realpath($image_path);
        $fb->api('/me/photos', 'POST', $image);
        echo "Success!";
        return true;
    }catch(FacebookApiException $e){
        echo $e;
        return false;
    }
}

As the name implies, the get_user method of the Facebook object retrieves the user ID (actually the Graph ID) of the logged-in user.

In conclusion, having just scratched the surface of the possibilities of the Graph API, I am very excited by its breadth and depth. Though lacking in complete documentation, when wrapped up in some of the reasonably well-done SDKs, it is both straightforward and indeed easy to include powerful Facebook functionality in web applications.

Country Selection Splash Pages Are Stupid

Posted on 20 June 2012 by Joseph

I love the Microplane kitchen tools (and would probably love the woodworking tools too if ever I had used them). What I don’t love is the unnecessary step of choosing my country upon arriving at their website. In a world where tools like visitor.js exist, much less the vast array of server-side techniques for doing just this, why am I ever forced to click ‘Microplane USA’ again?

And it’s not just kitchen tools either. I commonly see technology providers doing this same thing. In my opinion, it’s always better to make a best guess then let the user correct if they need to. This is what high-traffic projects like Firefox do to get people to the correct download. If their assumptions about your language or operating system are incorrect, you’re just a click away from the correct page, but most people never have to click anything to get to their final destination.

Recipe: Detect Console Session in Windows

Posted on 10 January 2012 by Joseph

Working on an upcoming version of my company’s software Granola today, I came upon the need to determine whether the program was running in the so-called “console session.aspx)” – the session in which the user is physically sitting at the terminal. The context of my interest was Windows XP power management, but I can think of other reasons, like changing the user interface based on the physical location and logon status of the user.

As with many things Windows, the solution is quite simple but the documentation quite sparse. Googling eventually brought me to the WTSGetActiveConsoleSessionId.aspx) and ProcessIdToSessionId.aspx) functions. The former retrieves the session ID for the console session, and the latter queries the session ID for a given process. Pass in the current process ID and compare the values to perform the required test:

bool check_console(){
    DWORD sid;
    ProcessIdToSessionId(GetCurrentProcessId(), &sid);
    if(sid == WTSGetActiveConsoleSessionId()){
        return true;
    }
    return false;
}

For more fine-grained control, you can register to receive session change messages with the WTSRegisterSessionNotification.aspx) function. Given a window handle, the following code will register for all session change notifications:

if(WTSRegisterSessionNotification(handle, NOTIFY_FOR_ALL_SESSIONS) != TRUE){
    // handle error (GetLastError)
}

Change NOTIFY_FOR_ALL_SESSIONS to NOTIFY_FOR_THIS_SESSION to only receive session changes for the current console. Once the registration has occurred, session changes will generate WM_WTSSESSION_CHANGE.aspx) message; your application can then respond to these messages as needed.

Implementing HTML5 Canvas Polyline Simplification

Posted on 09 January 2012 by Joseph

Or, fun with vector geometry and state machines!

Once again, I’m toying around with HTML5 canvas. As part of the larger project, I needed a way to generate simplified paths based on mouse drags where ‘simplified paths’ means polyline paths with as few internal points as possible to accurately express the movement of the mouse. I did a bit of research and came up with a bunch of papers on the topic, both for purely polyline simplification as well as polycurve simplification, but I decided it would be more fun to roll my own.

So I cranked up some math rock, busted out the notebook, and dusted off the brain cells dedicated to vector geometry. The breakthrough is realizing that the algorithm can run at a single point on a time. Here is the resulting algorithm in pseudocode:

  1. Initialize TMIN, LMIN, line_list = [].
  2. Save the mousedown point (s). Push s onto line_list.
  3. Save the point after the first mousemove (m). Push m onto line_list.
  4. For each new point, n (i.e. on mousemove event):
    1. Let p = n – m.
    2. If ||p|| < LMIN:
      1. Pop the last element from line_list.
      2. Push n onto line_list.
      3. Return.
    3. Else:
      1. Let o = m - s.
      2. Let θ = arccos(o . p / (||o|| * ||p||)).
      3. If θ < TMIN:
        1. Pop the last element from line_list.
        2. Push n onto line_list.4.
      4. Else:
        1. Push n onto line_list.
        2. Let s = m.
      5. Let m = n.

At the end, line_list is the simplified list. Here is a diagram of the relevant variables:

In normal words, the algorithms only include points that are close enough to the line established by the previous two points, assuming that the mouse has gone far enough away from the last point. The nice thing about this method relative to some more complex ones (e.g., least-squares fit to the original line) is that the algorithm only needs to hold the points of the resulting line and the latest point.

So DOES it work? You can give it a go here. Fork the code (Coffeescript) here.


Copyright © 2024 Joseph Turner