Data Viz and MousePressed()

edited August 2016 in Library Questions

Hey everybody,

I'm working on my first data viz project based on chapter 3 of Ben Fry's Visualizing Data book.

I have a map of the US states with different sized ellipses drawn for data in each state.

I am trying to figure out how when the mouse is pressed I can change the size and colour of the ellipses and also introduce some audio.

For this I have I have my sketch followed by void mousePressed(). This allows me to generate a duplicate image and also change the colour of the ellipses.

My problem at the moment is that I can't get the second image to 'stay' on the screen.I've tried with a global boolean variable but just can't get the code right!

And also although I am able to change the colour of the ellipses I am unable to make them expand over time.

Here is what I have so far, and suggestions appreciated

boolean button = false;
PImage mapImage;
PImage mapImage2;
Table locationTable;
int rowCount;
float index = 0;
Table dataTable;
float dataMin = MAX_FLOAT;
float dataMax = MIN_FLOAT;

void setup() {
  size(1280, 800);
  frameRate(10);
  //noLoop();
  mapImage = loadImage("bigmap.png");
  mapImage2 = loadImage("bigmap2.png");//


  // Make a data table from a file that contains 
  // the coordinates of each state.
  locationTable = new Table("locations.tsv");

  // The row count will be used a lot, store it locally.
  rowCount = locationTable.getRowCount();//this reads each locations x,y valuses

  //read the data Table
  dataTable = new Table("random2.tsv");

  //find the minimum and maximum values
  for (int row = 0; row< rowCount; row++) {
    float value =dataTable.getFloat(row, 1);
    if (value>dataMax) {
      dataMax = value;
    }
    if (value< dataMin) {
      dataMin = value;
    }
  }
}

void draw() {
  background(0);
  image(mapImage, 0, 0);


  // Drawing attributes for the ellipses   
  smooth();
  fill(255, 0, 0);
  noStroke();

  // Loop through the rows of the locations file and draw the points  
  for (int row = 0; row < rowCount; row++) {
    String abbrev = dataTable.getRowName(row);  // column 1
    float x  = locationTable.getFloat(abbrev, 1);
    float y = locationTable.getFloat(abbrev, 2);  // column 2
    drawData (x, y, abbrev);
  }
}

//map the size of the elloipse to the data value
void drawData(float x, float y, String abbrev) {
  //get data value for state
  index = index+1;
  float value = dataTable.getFloat(abbrev, 1);
  //re-map the value to a number between 2 and 40
  float mapped = map(value, dataMin, dataMax, 4, 80);
  //draw and ellipse for this item


  ellipse(x*2, y*2, mapped, mapped);

  String s = " the murder rate of";
  String i = "is";
  //println(abbrev + value);
  println(s, abbrev, i, value);
}

void mousePressed() {

  button =! button;//not working
  image(mapImage2, 0, 0);
  println("image2works");


  // Drawing attributes for the ellipses   
  smooth();
  fill( 0, 255, 0);
  noStroke();

  // Loop through the rows of the locations file and draw the points  
  for (int row = 0; row < rowCount; row++) {
    String abbrev = dataTable.getRowName(row);  // column 1
    float x  = locationTable.getFloat(abbrev, 1);
    float y = locationTable.getFloat(abbrev, 2);  // column 2
    drawData2 (x, y, abbrev);
  }
}

//map the size of the ellipse to the data value
void drawData2(float x, float y, String abbrev) {
  //get data value for state
  float value2 = dataTable.getFloat(abbrev, 1);
  //re-map the value to a number between 2 and 40
  float mapped2 = map(value2, dataMin, dataMax, 4, 80);
  //draw and ellipse for this item
  mapped2= mapped2+ 1;
  // an attempt to make ellipses expand that doesn't work 
  ellipse(x*2, y*2, mapped2, mapped2);
  println("duplicate works");
}
Tagged:

