Archive for the ‘code’ Category

Freedom for Our Files: Canvas starter (Facebook) app

Thursday, December 22nd, 2011

I’m happy to share the code from a Facebook app I created for a workshop earlier this year.

This is an example of a simple Facebook canvas application. This code was originally demoed during the Freedom for Our Files Facebook API workshop at the 2011 Art Meets Radical Openness festival in Linz, Austria. You can view and download the source code on github

The application is very simple; it creates a Facebook object, performs calls to get data belonging to the current user, then prints the data exactly as it is returned. It has examples of basic Facebook Graph API calls as well as an example of FQL (Facebook Query Language).

Stop SOPA Blackout

Thursday, December 15th, 2011

You might notice my site and blog looks a little, well, opaque this week. Here’s a screenshot.

I’m running a script on my site that censors all the content in order to bring attention to a law being pushed through congress right now. The SOPA (“Stop Online Piracy Act”) is a terrible piece of legislation that gives broad powers for the courts to take down sites by claims from “infringed” users. If SOPA passes as-is, it could devastate the artistic expression and livelihood of many artists, hackers, and entrepreneurs.

More information at fightforthefuture.org

You can protest the SOPA bill and install the blackout code on your site to let your visitors know what they could miss out if SOPA does pass.

Paste this code into your Tumblr themes, website, and more…

<script type="text/javascript">
  var FATLAB_Stop_SOPA = {
    color : '#000000',
    promote : true
  };

  document.write('<scr'+'ipt src="http://fffff.at/stop_sopa/blackout.js?v=1&e83a2c"></scr'+'ipt>');
</script>

New line plotter prints of I Am Unable to Fulfill Your Wish

Sunday, December 11th, 2011

Here are some images Ryan Boatright of Atelier Boba made while he was printing one of my network visualizations from the I Am Unable to Fulfill Your Wish series on their new line plotter. The prints arrived last week from their location in Paris and are great to see in person. The line plotter repeated so many of the lines it actually polished the surface of the paper causing the print to reflect light.

Processing.js – Missing Documentation

Saturday, September 10th, 2011

The Processing.js project is really cool. It allows you to run Processing .pde files inside (HTML5 compatible) web browsers using Javascript. You can pass data back and forth between the two programs, access the DOM with Processing, and you don’t need any plugins or Java.

Click here to run this Processing sketch in your browser

One caveat… When importing a Processing .pde file into the HTML5 canvas you must access the files on a web server or by using localhost (a server running on your computer, e.g. MAMP) because most (all modern?) web browsers don’t allow file:/// access for security reasons. Unfortunately this is not intuitive as Javascript should run in the browser regardless of file:/// access. Nor is it mentioned in any of the Processing.js Quick Start documentation. I found it by testing, and then confirmed it in their README. Darn, need to remember to read (all of) the instructions.

UPDATE: A friend pointed out that the problem accessing the .pde file could be due to the same origin policy. Though not explicitly stated on the Github page for Processing.js, they do mention that disabling same origin setting in your browser is a(n undesirable) workaround.

Some web browsers (e.g., Chrome) require secondary files to be loaded from a web server for security reasons. This means loading a web page that references a Processing.js sketch in a file via a file:/// URL vs. http:// will fail. You are particularly likely to run into this problem when you try to view your webpage directly from file, as this makes all relatively links file:/// links.

// Hello World file for Processing or Processing.js
void setup(){
  size(1000,700);
  background(255);
}
void draw(){
  stroke(random(255),random(255), random(255));
  line(random(width),random(height), random(width),random(height));
  println("Hello World!");
}
view raw hello.pde This Gist brought to you by GitHub.

Camp La Jolla Military Park: Creative Disturbance Through Adaption of National Park Iconography

Friday, September 9th, 2011

I recently published an essay, “Camp La Jolla Military Park: Creative Disturbance Through Adaption of National Park Iconography,” in the Parsons Journal for Information Mapping (PJIM) documenting my thesis work at the University of California, San Diego. Here is the abstract for the essay:

