Chernoff Processing

csv example

I found this example on the Processing forums.

csv_example01.jpg

The first thing to do is to pick through the code and see what it does …

//declare a string type variable called "URL" and define its value as the filename of the csv feed we are going to use
String URL = "http://finance.yahoo.com/d/quotes.csv?s=GOOG&f=p"; 
//declare an array of strings called "data"
String[] data;
//declare an array of floats called "dataConverted"
float[] dataConverted;
//declare a float type variable called "result" and define its value as 10.2 (don't need this)
//float result = 10.2;

void setup(){
  // make a window 100 x 100 pixels (this does nothing for now)
  //size(100,100);
  //loadStrings reads the contents of the url and creates the String array called "data" from its individual lines.
  data = loadStrings(URL);
  //prints the contents of "data" to the console window on a single line
  println(data);
  //Every array has a variable "length" which is an integer value for the total number of elements in the array.
  //define dataConverted as a new array of floats the same length as the array called "data"
  dataConverted = new float[data.length];

//loop - for each entry in the string array called "data" ...   
  for (int i = 0; i < data.length; i++){
    //... convert the string entry to a float and save the result in the same numbered entry of "dataConverted"
    dataConverted[i] = float(data[i]);
  }

  //print the contents of "dataConverted" to the console window. 
  println(dataConverted);
}

void draw() {
  //I can get rid of these two lines, it just draws a line in the window
  //"result" has nothing to do with anything else happening, it is defined at the start and doesn't change
  //this is where I will build the graphics for the faces.
  //stroke(255);
  //line(50, 90, 50, result);  
}

So I can get rid of a few bits and tidy it up …

//declare a string type variable called "URL" and define its value as the filename of the csv feed we are going to use
String URL = "http://finance.yahoo.com/d/quotes.csv?s=GOOG&f=p"; 
//declare an array of strings called "data"
String[] data;
//declare an array of floats called "dataConverted"
float[] dataConverted;

void setup(){
  //loadStrings reads the contents of the url and creates the String array called "data" from its individual lines.
  data = loadStrings(URL);
  //prints the contents of "data" to the console window on a single line
  println(data);
  //Every array has a variable "length" which is an integer value for the total number of elements in the array.
  //define dataConverted as a new array of floats the same length as the array called "data"
  dataConverted = new float[data.length];

  //loop - for each entry in the string array called "data" ...   
  for (int i = 0; i < data.length; i++){
    //... convert the string entry to a float and save the result in the same numbered entry of "dataConverted"
    dataConverted[i] = float(data[i]);
  }

  //print the contents of "dataConverted" to the console window. 
  println(dataConverted);
}

void draw() {
   //this is where I will build the graphics for the faces.
}

This works fine. Now I need to test it with other csv files.

csv_example02.jpg

So, it can't convert the data because it returns Not a Number. I need to extract the numbers from the incoming data first, before converting to float(s). Also, I don't think I need to use an array for "data" as it's only got one entry. I think what I need to build is …

  • a string variable to hold the data for each market
  • a function to separate the string into its component values
  • an array of floats for each market to hold just the numerical data (floats made from the short strings)
csv_example03.jpg

So, what I learnt is that I DO need a string array to hold the data as "loadStrings" only works with arrays. I end up with three string arrays containing only one entry each.

Separating the values …

csv_example04.jpg

A Working Example in Processing …

(well, not exactly working - it doesn't use any outside data) …

extreme_faces.jpg

I have written a separate function to actually draw the face, using Bezier curves for all the parts which will be altered by incoming data. The image above shows the extremes of the ranges of expressions - sad or happy for rises and falls, mixed with surprise or fear to represent market volatility.

void DrawFace (){
   if(mouthBottomHeight>=0){
   mouthMidHeight = 225 + mouthBottomHeight;
   }
   else{
     mouthMidHeight=300+mouthBottomHeight;
   }
   if(eyeTopHeight>=0){
     eyebrowHeight=eyeMidHeight-eyeTopHeight;
   }
   else{
     eyebrowHeight=(eyeMidHeight-eyeTopHeight)-20;
   }

 //upper left eye
  bezier((midFace - eyeOffset), eyeMidHeight, (midFace - eyeOffset), (eyeMidHeight - eyeTopHeight), ((midFace - eyeOffset)-eyeWidth), (eyeMidHeight - eyeTopHeight), ((midFace - eyeOffset)-eyeWidth), eyeMidHeight);

   //upper right eye
  bezier((midFace + eyeOffset), eyeMidHeight, (midFace + eyeOffset), (eyeMidHeight - eyeTopHeight), ((midFace + eyeOffset)+eyeWidth), (eyeMidHeight - eyeTopHeight), ((midFace + eyeOffset)+eyeWidth), eyeMidHeight);  //upper left eye

   //lower left eye
  bezier((midFace - eyeOffset), eyeMidHeight, (midFace - eyeOffset), (eyeMidHeight + eyeBottomHeight), ((midFace - eyeOffset)-eyeWidth), (eyeMidHeight + eyeBottomHeight), ((midFace - eyeOffset)-eyeWidth), eyeMidHeight);  

   //lower right eye
  bezier((midFace + eyeOffset), eyeMidHeight, (midFace + eyeOffset), (eyeMidHeight + eyeBottomHeight), ((midFace + eyeOffset)+eyeWidth), (eyeMidHeight + eyeBottomHeight), ((midFace + eyeOffset)+eyeWidth), eyeMidHeight);  

   //left eyebrow
  bezier(((midFace - eyeOffset)-eyeWidth), eyebrowHeight, ((midFace - eyeOffset)-(eyeWidth/2)), (eyebrowHeight - 30), ((midFace - eyeOffset)-(eyeWidth/2)), (eyebrowHeight - 30), (midFace - eyeOffset), (eyebrowHeight-eyebrowSlant));                 

  //right eyebrow
  bezier(((midFace + eyeOffset)+eyeWidth), eyebrowHeight, ((midFace + eyeOffset)+(eyeWidth/2)), (eyebrowHeight - 30), ((midFace + eyeOffset)+(eyeWidth/2)), (eyebrowHeight - 30), (midFace + eyeOffset), (eyebrowHeight-eyebrowSlant));

  //upper mouth
  bezier((midFace - mouthWidth), mouthMidHeight, (midFace - mouthWidth), (mouthMidHeight - mouthTopHeight), (midFace + mouthWidth), (mouthMidHeight - mouthTopHeight), (midFace + mouthWidth), mouthMidHeight);       

  //lower mouth
  bezier((midFace - mouthWidth), mouthMidHeight, (midFace - mouthWidth), (mouthMidHeight + mouthBottomHeight), (midFace + mouthWidth), (mouthMidHeight + mouthBottomHeight), (midFace + mouthWidth), mouthMidHeight);        

  triangle(180, 220, 200, 180, 220, 220);   //nose
  ellipse (200,200,380,380);                //face
  }

The next job is to begin calibrating the system so that it doesn't go off-scale, but still shows changes as interesting results.

Facial variable sad happy surprised afraid
eyeOffset 10 30 30 10
eyeWidth 40 90 90 40
eyeTopHeight -10 40 60 60
eyeBottomHeight 40 -10 60 60
eyebrowSlant 30 0 0 30
mouthWidth 40 100 60 40
mouthTopHeight 40 -10 80 80
mouthBottomHeight -10 40 80 80
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License