Answers

  • Where are you using button?

  • Hey Koogs,

    Line 80 but using it the wrong way!

  • Answer ✓

    line 80 is changing the value. nowhere is checking that value and acting upon it.

    i'd expect to see something like this somewhere

    if (button is pressed) {
      drawSomething()
    } else {
      drawSomethingElse()
    }
    
  • Thanks Koogs,

    I've been trying to use an if else statement for both images which is then triggered by void mousePressed:

    int screen = 1;
    boolean button = false;
    PImage mapImage;
    PImage mapImage2;
    Table locationTable;
    int rowCount;
    float index = 0;
    Table dataTable;
    float dataMin = MAX_FLOAT;
    float dataMax = MIN_FLOAT;
    
    void setup() {
      size(1280, 800);
      frameRate(10);
      //noLoop();
      mapImage = loadImage("bigmap.png");
      mapImage2 = loadImage("bigmap2.png");//
    
    
      // Make a data table from a file that contains 
      // the coordinates of each state.
      locationTable = new Table("locations.tsv");
    
      // The row count will be used a lot, store it locally.
      rowCount = locationTable.getRowCount();//this reads each locations x,y valuses
    
      //read the data Table
      dataTable = new Table("random2.tsv");
    
      //find the minimum and maximum values
      for (int row = 0; row< rowCount; row++) {
        float value =dataTable.getFloat(row, 1);
        if (value>dataMax) {
          dataMax = value;
        }
        if (value< dataMin) {
          dataMin = value;
        }
      }
    }
    
    void draw() { 
      if (screen ==1) { // for first image
        background(0);
        image(mapImage, 0, 0);
    
    
        // Drawing attributes for the ellipses   
        smooth();
        fill(255, 0, 0);
        noStroke();
    
        // Loop through the rows of the locations file and draw the points  
        for (int row = 0; row < rowCount; row++) {
          String abbrev = dataTable.getRowName(row);  // column 1
          float x  = locationTable.getFloat(abbrev, 1);
          float y = locationTable.getFloat(abbrev, 2);  // column 2
          drawData (x, y, abbrev);
        }
      }
    
      //map the size of the elloipse to the data value
      void drawData(float x, float y, String abbrev) {
        //get data value for state
        index = index+1;
        float value = dataTable.getFloat(abbrev, 1);
        //re-map the value to a number between 2 and 40
        float mapped = map(value, dataMin, dataMax, 4, 80);
        //draw and ellipse for this item
        ellipse(x*2, y*2, mapped, mapped);
      } else {  /// introduces second image
    
        image(mapImage2, 0, 0);
        println("image2works");
    
    
        // Drawing attributes for the ellipses   
        smooth();
        fill( 0, 255, 0);
        noStroke();
    
        // Loop through the rows of the locations file and draw the points  
        for (int row = 0; row < rowCount; row++) {
          String abbrev = dataTable.getRowName(row);  // column 1
          float x  = locationTable.getFloat(abbrev, 1);
          float y = locationTable.getFloat(abbrev, 2);  // column 2
          drawData2 (x, y, abbrev);
        }
      }
    
      //map the size of the ellipse to the data value
      void drawData2(float x, float y, String abbrev) {
        //get data value for state
        float value2 = dataTable.getFloat(abbrev, 1);
        //re-map the value to a number between 2 and 40
        float mapped2 = map(value2, dataMin, dataMax, 4, 80);
        //draw and ellipse for this item
        mapped2= mapped2+ 1;
        // an attempt to make ellipses expand that doesn't work 
        ellipse(x*2, y*2, mapped2, mapped2);
        println("duplicate works");
      }
    }
    
    void mousePressed() {
      if (screen > 2) {
        screen = 1;
      }
    

    This isn't working as i am getting an error on Void DrawData presumably because I am putting a function within a conditional..I think.

    Thanks again,

    Paul

  • Answer ✓

    you drawData() and drawData2() are within draw(). which is a syntax error. you can't have methods within methods*

    you might jut be missing a } after line 60, or the one on line 103 might be in the wrong place. you can use ctrl-t to indent your code and that'll often highlight errors.

    drawData2 is a terrible name fwiw. the name should tell you why it's different from drawData.

    • anonymous methods, yes.but lets not go there.
  • edited August 2016

    Thanks for the speedy reply!

    I am going try and make some changes and I will get back to you...I'll also tidy the code up and rename drawdata2...

    Could you tell if the set up for the conditional and Void MousePressed look ok?

    Lines 1- variable declared Lines 43 - if statement in void draw line 71 - else in void draw data lines 105-108 void mousepressed

    As for anonymous methods...definitely ok to not go there!

    Much appreciated,

    Paul

  • Hey Koogs..I got it : )

    int screen = 0; 
    PImage mapImage;
    Table locationTable;
    int rowCount;
    Table dataTable;
    float dataMin = MAX_FLOAT;
    float dataMax = MIN_FLOAT;
    
    void setup() {
      size(1280, 800);
      frameRate(10);
      //noLoop();
      mapImage = loadImage("bigmap.png");
      locationTable = new Table("locations.tsv");
      rowCount = locationTable.getRowCount();
      dataTable = new Table("random2.tsv");
    
      //find the minimum and maximum values
      for (int row = 0; row< rowCount; row++) {
        float value =dataTable.getFloat(row, 1);
        if (value>dataMax) {
          dataMax = value;
        }
        if (value< dataMin) {
          dataMin = value;
        }
      }
    }
    
    void draw() {
    image(mapImage, 0, 0);
      for (int row = 0; row < rowCount; row++) {
        String abbrev = dataTable.getRowName(row);  // column 1
        float x  = locationTable.getFloat(abbrev, 1);
        float y = locationTable.getFloat(abbrev, 2);  // column 2
        drawData (x, y, abbrev);
        newEllipse(x, y, abbrev);
      }
    }
    void drawData(float x, float y, String abbrev) {
      if (screen==0) {
        float value = dataTable.getFloat(abbrev, 1);
        float mapped = map(value, dataMin, dataMax, 4, 80);
        smooth();
        fill(255, 0, 0);
        noStroke();
        ellipse(x*2, y*2, mapped, mapped);
        println("first ellipse works");
      }
    }
    
    void newEllipse(float x, float y, String abbrev) {
      if (screen==1) {
        println("duplicate works");
        float value2 = dataTable.getFloat(abbrev, 1);
        float mapped2 = map(value2, dataMin, dataMax, 4, 80);
        smooth();
        fill(0, 255, 0);
        noStroke();
        ellipse(x*2, y*2, mapped2, mapped2);
        println("duplicate works");
      }
    }
    
    void mousePressed() {
      screen = screen+1;
      if (screen >=2) {
        screen = 0;
      }
    }
    

    My next challenge is to make the ellipse in Void newEllipse to expand..I'll keep working!

    Thanks for your input,

    Paul

  • Answer ✓

    I would move the condition into draw:

    If screen is 0 then draw data.
    Else new ellipse.

    That way it's a bit more obvious that only one of the two options is being called.

    And you're using an int as a boolean, a boolean would be clearer.

  • Answer ✓

    Draw data and new ellipse are the same!

    (Apart from the colour.)

    If this is the final code then that's inefficient

  • Hey Koogs,

    It's not the final code..but that will probably be inefficient too. I am triggering audio also in newEllipse (working on at the moment), when I get everything working I will review and try and tidy it up

    I've just tried moving the condition into draw

        void draw() {
    
          image(mapImage, 0, 0);
    
    
          for (int row = 0; row < rowCount; row++) {
            String abbrev = dataTable.getRowName(row);  // column 1
            float x  = locationTable.getFloat(abbrev, 1);
            float y = locationTable.getFloat(abbrev, 2);  // column 2
            drawData (x, y, abbrev);
            newEllipse(x, y, abbrev);
    
            if (screen == 0){
              drawData;
            }else{
              newEllipse;
          }
        }
        }
    

    However, I am getting syntax error, insert "variableDeclarators' to complete local variabledeclaration.

    Again, I know my way of working is inefficient but I am makeing some progress for now...

    Thanks again,

    Paul

  • Answer ✓

    lines 18 and 19. i think you're closing draw() twice.

    ctrl-t in the editor, indents the code, makes these errors obvious.

  • Answer ✓

    no, that's not it

  • Answer ✓

    drawData is a method. call it using drawData();

    ditto newEllipse();

  • Answer ✓

    and include the arguments.

  • Hey Koogs,

    I have tried to put in the conditional in draw. However, not both screens will 'play' at the same time.

    import ddf.minim.*;
    
    Minim minim;
    AudioPlayer song;
    
    int radius = 1; 
    int screen = 0;
    float mapped2=0;
    PImage mapImage;
    Table locationTable;
    int rowCount;
    Table dataTable;
    float dataMin = MAX_FLOAT;
    float dataMax = MIN_FLOAT;
    
    void setup() {
      size(1280, 800);
      frameRate(1);
      //noLoop();
      mapImage = loadImage("bigmap.png");
      locationTable = new Table("locations.tsv");
      rowCount = locationTable.getRowCount();
      dataTable = new Table("random2.tsv");
      minim = new Minim(this);
    
      // this loads mysong.wav from the data folder
      song = minim.loadFile("AK47.mp3");
    
    
      //find the minimum and maximum values
      for (int row = 0; row< rowCount; row++) {
        float value =dataTable.getFloat(row, 1);
        if (value>dataMax) {
          dataMax = value;
        }
        if (value< dataMin) {
          dataMin = value;
        }
      }
    }
    
    void draw() {
    
      image(mapImage, 0, 0);
    
      // Loop through the rows of the locations file and draw the points  
      for (int row = 0; row < rowCount; row++) {
        String abbrev = dataTable.getRowName(row);  // column 1
        float x  = locationTable.getFloat(abbrev, 1);
        float y = locationTable.getFloat(abbrev, 2);  // column 2
        drawData (x, y, abbrev);
        newEllipse(x, y, abbrev);
    
        if (screen == 0) {
          drawData(x, y, abbrev);
        } else {
          newEllipse(x, y, abbrev);
        }
      }
    }
    
    
    
    void drawData(float x, float y, String abbrev) {
      //if (screen==0) {
      //radius = radius;
      float value = dataTable.getFloat(abbrev, 1);
      float mapped = map(value, dataMin, dataMax, 4, 80);
      smooth();
      fill(255, 0, 0);
      noStroke();
      ellipse(x*2, y*2, mapped, mapped);
      println("first ellipse works");
      //}
      //}
    }
    
    void newEllipse(float x, float y, String abbrev) {
      // if (screen==1) {
      println("duplicate works");
    
      float value2 = dataTable.getFloat(abbrev, 1);
      float mapped2 = map(value2, dataMin, dataMax, 4, 80);
      smooth();
      fill(0, 255, 0);
      noStroke();
      song.play();
      radius = radius+1;
      //mapped2 = mapped2 +1;    
      ellipse(x*2, y*2, mapped2+ radius, mapped2 + radius);
      println("duplicate works");
      if (radius >= height) {
        radius = 0;
        screen = 0;
        //}
    
        // }
      }
    }
    void mousePressed() {
      screen = screen+1;
      if (screen >=2) {
        screen = 0;
      }
    }
    

    Also another new issue( if you don't mind) I am able to get screen 2(new Ellipise) to go back to screen 1 when the ellipses have covered the screen.

    I can then press the mouse again and the sketch will go to screen 2.

    However, the audio file will only play the first time screen 2 appears. I would like for it to play each time screen 2 starts.

    any suggestions would be great,

    Thanks,

    Paul

  • Answer ✓

    However, not both screens will 'play' at the same time.

    ('not' = 'now'?)

    you still have the old unconditional calls in draw(). lines 51 and 52.

    you might need to rewind the song. there's a rewind method iirc.

  • Not = Now!

    Doh! I thought the calls had to be declared independently and the used in the condition...good to know!

    Works perfectly!

    I'll try rewind method now,

    Thanks for time and patience!

  • Ok this seems to solve the audio issue

    void newEllipse(float x, float y, String abbrev) {
      // if (screen==1) {
      println("screen2");
    
      float value2 = dataTable.getFloat(abbrev, 1);
      float mapped2 = map(value2, dataMin, dataMax, 4, 80);
      smooth();
      fill(0, 255, 0);
      noStroke();
      song.play();
      radius = radius+1;
      //mapped2 = mapped2 +1;    
      ellipse(x*2, y*2, mapped2+ radius, mapped2 + radius);
    
    
      if (radius >= height) {
        radius = 0;
        screen = 0;
        song.rewind();
        if (screen == 1) {
          song.play();
        }
      }
    }
    void mousePressed() {
      screen = screen+1;
      if (screen >=2) {
        screen = 0;
      }
    }
    

    The audio stops after playing in screen 2. Screen 2 reverts to screen one. I can then click mouse to start process again.

    I am now trying to make it so that user can toggle between screen one and two. When they are on screen two and they click it returns to screen one and resets screen two to beginning. At the moment screen two will keep going until it finishes ,

    Thanks,

    Paul

  • OK I might have been a bit too sudden with last comment!

    it works..sometimes!

    And when I export it in finder when the audio starts in screen 2, it then plays once in screen 1...I'll keep working on it.

Sign In or Register to comment.