Final Project – James Katungyi

james-finalproject

//James Katungyi
//Section A 0900
//jkatungy@andrew.cmu.edu
//Project

/* Title: Annual average temperature of a location = Title text showing 
 - location
 - climate  type
 - hour - interactive; to be changed by user. Make a function that returns value for the hour. Hour value changes with slider (make a simple slider)
 ========
 Background: gradient color for canvas pixels from red to blue
 Comfortable band: import data points from excel file;
 connect the data points with red/blue line for upper/lower limit.
 for each month.
 ========
 Temperature bars: low alpha value to show background color
 Height of bars linked to excel data points imported into an array. Height changes with hour value
 Make each bar an object with function to change height 
 ========
 Locate labels outside the colored part of the canvas; left of canvas, above canvas and below canvas???
*/

//var allMonths = [JanTemp, FebTemp, MarTemp, AprTemp, MayTemp, JunTemp, JulTemp, AugTemp, SepTemp, OctTemp, NovTemp, DecTemp];
var Khartoum;
var KhartoumComfortAverages;
var Miami;
var MiamiComfortAverages;
var Pittsburgh;
var PittsburghComfortAverages;
var annualTempAverages = [];//has 12 strings of 24 hourly temperatures each
var comfortTempLimits = [];//has 2 strings of 12 temperatures each
var comfortLimitColors = [];//has two colors - red for upper and blue for lower limit
var counter = 0;//initialize counter at 0;
var myTime = 0;
var myTemp;
var cities = [];
var csvAvTempData = [];
var csvComfLimitData = [];
var cityIndex = 0;

function preload(){
    //load csv file
    Pittsburgh = loadStrings("https://courses.ideate.cmu.edu/15-104/f2016/wp-content/uploads/2016/12/PittsburghAverageTemperatures.csv");
    PittsburghComfortAverages = loadStrings("https://courses.ideate.cmu.edu/15-104/f2016/wp-content/uploads/2016/12/PittsburghComfortLimits.csv");
    Miami = loadStrings("https://courses.ideate.cmu.edu/15-104/f2016/wp-content/uploads/2016/12/MiamiAverageTemperatures.csv");
    MiamiComfortAverages = loadStrings("https://courses.ideate.cmu.edu/15-104/f2016/wp-content/uploads/2016/12/MiamiComfortLimits.csv");
    Khartoum = loadStrings("https://courses.ideate.cmu.edu/15-104/f2016/wp-content/uploads/2016/12/KhartoumAverageTemperatures.csv");
    KhartoumComfortAverages = loadStrings("https://courses.ideate.cmu.edu/15-104/f2016/wp-content/uploads/2016/12/KhartoumComfortLimits.csv");
}

