I’m a computer science professor, data scientist, and web geek.

Category — blog

My Barcamp Presentation: Have Data? What Now?!

I gave a talk at BarCampNYC4 on Saturday on common data problems and a very light overview of algorithms that address them.

My talk at barcampnyc4. - photo courtesy of dynamist on flickr.

My talk at barcampnyc4 - photo courtesy of dynamist on flickr.

I delivered the majority of the content verbally, by talking through examples of problems and how to solve them, so there’s no guarantee that these slides will make sense, but they might be funny!

Sanford took some excellent notes during the presentation.

There were some very nice comments on twitter.

The discussion was so lively and engaging that I’m planning to expand on this content — I really welcome your suggestions and comments!

June 1, 2009   No Comments

I’m on Jon Udell’s Interviews with Innovators!

Jon Udell hosted Charlie and I on his Interviews with Innovators podcast.

We discussed Path101’s approach to career advice through data, and how the high availability of data is changing the way we make decisions.

Listen here.

May 7, 2009   No Comments

LSL: AOL IM Status Indicator

I think this might be my very first LSL script, from back in 2005! This script indicates whether your AIM (AOL Instant Messenger) account is online by changing the color of an object. You can configure it to either share your AIM ID publicly, or keep it private.

AIM Indicators in Second LIfe

AIM Indicators in Second LIfe

This script uses the AIM web services API to check your online status — you only need to give it your username, not your password! This is not a proxy service. You can’t send messages through this script, just show your online status in SL.

To use this script, create an object in your favorite shape, create a new script inside of it, paste this code into it and save.

key request_id;
string aim_id;
string av_name;
key data_card;
integer nLine = 0;
integer public = TRUE;
 
default
{
    state_entry()
    {
        llSetText("AIM Indicator... setting up",<1,1,1>,1);
        data_card = llGetNotecardLine("Settings",nLine); // load settings
        llSetTimerEvent(60); // check once per min
    }
 
    // reset when owner touches it
    touch_start(integer total_number) {
        if (llDetectedKey(0) == llGetOwner()) {
            llResetScript();
        }
    }
 
    // read settings from notecard
    dataserver(key query_id, string data) {
        if (query_id == data_card) {
            if (data != EOF) { // not at the end of the notecard
                if (nLine == 0) {
                    av_name = data;
                } if (nLine == 1) {
                    aim_id = data;
                } if (nLine == 2) {
                    if (data == "private") { // if they do not want their ID shared
                        public = FALSE;
                    }
                }
                ++nLine; // increase line count
                data_card = llGetNotecardLine("Settings", nLine); // request next line
            }
        }
    }
 
    timer() {
        string url = "http://api.oscar.aol.com/SOA/key=hi15uD79wuEukQTS/resource-lists/users/*anonymous*/presence/~~/resource-lists/list%5Bname=%22users%22%5D/entry%5B@uri=%22user:"+aim_id+"%22%5D";
        request_id = llHTTPRequest(url,[HTTP_METHOD, "GET"],"");
    }
 
    http_response(key req_id, integer status, list metadata, string body) {
        if (req_id == request_id) {
            list result = llParseString2List(body,["<",">","\n"],[]);
 
            // if user is online
            if (llList2String(result,24) != "http://cdn.digitalcity.com/presence/offline.gif") {
                if (public == FALSE) { 
                    llSetText(av_name+"'s AIM account is online",<1,1,1>,1);
                } else {
                    llSetText("AIM "+av_name+": "+aim_id+" is online",<1,1,1>,1);
                }
                llSetColor(llVecNorm(<160,237,160>),ALL_SIDES);
            } else { // user is offline
                llSetText(av_name+"'s AIM account is offline",<1,1,1>,1);
                llSetColor(llVecNorm(<237,160,160>),ALL_SIDES);
            }
        }
    }
}

This script is released under Creative Commons License. Have fun!

Create a notecard called “Settings” with your avatar name on the first line* and your AIM username on the second line. If you do not want your AIM username shared, put the word “private” on the third line. If you do want it shared, change the line to anything else (”public”, or even blank will do). For example:

Ann Enigma
hilm1
private

The script polls the AIM server every 60 seconds, so give it a minute to update. It will reset if the owner clicks on it.

