twitter data visualization

3D data visualization for the last twitter messages containing a certain term or group of terms. the visualization was made in processing, using a ‘compact’ version of the twitter4j library and the twitter API. this was proposed as an exercise for the workshop datajockey, that took place in the Museum of Image and Sound of São Paulo, Brazil, from may 17th to 31st, 2011.

it searches for a term in the last tweets stored in twitter database, and shows those tweets in a 3D space, the position and the color are given according to the time of the post. if two or more posts are close in time, a line that connects them in the space, forming structures. the size of the cubes are given by the minute of the post.

sorry if i can’t post the actual sketch here, it’s due to processing.js limitations. but the source code is below, you can try it for yourself. before you test this out in processing, you must download the twitter4j library file, and insert it in a folder called “code”, inside your sketch folder. also, you need to get a couple of keys to access twitter databank. to do that, register a new application in twitter developers page.

//twitter 3D data visualization
//by medul.la
//http://medul.la
//based on the sketch '3D Processing World', by Josue Page
//http://www.openprocessing.org/visuals/?visualID=19216
//the twitter connection is made by using the twitter4j java library:
//http://twitter4j.org
 
// Before you use this sketch, register your Twitter application at dev.twitter.com
// Once registered, you will have the info for the OAuth tokens
 
//setting twitter API info:
static String OAuthConsumerKey = "PUT YOUR CONSUMER KEY HERE";
static String OAuthConsumerSecret = "PUT YOUR CONSUMER SECRET KEY HERE";
static String AccessToken = "PUT YOUR ACCESS TOKEN HERE";
static String AccessTokenSecret = "PUT YOUR ACCESS TOKEN SECRET HERE";
 
//define parameters
//a word to search for in the tweets database:
String searchTerm = "PUT YOUR SEARCH TERM HERE";
//a number of tweets to work with (you can choose any number up to 100) :
int numOfTweets = 50;
 
java.util.List statuses = null;
Twitter twitter = new TwitterFactory().getInstance();
RequestToken requestToken;
String[] theSearchTweets = new String[numOfTweets];
Date[] tweetTimeData = new Date[numOfTweets];
String[] tweetTimeStrings = new String[0];
int[] tweetTimeInts = new int[0];
color[] colors = new color[0];
int[] coords = new int[0];
int objects = numOfTweets, zoom = -300, xCube, yCube, zCube;
Pts[] cubes = new Pts[objects];
color bgColor = 0, lineColor = 255;
float R, G, B;
PFont theFont;
 
void setup() {
  size(1024, 750, P3D);
  connectTwitter();
  getSearchTweets(searchTerm);
  convertDateToString();
  convertStringToInts();
  convertIntsToColor();
  convertIntsToPosition();
  checkColors();
  checkCoords();
  background(255);
  translate(width, 0, 0);
  theFont = createFont("Arial",1000);
  for (int i = 0; i < numOfTweets ; i++) {
    String t = theSearchTweets[i];
    //println(t);
    cubes[i] = new Pts(coords[i], coords[i+1], coords[i+2], colors[i], 1, t);
  }
}
 
void draw() {
  translate(width/2, height/2, width/2+zoom);
  rotateX(map(mouseY, 0, height, -2*PI, 2*PI));
  rotateY(map(mouseX, 0, width, -2*PI, 2*PI));
  background(bgColor, 50);
  for (int u = 0; u < objects ; u++) {
    cubes[u].drawCubes();
    for (int v=0;v<objects;v++) {
      if (abs(cubes[u].z-cubes[v].z)<200) {
        if (abs(cubes[u].x-cubes[v].x)<200) {
          if (abs(cubes[u].y-cubes[v].y)<200) {
            stroke(lineColor, 50);
            beginShape(LINES);
            vertex(cubes[u].x, cubes[u].y, cubes[u].z);
            vertex(cubes[v].x, cubes[v].y, cubes[v].z);
            endShape();
          }
        }
      }
    }
    cubes[u].change();
  }
 
  if (mousePressed) {
    bgColor = 255;
    lineColor = color(255, 0, 0);
  }
  else {
    bgColor = 0;
    lineColor = 255;
  }
}
 
class Pts {
  int x, y, z;
  float tem;
  color cubeColorC;
  String theText;
 
  Pts(int a, int b, int c, color d, float e, String t) {
  x = a;
  y = b;
  z = c;
  cubeColorC = d;
  tem = b/20;
  theText = t;
 
  }
 
  void drawCubes() {
    if (mousePressed) {
      fill(0, 50);
    }
    else {
      fill(lineColor, 50);
    }
    noStroke();
    fill(cubeColorC);
    text(theText, x+30, y, 100, 1000, z);
    pushMatrix();
    translate(x, y, z); 
    fill(cubeColorC);
    box(tem);
    popMatrix();
  }
 
