Proj 2: 2D Matrix

kurtoon
Posts: 5
Joined: Sat Jan 10, 2015 11:28 am

Re: Proj 2: 2D Matrix

Post by kurtoon » Thu Jan 22, 2015 9:03 am

Urban Agriculture in Seattle

Seattle is home to a widespread community garden program. I was curious if any patterns could be discerned from Seattle Public Library checkout habits within the Dewey class 630: Agriculture. MySQL was used to query each Dewey number, from 630 to 631, accumulating the number of checkouts per month across 8 years, from 2006 to 2013.

In Processing I arranged the data vertically by Dewey number, and within each Dewey number, 8 rows represent each successive year. Months of the year are represented horizontally. I implemented a slightly unorthodox method of coloring the data. There is a lot of variation within each Dewey class across time, but some Dewey classes dominate the data, for example 635 gets well into the thousands per month, whereas 630 stays in the hundreds. By modulating not only the brightness but also the transparency of each cell in the matrix, more variation can be revealed in the low range while maintaining variation in the high ranges. I made the alpha channel have a minimum value of 20 (out of 255) for legibility and aesthetic reasons. Hue varies based on Dewey number.
Screen Shot 2015-01-22 at 1.00.45 AM.png
Analysis
From the visualization it becomes obvious that the most activity occurs during the Spring, with March being the most important month for those interested in horticulture. Checkouts tend to dwindle as winter approaches, but items related to hunting and fishing see a slight increase before Fall as people prepare for the hunting season. Interest in insect culture regularly spikes during the month of June as gardeners likely seek defense against summer pests. Overall, fewer items have been checked out across all Dewey numbers in 2012 and 2013 compared to prior years.

MySQL query:

Code: Select all

SELECT
MONTH(cout),
YEAR(cout),
COUNT(IF( deweyClass >=630 AND deweyClass < 631, 1, NULL)) as "630",
COUNT(IF( deweyClass >=631 AND deweyClass < 632, 1, NULL)) as "631",
COUNT(IF( deweyClass >=632 AND deweyClass < 633, 1, NULL)) as "632",
COUNT(IF( deweyClass >=633 AND deweyClass < 634, 1, NULL)) as "633",
COUNT(IF( deweyClass >=634 AND deweyClass < 635, 1, NULL)) as "634",
COUNT(IF( deweyClass >=635 AND deweyClass < 636, 1, NULL)) as "635",
COUNT(IF( deweyClass >=636 AND deweyClass < 637, 1, NULL)) as "636",
COUNT(IF( deweyClass >=637 AND deweyClass < 638, 1, NULL)) as "637",
COUNT(IF( deweyClass >=638 AND deweyClass < 639, 1, NULL)) as "638",
COUNT(IF( deweyClass >=639 AND deweyClass < 640, 1, NULL)) as "639"
FROM
spl2.inraw
WHERE
deweyClass >= 630 AND deweyClass < 640
AND DATE(cout) >= '2006­01­01'
AND DATE(cout) <= '2013­12­31'
AND (itemtype = "acbk" OR itemtype = "arbk")
GROUP BY MONTH(cout), YEAR(cout)
ORDER BY YEAR(cout), MONTH(cout)
Query time: 91 seconds

Processing code:

Code: Select all

int radius = 100;
int xPosition = 20;
int pos = 0;

int [][] dataMatrix = null;
int maxCount;
int numRows, numColumns;
int cellWidth, cellHeight, cellMarginHorizontal, cellMarginVertical, rowSpacing;

String [] deweyNames = new String[10];
PFont fontHeader = createFont("SukhumvitSet-SemiBold", 30, true);
PFont fontHeader2 = createFont("SourceSansPro-Semibold", 14, true);
PFont fontHeader3 = createFont("SukhumvitSet-SemiBold", 16, true);
PFont fontBracket = createFont("SourceSansPro-Regular", 80, true);
PFont fontMain = createFont("SourceSansPro-Semibold", 12, true);

color bgColor, textColor;

Table myTable;

void setup()
  {
    size(1200,900);
    smooth();
    cellWidth = 70;
    cellHeight = 5;
    cellMarginHorizontal = 220;
    cellMarginVertical = 140;
    rowSpacing = 60;
    
    bgColor = color(234,233,237);

    println("setup done");
  
    myTable = loadTable("hw1_yearmonth.csv", "header");
    
    numRows = myTable.getRowCount();
    numColumns = myTable.getColumnCount() - 2;
    
    dataMatrix = new int[numRows][numColumns];
    maxCount = dataMatrix[0][0];

    for (int i = 0; i < numRows; i++)
      {
        for (int j = 0; j < numColumns  ; j++) //skipping two columns j=2
          {
            dataMatrix[i][j] = myTable.getInt(i,(j+2));
            print(dataMatrix[i][j] + " " );

            if (dataMatrix[i][j] > maxCount)
             maxCount = dataMatrix[i][j];

          }
          println();
      }
    

      
    println("Rows: " + numRows + ", Columns: " + numColumns + ", max: " + maxCount);
    println();
    println();
    
    deweyNames[0] = "Agriculture & related technology";
    deweyNames[1] = "Apparatus, equipment, materials";
    deweyNames[2] = "Plant injuries, diseases, pests";
    deweyNames[3] = "Field & plantation crops";
    deweyNames[4] = "Orchards, fruits, forestry";
    deweyNames[5] = "Garden crops, horticulture";
    deweyNames[6] = "Animal husbandry";
    deweyNames[7] = "Processing dairy";
    deweyNames[8] = "Insect culture";
    deweyNames[9] = "Hunting, fishing, conservation";
 
  }
  
  
void draw()
  {
    background(bgColor);
    noStroke();
   
   for (int i = 0; i < numColumns; i++)
    {
      for (int j = 0; j < 12; j++)
        {
          for (int k = 0; k < 8; k++)
          {
            colorMode(HSB);
            float fillColor = 255 * dataMatrix[(k+(j*8))][i] / maxCount;
            fill(255*i/12 + (k*1), 255, (fillColor+30), (fillColor*20)+20);
            rect(cellMarginHorizontal + j * cellWidth * 1 , cellMarginVertical + (k * (cellHeight)) + (i * 60), 
                 cellWidth, cellHeight);
            fill(255,100);
            colorMode(RGB);
          }
      }
    }
    
    // Y label
    textFont(fontMain);
    fill(84,81,109);
    for (int i = 0; i < numColumns; i++)
      {
        textFont(fontHeader3);
        textAlign(RIGHT);
        text("63" + i, cellMarginHorizontal-10, cellMarginVertical + (i * rowSpacing) + 15);
        textFont(fontMain);
        textLeading(14);
        text(deweyNames[i], cellMarginHorizontal-10, cellMarginVertical + (i * rowSpacing) + 35);

      }
    for (int i = 0; i < 13; i++)  //vertical lines
      {
        if (i > 0) 
          text(i, (cellMarginHorizontal - 35) + (i*71), height-(cellMarginVertical*1.2)); //X label
        stroke(84,81,109,100);
        if (i != 0 && i != 12)
          line(cellMarginHorizontal + (i*70), cellMarginVertical, cellMarginHorizontal + (i*70), cellMarginVertical + (118*cellHeight));
      }
    for (int i = 0; i< numColumns; i++)  //horizontal lines
      {
        stroke(84,81,109,100);
        line(cellMarginHorizontal-100, cellMarginVertical + cellHeight*8 + (i*rowSpacing), 
             width-(cellMarginHorizontal*.64), cellMarginVertical + cellHeight*8 + (i*rowSpacing));
      }
    
    //TITLE
    textFont(fontHeader);
    textAlign(LEFT);
    text("Urban Agriculture in Seattle", cellMarginHorizontal, cellMarginVertical - 40);
    
    textFont(fontHeader2);
    text("Number of items checked out monthly with Dewey Decimal classifcation 630: Agriculture, 2006-2013", 
          cellMarginHorizontal, cellMarginVertical - 20);

    // LEGEND
    textFont(fontMain);
    pushMatrix();
    textAlign(LEFT);
    translate(width-(cellMarginHorizontal*.4), cellMarginVertical);
    textLeading(14);
    translate(0,32);
    text("Checkouts\nper month",-35,-25);

    colorMode(HSB);
    noStroke();
    for(int i = 0; i<50; i++)
      {
        float fillColor = (255*i)/49;
        fill(120, 255, fillColor+30, (fillColor*20)+20);
        rect(-cellWidth*.5, i*cellHeight, cellWidth*.2, cellHeight);
      }
     stroke(84,81,109,130);
     fill(0, 0);
     rect(-cellWidth*.5, 0, cellWidth*.2, cellHeight*50);
      
    translate(0,10); 
    for(int i = 0; i<5; i++)
    {
      fill(84,81,109);
      text(i*1000, -15, i * 60);
    } 
    colorMode(RGB);
    popMatrix();
 
   
  }
  