* I’m aware that you can get the avatar name via LSL — this was my first script, be nice!

April 28, 2009   1 Comment

From the ACM: Learning More About Active Learning

The April edition of Communications of the ACM has an interesting article on recent advances in active learning by Graeme Stemp-Morlock.

In passive learning (a more traditional approach), you build a large training set of classified data by (often) manually assigning labels. This data is used as the basis of your analysis.

In the real world, we find that generating these large sets of labeled data is often expensive and time consuming. With active learning, you identify the most ambiguous data to label, resulting in a much higher payoff for each label defined (and fewer headaches for your labelers).

The article goes on to mention that active learning is being used in practice with excellent results (for example in music identification, text classification, and even bioinformative), but that the theory lags. This is another example of a gap between the world of the practitioner and the academic work behind it.

April 2, 2009   2 Comments

LSL: Newspaper Stand (Pull Data From an API and Display it in Second Life)

Second Life news stand

Second Life news stand

One of the more popular objects that I created in Second Life is the News Stand. This charming device takes any query term and displays the two latest headlines from Yahoo! News. Clicking the news stand will load the top news story for the topic in a web browser.

I’ve gotten more requests to customize the script than I can possibly keep up with, so I’ve decided to release the code under a creative commons license. I hope you find it useful! Please let me know if you make improvements, so that I can link to them from here.

Unfortunately, parsing XML at all and RSS feeds in particular is extremely messy in LSL. This script doesn’t contain a general RSS feed parser — the parsing code was written specifically for the Yahoo! news feed.

// News Stand script
// by Ann Enigma
 
string url="http://news.search.yahoo.com/news/rss?p=";
key requestid;
string current_url = "http://news.yahoo.com";
integer gLine = 0;
key data_card; // for settings notecard
string query;
 
integer mins = 10; // number of minutes between refreshes
 
get_news() {
    llWhisper(0, "Refreshing the news...");
    requestid = llHTTPRequest(url,[HTTP_METHOD,"GET"],"");       
}
 
default
{
    state_entry()
    {
        data_card = llGetNotecardLine("Settings",gLine); // load settings from notecard
    }
 
    // read data from the notecard
    dataserver(key query_id, string data) {
        if (query_id == data_card) {
            if (data != EOF) {    // not at the end of the notecard
                if (gLine == 0) {
                    query = data;
                } 
            }
        }
        state setup;
    }
    changed(integer change) {
        llResetScript();
    }
}
 
state setup {
    state_entry()
    {
        url += llEscapeURL(query); // set the url
        get_news(); // get the news!
        llSetTimerEvent(60*mins); // every mins # of minutes
    }
 
    touch_start(integer total_number)
    {
       llLoadURL(llDetectedKey(0), "Current Top Story", current_url);
    }
    http_response(key req_id, integer status, list metadata, string body) {
 
        integer count = 0;
        string display;
 
        if (req_id == requestid) { // parse the results (unfortunately messy)
            list result = llParseString2List(body,["<",">","\n","[","]"],[]);
            integer length = llGetListLength(result);
            integer i = 0;
            for (i = 0; i < length; i++) {
                if (llList2String(result,i) == "title" && llList2String(result,i+4) == "/title") {
                    display += llList2String(result,i+3) + "\n";
                    if (count == 1) { 
                        current_url = llList2String(result,i+6);
                    }
                    count++;
                }
            }
            llSetText(display, <1,1,1>, 1.0);
        }
    }
    timer() {
        get_news();
    }
    changed(integer change) {
        llResetScript();
    }
 
}

This script is released under Creative Commons License. Have fun!

Create a notecard called “Settings”, with a single line containing your search term. For example:

Educational Technology

The original news stand comes with these instructions, which may come in handy:

To set up the News Stand, simply open the "Settings" notecard, delete the default search term, and type in your own!

This gadget will refresh every 10 minutes, and will display the top two headlines on Yahoo! News for any search term. If you click on the news stand, it will load the top story in a web browser.

If you would like to build your own news stand, you can simply drag the script and "Settings" notecard into any object.

If you want the no-assembly-required version, the News Stand is available for L$350 at Xstreet SL Marketplace or from the ICT Library on Info Island in-world.

The original news stand object was created by (now former) student Kyle Pouliot.

February 28, 2009   4 Comments