This paper details the motivation and the method behind the creation of Camp La Jolla Military Park, a fictional national park on the current site of the University of California’s San Diego campus. Camp La Jolla Military Park borrows the iconography and language from historical battlefields as designated and protected by the U.S. Congress; the use of such iconography and language allows for the investigation, as well as consideration of the campus as a site for research and development of weapons and technology for the defense industry. The website http://camplajolla.org/ is the publicly accessible collective of the research and expression behind Camp La Jolla Military Park.

The project began by developing a data-collection system in order to record the historical, geographic, and economic ties that bind the relationships of power within the complex of military, industrial, and academic institutions in Southern California. Through appropriating the vernacular language and imagery of the National Park System the research was made public and accessible to audiences both within and outside of the protected spaces of art and academia. This writing introduces the concepts and processes of the project in order to encourage the restaging of other similar creative disturbances.

Internet service just got creepy: How to set up a wireless router with Comcast internet service

Saturday, August 27th, 2011

I just moved back to Florida after a one year research project in Berlin and have subscribed to Comcast broadband service. The whole experience left a bad taste in my mouth, though not because the tech showed-up 2 hours after the installation appointment window. Nor was it because he held loud personal conversations on his cell phone while he was setting up the service. No, the icky feeling is more corporate and selfish, and impedes much more into my private space than “Joe the cable guy” ever could.

Comcast made me install software on my computer in order to use their broadband.

Upon his arrival, “Joe” announced he would need access to my computer to setup broadband service. Understanding that most of the people Joe deals with might not be IT whizzes, and could manage to not be able to connect their machines without his help, I decided to let him use it rather than attempt to prove I was not a member of the usual group. After half an hour of complaining about previous customers to his friend on his cellphone, waiting for an other Comcast person to flip a switch allowing him to do his job, and multiple trips to his truck, he showed me that the internet was indeed accessible on my computer.

At this point the laptop was directly connected to the cable modem via an ethernet cable. He announced I was to follow the steps on the screen and he was out the door. The web page he had left up required me to agree to some terms, create a username and then… install software? Really? I tried to access the net without the final step but nothing doing. Unless I installed this software I was stuck. So I did it, still not believing that a company had really initiated this final invasion onto every customer’s computer. After it was done I had new bookmarks everywhere, for Comcast email, security, and some branding nonsense called “XFINITY” (I thought “X” was out with the ’90′s and “X”games?)

So I thought, “OK, Comcast, you got me, hit me with your best marketing slime. Whatever, I can delete the bookmarklets you installed in my browser, just let me access the service I paid for, wirelessly, on whichever device I want.”

But this is where the relationship got really creepy. Apparently when I installed the Comcast (spyware?) on my machine, it made note of my MAC address, a unique identifier of networked machines, so that it would only allow my machine (or another machine with that MAC address) to connect to the internet. This means when I attached a wireless router to the cable modem I could connect to the wifi, but there was no internet.

So it turns-out that Comcast is not only forcing their adware on customers, it’s also making it difficult (though not impossible) for them use more than one device. Presumably Comcast is doing this in order to circumvent sharing of services among neighbors, but the end result is that you can’t share the service between more than one device, or between roommates or spouses for that matter.

An example (albeit a geeky one): between my wife and I we have 2 laptops, 2 smartphones, and a desktop computer that all might be talking to each other or accessing the net. Comcast’s so-called internet service didn’t allow for any such geekery because it only allows one device, with the correct MAC address, to connect.