Attached is a CSV file containing the data.
Attachments
kaminski_hw1.zip
(289.79 KiB) Downloaded 275 times
hw1_yearmonth.csv
(4.03 KiB) Downloaded 311 times
Last edited by kurtoon on Sun Mar 22, 2015 2:02 pm, edited 1 time in total.

younkeehong
Posts: 4
Joined: Sat Jan 10, 2015 11:36 am

Re: Proj 2: 2D Matrix

Post by younkeehong » Thu Jan 22, 2015 9:13 am

2D Spatial Map, Loan Period vs. Pages and Dewey Class

Does longer books get to checked out for longer time? Is there specific subject of books that would be checked out for longer time? This visualization investigates loan period of books with respect to page lengths and Dewey Classification Numbers(hereafter referred to as "Dewey number") in order to answer those questions above.
Attachments
loantime.png
doc.pdf
(118.44 KiB) Downloaded 330 times

boyan
Posts: 5
Joined: Tue Jan 14, 2014 11:48 am

Re: Proj 2: 2D Matrix

Post by boyan » Thu Jan 22, 2015 9:29 am

In my previous project, I used SQL to retrieve the average and standard deviation of checkout duration from 2006 to 2014. The results show that each of the 10 dewey classes has its distinct checkout duration pattern and the difference among these classes implies some interesting phenomenon. But the result is statistically biased in that the aggregation level shadowed differences among individuals within each class. Inspired by the Modifiable Areal Unit Problem (MAUP), “a problem arising from the imposition of artificial units of spatial reporting on continuous geographical phenomena resulting in the generation of artificial spatial patterns” (Heywood, 1988), I want to know what the checkout duration pattern will look like if I change the scale (aggregation) level.