JWU Guest Lecture: Introduction to JavaScript and AJAX

I was invited to give a talk at JWU for an audience of graphic design students on how to enhance their XHTML/CSS skills with JavaScript and AJAX. Enjoy the slides, and I’m looking forward to part 2!

February 10, 2009   No Comments

Wordpress tip: Move comments from one post to another post

I recently ended up with two posts on this site about the same project — one was a short summary, and the other a long, detailed article. I decided to consolidate them into the longer article, but I didn’t want to lose the six comments that had been posted to the short article.

I couldn’t find a way in the Wordpress UI to move comments from one post to another, so I jumped into the database. If you run Wordpress on a host, they probably provide a MySQL management tool like PHPMyAdmin, or you can log in with a mysql client.

First, find the table that contains the posts for your blog (the table name usually ends in _posts). Find the ID that matches the post you want to move comments from, and the ID for the post that you want to move comments to.

Note: An easy way to do this is to search by the post title. If you need to write the SQL by hand, use something like this:

SELECT * FROM wp_posts WHERE post_title LIKE '%posttitlekeyword%';

Replace wp_posts with the name of the database table containing your posts, and posttitlekeyword with a relatively unique keyword or phrase from the title of your post.

Second, switch to the comments table. Each comment is linked to a particular post by the ID in the comment_post_ID field. You want to switch all of the entries that point to the ID for the first post to the ID for the second post. You can do this in a visual interface by searching for the relevant comments and updating them one by one, or using this SQL:

UPDATE wp_comments SET comment_post_id=2 WHERE comment_post_id=1;

Change 1 to the ID of the original post and 2 to the ID of the post you want to move the comments to.

Note: You are making changes to your Wordpress database! If things go awry, you could lose your data. Make sure you have a robust backup strategy before you attempt to change anything.

January 31, 2009   1 Comment

Twitter: A greasemonkey script to show who follows you

A couple of days ago I saw @skap5’s comment:

“Dear Twitter Is it too much to ask to add a follower marker so I can know if someone is following me and not just if I am following them?”

I think that Twitter could benefit from displaying more information on the home page, and this idea was easy enough to code up. It should save some time and make the Twitter homepage that much more useful.

twitter_showfollowers_screenshotThe script displays a tiny icon on top of the portrait of people who are following you back on your Twitter home page. It leaves your non-followers alone, though it would be easy enough to develop a version that puts silly mustaches on them.

This is only a first version, and I welcome your comments and suggestions.

If you already have Greasemonkey installed, get the script here, or install it from here as a Firefox extension thanks to the script compiler.

The icon is a free icon courtesy of famfamfam.

Updated February 5, 2009: The script has been updated to work with Twitter’s recent UI changes.

Updated March 31, 2009: The script has been updated to account for Twitter’s recent UI changes and the addition of AJAX updates.

January 1, 2009   9 Comments

Mobile app: WHEREAMI <username>

WHEREAMI is a mobile application that accepts a username as input, searches public profiles on various location-aware services, and returns the user’s last known location via text message.

Just text 41411 with whereami <username>, where <username> is a username that you or someone you know is likely to use.

results of WHEREAMI hmason

For example, if you text whereami hmason to 41411, you’ll see a response much like the image to the left.

This app works on the principle that people tend to use the same username for many applications. The WHEREAMI script will search through a variety of web services for a result for that username. All of the information is public and available without logging in.

Right now, the script will search Brightkite, then Dopplr, and finally Twitter. If you know of another site with public user location information, please comment below and I’ll add it!

October 19, 2008   5 Comments

What am I like? How about you?

My Path 101 Personality Quiz Traits

Highest Scoring Traits

Love of Thinking

Relativism

Compartmentalization

Lowest Scoring Traits

Concreteness

Idealism

Emotion

Like-minded people work in:

Biotechnology and Pharmaceuticals

Medical Equipment Manufacturing

Computer Hardware and Infrastructure

Urban Planning

Corporate Law

See hmason’s full assessment and get your own.

I’ve always been skeptical of and fascinated by personality tests. On the one hand, it’s your personality — who could possibly know more about you than you do? On the other, there’s something alluring about quantifying your characteristics, especially when you can compare them to others.

These are my results from the Path101 personality test. Go see how you compare!

September 26, 2008   No Comments