So, here’s what I did, on my Mac, with some help from my sister’s boyfriend, Tom, and a lot from Google, to get my linksys wireless router to work with Comcast internet.

  1. Confirm you can access the internet with your machine connected directly to the Comcast cable modem.
  2. Open Terminal and type (without the quotes): “ifconfig en0 | grep ether”
  3. Now disconnect your computer from the modem and connect the modem ethernet cable to your wireless router. Make sure both are plugged-in.
  4. Connect to your wireless router via the airport on your machine.
  5. Go to the following link: http://192.168.1.1
  6. Under Setup, choose DHCP as the Internet Connection Type. Save Settings.
  7. Under Setup : Mac Address Clone, enter the alpha numeric characters returned from Terminal. Save Settings.
  8. Configure your wireless router like you normally would and you are up and running.
  9. Snicker at Comcast

Give Me My Data upgrade: New API, authorization, and data formats

Monday, July 4th, 2011

No one would be surprised to learn that almost all of the user-generated content websites use our personal data to sell advertisements. In fact 97% of Google’s revenue comes from advertising.[1] That’s why it’s important these sites provide as much access as possible to the real owners of our data‐us. After all, we put it there and allow them to use it in exchange for the use of their software. Seems like a fair trade if you ask me.

A year and a half ago Facebook didn’t provide any access. That’s why I created Give Me My Data, to help users reclaim and reuse their personal data they put on Facebook.

By giving more agency to users of online systems, Give Me My Data may have already impacted the nature of online application development. In November 2010, almost a year after I launched Give Me My Data, Facebook created their own service for users to export their profile from Facebook as a series of HTML pages. Unlike Give Me My Data, the Facebook service doesn’t allow you to select which data you want or to choose custom formats to export. It also doesn’t give you options for visualization like the custom network graphs that Give Me My Data offers.

I believe their motivation originates in part with my application, likely due to the popularity of Give Me My Data, and points to the potential usefulness of similar apps. While years down the road may reveal many other online systems giving users control over their data, I see this as a positive effect where the content we create, as well as the means to share and manage it, are democratized.

Meanwhile, the above also keeps me hard at work developing the Give Me My Data project. This week I rewrote the program to use Facebook’s new OAuth authorization, which also required rewriting all of the code that fetches the data. Previously it used the REST API which is being deprecated (sometime?) in the future. I also added new data types, fixed the CSV format (which had the rows and columns mixed-up), and added the possibility to export in the JSON data format.

Finally, in the data selector, I distinguished standard data and customized data types. When I say customized, I mean that I’ve written code that mashes together more than one data table and/or addresses a specific question. For example, right now users can select from two types of network graphs and corresponding formats. One describes the user’s relationship to their friends, and the other describes the user’s relationship to their friends, as well as all their friends’ relationships to each other in various graph description languages. This is how I made the network graph image below. I’m also interested in hearing other suggestions for custom queries I might add. The project will be open source on Github soon, so even code contributions will be welcome.

Anyway, please try out the new version. You may have to delete the app from your allowed applications and then re-authorize it if you’ve used it before. As usual, you can provide feedback on the application page, and you can also contact me on Twitter via @givememydata.

[1] “Google Financial Tables for Quarter ending June 30, 2009” Retrieved October 13, 2010

Semantic network of hierarchical tags from Camp La Jolla Military Park

Wednesday, June 29th, 2011

A semantic network visualization and detail using tags generated from the hierarchical tagging system I created with Thomas Evan Lecklider as part of my Camp La Jolla Military Park project.

For example this item, Defense Contractors recruit at UCSD Job Fair, in the park is filed under: business » arms industry » spending » recruiting

Give Me My Data 2.0 advances to 2nd round of Rhizome Commission voting

Friday, June 17th, 2011

I just learned the Give Me My Data 2.0 proposal I put together with Dr. Phil Steinberg has advanced to the second stage of 2011 Rhizome Commission voting. Give Me My Data 2.0 is an open source web application that exports your user data from any crowdsourcing website in multiple, reusable formats.

I created Give Me My Data while working on Automata, a project which visualizes powerful relationships and which also made it to the second round of the Rhizome Commissions two years ago.

Please VOTE for Give Me Me Data if you are a Rhizome member!

Freedom for Our Files: Code and Slides

Monday, May 16th, 2011