This visualization shows the average checkout duration time of each of the 908 dewey sections (there are only 908 of 999 sections in total, as some are no longer in use or have not been assigned). Each column represents one of the 99 dewey divisions and each of this dewey division is divided by 10 (some of them less than 10) sections shown in each row. I used the color brewer (http://colorbrewer2.org/) provided by Cynthia Brewer (a geographer at Penn State, known for her work on map design and color theory in cartography). Since the color only symbolizes one variable, namely the average checkout duration, it is better to use single hue to visualize the trend and difference. In order to make the color scheme represent the whole data set instead of focusing on some outliers, I also did some statistical analysis and used what we called Quantile Classification, one of the classification method used to develop choropleth map. The darker the color, the less the duration.

Update: This visualization shows the 908 sections in default, but as an interactive feature of this revised version, you can choose different levels of classification using the radio button on the right. You can compare the different level of details for three aggregation levels.

The visualization result confirms my previous thought that there is a big variance in terms of checkout duration time for Literature books.

SQL Code:

Code: Select all

 
SELECT 
    floor(deweyClass/10)*10 AS DeweyDiv,
    floor(deweyClass) AS DeweySec,
    (TIMESTAMPDIFF(DAY, cout, cin)) AS TimeAvg,
    VARIANCE(TIMESTAMPDIFF(DAY, cout, cin)) AS TimeVar
FROM
    spl2.inraw
WHERE
    YEAR(cout) <= 2014
        AND YEAR(cout) >= 2006
        AND deweyClass <> ''
        AND itemtype = 'acbk'
GROUP BY floor(deweyClass/10)*10 , floor(deweyClass)
SQL Code:

Code: Select all

SELECT 
    FLOOR(deweyClass / 100) * 100 AS DeweyDiv,
    AVG(TIMESTAMPDIFF(DAY, cout, cin)) AS TimeAvg,
    VARIANCE(TIMESTAMPDIFF(DAY, cout, cin)) AS TimeVar
FROM
    spl2.inraw
WHERE
    YEAR(cout) <= 2014
        AND YEAR(cout) >= 2006
        AND deweyClass <> ''
        AND itemtype = 'acbk'
GROUP BY FLOOR(deweyClass / 100) * 100
SQL Code:

Code: Select all

SELECT 
    FLOOR(deweyClass / 10) * 10 AS DeweyDiv,
    AVG(TIMESTAMPDIFF(DAY, cout, cin)) AS TimeAvg,
    VARIANCE(TIMESTAMPDIFF(DAY, cout, cin)) AS TimeVar
FROM
    spl2.inraw
WHERE
    YEAR(cout) <= 2014
        AND YEAR(cout) >= 2006
        AND deweyClass <> ''
        AND itemtype = 'acbk'
GROUP BY FLOOR(deweyClass / 10) * 10
Processing Code:

Code: Select all

//Author: Bo Yan (boyan@geog.ucsb.edu)
//Date: 1/27/2015
//Project: MAT259 Week 2 Project


import controlP5.*;

ControlP5 cp5;
RadioButton r;

// cell size
int cellWidth = 10;
int cellHeight = 65;

//margin
int rowMargin = 145;
int colMargin = 75;

// matrix to store data
double[][] dataMatrix, dataMatrix10, dataMatrix100;

// create a table to store matrix data
Table myTable;
Table myTable10;
Table myTable100;

int rowNum, colNum, rowNum10, colNum10, rowNum100, colNum100;

// create a font
PFont myFont;

int[][] colorbrewerG = {
    {237,248,233}, // light
    {199,233,192},
    {161,217,155},
    {116,196,118},
    {65,171,93},
    {35,139,69},
    {0,90,50}, // dark
    {80,80,80} // no data
};

int colorbrewerSelect(double value){
    int selector;
    if (value<0) {
        selector = 7;
    } 
    else if (value>=0 && value<40.77981) {
        selector = 6;
    } 
    else if (value>=40.77981 && value<46.17083) {
        selector = 5;
    }
    else if (value>=46.17083 && value<52.38916) {
        selector = 4;
    }
    else if (value>=52.38916 && value<59.87942) {
        selector = 3;
    }
    else if (value>=59.87942 && value<71.76164) {
        selector = 2;
    }
    else if (value>=71.76164 && value<113.69310) {
        selector = 1;
    } else {
        selector = 0;
    }
     
    return selector;
}

void setup() {
    //set the canvas size to 1280*800, use the PGraphicsRetina2D renderer
    size(1280, 800, "processing.core.PGraphicsRetina2D"); 
    colorMode(RGB); //set the default colormode to RGB
    //frame.setResizable(true); //make the window resizable

    //activate smoothing anti-aliasing functions between pixels
    smooth();
    cp5 = new ControlP5(this);
    r = cp5.addRadioButton("radioButton")
           .setPosition(width-rowMargin+2*cellWidth, 100)
           .setColorForeground(color(120))
           .setColorActive(color(255))
           .setColorLabel(color(255))
           .setSize(20,20)
           .setSpacingRow(10)
           .addItem("000-900",1)
           .addItem("000-990",2)
           .addItem("000-999",3)
           ;
    r.activate("000-999");
 
    
    // set the font to size 16 and helvetica, smooth is true
    myFont = createFont("Helvetica", 16, true);
    
    textAlign(CENTER, CENTER);
    
    //read the csv data, ignore the first line (header)
    myTable = loadTable("outputAvg.csv", "header");
    rowNum = myTable.getRowCount();
    colNum = myTable.getColumnCount()-1; //The 1st col is not data
    
    myTable10 = loadTable("10class.csv", "header");
    rowNum10 = myTable10.getRowCount();
    colNum10 = myTable10.getColumnCount()-1;
    
    myTable100 = loadTable("100class.csv", "header");
    rowNum100 = myTable100.getRowCount();
    colNum100 = myTable100.getColumnCount()-1;
    
    //initialize data matrix
    dataMatrix = new double[rowNum][colNum];
    dataMatrix10 = new double[rowNum10][colNum10];
    dataMatrix100 = new double[rowNum100][colNum100];
    
    //copy the table to the datamatrix
    for (int i=0; i<rowNum; i++) {
        //start from the 2nd col, the 1st col is not the data
        for (int j=0; j<colNum; j++) {
            dataMatrix[i][j] = myTable.getFloat(i,j+1);
            //print(dataMatrix[i][j] + " ");
        }
        //println();
    }
    
    for (int i=0; i<rowNum10; i++) {
        //start from the 2nd col, the 1st col is not the data
        for (int j=0; j<colNum10; j++) {
            dataMatrix10[i][j] = myTable10.getFloat(i,j+1);
            //print(dataMatrix[i][j] + " ");
        }
        //println();
    }
    
    for (int i=0; i<rowNum100; i++) {
        //start from the 2nd col, the 1st col is not the data
        for (int j=0; j<colNum100; j++) {
            dataMatrix100[i][j] = myTable100.getFloat(i,j+1);
            //print(dataMatrix[i][j] + " ");
        }
        //println();
    }
    
    
}

//Author: Bo Yan (boyan@geog.ucsb.edu)
//Date: 1/27/2015
//Project: MAT259 Week 2 Project

void draw() {
  
    background(0); //refresh background
    
    textFont(myFont, 30);
    
    text("Average Checkout Duration of Different Levels of Dewey Classification", width/2, colMargin/2);
    
    textFont(myFont);
    
    
    stroke(255);
    strokeWeight(0.5);
    if (r.getState("000-999")) {
        for (int i=0; i<rowNum; i++) {
            for (int j=0; j<colNum; j++) {
                int fillR = colorbrewerG[colorbrewerSelect(dataMatrix[i][j])][0];
                int fillG = colorbrewerG[colorbrewerSelect(dataMatrix[i][j])][1];
                int fillB = colorbrewerG[colorbrewerSelect(dataMatrix[i][j])][2];
                fill(fillR,fillG,fillB);
                rect(rowMargin-9*5+i*cellWidth+(i/10)*5,colMargin+j*cellHeight,cellWidth,cellHeight);
       
            }
        }
        
        fill(255);
        for (int i=0; i<1000; i+=100) {
            String j;
            if (i==0) {
                j = "000";
            } else {
                j = str(i);
            }
            text(j + " - " + (i+100), rowMargin+5*cellWidth-9*5+i/10*cellWidth+i/100*5, height-0.8*colMargin);
        }
        
        for (int i=0; i<10; i++) {
            text(i, rowMargin*0.6, colMargin+cellHeight/2+i*cellHeight);
        }
    }
    
        
    if (r.getState("000-900")) {
        for (int i=0; i<rowNum10; i++) {
            int fillR = colorbrewerG[colorbrewerSelect(dataMatrix10[i][0])][0];
            int fillG = colorbrewerG[colorbrewerSelect(dataMatrix10[i][0])][1];
            int fillB = colorbrewerG[colorbrewerSelect(dataMatrix10[i][0])][2];
            fill(fillR,fillG,fillB);
            rect(rowMargin-9*5+i*cellWidth*10+i*5,colMargin,cellWidth*10,cellHeight*10);
            fill(255);
            String j;
            j = str(i)+"00";
            text(j, rowMargin+5*cellWidth-9*5+i*10*cellWidth+i*5, height-0.8*colMargin);
        }
    }
    
    if (r.getState("000-990")) {
        for (int i=0; i<rowNum100; i++) {
            int fillR = colorbrewerG[colorbrewerSelect(dataMatrix100[i][0])][0];
            int fillG = colorbrewerG[colorbrewerSelect(dataMatrix100[i][0])][1];
            int fillB = colorbrewerG[colorbrewerSelect(dataMatrix100[i][0])][2];
            fill(fillR,fillG,fillB);
            rect(rowMargin-9*5+i*cellWidth+i/10*5,colMargin,cellWidth,cellHeight*10);
            fill(255); 
        }
        
        for (int i=0; i<1000; i+=100) {
            String j;
            if (i==0) {
                j = "000";
            } else {
                j = str(i);
            }
            text(j + " - " + (i+100), rowMargin+5*cellWidth-9*5+i/10*cellWidth+i/100*5, height-0.8*colMargin);
        }
    }

    textFont(myFont, 7);
    
    for (int i=0; i<8; i++){
        fill(colorbrewerG[i][0],colorbrewerG[i][1],colorbrewerG[i][2]);
        rect(width-rowMargin+3*cellWidth, height-colMargin-5-7*(7-i), 30, 5);
    }
    
    fill(255);
    text(">=113", width-rowMargin+3*cellWidth+50, height-colMargin-4-7*7);
    text("71 - 113", width-rowMargin+3*cellWidth+50, height-colMargin-4-7*6);
    text("59 - 71", width-rowMargin+3*cellWidth+50, height-colMargin-4-7*5);
    text("52 - 59", width-rowMargin+3*cellWidth+50, height-colMargin-4-7*4);
    text("46 - 52", width-rowMargin+3*cellWidth+50, height-colMargin-4-7*3);
    text("40 - 46", width-rowMargin+3*cellWidth+50, height-colMargin-4-7*2);
    text("0 - 40", width-rowMargin+3*cellWidth+50, height-colMargin-4-7*1);
    text("No Data", width-rowMargin+3*cellWidth+50, height-colMargin-4-7*0);
    text("Legend", width-rowMargin+3*cellWidth+13, height-colMargin-3-60);


}
Attachments
MAT259_PROJ2_BYAN.zip
(954.78 KiB) Downloaded 299 times
Screen Shot 2015-01-27 at 9.16.52 AM.png
Screen Shot 2015-01-27 at 9.17.04 AM.png
Screen Shot 2015-01-27 at 9.16.36 AM.png
Screen Shot 2015-01-22 at 9.28.01 AM.png
Last edited by boyan on Tue Jan 27, 2015 9:30 am, edited 1 time in total.

chicobrando
Posts: 5
Joined: Sat Jan 10, 2015 11:25 am

Re: Proj 2: 2D Matrix

Post by chicobrando » Thu Jan 22, 2015 9:58 am

Seattle is known as one of the most rainy capitals of the United States, among the top five cities with more cloudy days – an average of 226 per year.
This projects proposes a query on checkouts of books written by the most representative authors of Gothic Literature, known by mystery and Romantic plots with rainy scenarios. It questions: Are Gothic books more read during rainy days? As control, the table also brings two books that are not representative of the Gothic Literature ("Travels with Charley" and "Into the Wild").
The matrix frequency of the books' checkouts will be analyzed by month and then it will be verified if the Gothic books are rented more commonly on rainy months (Seattle gets more rain between October and March).

Design
The colors of the matrix are based on a poster that represents the Swiss Style Graphic Design:
swiss-graphic-design-150.jpg
After deciding to use the same grey background, with a font Helvetica in white, I tried different alignments for the text on the y-axis. As the design is based on the grid, it could be aligned by the border (on left) or by the matrix (on right). After testing the two options, I chose the second one.
2D.jpg
2Db.jpg
In the next step, I tried different patterns of colors and grids, finally deciding to use the same orange of the poster, with a light black grid. The versions can be observed as follows:
2Dc.jpg
2Dd.jpg
2De.jpg
2Df.jpg
Following, one can find the code and the data.

Code: Select all

int radius =100;
int xPosition  = 20;

int cellWidth =12;
int cellHeight = 50;

int rowMargin =140;
int columnMargin =100;
int [][] dataMatrix = null;
int maxCount ;
int numRows, numColumns;

PFont font = createFont( "Helvetica", 16, true);

Table myTable;

 
void setup()
    {
      size( 1300,600);
      background(104);
      smooth();
      frameRate( 10);
      println( " setup done");
      
    
      myTable = loadTable( "gothicnovels4.csv", "header");
      
      numRows = myTable.getRowCount();
      numColumns = myTable.getColumnCount();
      
      
      dataMatrix = new int[numRows][numColumns];
      
      
      
      for ( int i = 0 ; i< numRows ; i++)          
          {
            for ( int j = 0 ; j< numColumns ; j++)
                {
                  dataMatrix[i][j] = myTable.getInt(i,j);      
                  print( dataMatrix[i][j ] + " ");            
                  
                }
                println();      
          }
     
     maxCount = dataMatrix[0][0];        
     
      
     for ( int i = 0 ; i< numRows ; i++)
          {
            for ( int j = 0 ; j< numColumns ; j++)
                {
                  if ( dataMatrix[i][j] > maxCount)      
                                                         
                      {
                        maxCount = dataMatrix[i][j];
                      }
                }
          }
      
      println( numRows +"  "+ numColumns + " " + maxCount ); 
    }
void draw()
      {
       background(100);
       
    
        for ( int  i = 0 ; i<  numRows ; i++) 
            {
              for ( int  j = 0 ; j < numColumns ; j++)           
                    {                    
                        stroke(0);
                        strokeWeight(0.02);
                        colorMode(RGB);
                        //fill (255* dataMatrix[i][j] / maxCount ,255,255);
                        fill(230, 86, 36+700* dataMatrix[i][j] / maxCount);
                        colorMode(RGB);
                        rect(rowMargin+ i * cellWidth,columnMargin +j * cellHeight ,cellWidth, cellHeight );
                       
                    }
            }
            
        textAlign(RIGHT,CENTER );
        fill(255);
        text( "Mysteries of Udolpho " , rowMargin, columnMargin + cellHeight/2); 
        if ( frameCount % 20 ==0)
        textAlign(RIGHT,CENTER );
        fill(255);
        text( "Hound of Baskervilles " , rowMargin, columnMargin + cellHeight * 1.50); 
        if ( frameCount % 20 ==0)
                textAlign(RIGHT,CENTER );
        fill(255);
        text( "Dracula " , rowMargin, columnMargin + cellHeight * 2.50); 
        if ( frameCount % 20 ==0)
        textAlign(RIGHT,CENTER );
        fill(255);
        text( "Edgar Allan Poe " , rowMargin, columnMargin + cellHeight * 3.50); 
        if ( frameCount % 20 ==0)
        textAlign(RIGHT,CENTER );
        fill(255);
        text( "Northanger Abbey " , rowMargin, columnMargin + cellHeight * 4.50); 
        if ( frameCount % 20 ==0)
        textAlign(RIGHT,CENTER );
        fill(255);
        text( "Frankenstein " , rowMargin, columnMargin + cellHeight * 5.50); 
        if ( frameCount % 20 ==0)
        textAlign(RIGHT,CENTER );
        fill(255);
        text( "Dr. Jekyll & Mr. Hyde " , rowMargin, columnMargin + cellHeight * 6.50); 
        if ( frameCount % 20 ==0)
        textAlign(RIGHT,CENTER );
        fill(255);
        text( "Travels with Charley " , rowMargin, columnMargin + cellHeight * 7.50); 
        if ( frameCount % 20 ==0)
        textAlign(RIGHT,CENTER );
        fill(255);
        text( "Into the Wild " , rowMargin, columnMargin + cellHeight * 8.50); 
        if ( frameCount % 20 ==0)
        textAlign(RIGHT,CENTER );
        fill(255);
        text( "Drought/06 " , rowMargin + cellWidth * 9, columnMargin - cellHeight * 0.50);
        if ( frameCount % 20 ==0)
        textAlign(RIGHT,CENTER );
        fill(255);
        text( "Rain/06    " , rowMargin + cellWidth * 14, columnMargin - cellHeight * 0.50); 
        if ( frameCount % 20 ==0)
        textAlign(RIGHT,CENTER );
        fill(255);
        text( "Drought/07 " , rowMargin + cellWidth * 21, columnMargin - cellHeight * 0.50); 
        if ( frameCount % 20 ==0)
        textAlign(RIGHT,CENTER );
        fill(255);
        text( "Rain/07 " , rowMargin + cellWidth * 25, columnMargin - cellHeight * 0.50); 
        if ( frameCount % 20 ==0)
        textAlign(RIGHT,CENTER );
        fill(255);
        text( "Drought/08 " , rowMargin + cellWidth * 33, columnMargin - cellHeight * 0.50); 
        if ( frameCount % 20 ==0)
        textAlign(RIGHT,CENTER );
        fill(255);
        text( "Rain/08 " , rowMargin + cellWidth * 37, columnMargin - cellHeight * 0.50); 
        if ( frameCount % 20 ==0)
        textAlign(RIGHT,CENTER );
        fill(255);
        text( "Drought/09 " , rowMargin + cellWidth * 45, columnMargin - cellHeight * 0.50); 
        if ( frameCount % 20 ==0)
        textAlign(RIGHT,CENTER );
        fill(255);
        text( "Rain/09 " , rowMargin + cellWidth * 49, columnMargin - cellHeight * 0.50); 
        if ( frameCount % 20 ==0)
        textAlign(RIGHT,CENTER );
        fill(255);
        text( "Drought/10 " , rowMargin + cellWidth * 57, columnMargin - cellHeight * 0.50); 
        if ( frameCount % 20 ==0)
        textAlign(RIGHT,CENTER );
        fill(255);
        text( "Rain/10 " , rowMargin + cellWidth * 61, columnMargin - cellHeight * 0.50); 
        if ( frameCount % 20 ==0)
        textAlign(RIGHT,CENTER );
        fill(255);
        text( "Drought/11 " , rowMargin + cellWidth * 69, columnMargin - cellHeight * 0.50); 
        if ( frameCount % 20 ==0)
        textAlign(RIGHT,CENTER );
        fill(255);
        text( "Rain/11 " , rowMargin + cellWidth * 73, columnMargin - cellHeight * 0.50); 
        if ( frameCount % 20 ==0)
        textAlign(RIGHT,CENTER );
        fill(255);
        text( "Drought/12 " , rowMargin + cellWidth * 81, columnMargin - cellHeight * 0.50); 
        if ( frameCount % 20 ==0)
        textAlign(RIGHT,CENTER );
        fill(255);
        text( "Rain/12 " , rowMargin + cellWidth * 85, columnMargin - cellHeight * 0.50); 
        if ( frameCount % 20 ==0)
        textAlign(RIGHT,CENTER );
        fill(255);
        text( "Drought/13 " , rowMargin + cellWidth * 93, columnMargin - cellHeight * 0.50); 
        if ( frameCount % 20 ==0)
        textAlign(RIGHT,CENTER );
        fill(255);
        text( "Rain/13 " , rowMargin + cellWidth * 97, columnMargin - cellHeight * 0.50); 
        if ( frameCount % 20 ==0)
        textAlign(RIGHT,CENTER );
        fill(255);
                text( "Are Gothic books more read during rainy days?" , rowMargin + cellWidth*23, columnMargin - cellHeight * 1.5); 
        if ( frameCount % 20 ==0)
        
           {
             println( "draw called " + frameCount );                     
           }
}
gothicnovels4.csv
(2.49 KiB) Downloaded 303 times
Last edited by chicobrando on Thu Jan 22, 2015 12:07 pm, edited 1 time in total.

matzewagner
Posts: 5
Joined: Sat Jan 10, 2015 11:35 am

Re: Proj 2: 2D Matrix

Post by matzewagner » Thu Jan 22, 2015 10:48 am


God's favorite medium

Due to the nature of the data output of my Project 1 query, I made the decision to create another query for my 2D matrix visualization. The new query searches through the Dewy numbers beginning with 2, which corresponds to the subject area of religion. I group the results according to itemtype, with the restriction that the medium has to be electronic. Finally, I order the results by checkout date.

Code: Select all

#SQL QUERY
SELECT 
    SUM(CASE
        WHEN
            (itemtype = 'acvhs' OR itemtype = 'alvhs'
                OR itemtype = 'arvhs'
                OR itemtype = 'bcvhs'
                OR itemtype = 'blvhs')
        THEN
            1
        ELSE 0
    END) AS adultvhs,
    SUM(CASE
        WHEN
            (itemtype = 'acdvd' OR itemtype = 'ardvd'
                OR itemtype = 'bcdvd')
        THEN
            1
        ELSE 0
    END) AS adultdvd,
    SUM(CASE
        WHEN
            (itemtype = 'jcvhs' OR itemtype = 'jlvhs'
                OR itemtype = 'jrvhs')
        THEN
            1
        ELSE 0
    END) AS juvvhs,
    SUM(CASE
        WHEN (itemtype = 'jcdvd' OR itemtype = 'jrdvd') THEN 1
        ELSE 0
    END) AS juvdvd,
    SUM(CASE
        WHEN
            (itemtype = 'acvhs' OR itemtype = 'alvhs'
                OR itemtype = 'accdrom'
                OR itemtype = 'arcdrom'
                OR itemtype = 'blcdrom'
                OR itemtype = 'drcdrom'
                OR itemtype = 'jccdrom')
        THEN
            1
        ELSE 0
    END) AS cdrom,
    SUM(CASE
        WHEN
            (itemtype = 'acvhs' OR itemtype = 'alvhs'
                OR itemtype = 'accd'
                OR itemtype = 'arcd'
                OR itemtype = 'jrcd'
                OR itemtype = 'jccd')
        THEN
            1
        ELSE 0
    END) AS cd,
    SUM(CASE
        WHEN
            (itemtype = 'acvhs' OR itemtype = 'alvhs'
                OR itemtype = 'accas'
                OR itemtype = 'arcas'
                OR itemtype = 'bccas'
                OR itemtype = 'jrcas'
                OR itemtype = 'jccas')
        THEN
            1
        ELSE 0
    END) AS cassette,
    SUM(CASE
        WHEN
            (itemtype = 'acvhs' OR itemtype = 'alvhs'
                OR itemtype = 'acdisk'
                OR itemtype = 'ardisk'
                OR itemtype = 'jrdisk')
        THEN
            1
        ELSE 0
    END) AS diskette,
    SUM(CASE
        WHEN (itemtype = 'arweb' OR itemtype = 'jrweb') THEN 1
        ELSE 0
    END) AS web,
    SUM(CASE
        WHEN
            (itemtype <> 'acbk'
                AND itemtype <> 'arbk'
                AND itemtype <> 'bcbk'
                AND itemtype <> 'achvs'
                AND itemtype <> 'alvhs'
                AND itemtype <> 'arvhs'
                AND itemtype <> 'bcvhs'
                AND itemtype <> 'blvhs'
                AND itemtype <> 'acdvd'
                AND itemtype <> 'ardvd'
                AND itemtype <> 'bcdvd'
                AND itemtype <> 'jcbk'
                AND itemtype <> 'jrbk'
                AND itemtype <> 'jcvhs'
                AND itemtype <> 'jlvhs'
                AND itemtype <> 'jrvhs'
                AND itemtype <> 'jcdvd'
                AND itemtype <> 'jrdvd'
                AND itemtype <> 'accdrom'
                AND itemtype <> 'arcdrom'
                AND itemtype <> 'blcdrom'
                AND itemtype <> 'drcdrom'
                AND itemtype <> 'jccdrom'
                AND itemtype <> 'accd'
                AND itemtype <> 'arcd'
                AND itemtype <> 'jrcd'
                AND itemtype <> 'jccd'
                AND itemtype <> 'accas'
                AND itemtype <> 'arcas'
                AND itemtype <> 'bccas'
                AND itemtype <> 'jrcas'
                AND itemtype <> 'jccas'
                AND itemtype <> 'acdisk'
                AND itemtype <> 'ardisk'
                AND itemtype <> 'jrdisk'
                AND itemtype <> 'arweb'
                AND itemtype <> 'jrweb')
        THEN
            1
        ELSE 0
    END) AS other
FROM
    spl2.inraw
WHERE
    DATE(cout) > '2005-12-31'
        AND (deweyclass >= 200 AND deweyclass < 300)
GROUP BY MONTH(cout) , YEAR(cout)
ORDER BY YEAR(cout) , MONTH(cout)

I began the visualization with the Processing code, which Mohit demonstrated during the last class. I first added the respective labels for the x-axis (time) and y-axis (type of medium). Then I experimented with different color mappings of the data, as well as the background and the font.

Code: Select all

//PROCESSING CODE
int radius =100;
int xPosition  = 20;

int cellWidth = 10; 
int cellHeight = 60; 
int rowMargin = 180;
int columnMargin = 100;

int [][] dataMatrix = null;
int maxCount ;
int numRows, numColumns;

PFont font = createFont( "Futura-CondensedMedium-48.vlw", 16, true);

Table myTable;

void setup()
{
  size( 1280, 800);
  background(255);
  smooth();
  frameRate( 10);
  println( " setup done");

  myTable = loadTable( "GodsPreferredElectronicMedium.csv", "header");

  numRows = myTable.getRowCount();
  numColumns = myTable.getColumnCount();

  dataMatrix = new int[numRows][numColumns];


  for ( int i = 0; i< numRows; i++)         
  {
    for ( int j = 0; j< numColumns; j++)
    {
      dataMatrix[i][j] = myTable.getInt(i, j);      
      print( dataMatrix[i][j ] + " ");
    }
    println();
  }


  maxCount = dataMatrix[0][0];        


  for ( int i = 0; i< numRows; i++)
  {
    for ( int j = 0; j< numColumns; j++)
    {
      if ( dataMatrix[i][j] > maxCount)      
      {
        maxCount = dataMatrix[i][j];
      }
    }
  }

  println( numRows +"  "+ numColumns + " " + maxCount );
}
void draw()
{
  background(120, 120, 110); // 120 gray is good

  for ( int  i = 0; i<  numRows; i++) 
  {
    for ( int  j = 0; j < numColumns; j++)           
    {                    
      //fill( 255* dataMatrix[i][j] / maxCount );     // when we divide dataMatrix by maxCount, we should recieve a value between 0 and 1.
      // on multiplying it by 255, we use the full color range from 0 to 255
      // fill( 0, 0, 255* dataMatrix[i][j] / maxCount, 200 ); // blue
      stroke(100);
      strokeWeight(1);
      colorMode(HSB); 
      // fill( 255 * dataMatrix[i][j] / maxCount, 192, 192);
      // fill( 255, 255 * dataMatrix[i][j] / maxCount, 192);
      fill( 20, 180, 255* dataMatrix[i][j] / (maxCount/1.7));
      // fill( map(mouseX, 0,width,0,255), 180, 255* dataMatrix[i][j] / (maxCount/1.7));
      //fill(150, 255* dataMatrix[i][j] / (maxCount/1.7),255);
      //fill( 130, 255, 255 - 255* dataMatrix[i][j] / (maxCount/1.5));
      colorMode(RGB);
      rect( rowMargin + i * cellWidth, columnMargin + j * cellHeight, cellWidth, cellHeight );
    }
  }

  fill(255, 255, 220);
  textAlign(CENTER, CENTER);
  textSize(18);
  text("God's Preferred Electronic Medium", width/2, rowMargin/3);
  textAlign(CENTER, CENTER);
  textSize(12);
  //for ( int i=0; i<1000; i+=100) {
      //text( i + " - " + (i+100), rowMargin * 0.75, columnMargin + cellHeight/2 + (i/100 * cellHeight));
      text( "Adult VHS ", rowMargin * 0.75, columnMargin + cellHeight/2 + (0 * cellHeight));
      text( "Adult DVD ", rowMargin * 0.75, columnMargin + cellHeight/2 + (1 * cellHeight));
      text( "Youth VHS ", rowMargin * 0.75, columnMargin + cellHeight/2 + (2 * cellHeight));
      text( "Youth DVD ", rowMargin * 0.75, columnMargin + cellHeight/2 + (3 * cellHeight));
      text( "CD_ROM ", rowMargin * 0.75, columnMargin + cellHeight/2 + (4 * cellHeight));
      text( "Audio CD ", rowMargin * 0.75, columnMargin + cellHeight/2 + (5 * cellHeight));
      text( "Audio Cassette ", rowMargin * 0.75, columnMargin + cellHeight/2 + (6 * cellHeight));
      text( "Diskette ", rowMargin * 0.75, columnMargin + cellHeight/2 + (7 * cellHeight));
      text( "Web ", rowMargin * 0.75, columnMargin + cellHeight/2 + (8 * cellHeight));
      text( "Other ", rowMargin * 0.75, columnMargin + cellHeight/2 + (9 * cellHeight));
  //}
  textSize(13);
  for ( int i=1; i<=96; i+=12) {
    text(i/12 + 2005, rowMargin - cellWidth/2 + i * cellWidth, height - 0.75 * columnMargin);
  }
}
The images below document some stages of the process I went through.
Screen Shot 2015-01-21 at 5.23.48 PM.png
adding x and y labels
Screen Shot 2015-01-21 at 5.37.03 PM.png
adding title, scaling intensity coloring
Screen Shot 2015-01-21 at 5.42.53 PM.png
changing background and font color
Screen Shot 2015-01-21 at 5.54.17 PM.png
changing intensity color scheme
Screen Shot 2015-01-21 at 6.03.34 PM.png
adjust background color and font color

dimberman
Posts: 6
Joined: Sat Jan 10, 2015 11:28 am

Re: Proj 2: 2D Matrix

Post by dimberman » Thu Jan 22, 2015 11:09 am

Image
http://i.imgur.com/F5S6C8r.png
Description:
I wanted to look into the amount of time dependency found in different genres of books. For each genre I took a reading of each hour of the week, normalized the values, and then effected the brightness based on the deviation of that hour. I wanted to find out if there were correlations between time of day, day of week, and amount that genre is lent out.

Query:

Code: Select all

SELECT * FROM(SELECT count(case when (deweyclass >= 810 or deweyclass<820)  then 1 else 0 end) as day1
  FROM spl2.inraw  
  where date(cout)>="2013-03-01" and date(cout)<"2013-04-01" and dayofweek(date(cout))=1
  group by hour(cout)  
  order by hour(cout))

graph code:

Code: Select all

/*
class demo on Jan 15, 2015
By Mohit Hingorani
if you have any questons regarding the code please email me at mohit@mat.ucsb.edu


we will be going over on how to import any table into processing and arrays again in next class
in this demo we are importing a simple integer table 

This demo creates a two-dimensional grid where each cell has 3 values: a verticallocation, a horizontal location, 
and a cell colorvalue. All the values are stored in a csv file which has 11 columns of integers acquired through 
a MySQL quary in the SPL database. There are 31rows of data representing a query which has looked for data for 31 days

COMMENTS: any line that begins with // or is in-between /*    */
/* is commented out and the program does not see it, only humans. 
------------
Variables include
int = are integers such as, 5, 89, 594803
float = are decimal based numbers such as 5.45, 1489.3482
string = "life", "overthetop" strings are a sequence of characters and alwasy in double quotes
int []array = {34,65,2} is a 1 dimensional array, a list of data separated by commas
int[][]array = a 2 dimensional array as we use in this demo
*/

/* initializing a variable outside of a function makes it global. The variable is active and available throughtout the programe 
Variables initialized inside a function are called local variables and lose their values once the program exits the function 
*/
int radius =100;
int xPosition  = 20;


// we added these variables in class on tuesday

int cellWidth = 20;
int cellHeight = 50;

int rowMargin =180;
int columnMargin = 80;

/*Creating a two-dimensional array we are calling "Data Matrix", and initialize its values to null. 
A two-dimensional array is really nothing more than an array of arrays (a three-dimensional array 
is an array of arrays of arrays).
*/
int [][] standardDevMatrix = null;
int [][] averageMatrix = null;

// a variable to keep track of the MaxCount
int maxCount ;
int maxCount2;
//variables to represent the vertical and horizontal locations of the grid we will draw
int numRows, numColumns;

// crating a font of size 16 and helvetica 
PFont font = createFont( "Helvetica", 24, true);

// creating a table. Table objects store data with multiple rows and columns, much like in a traditional spreadsheet
Table myTable;
Table avTable;

 
void setup()
    {
      //setting up a screen size 640*360
      size( 1280,800);
      //colorMode(HSB);
      // set background to white
      background(0,2,2);
      //activate smoothing anti-aliasing functions between pixels
      smooth();
      // set framerate to 10 per second. NOrmal video is 30 or 60
      frameRate( 10);
      //Print out the text in the command prompt once the program reaches here
      println( " setup done");
      
    
      //in this step we copy the data from the csv file into our own table.
      //we use header flag to tell processing to ignore the first line of the csv file as it contains the names of the columns
      myTable = loadTable( "onemonthmindacbkjcbk.csv");
      avTable = loadTable("averageData.csv");
      
      // assign these variables to contain the number of rows and columns from myTable
      numRows = myTable.getRowCount();
      numColumns = myTable.getColumnCount();
      
      // initialize the 2D array with number of rows and columns
      standardDevMatrix = new int[numRows][numColumns];
      averageMatrix = new int[numRows][numColumns];
      
      // copy everything from table into a 2D array
      // use two for loops to iterate over both rows and columns
      // this step is not necessary, but helps in matrix manipulations which we will be doing later
      
      for ( int i = 0 ; i< numRows ; i++)          // a for loop where i is set to 0  and increments all the way to numRows by 1
          {
            for ( int j = 0 ; j< numColumns ; j++)// a for loop where j is set to 0  and increments all the way to numColumns by 1
                {
                  standardDevMatrix[i][j] = myTable.getInt(i,j);      // copying the table integer value at mytable (i,j) position into the standardDevMatrix
                  print( standardDevMatrix[i][j ] + " ");            // print out the value of standardDevMatrix
                  
                }
                println();      // switch to next line in the prompt, improves legibility
          }
     
           for ( int i = 0 ; i< numRows ; i++)          // a for loop where i is set to 0  and increments all the way to numRows by 1
          {
            for ( int j = 0 ; j< numColumns ; j++)// a for loop where j is set to 0  and increments all the way to numColumns by 1
                {
                  averageMatrix[i][j] = avTable.getInt(i,j);      // copying the table integer value at mytable (i,j) position into the standardDevMatrix
                  print( standardDevMatrix[i][j ] + " ");            // print out the value of standardDevMatrix
                  
                }
                println();      // switch to next line in the prompt, improves legibility
          }
     
     // selecting the maximum number from standardDevMatrix 
     maxCount = standardDevMatrix[0][0];        // we set our maxCount variable to standardDevMatrix[0][0] , then change it if we encounter a larger number
     
      
     for ( int i = 0 ; i< numRows ; i++)
          {
            for ( int j = 0 ; j< numColumns ; j++)
                {
                  if ( standardDevMatrix[i][j] > maxCount)      // this is an if statement which checks for the condition in brackets
                                                         // if true, it executes the statements in brackets 
                      {
                        maxCount = standardDevMatrix[i][j];
                      }
                }
          }
      
      
      
           maxCount2 = averageMatrix[0][0];        // we set our maxCount variable to standardDevMatrix[0][0] , then change it if we encounter a larger number
     
      
     for ( int i = 0 ; i< numRows ; i++)
          {
            for ( int j = 0 ; j< numColumns ; j++)
                {
                  if ( averageMatrix[i][j] > maxCount2)      // this is an if statement which checks for the condition in brackets
                                                         // if true, it executes the statements in brackets 
                      {
                        maxCount2 = averageMatrix[i][j];
                      }
                }
          }
      
      println( numRows +"  "+ numColumns + " " + maxCount ); // printing out the variables
    }
//The Draw() processing function repeats itselfs continuously at 60 frames per second unless the frameRate is changed
void draw()
      {
        // refresh background every frame
       background(200);
       
        int addedWeight = 0;
        //creating the cells sequentially
        // this where the actual drawing of data happens 
        // we run two nested loops, one for rows and the other for columns , we go through each cell to retrive its value 
        // and fill the color of the cell accordingly
        for ( int  i = 0 ; i<numRows ; i++) 
            {
                 if(i%7==0 && i!=0){
//                               fill(200); 
//                               rect(rowMargin+ i * cellWidth ,columnMargin +j * cellHeight ,cellWidth, cellHeight );                // draw the rectange of size 15,25 at the appropriate position, the position of the cell depends on its value in the table position (i,j)
                              addedWeight++;
                              println("calling addweight");
                 }
              for ( int  j = 0 ; j < numColumns ; j++)           // -1 as the last column is empty, our standardDevMatrix is smaller than the table by one column
                    {                    
                        //fill( 255* standardDevMatrix[i][j] / maxCount );     // when we divide standardDevMatrix by maxCount, we should recieve a value between 0 and 1.
                                                                      // on multiplying it by 255, we use the full color range from 0 to 255
                        
                        
                        stroke(128);                                      // turn color of borders to gray
                        strokeWeight(0.5);                                // make the borders thinner

                        colorMode(HSB);                                  // switch color mode to HSB space
                        //fill ( 255* standardDevMatrix[i][j] / maxCount ,128,192);
                        println(255* standardDevMatrix[i][j] / maxCount);
                        fill(255*standardDevMatrix[i][j]/maxCount ,255 * averageMatrix[i][j]/maxCount2, standardDevMatrix[i][j] );  // 
                        
                        colorMode(RGB);                                  //switch colorspace back to RGB
                        rect(rowMargin+ (i + addedWeight)* cellWidth ,columnMargin +j * cellHeight ,cellWidth, cellHeight );                // draw the rectange of size 15,25 at the appropriate position, the position of the cell depends on its value in the table position (i,j)
                    }
            }
            
         //the % is called modulo. It finds the remainder after division. So 21% 20 returns 1, 21%12 returns 7, 21%21 returns 0
        
        textAlign(CENTER ,CENTER );              // align text to CENTER
        fill( 100);                              // make color of text to light gray
        
               for ( int i = 0 ; i<=12 ;i++)
                  text( i+8 + ":00" , rowMargin *.75  , columnMargin+cellHeight/2+i*cellHeight);
            
//        
//        text( "Arts" , rowMargin * 0.75, columnMargin + cellHeight/2 );
//        text( "Astronomy" , rowMargin * 0.75, columnMargin + cellHeight/2 +   cellHeight);
//        text( "Home+Family" , rowMargin * 0.75, columnMargin + cellHeight/2 +  2 * cellHeight);
//        text( "Literature" , rowMargin * 0.75, columnMargin + cellHeight/2 +  3 * cellHeight);

            text( "Arts"  , rowMargin + cellWidth*3.5  , columnMargin/2);
            text("Astronomy"  , rowMargin + cellWidth*3.5 +  cellWidth*8, columnMargin/2);
            text("Home+Family"  , rowMargin + cellWidth*3.5 +  cellWidth*16, columnMargin/2);
            text("Literature"  , rowMargin + cellWidth*3.5 +  cellWidth*24, columnMargin/2);


        // repeat the process for day numbers
//        for ( int i = 1 ; i<=13 ;i++)
//            text( i+7 + ":00" , rowMargin -  cellWidth/2 + i * cellWidth  , height- 1.25 * columnMargin);
//            
        if ( frameCount % 20 ==0)
           {
             println( "draw called " + frameCount );                    // here we are printing out the frameCount ( how many frames have been drawn so far) 
           }
}
    
    

checorh
Posts: 2
Joined: Sat Jan 10, 2015 11:34 am

Re: Proj 2: 2D Matrix

Post by checorh » Thu Jan 22, 2015 5:59 pm

Description
Analyze hourly frequency of check-outs during any day of the week.

Approach
  • - 2X2 grid correspoding to Day of the week vs Hour
    - Each cell will contain a Pie Chart whose radius will be proportional to the average number of checkouts and its categories are: CD, Book, DVD and Other
Sketch
IMG_2114.JPG
Results
First attempt:
Screen Shot 2015-01-22 at 17.30.59.png
Final version:
Screen Shot 2015-01-22 at 21.06.54.png
Processing Code

Code: Select all

import java.util.*;

PFont font = createFont( "Helvetica",16, true);

int xPosition  = 20;

int cellHeight  = 55;
int cellWidth = cellHeight;


int rowMargin  = 120;
int colMargin  = 100;

Table myTable;

void setup(){
   //setting up a screen size 640*360
      size( 1280,800);
      colorMode(HSB); // for hsb color mode
      // set background to white
      background(255);
      //activate smoothing anti-aliasing functions between pixels
      smooth();
      // set framerate to 10 per second. NOrmal video is 30 or 60
      //frameRate( 10);
      strokeWeight(0);
      //Print out the text in the command prompt once the program reaches here
      println( " setup done");
      
  myTable = loadTable( "splHour.csv","header"); // read data
  
        float[] mean_obs;
        mean_obs = myTable.getFloatColumn("mean_obs");
        float[] num_obs;
        num_obs = myTable.getFloatColumn("num_obs");
        int numTableRows;
        numTableRows = myTable.getRowCount();
        float[] angles;
        angles = new float[4];
        
        float dataMin = min(myTable.getFloatColumn("mean_obs"));
        float dataMax = max(myTable.getFloatColumn("mean_obs"));
                
        for(int i=0; i < (numTableRows/4); i++){         
          // radious proportional to mean of observations
          float diameter = map(myTable.getFloatColumn("mean_obs")[i*4],//mean of obs
                              dataMin,dataMax,
                              cellHeight/1.5,cellHeight); 
 
          // Draw pie chart
                        
          int xCoord = (myTable.getIntColumn("hour_out")[i*4]-6);
          int yCoord = myTable.getIntColumn("week_day")[i*4];
          
          
          stroke(0); 
          // color of border
             strokeWeight(.3);
             fill(255);
//                        rect(rowMargin + xCoord * cellWidth ,
//                              colMargin + yCoord * cellHeight ,
//                              cellWidth,
//                              cellHeight);
             
          for(int k=0;k<4;k++){
            angles[k] = myTable.getFloatColumn("num_obs")[(i*4 + k)];
            }
            
          printArray(mapArray(Proportion(angles),0,1,0,360));
          
          
          // Draw pie chart at a specific location
          pieChart(diameter,//diameter, // diameter
                   mapArray(Proportion(angles),0,1,0,360), // angles for the pie chart
                   (rowMargin + cellWidth/2) + xCoord*cellWidth, //x
                   (colMargin + cellHeight/2) + yCoord*cellHeight); //x
                //println(myTable.getIntColumn("num_obs")[1]);
             
             
          ////// For adding text!!
         textAlign(CENTER, // horizontal
                   CENTER); // vertical
         fill(0);
         
           
        }  
       //// adding text
       // row lables
         String [] Days = {"Sun", "Mon","Tue","Wed","Thu","Fri","Sat"};
         for(int d = 0; d< Days.length;d++){
           text(Days[d],
               rowMargin * 0.75, // x-coordinate
               (colMargin + cellHeight/2) + (d+1)*cellHeight); // y-coordinate
         }
         
          // Col lables 
          textAlign(CENTER,BOTTOM); // vertical
        for(int r = 0; r<18;r++){
             text(r + 6 + ":00", // actual text 
                 (rowMargin + cellWidth/2) + r*cellWidth, // x-coordinate
                 rowMargin + 0.6*cellHeight); // y-coordinate
        }  
                 
            textSize(50); 
            textFont(font);    
           text("Most Popular Items from Dewey Class 0 -100", // actual text 
               width/2, // x-coordinate
                 rowMargin ); // y-coordinate
                 
        // place guides for colors
        //stroke(10); 
          // color of border
             //      strokeWeight(.5);
           String [] ItemType = {"Other","Book","CD","DVD"};
           
           for(int col = 0;col<4;col++){
             float gray = map(col,0,4,0, 255);
             fill(gray);
             strokeWeight(0);
             rect(width - 1.20*rowMargin,
                  (0.45*height) - col*cellWidth/2,
                  cellWidth/2,
                  cellHeight/2);
              // Add lables   
             fill(0); 
             textSize(16);   
             textAlign(CENTER,CENTER);
              text(ItemType[col],
               width - .75*rowMargin, // x-coordinate
               (0.45*height - col*cellWidth/2) + cellWidth/4);  // y-coordinate   
                                
           }  
           textSize(20);
              text("Sergio Rodriguez",
               .75*width, // x-coordinate
               0.75*height);  // y-coordinate
             
   
        
}



////////////////
// Functions
///////////////////


// Get unique values
static final int[] getUniqueValues(int[] values) {
  Collection<String> noDups = new HashSet( Arrays.asList(str(values)) );
  Arrays.sort(values = int( noDups.toArray(new String[noDups.size()]) ));
  return values;
}

static final float[] getUniqueValues(float[] values) {
  Collection<String> noDups = new HashSet( Arrays.asList(str(values)) );
  Arrays.sort(values = float( noDups.toArray(new String[noDups.size()]) ));
  return values;
}



/// For creating a pie chart
void pieChart(float diameter, float[] data, float xPosition,
              float yPosition) {
  float lastAngle = 0;
  for (int i = 0; i < data.length; i++) {
    float gray = map(i, 0, data.length, 0, 255);
    fill(gray);
    strokeWeight(0);
    arc(xPosition, 
        yPosition, 
        diameter, 
        diameter, 
        lastAngle, 
        lastAngle+radians(data[i]));
        lastAngle += radians(data[i]);
  }
}


//// Sum float arrays
float sumFloat( float [] data){
      float [] xout;
      xout = new float[data.length];
      float sum = 0;
      for (int s=0; s<data.length; s++) {
        sum += data[s];
        }
        return sum;
} 


// Proportions of counts
float [] Proportion( float [] data){
      float [] xout;
      xout = new float[data.length];
      
      for (int s=0; s<data.length; s++) {
        if(data[s]==0){
          xout[s] =0;
        } else {
        xout[s] = data[s]/sumFloat(data);  
        }
        }
        return xout;
}

// Map function applied to an array
float [] mapArray( float [] data, float start1,float start2,
                      float stop1,float stop2 ){
      float [] xout;
      xout = new float[data.length];
      for (int s=0; s<data.length; s++) {
        xout[s] = map(data[s],start1,start2,stop1,stop2);
        }
        return xout;
} 





Last edited by checorh on Thu Jan 22, 2015 9:16 pm, edited 2 times in total.

brocknoah
Posts: 5
Joined: Sat Jan 10, 2015 11:36 am

Re: Proj 2: 2D Matrix

Post by brocknoah » Thu Jan 22, 2015 9:01 pm

At first I was going to track books on programming languages and the number of checkouts over time, but as most queries about checkouts over time, the trend was decreasing checkouts. The fact that more people are learning programming from online sources did not help too, so this was not very interesting.

I switched my focus, and for this assignment I searched for the most popular week day to checkout books. The year was set to 2010 to minify the query time (SUM CASE statements can be costly), but the search was open to juvenile, young adult and adult books. Finished at 265 seconds.

I count the number of checkouts per day, then sort an array of weekdays that belongs to a dewey grouping of 10. The sorted low to high array allows me to rank the most popular day by determining the index position of a certain week day. This value will determine the opacity for the weekday. Each dewey grouping consists of the same colors, and the same increment of opac value. The darker colors represent more checkouts and lighter colors represent less checkouts.

Later I can compare a graph of the most popular days to return books or include hovers to focus on a dewey decimal category (this would fill the gap between the dewey column and results visual).

SQL

Code: Select all

SELECT
sum(CASE WHEN weekday(cout) = 1 THEN 1 ELSE 0 END) as Sunday,
sum(CASE WHEN weekday(cout) = 2 THEN 1 ELSE 0 END) as Monday,
sum(CASE WHEN weekday(cout) = 3 THEN 1 ELSE 0 END) as Tuesday,
sum(CASE WHEN weekday(cout) = 4 THEN 1 ELSE 0 END) as Wednesday,
sum(CASE WHEN weekday(cout) = 5 THEN 1 ELSE 0 END) as Thursday,
sum(CASE WHEN weekday(cout) = 6 THEN 1 ELSE 0 END) as Friday,
sum(CASE WHEN weekday(cout) = 7 THEN 1 ELSE 0 END) as Saturday
FROM spl2.inraw
WHERE year(cout) ="2010" 
AND itemtype LIKE "%bk"
AND deweyClass is not null
group BY floor(deweyClass/10)*10
Processing

Code: Select all

Table table1;
PFont font = createFont("Arial", 16, true);
Boolean V;

int [] unorg = null;
int [] lowToHigh = null;

int numRows, numCols;  
int [][] dataMatrix1 = null;

/* vars for style */
int BLACK = 56;
int SOFTWHITE = 222;
int boxH = 7;
int boxW = 21;
int pad=3;
int mar=60;
int column = (boxW+pad)*7;
int gutter = pad+boxW;

/* Determine the location of a value in an array */
public int findIndex(int[] array, int v) {
  int index= -1;
  for(int i=0; i<numCols; i++) {
    if(array[i] == v) index = i;
  }
  if(V) println("found " + v + " at index " + index);
  return index;
}

/* paints the weekdays to the screen */
void header() {
  fill(BLACK);
  text("S", (column*2)+(pad*2), boxW);
  text("M", (column*2)+(boxW*1+pad*2), boxW);
  text("T", (column*2)+(boxW*2+pad*4), boxW);
  text("W", (column*2)+(boxW*3+pad*5), boxW);
  text("R", (column*2)+(boxW*4+pad*6), boxW);
  text("F", (column*2)+(boxW*5+pad*7), boxW);
  text("S", (column*2)+(boxW*6+pad*9), boxW); 
}

/* paints column for dewey decimal system */
void deweyNums() {
 fill(BLACK);
 textAlign(BOTTOM);
 textSize(8);
 int currentNum = 0;
 for(int i=0; i< (numRows*10); i+=10) {
   if(currentNum < 1000) {
     text(currentNum, column-gutter, (boxH*i)+gutter);
     currentNum += 100;
   }
 } 
 textAlign(TOP);
 text("dewey decimal", column-gutter, (boxH)*100);
}

/* paints the title */
void content() {
 fill(92);
 textSize(18);
 textAlign(RIGHT);
 text("POPULAR", (column*2-gutter), (column*3));
 fill(56, 120, 155);
 text("DAYS OF", (column*2-gutter), (column*3)+20);
 text("THE WEEK", (column*2-gutter), (column*3)+40);
 fill(92);
 textSize(26);
 text("for book", (column*2-gutter), (column*3)+65);
 text("checkouts", (column*2-gutter), (column*3)+88);
}

void setup() {
 size(column*4,800);
 background(255);
 noLoop();
 smooth();
 
 /* Verbose mode */
 V = false;

 table1 = new Table();
 table1 = loadTable("weekday_cout_2010_by10s_books.csv", "header"); 

 numRows = table1.getRowCount(); 
 numCols = table1.getColumnCount();
 if(V) println("Rows: " + numRows + "  Cols: " + numCols);
 
 dataMatrix1 = new int[numRows][numCols];
 /* these arrays will hold a row, a full week belonging to a dewey category */ 
 unorg = new int[numCols];
 lowToHigh = new int[numCols];

 for ( int i = 0; i< numRows; i++) {
    for ( int j = 0; j< numCols; j++) {
      dataMatrix1[i][j] = table1.getInt(i, j);   
      if(V) print( dataMatrix1[i][j] + " ");
    }
    if(V) println(",");
  }  
 
}



void draw() {
  background(SOFTWHITE);
  noStroke();
  
  header();
  deweyNums();
  content();
  
  int i, j, h, temp;
  
  for(i = 0; i < numRows; i++) {
    /* populate unorg with the raw data from the row */
    for(h=0; h < numCols; h++) {
      unorg[h] = dataMatrix1[i][h]; 
    }
    /* sort the previous array, call that lowToHigh,
       this secondary array actually isn't necessary
       because dataMatrix holds all unorg arrays */
    lowToHigh = sort(unorg);
    if(V) println("Row # " + i);
    
    for(j = 0; j < numCols; j++) {
      /* return a return between 0 and 6 */
      temp = findIndex(lowToHigh, dataMatrix1[i][j]);
      //println( "(" + i + " , " + j + ") temp " + temp);
     
      /* The higher temp value will result in a less 
         transpracy. Low checkouts are lighter */
      fill(56, 155, 120, temp*30 +30);
      rect(j*(boxW+pad)+(column*2),i*(boxH)+(gutter),boxW,boxH);
    }
  }  
  
}
Attachments
weekday_cout_2010_by10s_books.csv
(3.09 KiB) Downloaded 235 times
book_checkouts.png
Last edited by brocknoah on Sat Jan 24, 2015 1:16 pm, edited 1 time in total.

nedda.amini
Posts: 5
Joined: Tue Jan 14, 2014 11:55 am

Re: Proj 2: 2D Matrix

Post by nedda.amini » Fri Jan 23, 2015 1:56 am

I followed the same query I made from last section, because I felt that even though the data wasn't substantial on its own, it could be visualized in an interesting way that could engage the viewer to question absence from the collection as a whole.
For this visualization, I chose to stay with a simple monochromatic scale (unless you consider Gray-Black a color, in which case this is di-chromatic). I felt that something minimal would best represent the data I showed.
I cross referenced Dewey Numbers and Months Total of absence from the collection, and I found the total amount of books that were gone in those times. Longer periods show less books being returned and accounted for. Darker colors denote more books gone for that month span in the related Dewey column.
While this data doesn't whole much interest as a 2D visualization, I believe that rendered 3 dimensionally would give the added depth and interactive feel to the data shown. I guess I'm a bit stuck on it, because I feel it could be interesting if done right.
Attachments
800.png
800.csv
(107.76 KiB) Downloaded 266 times
700.csv
(166.94 KiB) Downloaded 228 times
Screen Shot 2015-01-23 at 1.40.46 AM.png

Post Reply