//+++++ canvas & background color ++++++
function setup(){
    createCanvas(700 * 0.8, 400);//scale canvas to fit wordpress
    pixelDensity(1);//regular density
    loadPixels();
    var lowerLimitColor = color(0, 0, 255);
    var upperLimitColor = color(255, 0, 0);
    comfortLimitColors.push(lowerLimitColor);
    comfortLimitColors.push(upperLimitColor);
    //csvAvTempData is an array with average temperatures for 3 cities
    csvAvTempData.push(Khartoum);
    csvAvTempData.push(Miami);
    csvAvTempData.push(Pittsburgh);
    //println(csvAvTempData);
    csvComfLimitData.push(KhartoumComfortAverages);
    csvComfLimitData.push(MiamiComfortAverages);
    csvComfLimitData.push(PittsburghComfortAverages);
    
    //titles array
    cities.push("KHARTOUM");
    cities.push("MIAMI");
    cities.push("PITTSBURGH");
}
function draw(){
    scale(0.8, 1);//scale canvas to fit wordpress
    //change canvas color from pixel array
    for (var y = 50; y < height - 50; y++){//exclude 100 pixels above and below canvas for labels
        for (var x = 80; x <  width; x++){//exclude 100 pixels to left of canvas for labels
            var index = (x + y * width) * 4;//locate each pixel
            pixels[index + 0] = map(y, 0, height, 255, 0);//decrease red down the canvas
            pixels[index + 1] = 0;
            pixels[index + 2] = map(y, 0, height, 0, 255);//increase blue down the canvas
            pixels[index + 3] = 255;
        }
    }
    updatePixels();
    //+++++graph labels++++++
    //graph title
    stroke(0);
    fill(0);
    strokeWeight(1);
    textSize(18);
    textAlign(RIGHT);
    text(("AVERAGE HOURLY TEMPERATURES IN " + cities[cityIndex]), 400, 0, 300, 50);
    textSize(10);
    strokeWeight(0.5);
    textAlign(LEFT, TOP);
    text("click to change time", 100, 0);
    //legend comfort temperature limit
    for (var i = 0; i < comfortLimitColors.length; i++) {
        noFill();
        stroke(comfortLimitColors[i]);
        line(100 + (i * 200), 390, 150 + (i * 200), 390);
        ellipse(100 + (i * 200), 390, 8, 8);
        ellipse(150 + (i * 200), 390, 8, 8);
    }
    stroke(0);
    strokeWeight(1);
    textAlign(LEFT, CENTER);
    text(("Lower Comfort Limit"), 160, 390);
    text(("Upper Comfort Limit"), 360, 390);
    //time check at top of the graph
    
    fill(0);
    textAlign(LEFT);
    textSize(14);
    var timeCheck = ("TIME: " + nf(myTime, 2, 0) + ":" + "00");
    text(timeCheck, 100, 30);
    //y scale from 0 to 120 degrees fahrenheight
    for (var t = 0; t < 121; t+=20){
        var tempScale = map(t, 0, 120, 350, 50);
        textAlign(RIGHT);
        stroke(0);
        text(t, 80, tempScale);
        //y scale grid lines
        stroke(255, 100);//lower alpha value for the grid lines
        //strokeWeight(0.5);
        line(100, tempScale, 700, tempScale);
    }
    //x scale Jan to Dec at bottom of graph
    var monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
    for (var i = 0; i < monthNames.length; i++){
        var xPosText = 125 + i * 50;
        stroke(0);
        textAlign(CENTER, BOTTOM);
        text(monthNames[i], xPosText, 375);
    }
    //call function to parse csv data into monthly arrays
    csvDataToArray(csvAvTempData[cityIndex], annualTempAverages);
    csvDataToArray(csvComfLimitData[cityIndex], comfortTempLimits);

    //bar graphs: loop through the 12 months and plot the temperature of each month
    //depending on the hour.
    var LimitsForEachCity = comfortTempLimits;
    // var TempAveragesForEachCity = cityAverageTemp[cityIndex];

    var lowerLimitValues = LimitsForEachCity[0];
    var upperLimitValues = LimitsForEachCity[1];
    for (var i = 0; i < annualTempAverages.length; i++){
        var monthlyMin = lowerLimitValues[i];
        var monthlyMax = upperLimitValues[i];
        drawTemperatureBar(annualTempAverages[i], i, monthlyMin, monthlyMax);
    }

    //loop through the 2 sets of limits and plot the max and minimum comfort temperature
    //for each month
    
    for (var i = 0; i < LimitsForEachCity.length; i++){
        stroke(comfortLimitColors[i]);
        TemperatureBoundary(LimitsForEachCity[i]);
    }
}

/*increase the time whenever mouse clicks; increase upto 23;
may integrate a sliding scale to determine the time*/
function mousePressed(){
    counter++;
    myTime = counter%24;//myTime is an integer between 0 and 23
}

