Processing… Processing

Like most people I’ve been bitten by the “social networks take up all my blogging time” bug.

But in reality, I think that’s OK. I once read someone who said SMS is becoming the polite way of conversing, as opposed to a phone call, because it permits the recipient to respond when it’s convenient for them as opposed to when it’s convenient for the initiator.

So blogging, remains a ‘slow and steady’ system to support the hivemind; Convenient for the author, and the searcher.

With that in mind here’s a bit of code I wrote a while back to create a Processing visualization.

I’ve loved the ‘clock’ charts where data is presented around a circle, from 1 o’clock to 12 o’clock, but never had a solid reason to use one. Unlike the Sunlight Foundation’s excellent example visualizing transparency.

However, ‘recently’ (in blogger time) I had a unique opportunity at work to apply the technique to visualizing how participants interacted with a site over time.

Here’s what I came up with:

'clock' chart of activity

User Website Activity

This represents how often users interacted with our site during it’s availability period (which spanned a number of days).

I first created the data with Python, taking the time portion of each action and creating a count, which I recorded East Coast (blue) and West Coast (orange) time. You’ll notice that the data is exactly the same in intensity, simply shifted by the appropriate timezone. This is because we had no way of knowing where the users were connecting from and wanted to simply look at the overall data to discern any patterns (and my brain doesn’t have a timezone converter built in).

Looking at the data, it should be fairly obvious that:

  • An “East Coast” interepretation meant that users interacted with the site either as the first thing during their day (i.e. 8am) or during the latter part of lunch (noon and 1:00 PM).
  • Meanwhile, “West Coast” users probably responded before lunch (11) or towards the end of the day.

I was able to build upon a great example from Jer Thorp and I apologize greatly for butchering his solution. Thankfully I didn’t need anything near as complex (and didn’t have to fight Java for JSON data since I embedded my arrays directly in the code).

So in case it helps anyone else, here’s my solution with all its warts (e.g. I know the data keys are drawn twice and there’s some manual tweaking to the drawHeight for sizing):

import processing.opengl.*;

int maxVal = 0;           //Keeps track of the maximum returned value over the all terms
int localMax = 0;         //Keeps track of the maximum returned value over the each term
float drawHeight = 0.45;  //Portion of the screen height that the largest bar takes up
//.45 for hours .65 for dates
float drawWidth = .25;  //Portion of the screen height that the largest bar takes up

int center_size = 10;
int border = 1;           //Border between bars
int lastTotal = 0;        

color[] colours = { #400101, #E46D0A, #009BF1 }; //Graph Colours
color textColor1 = #D98D30;
color textColor = #333333;
color backColor = #F2F2F2;
color curColor;

int MAX_HEIGHT = 1200;
int MAX_WIDTH = 800;

// Time Shifted Data built with a separate Python script 
String[] Hours = {"00:00", "01:00", "02:00", "03:00", "04:00", "05:00", "06:00", "07:00", "08:00", "09:00", "10:00", "11:00", "12:00", "13:00", "14:00", "15:00", "16:00", "17:00", "18:00", "19:00", "20:00", "21:00", "22:00", "23:00"};

int[] mod_est_Activity_Hours_Values = {3, 0,0,0,0,0,0, 3, 7, 9, 10, 26, 4, 7, 6, 20, 38, 10, 1, 5, 3, 2, 1, 1};
int[] mod_pdt_Activity_Hours_Values = {0,0,0,0, 3, 7, 9, 10, 26, 4, 7, 6, 20, 38, 10, 1, 5, 3, 2, 1, 1,3, 0,0};
// end generated Data

void draw() {

};

void setup() {
  PFont font = loadFont("Meta-Normal-48.vlw");
  textFont(font);

  //Set the size of the stage & set the background
  size(MAX_HEIGHT,MAX_WIDTH);
  frameRate(60);
  background(backColor);
  smooth();

  curColor = colours[1];
  drawData(Hours, mod_est_Activity_Hours_Values, Hours.length);

  curColor = colours[2];
  drawData(Hours, mod_pdt_Activity_Hours_Values, Hours.length);

  save("visual.png");
};

void drawKey(String key, float xinc, float theta) {
      float y = 0;
      float x = .5;
      String s = key;

      pushMatrix();
      translate(x + xinc/2 * drawWidth, y - (xinc * 2) * drawHeight);

      //Draw key
      rotate(-PI/2);
      fill(textColor);

      textSize(max(xinc/2, 13));
      text(s, 0, 0);

      translate(cos(theta), sin(theta));

      popMatrix();
};

void drawData(String[] keys, int[] data, int len) {
  parseData(keys, data, len);

  fill(curColor);
  float xinc = float(width)/len;

  //Move to the center of the screen
  pushMatrix();
  translate(width/2, height/4);
  noStroke();

  //Draw each value as a bar
  for (int i = 0; i < len; i++) {
    color c = color(red(curColor), green(curColor), blue(curColor), random(100,255));
    fill(c);

    float h = float(data[i])/float(maxVal);
    float theta = i * (PI / (len/2));

    translate(cos(theta) * center_size, sin(theta) * center_size);

    //Rotate
    pushMatrix();
    rotate(theta);

    //Draw the bar
    rect(0, 0, xinc * drawWidth, -h * height * drawHeight);

    drawKey(keys[i], xinc, theta);

    popMatrix();
  };

  popMatrix(); //back to original center
};

// Helps normalize the chart
void parseData(String[] keys, int[] data, int len) {
  for (int i = 0; i < len; i++) {
    if (data[i] > localMax) {
      localMax = min(data[i], 3000);
      if (localMax > maxVal) maxVal = localMax;
    };
  };
};

To make it work you’ll need to make sure the font’s installed (see Jer’s original tutorial) but it should be relatively straightforward after that.

Cheers!

About jay

I'm trying to build something interactive where I can learn from others and hopefully share useful knowledge too. thecapacity@gmail.com
This entry was posted in code, visualization. Bookmark the permalink.

2 Responses to Processing… Processing

  1. rob says:

    Re: your comment about SMS being a “polite” asynchronous way to communicate – funny, that’s how email started out 🙂
    ~rob

Comments are closed.