  void change() {
    if (x <- width) {
      x =- width + 10;
    }
    else {
      if (x > height) {
        x = height - 10;
      }
      else {
        x = x + int(random(-3, 3));
      }
    }
    if (y <- height) {
      y =- height+10;
    }
    else {
      if (y > width) {
        y = width - 10;
      }
      else {
        y = y + int(random(-5, 5));
      }
      if (z > width) {
        z = width - 10;
      }
      else {
        z = z + int(random(-5, 5));
      }
      if ( z<- width) {
        z =- width + 10;
      }
    }
  }
}
 
void keyPressed() {
  if (keyCode == 40) {
    zoom -= 300;
  }
  if (keyCode == 38) {
    zoom += 300;
  }
}
 
//twitter API functions
 
// Initial connection
void connectTwitter() {
  twitter.setOAuthConsumer(OAuthConsumerKey, OAuthConsumerSecret);
  AccessToken accessToken = loadAccessToken();
  twitter.setOAuthAccessToken(accessToken);
}
 
// Loading up the access token
private static AccessToken loadAccessToken() {
  return new AccessToken(AccessToken, AccessTokenSecret);
}
 
// Search for tweets
void getSearchTweets(String searchTerm) {
 
  String queryStr = searchTerm;
 
  try {
    Query query = new Query(queryStr);    
    query.setRpp(numOfTweets); // Get 10 of the 100 search results  
    QueryResult result = twitter.search(query);    
    ArrayList tweets = (ArrayList) result.getTweets();    
 
    for (int i = 0; i < tweets.size(); i++) {	
      Tweet t = (Tweet)tweets.get(i);	
      String user = t.getFromUser();
      String msg = t.getText();
      Date d = t.getCreatedAt();	
      theSearchTweets[i] = msg;
      tweetTimeData[i] = d;
      println(theSearchTweets[i]);
      println("----------------");
      println("Tweet by " + user + " at " + d);
      println("----------------");
      println(tweetTimeData[i]);
      println("----------------");
    }
 
  } catch (TwitterException e) {    
    println("Search tweets: " + e);  
  }
 
}
 
void convertDateToString(){
   for (int i = 0; i < tweetTimeData.length; i++){
    SimpleDateFormat df = new SimpleDateFormat("dd/MM/yyyy/HH/mm/ss");
    String s = df.format(tweetTimeData[i]);
    String sArray[] = new String [0];
    sArray = splitTokens(s, "/");
    for (int j = 0; j < sArray.length; j++){
      tweetTimeStrings = append(tweetTimeStrings, sArray[j]);
      println(tweetTimeStrings[j]);
    } 
   }
}
 
void convertStringToInts(){
   for (int i = 0; i < tweetTimeStrings.length; i++){
    int num = int(tweetTimeStrings[i]);
    tweetTimeInts = append(tweetTimeInts, num);
    println("tweetTimeInts at the index of " + i + " is: " + num);
   }
}
 
void convertIntsToColor(){
   for (int i = 3; i < tweetTimeInts.length; i = i+6){
      R = map (tweetTimeInts[i], 0, 24, 0, 255);
      G = map (tweetTimeInts[(i+1)], 0, 60, 0, 255);
      B = map (tweetTimeInts[(i+2)], 0, 60, 0, 255);
      color clr = color (R, G, B); 
      colors = append (colors, clr);
      //println("color stored is = R " + red(clr) + ", G " + green(clr) + ", B " + blue(clr));   
   }
}
 
void convertIntsToPosition(){
   for (int i = 3; i < tweetTimeInts.length; i = i+6){
      xCube = int(map (tweetTimeInts[i], 0, 24, -width, width));
      yCube = int(map (tweetTimeInts[(i+1)], 0, 60, -height, height));
      zCube = int(map (tweetTimeInts[(i+2)], 0, 60, -width, width));
      coords = append (coords, xCube);
      coords = append (coords, yCube);
      coords = append (coords, zCube);
      //println("position stored is = xCube " + xCube + ", yCube " + yCube + ", zCube " + zCube);   
   }
}
 
void checkColors(){
   for (int i = 0; i < objects; i++){
      println("color stored is = R " + red(colors[i]) + ", G " + green(colors[i]) + ", B " + blue(colors[i]));
   }
}
 
void checkCoords(){
   for (int i = 0; i < coords.length; i=i+3){
      println("position stored is = xCube " + coords[i] + ", yCube " + coords[i+1] + ", zCube " + coords[i+2]);
   }
}

..........................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................