A two-day workshop, with both technical hands-on and idea-driven components. Learn to scrape data and reuse public and private information by writing custom code and using the Facebook API. Additionally, we’ll converse and conceptualize ideas to reclaim our data literally and also imagine what is possible with our data once it is ours!

Here are the slides and some of the code samples from the Freedom for Our Files (FFOF) workshop I just did in Linz at Art Meets Radical Openness (LiWoLi 2011).

The first one is a basic scraping demo that uses “find-replace” parsing to change specific words (I’m including examples below the code)

<?php

/* Basic scraping demo with "find-replace" parsing
* Owen Mundy Copyright 2011 GNU/GPL */

// url to start
$url = "http://www.bbc.co.uk/news/";

// get contents of url in a string
$contents = file_get_contents($url);

// replace contents
$contents = str_replace("News",
"<b style='background:yellow; padding:2px'>LIES</b>",$contents);

// display results
print $contents;

?>

Basic scraping demo with “foreach” parsing

<?php

/* Basic scraping demo with "foreach" parsing
* Owen Mundy Copyright 2011 GNU/GPL */
 
// url to start
$url = "http://www.bbc.co.uk/news/";

// get contents of url in an array
$lines = file($url);

// look for the string
foreach ($lines as $line_num => $line)
{
// find opening string
if(strpos($line, '<h2 class="top-story-header ">'))
{
$get_content = true;
}

// if opening string is found
// then print content until closing string appears
if($get_content == true)
{
$data .= $line . "\n";
}

// closing string
if(strpos($line, "</h2>"))
{
$get_content = false;
}
}

print $data;

?>

Basic scraping demo with “regex” parsing

<?php

/* Basic scraping demo with "regex" parsing
* Owen Mundy Copyright 2011 GNU/GPL */
 
// url to start
$url = "http://www.bbc.co.uk/news/";

// get contents of url in a string
$contents = file_get_contents($url);

// get title
preg_match('/<title>(.*)<\/title>/i', $contents, $title);

// display results
print $title[1];

?>

Basic scraping demo with “foreach” and “regex” parsing

<?php

/* Basic scraping demo with "foreach" and "regex" parsing
* Owen Mundy Copyright 2011 GNU/GPL */

// url to start
$url = "http://www.bbc.co.uk/news/";

// get contents of url in an array
$lines = file($url);

// look for the string
foreach ($lines as $line_num => $line)
{
// find opening string
if(strpos($line, '<h2 class="top-story-header ">'))
{
$get_content = true;
}

// if opening string is found
// then print content until closing string appears
if($get_content == true)
{
$data .= $line . "\n";
}

// closing string
if(strpos($line, "</h2>"))
{
$get_content = false;
}
}

// use regular expressions to extract only what we need...

// png, jpg, or gif inside a src="..." or src='...'
$pattern = "/src=[\"']?([^\"']?.*(png|jpg|gif))[\"']?/i";
preg_match_all($pattern, $data, $images);

// text from link
$pattern = "/(<a.*>)(\w.*)(<.*>)/ismU";
preg_match_all($pattern, $data, $text);

// link
$pattern = "/(href=[\"'])(.*?)([\"'])/i";
preg_match_all($pattern, $data, $link);

/*
// test if you like
print "<pre>";
print_r($images);
print_r($text);
print_r($link);
print "</pre>";
*/

?>