//parse csv data into strings and create 12 arrays with 24 data points each
function csvDataToArray(csvFile, myArray){
    for (var i = 0; i < csvFile.length; i++){
        myArray[i] = csvFile[i].split(",");
    }
}
/*drawTemperatureBar is a function that draws one bar for all temperatures of a given month. 
The height of the monthly bar depends on the time of day*/
function drawTemperatureBar(monthlyvalues, monthIndex, MinTemp, MaxTemp){
    stroke(255);
    strokeWeight(2);
    var BarWidth = 50;//bar width distributed evenly across width
    var xPos = 100 + (monthIndex * 50);//x position of bar is determined by month number
    myTemp = monthlyvalues[myTime];//use myTime value as index for Temperature values array
    var barHeight = map(myTemp, 0, 120, 0, 300);//scale temperature value to screen size
    var yPos = height - 50 - barHeight;

    
    //if monthly temperature exceeds comfort temperature limits, highlight the bar with red tint
    //if monthly temperature falls below comfort temperature limit, highlight the bar with blue tint
    if (float(myTemp) > float(MaxTemp)){
        fill(255, 0, 0, 100);
    } else
    if (float(myTemp) < float(MinTemp)){
        fill(0, 0, 255, 100);
    } else {
        fill(255, 50);
    }
    rect(xPos, yPos, BarWidth, barHeight);
    //println("monthIndex" monthIndex myTemp 100 MaxTemp 84 MinTemp 74);
}

/*Comfortable temperature limits differ from one month to the other;
draw upper boundary and lower boundary */
function TemperatureBoundary(LimitValues){
    for (var i = 0; i < LimitValues.length; i++){
        strokeWeight(2);
        noFill();
        var xPos = 125 + (i * 50);//scale x values to fit screen
        var xPos1 = 125 + ((i + 1) * 50);
        var yPos = map(LimitValues[i], 0, 120, 350, 50);//scale temperature value to screen size
        var yPos1 = map(LimitValues[i + 1], 0, 120, 350, 50);
        ellipse(xPos, yPos, 10, 10);
        line(xPos, yPos, xPos1, yPos1);
    }
}
//press keys to change from one city to another
function keyTyped(){
    // if (key == k){
    //     cityIndex = 0;
    //} else 
    if (key === 'm'){
        cityIndex = 1;
    } else if (key === 'p'){
        cityIndex = 2;
    } else if (key === 'k'){
        cityIndex = 0;
    }
}

Introduction

For the final project, I explored weather data visualization for three cities in different climates (Pittsburgh, Miami and Khartoum). Data visualization can make technical information intelligible to the non-technical. This can be useful for convincing building occupants to use less energy. If building occupants can be shown how to use less energy without compromising comfort, they can be instrumental in reducing energy consumption.

khartoum0600hrsmiami1500hrspittsburgh1100hrs

Description

The project consists of an interactive platform that graphs the average hourly temperatures for each month against a blue to red scaled background – blue for cold and red for hot. A comfort band in the middle of the graph represents the narrow range of comfortable temperatures based on the adaptive comfort model (de Dear and Brager, 1998). The upper limit of the comfort band is marked in red while the lower limit is marked in blue. The bars show the outdoor temperature at any given hour for each of the 12 months. When the temperature is below the lower limit, the bar is blue. When it is above the limit, the bar is red. When it is within the limit, the bar is a translucent white. Temperature values were obtained from weather files that are freely available online at https://energyplus.net/weather. The files in epw format were processed in Microsoft Excel to obtain average hourly data which was then saved as csv files. The csv files were then loaded into p5.js. The program runs smoothly in firefox but not in chrome because of the link to the csv files.

Interactivity/Operation

There are two levels of interactivity:

  1. The user, by clicking the mouse, can incrementally advance the hour by 1 from midnight (00:00 hrs) to 23:00 hrs. At each hour, the average temperature is displayed for each month.
  2. The user can also choose one of three cities by pressing the key corresponding to the first letter of the city – ‘m’, ‘p’ or ‘k’.

I hope to enrich it by incorporating humidity and wind speed in the input data. This would better portray human indoor comfort against outdoor weather conditions.

de Dear, R.J., and G.S. Brager, 1998. Towards an adaptive model of thermal comfort and preference. ASHRAE Transactions, Vol 104 (1), pp. 145-167

Leave a Reply