Final Project: COVID cases and temperatures

https://editor.p5js.org/ssahasra/present/mf6vOSPgw

This is a video of the Final p5.js program.

The idea was to correlate temparatures and COVID cases of two months far apart from each other in the year 2020.

I used arrays to fill in the values of the number of cases (height of bar) with loops and used the buttons [mouse interactions] and array, objects to create effects of different weather conditions. For some of the weather effects I sourced code from current projects on the internet.

[This was the very first version, and evolved to a much different version with iteration after I received feedback from the Instructor and TAs

After receiving feedback on my proposal, I made two key changes:

1. Instead of using files to load data I added the values to indices of an array, to create a data visualization + monthly calendar that shows the number of COVID cases

2. I made it more relevant to the theme of 2020. Earlier I was working only with temperature data, but now I decided to represent the relationship between temperature and COVID cases.

The central idea of my projects is to create an interactive visualization + calendar that allows the viewer to compare different months of the year and see how temperature affects the rise in COVID cases (although there are of course other factors for the rise) Furthermore, I want to use mouse interactions to filter certain days when temperatures are in particular range using the buttons on the right (see diagram and code). I am still in the process of adding interactivity and controls using the <function mousePressed()> Optionally, a hover state over one or two of the bars (if time permits, to show the temperature and number of COVID cases to make it a more realistic visualisation)

When the button is pressed, some bar graphs that are not in that temperature range, will disappear and I want to use random motion, I learnt in class to create effects of snow, rain, sun etc in the background of each month. If I am successful in this, as a next step, I would also like to add sound files that create sound effects along with the visual effects of the weather. For the visual effects, my plan is to use the code I used for the snow and change parameters, color, speed etc, to create the other weather effects. For examples: raindrops will be blue and would sway less, and fall down in straighter lines than snow.

Below is the code snippet for the entire final program:

let lastFramePress = false;
let toggle = false;
let value = 0;
let button;
let snowflakes = []; // array to hold snowflake objects
let rain = [];

let snow ;







mayCases = [1540, 1307, 1008, 913, 975, 1022, 1160, 1352, 1160, 
            1376, 520, 850, 787, 964, 1020, 1050, 517, 931, 728, 
            747, 1101, 1053, 797, 554, 700, 517, 773, 666, 761, 716, 429]

mayMidTempCases = [0, 1307, 1008, 0, 0, 0, 1160, 0, 0, 
            1376, 0, 0, 787, 964, 0, 1050, 0, 931, 728, 
            747, 1101, 1053, 797, 0, 0, 0, 0, 0, 761, 716, 429] //on high temparature days

mayHighTempCases = [0, 0, 0, 0, 0, 0, 0, 0, 0, 
            0, 0, 0, 0, 0, 1020, 0, 517, 0, 0, 
            0, 0, 0, 0, 554, 700, 517, 773, 666, 761, 716, 429] //on mid temparature days    

mayLowTempCases = [1540, 0, 0, 913, 975, 1022, 0, 1352, 1160, 
            0, 520, 850, 0, 0, 0, 0, 0, 0, 0, 
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] //on low temparature days           

novCases = [2815, 3648, 3236, 2580, 4562, 4322, 4098, 6023,
            5834, 4395, 4647, 6241, 5721, 6486, 6881, 7028, 
            5874, 6541, 6462, 6365, 6956, 7427, 8362, 6883,
            5144, 5584, 6956, 8654, 11268, 5000]

novHighTempCases = [0, 0, 3236, 2580, 4562, 4322, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 
            0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0]

novMidTempCases = [2815, 3648, 0, 0, 0, 0, 4098, 6023,
            0, 0, 4647, 0, 0, 0, 6881, 7028, 
            5874, 6541, 0, 0, 0, 7427, 8362, 6883,
            0, 5584, 0, 0, 0, 0]

novLowTempCases = [0, 0, 0, 0, 0, 0, 0, 0,
            0, 4395, 0, 6241, 5721, 6486, 0, 0, 
            0, 0, 6462, 0, 6956, 0, 0, 0,
            5144, 0, 6956, 8654, 11268, 5000]


function preload() {
    cloud = loadImage('https://i.imgur.com/MsvLwqH.png');   
    snowFlake = loadImage('https://i.imgur.com/wvzYocn.png');
    sun = loadImage('https://i.imgur.com/AGRTqDm.png');
}


function setup() {

    //star-size
    let SWH1 = random(2, 8);
    let SWH2 = random(6, 10);
    let SWH3 = random(10, 13);


    background(51,59,68);
    createCanvas(1300, 900);

    button = createButton("☀️");
    button.mousePressed();
    button.position(1180, 90);
    button.size(50,50);
    button.style('font-size', '25px');


    button = createButton("☁️");
    button.mousePressed();
    button.position(1180, 160);
    button.size(50,50);
    button.style('font-size', '25px');

    button = createButton("❄️");
    button.mousePressed();
    button.position(1180, 230);
    button.size(50,50);
    button.style('font-size', '25px');

    

    
         

}

function draw() {
    background(51,59,68);
    fill(255);
    textSize(12);
    text ('M A Y  :  C O V I D   C A S E S', 50, 80);
    text ('N O V E M B E R  :  C O V I D   C A S E S', 50, 780);

    textSize(21);
    text ('D o    C O V I D    C a s e s    I n c r e a s e    W h e n    T e m p ar a t u r e s    L o w e r  ?', 50, 840, 900, 60);
    strokeWeight(3.2);
    fill(255,10);
    noStroke();

    rect(50,80,width-200,320);
    rect(50,450,width-200,320);
    
    translate(30,50);

    fill(255, 80);
    may();

    fill(255,0,0,80);
    november();
    
    calendar();

    //sunrays();
    rainfall();

    noStroke();
    
    fill(255);
    //mayHigh();

    mousePressed();


    fill(255,10);

    rect(1137, 27, 60, 60);
    rect(1137, 97, 60, 60);
    rect(1137, 167, 60, 60);




  
}


function calendar() {
  fill(51,59,68);
  for (let i=0;i<31;i++) {
      let index = i + 1;
      //stroke(255, 50);
      
      push();
      fill(255);
      noStroke();
      textSize(12);
      text(index, i*(245/7)+38, 380);
      pop();
    }

}


    


 //____////____////____////____////____////____////____////____////____////____////____////____//   

function createSnowflake() {
    // create a random number of snowflakes each frame
    let t = frameCount / 60; // update time

    for (let i = 0; i < random(5); i++) {
        fill(255);
        snowflakes.push(new snowflake()); // append snowflake object
    }

    // loop through snowflakes with a for..of loop
    for (let flake of snowflakes) {
       flake.update(t); // update snowflake position
       flake.display(); // draw snowflake
    }
}

function snowflake() {
  //referenced from the p5.js open source examples
  // initialize coordinates
  this.posX = 0;
  this.posY = random(-50, 0);
  this.initialangle = random(0, 2 * PI);
  this.size = random(2, 5);

  // radius of snowflake spiral
  // chosen so the snowflakes are uniformly spread out in area
  this.radius = sqrt(random(pow(width / 2, 2)));

  this.update = function(time) {
    // x position follows a circle
    let w = 0.6; // angular speed
    let angle = w * time + this.initialangle;
    this.posX = width / 2 + this.radius * sin(angle);

    // different size snowflakes fall at slightly different y speeds
    this.posY += pow(this.size, 0.5);

    // delete snowflake if past end of screen
    if (this.posY > height) {
      let index = snowflakes.indexOf(this);
      snowflakes.splice(index, 1);
    }
  };

  this.display = function() {
    ellipse(this.posX, this.posY, this.size);
  }
}

//____////____////____////____////____////____////____////____////____//


function createRain() {
    // create a random number of snowflakes each frame
    let t = frameCount / 60; // update time

    for (let i = 0; i < random(5); i++) {
        fill(255);
        rain.push(new rainfall()); // append snowflake object
    }

    // loop through snowflakes with a for..of loop
    for (let drop of rain) {
       drop.update(t); // update snowflake position
       drop.display(); // draw snowflake
    }
}

function rainfall() {
  this.posX = 10;
  this.posY = random(0, width);
  this.initialangle = random(0, PI);
  this.size = random(4, 20);

  // radius of snowflake spiral
  // chosen so the snowflakes are uniformly spread out in area
  this.radius = sqrt(random(0,1000), 1);

  this.update = function(time) {
    // x position follows a circle
    let w = 1; // angular speed
    let angle = w * time + this.initialangle;
    this.posX = width / 35 + 1000 * sin(angle); // change this angle for rain

    // different size snowflakes fall at slightly different y speeds
    this.posY += pow(this.size, 5);

    // delete snowflake if past end of screen
    if (this.posY > 260) {
      let index = rain.indexOf(this);
      rain.shift(index, 3);
    }
  }

  this.display = function() {
    ellipse(this.posX, this.posY, this.size);
  }
}

//____////____////____////____////____////____////____////____////____////____//

function sunrays() {


  rays = random(280, 650);
 
  //stars in the universe
  fill(250, 200, 0);
  ellipse(mouseX*1.1, mouseY*1.8, random(2, 8), random(2, 8));
  ellipse(mouseX*1.3, mouseY*2.5, random(6, 10), random(6, 10));
  ellipse(mouseX*2.3, mouseY*1.5, random(10, 13), random(10, 13));
  ellipse(mouseX/1.1, mouseY/1.8, random(2, 8), random(2, 8));
  ellipse(mouseX/1.3, mouseY/2.5, random(6, 10), random(6, 10));
  ellipse(mouseX/2.3, mouseY/1.5, random(10, 13), random(10, 13));
  
  //glow
  fill(200, 130, 10, 20);
  ellipse(0, 0, (frameCount % 500)*2, (frameCount % 500)*2);
  ellipse(0, 0, (frameCount % 500)*4, (frameCount % 500)*4);
  ellipse(0, 0, (frameCount % 500)*8, (frameCount % 500)*8);
  ellipse(0, 0, (frameCount % 500)*16, (frameCount % 500)*16);
  ellipse(0, 0, (frameCount % 500)*24, (frameCount % 500)*24);
  
  //sun
  fill(250, 200, 0);
  ellipse(5, -11, rays - 20, rays - 30);

}







function may() {
    for (var i=0; i <= mayCases.length; i++) {
        fill(255, 99);
        rect((i*35+3)+25,350,33,-mayCases[i]*0.035);
        //ellipse((i*35+3)+25,190,-mayCases[i]*0.035);
    }
    if (mayCases[i]*0.25 >= 20) {
        fill(255, 99);
    }

}

function mayHigh() {
    for (var i=0; i <= mayHighTempCases.length; i++) {
        fill(255,99);
        rect((i*35+3)+25,350,33,-mayHighTempCases[i]*0.035);
    }
    if (mayHighTempCases[i]*0.25 >= 20) {
        fill(255,0,0,99);
    }
}

function mayMid() {
    for (var i=0; i <= mayMidTempCases.length; i++) {
        fill(255,99);
        rect((i*35+3)+25,350,33,-mayMidTempCases[i]*0.035);
    }
    if (mayMidTempCases[i]*0.25 >= 20) {
        fill(255,99);
    }
}

function mayLow() {
    for (var i=0; i <= mayLowTempCases.length; i++) {
        fill(255,99);
        rect((i*35+3)+25,350,33,-mayLowTempCases[i]*0.035);
    }
    if (mayLowTempCases[i]*0.25 >= 20) {
        fill(255,0,0,99);
    }
}



function november() {
    for (var i=0; i <= novCases.length; i++) {
        rect((i*35+3)+25,400,33,novCases[i]*0.035);
        //ellipse((i*35+3)+25,560,-novCases[i]*0.035);
    }
}

function novLow() {
    for (var i=0; i <= novLowTempCases.length; i++) {
        fill(255,0,0,99);
        rect((i*35+3)+25,400,33,novLowTempCases[i]*0.035);
        //ellipse((i*35+3)+25,560,-novCases[i]*0.035);
    }
    if (novLowTempCases[i]*0.25 >= 20) {
        fill(255,0,0,99);
    }
}

function novMid() {
    for (var i=0; i <= novMidTempCases.length; i++) {
        fill(255,0,0,99)
        rect((i*35+3)+25,400,33,novMidTempCases[i]*0.035);
        //ellipse((i*35+3)+25,560,-novCases[i]*0.035);
    }
    if (novMidTempCases[i]*0.25 >= 20) {
        fill(255,0,0,99);
    }
}

function novHigh() {
    for (var i=0; i <= novHighTempCases.length; i++) {
        fill(255,0,0,99);
        rect((i*35+3)+25,400,33,novHighTempCases[i]*0.035);
        //ellipse((i*35+3)+25,560,-novCases[i]*0.035);
    }
    if (novHighTempCases[i]*0.25 >= 20) {
        fill(255,0,0,99);
    }
}


function mousePressed() {
  //rect(1137, 27, 60, 60);
  //rect(1137, 97, 60, 60);
  //rect(1137, 167, 60, 60);
  if (mouseX >= 1137 && mouseX <= 1197 && mouseY >= 40 && mouseY <= 110) {
    mayHigh();
    novHigh();
    sunrays();
    
  } else if (mouseX >= 1137 && mouseX <= 1197 && mouseY >= 110 && mouseY <= 180) {
    mayMid();
    novMid();
    createRain();
  } else if (mouseX >= 1137 && mouseX <= 1197 && mouseY >= 200 && mouseY <= 250) {
    mayLow();
    novLow();
    createSnowflake();

}
}

Project 5 – Groovy Wallpaper

It seems in my experience, wallpaper gets a bad reputation. One quick search of “interior design” on Pinterest will reveal the modern day obsession with sleek and minimal aesthetic choices. In the face of this, I chose to design a wallpaper that riffs off of aesthetic choices perhaps equally as brawny – inspired by the loud colors of post modernism.

sketchDownload
// JUBBIES STEINWEH-ADLER
// PROJECT 05 - GROOVY WALLPAPER
// SECTION D

//GLOBAL VALUES
x = 0;
y = -150;// initial y value off canvas to create seamless pattern
d = 0; // arrow direction ( 1 = left 0 = right )

function setup() {
  createCanvas(500, 400);
  background(250, 240, 220);
  blendMode(MULTIPLY); // color blend mode multiplies rgb value of overlapping colors
}

function draw() {
    //ROW PROPERTIES
  for(var loop = 0; loop < 5; loop +=1) { // number of total rows limited to 5
     if (d == 0) { //switching direction for each loop
     d = 1; //left arrows
    } else {
     d = 0; //right arrows
 }
        //TRIANGLE PROPERTIES
         for(var row = 0; row < 1; row +=1) {  // triangle x-offset and tracking
               x = -120; // initial x value for the first triangle
               y += 110; // vertical spacing, tracking
       
            for(var rep = 0; rep < 7; rep +=1) { 
            x += 120; // distance between each module (width)
            stack(d, x, y); 
       }
     }
  }
  noLoop(); //disables automatic looping from draw function
}

// TRIANGLE PACKAGE - Grouped for single 'anchor point'
function stack(d, x, y) { 
  push();
  translate(x, y);  // translate by determined x and y value
  module(d); // draw a single triangle module
  pop();
}

//TRIANGLE MODULE DRAW COMMAND
function module(d) {
  noStroke();
  var r = 180; //red value
  var g = 40;  //green value
  var b = 190; //blue value


    //RIGHT ARROW MODULE
        if (d == 0){ 
         px = 0; //linked X coordinate
         py = 0; //linked y coordinate
  
        //vertical leg
        fill(r, g, b);
        push();
        translate(px, py);
        rect(0, 0, 50, 170, 70);
        pop();

        //top angled leg
        fill(g, b, r);
        push();
        translate(px-10, py+35);
        rotate(radians(300));
        rect(0, 0, 50, 170, 70);
        pop();


        //bottom angled leg
        fill(b, r, g);
        push();
        translate(px+15, py+180);
        rotate(radians(240));
        rect(0, 0, 50, 170, 70);
        pop();
  
    //LEFT ARROW MODULE
    } else if (d == 1) { 
        
        fill(r, g, b);
        ptO = 60; // OFFSET VALUE TO ALTERNATE ROW START POSITION 
        ptT = 0;
  
        //vertical leg
        push();
        translate(ptO, ptT);
        rect(0, 0, 50, 170, 70);
        pop();
  
        //top leg
        fill(g, b, r);
        push();
        translate(ptO +35, ptT - 10);
        rotate(radians(60));
        rect(0, 0, 50, 170, 70);
        pop();
  
        //bottom leg
        fill(b, r, g);
        push();
        translate(ptO + 60, ptT + 135);
        rotate(radians(120));
        rect(0, 0, 50, 170, 70);
        pop();
  }    

}

For the actual pattern shape, I was inspired by this pattern I found on the internet. I really enjoyed how the colors interacted where the shapes overlapped. This pushed me to discover that p5.js has blending modes. Using multiply blending mode and adjusting the opacity is how I got my final result.

Looking Outwards 2 – Generative Art

I really admire the video game “Panoramical” by Fernando Ramallo and David Kanaga. It is a very beautiful and immersive experience through a world of stunning visuals and music. The landscapes and music inside the game change based on the player’s input. 

I admire this work of generative art because of its beauty and interactivity. To put it bluntly, a lot of computer generated artworks have interesting concepts but are lacking in the quality of experience they provide. “Panoramical” on the other hand draws you in with otherworldly visuals and sounds. It is otherworldly due to the usage of algorithms, but it is beautiful due to the creators’ sensibilities to colors and sound. Each landscape and how they change is designed with care, and the music is designed to immerse players into the landscape.

“Panoramical” stands out from motion graphics and animated experiences due to its interactivity. Thanks to the creators’ usage of algorithms to  “connect multiple sensory variables to [the player’s] actions” (1), the player actively becomes a part of the experience. 

I think “Panoramical” is a good example of how the infinite possibilities of algorithms working inside the bounds of an artist’s design can create an unique and beautiful experience. 

Work Cited

  1. “Generative Art: Best Examples, Tools & Artists (2020 GUIDE).” AIArtists.org, aiartists.org/generative-art-design.

LO 1

“This Person Does Not Exist” is a computational project that was created by Phillip Wang using StyleGAN, a machine learning framework made available by the technology company Nvidia. Phillip is a former Uber software engineer who created the program to show the impressive capabilities of GANs (generative adversarial networks.) It was originally shared to a small Facebook group but went on to get over 4 million hits. His inspiration for the project likely came from the rise of intelligent video manipulation and “deepfakes” on the internet.

Upon loading the webpage, the screen is filled with a high definition headshot of a random person. Reloading the page brings up another person, and so on. While the images look believable, they are all completely fabricated by an artificial intelligence; thus the title “This Person Does not Exist.”

What makes this project so interesting to me is the questions it brings up. If a computer program can so easily trick us into thinking a face is real, what else could we be made to believe? In a world where we already question almost every piece of information fed to us from entertainment media and the news, it seems as though tools for digital deception are only becoming more advanced. By highlighting the exponentially expanding capabilities of artificial intelligence, this work leaves the user feeling both deep discomfort and utter awe.

An artificially generated face from the website.