<html>
<head>
<style>
body { margin:0; }
.textblock { position:absolute; top:600px; left:0px; }
span { font:5.0em/1.0em Arial, Helvetica, sans-serif; line-height:normal;
background:url(trans.png); color:#fff; font-weight:bold; padding:5px }
a { text-decoration:none; color:#900 }
</style>
</head>
<body>
<img src="<?php print $images[1][0] ?>" height="100%"> </div>
<div class="textblock"><span><a href="<?php print "http://www.bbc.co.uk".$link[2][0] ?>"><?php print $text[2][0] ?></a></span><br>
</div>
</body>
</html>

And the example, which presents the same information in a new way…

Advanced scraping demo with “regex” parsing. Retrieves current weather in any city and colors the background accordingly. The math below for normalization could use some work.

<?php

/* Advanced scraping demo with "regex" parsing. Retrieves current
* weather in any city and colors the background accordingly.
* The math below for normalization could use some work.
* Owen Mundy Copyright 2011 GNU/GPL */

?>

<html>
<head>
<style>
body { margin:20; font:1.0em/1.4em Arial, Helvetica, sans-serif; }
.text { font:10.0em/1.0em Arial, Helvetica, sans-serif; color:#000; font-weight:bold; }
.navlist { list-style:none; margin:0; position:absolute; top:20px; left:200px }
.navlist li { float:left; margin-right:10px; }
</style>
</head>

<body onLoad="document.f.q.focus();">

<form method="GET" action="<?php print $_SERVER['PHP_SELF']; ?>" name="f">

<input type="text" name="q" value="<?php print $_GET['q'] ?>" />
<input type="submit" />

</form>

<ul class="navlist">
<li><a href="?q=anchorage+alaska">anchorage</a></li>
<li><a href="?q=toronto+canada">toronto</a></li>
<li><a href="?q=new+york+ny">nyc</a></li>
<li><a href="?q=london+uk">london</a></li>
<li><a href="?q=houston+texas">houston</a></li>
<li><a href="?q=linz+austria">linz</a></li>
<li><a href="?q=rome+italy">rome</a></li>
<li><a href="?q=cairo+egypt">cairo</a></li>
<li><a href="?q=new+delhi+india">new delhi</a></li>
<li><a href="?q=mars">mars</a></li>
</ul>

<?php

// make sure the form has been sent
if (isset($_GET['q']))
{
// get contents of url in an array
if ($str = file_get_contents('http://www.google.com/search?q=weather+in+'
. str_replace(" ","+",$_GET['q'])))
{

// use regular expressions to extract only what we need...

// 1, 2, or 3 digits followed by any version of the degree symbol
$pattern = "/[0-9]{1,3}[º°]C/";
// match the pattern with a C or with an F
if (preg_match_all($pattern, $str, $data) > 0)
{
$scale = "C";
}
else
{
$pattern = "/[0-9]{1,3}[º°]F/";
if (preg_match_all($pattern, $str, $data) > 0)
{
$scale = "F";
}
}

// remove html
$temp_str = strip_tags($data[0][0]);
// remove everything except numbers and points
$temp = ereg_replace("[^0-9..]", "", $temp_str);

if ($temp)
{

// what is the scale?
if ($scale == "C"){
// convert ºC to ºF
$tempc = $temp;
$tempf = ($temp*1.8)+32;
}
else if ($scale == "F")
{
// convert ºF to ºC
$tempc = ($temp-32)/1.8;
$tempf = $temp;
}
// normalize the number
$color = round($tempf/140,1)*10;
// cool -> warm
// scale -20 to: 120
$color_scale = array(
'0, 0,255',
'0,128,255',
'0,255,255',
'0,255,128',
'0,255,0',
'128,255,0',
'255,255,0',
'255,128,0',
'255, 0,0'
);

?>

<style> body { background:rgb(<?php print $color_scale[$color] ?>) }</style>
<div class="text"><?php print round($tempc,1) ."&deg;C " ?></div>
<?php print round($tempf,1) ?>&deg;F

<?php

}
else
{
print "city not found";
}
}
}
?>

</body>
</html>




For an xpath tutorial check this page.

For the next part of the workshop we used Give Me My Data to export our information from Facebook in order to revisualize it with Nodebox 1.0, a Python IDE similar to Processing.org. Here’s an example:

Update: Some user images from the workshop. Thanks all who joined!

Mutual friends (using Give Me My Data and Graphviz) by Rob Canning

identi.ca network output (starting from my username (claude) with depth 5, rendered to svg with ‘sfdp’ from graphviz) by Claude Heiland-Allen