//import java.util.regex.*; FloatTable data; FloatTable chicagoTempData; float dataMin, dataMax; float plotX1, plotY1; float plotX2, plotY2; float labelX, labelY; PFont plotFont; boolean dataNotLoaded = true; long timeMin, timeMax; String[] times; Date[] dates; Date[] chicagoDates; static final long MILIS_PER_MIN = 60 * 1000; DateFormat stampFormat = new SimpleDateFormat("yyyyMMdd/HHmm"); int selectedYear = 2011; int selectedMonth = 6; // Date.Month(): 0 - 11 int daysOfMonth = 31; //manually set checking the month. boolean[] visibleColumns; int currentColumn = 5; int rowCount, columnCount; int rowMin, rowMax; int temperatureInterval = 10; long timeInterval = 365 * 24 * 60 * MILIS_PER_MIN; int dayHourLow, dayHourHigh; CheckBox chkMultipleRooms; CheckBox chkOutdoor; CheckBox chkMonthView; CheckBox[] chkF_C; CheckBox[] chkAvg; Slider sliderHoursOfDay; OptionLabel[] yearOptions; OptionLabel allYear; OptionLabel[] monthOptions; // room colors color[] color_room = new color[7]; color color_room_inactive; // room vertices, 8th one for the container float[] roomX1 = new float[8]; float[] roomY1 = new float[8]; float[] roomX2 = new float[8]; float[] roomY2 = new float[8]; // initialization void setup() { size(1024, 700); data = new FloatTable("processed_history.txt"); rowCount = data.getRowCount(); columnCount = data.getColumnCount(); visibleColumns = new boolean[columnCount]; for (int i=0; i 30 && value <= 40 ) stroke(#6600ff); // else if (value > 40 && value <= 50 ) stroke(#3366ff); // else if (value > 50 && value <= 60 ) stroke(#3399ff); // else if (value > 60 && value <= 70 ) stroke(#33ccff); // else if (value > 70 && value <= 80 ) stroke(#33ff66); // else if (value > 80 && value <= 90 ) stroke(#ff9900); // else if (value > 90 && value <= 100 ) stroke(#ff3300); // else stroke(#ff0000); //} void drawDataLine() { for (int i=0; i < visibleColumns.length; i++) { noFill(); strokeWeight(2); if (chkAvg[2].checked || chkMonthView.checked) strokeWeight(3); // bolder line if (chkMultipleRooms.checked && visibleColumns[i] || (!chkMultipleRooms.checked) && currentColumn == i) { if (chkMonthView.checked) { int k = 0; textSize(13); //for (int j=0; j=0; j--) { if (yearOptions[j].selected) { timeMin = new Date(2005 - 1900 + j, selectedMonth, 1).getTime(); timeMax = new Date(2005 - 1900 + j, selectedMonth, daysOfMonth, 23, 59).getTime(); stroke(color_room[(i+ k)%visibleColumns.length] );//(yearOptions.length-j-1)*30); drawDataLine(i); // legends if (!chkMultipleRooms.checked) // no legend needed { line(plotX2 - 75, plotY1 - 5 + 20 * ++k, plotX2 - 55, plotY1 - 5 + 20*k); fill(224); //fill(color_room[(i+ k-1)%visibleColumns.length] ); text(2005 + j, plotX2 - 95, plotY1 + 20*k); noFill(); } } } } else { stroke(color_room[i]); drawDataLine(i); } } } } // Draw the data as a line void drawDataLine(int col) { beginShape(); int hr, month=-1, day=-1, dataCount = 0, year=-1; float temp = 0, t=0, value =0, x = 0, y =0; long time = 0, lastTime = 0; // lastTime needed for last point //boolean newSeries = false; // to restart drawing of a new year for (int row = rowMin; row <= rowMax; row++) { hr = dates[row].getHours() ; time = dates[row].getTime(); // normal time, without averaging or something //println(dayHourLow + " " + hr + " " + dayHourHigh); if (hr < dayHourLow || hr > dayHourHigh || time < timeMin || time>timeMax) { time = 0; // time is used below continue; } if (data.isValid(row, col)) { value = data.getFloat(row, col); if (value < dataMin || value > dataMax) continue; // consider them error if (chkAvg[1].checked) // get daily average { // 1 - 31 if (day != dates[row].getDate()) // new day beginning { t = value; if (dataCount > 0) // 0 for firsttime, other times plot previous { Date d = new Date(dates[row].getYear(), month, day, 23, 59); time = d.getTime(); value = temp / dataCount; } dataCount = 1; temp = t; day = dates[row].getDate(); month = dates[row].getMonth(); if (time == 0) continue; // first time starting with a new date } else { lastTime = time; temp += value; dataCount++; continue; } } else if (chkAvg[2].checked) // get monthly average { // 0 - 11 if (month != dates[row].getMonth()) // new day beginning { t = value; if (dataCount > 0) // 0 for firsttime, other times plot previous { Date d = new Date(year, month, getDaysOfMonth(month));//day, 23, 59); time = d.getTime(); value = temp / dataCount; } dataCount = 1; temp = t; year = dates[row].getYear(); month = dates[row].getMonth(); if (time == 0) continue; // first time starting with a new date } else { lastTime = time; temp += value; dataCount++; continue; } } // else // normally calcuate time // time = dates[row].getTime();// / MILIS_PER_MIN; //if (value < dataMin || value > dataMax) continue; /// first time still too low x = map(time, timeMin, timeMax, plotX1, plotX2); y = map(value, dataMin, dataMax, plotY2, plotY1); vertex(x, y); // if (x>plotX2-50 || x < plotX1+ 20) // println(new Date(time) + " " + new Date(timeMin) +" " + new Date(timeMax)+" " + plotX1+" " +plotX2+ " " + " " +x + " " + y); } } if (lastTime != 0) // so date aggregation used, plot the last point, it is not ploted as date has not changed past it. { x = map(lastTime, timeMin, timeMax, plotX1, plotX2); y = map(temp/dataCount, dataMin, dataMax, plotY2, plotY1); vertex(x, y); } endShape(); } void drawGraphLabels() { //temp label fill(255); textSize(10); textAlign(RIGHT); stroke(200); strokeWeight(1); float dm = dataMin; float dx = dataMax; float ti = temperatureInterval; if (chkF_C[1].checked) // Celsius { dm = (dataMin - 32.0) * 5.0/9; dx = (dataMax - 32.0) * 5.0/9; ti = 5; dm = ceil(dm/ti); //println(dm + " " + dx); } for (float v = dm; v <= dx; v += ti) { if (v % ti == 0) { // If a tick mark float y = map(v, dm, dx, plotY2, plotY1); if (v % ti == 0) { // If a major tick mark float textOffset = textAscent()/2; // Center vertically if (v == dm) { textOffset = 0; // Align by the bottom } else if (v == dx) { textOffset = textAscent(); // Align by the top } text(floor(v), plotX1 - 10, y + textOffset); line(plotX1 - 4, y, plotX2, y); // Draw major tick } else { line(plotX1 - 2, y, plotX2, y); // Draw minor tick } } } // time labels textAlign(CENTER); // Use thin, gray lines to draw the grid stroke(200); strokeWeight(1); if (chkMonthView.checked) { for (int i=1; i<=daysOfMonth; i++) { float x = map(i, 0, daysOfMonth, plotX1, plotX2); text(i, x, plotY2 + textAscent() + 10); line(x, plotY1, x, plotY2); } textSize(15); switch(selectedMonth) { case 0: text("January", (plotX1+plotX2)/2, plotY2 + textAscent() + 30); ; break; case 1: text("February", (plotX1+plotX2)/2, plotY2 + textAscent() + 30); ; break; case 2: text("March", (plotX1+plotX2)/2, plotY2 + textAscent() + 30); ; break; case 3: text("April", (plotX1+plotX2)/2, plotY2 + textAscent() + 30); ; break; case 4: text("May", (plotX1+plotX2)/2, plotY2 + textAscent() + 30); ; break; case 5: text("June", (plotX1+plotX2)/2, plotY2 + textAscent() + 30); ; break; case 6: text("July", (plotX1+plotX2)/2, plotY2 + textAscent() + 30); ; break; case 7: text("August", (plotX1+plotX2)/2, plotY2 + textAscent() + 30); ; break; case 8: text("September", (plotX1+plotX2)/2, plotY2 + textAscent() + 30); ; break; case 9: text("October", (plotX1+plotX2)/2, plotY2 + textAscent() + 30); ; break; case 10: text("November", (plotX1+plotX2)/2, plotY2 + textAscent() + 30); ; break; case 11: text("December", (plotX1+plotX2)/2, plotY2 + textAscent() + 30); ; break; } } else if (allYear.selected) { long time = timeMin, tM; Date d = new Date(timeMin); d.setDate(getDaysOfMonth(d.getMonth())); tM = d.getTime(); //textAlign(TOP); for (int i = 0; time < timeMax; i++) { d.setDate(1); d.setMonth(i); d.setDate(getDaysOfMonth(d.getMonth())); time = d.getTime(); if (time timeMax) break; // Aug 2011 float x = map(time, tM, timeMax, plotX1, plotX2); translate(x + textAscent()/2, plotY2+20); rotate(-PI/2); if ((i+2)%4 == 1) text(new SimpleDateFormat("MMM yy").format(d), 0, 0); //text(i, 0, 0); rotate(PI/2); translate(-(x + textAscent()/2), -(plotY2+20)); line(x, plotY1, x, plotY2); //if(i==7) if (i>11) i = 0; } } else { long timeDiff = timeMax - timeMin; if (timeDiff > 32 * 24 * 3600000) // obsolete condition, need to redefine { int mid = 35;//;timeDiff / 12 / (365 * 24 * 3600000) / 2; Date d = new Date(timeMin); for (int i = 0; i < 12; i++) { d.setMonth(i); float x = map(d.getTime(), timeMin, timeMax, plotX1, plotX2); text(new SimpleDateFormat("MMMMM").format(d), x + mid, plotY2 + textAscent() + 10); line(x, plotY1, x, plotY2); } } } // println(timeDiff); } void mouseClicked() { if (overRect(yearOptions[0].x, yearOptions[0].y, yearOptions[0].width * (yearOptions.length), yearOptions[0].height)) { // deselect the All year allYear.selected = false; } } void mouseMoved() { cursor(ARROW); if (overRect(yearOptions[0].x, yearOptions[0].y, yearOptions[0].width * (yearOptions.length), yearOptions[0].height) // year lebels || overRect(chkMultipleRooms.x, chkMultipleRooms.y, chkMultipleRooms.size, chkMultipleRooms.size) || overRect(chkOutdoor.x, chkOutdoor.y, chkOutdoor.size, chkOutdoor.size) || overRect(chkMonthView.x, chkMonthView.y, chkMonthView.size, chkMonthView.size) || (chkMonthView.checked && overRect(monthOptions[0].x, monthOptions[0].y, monthOptions[0].width * (monthOptions.length), monthOptions[0].height )) ) { cursor(HAND); } else { for (int i=0; i=0; j--) // { // if(visibleColumns[j]) // { // currentColumn = j; // break; // } // } } } void update() { if (!chkAvg[2].checked) // otherwise no need { if (allYear.selected) // set back a year { yearOptions[(selectedYear - 2005)].selected = true; allYear.selected = false; } } else chkMonthView.checked = false; if (chkMonthView.checked) { // Allmonths is selected by default //monthOptions[selectedMonth + 1].selected = true; yearOptions[0].allowMultiple(true); // all are updated inside for (int i=1; i= 0 && !yearOptions[i].selected; i--); //selectedYear = 2005 + i; for (i-=1; i >= 0; i--) yearOptions[i].selected = false; // for ( i=0; i 0) rowMin++; rowMax = rowCount-1; while (times[rowMax].compareTo (endDate) > 0 ) rowMax--; } catch (ParseException e) { die("Problem while setting up dates", e); } catch (Exception e) { die("Problem while setting up dates", e); } } void showChicagoTemperature() { loadChicagoTemperature(); beginShape(); int hr, month=-1, day=-1, dataCount = 0, year=-1; int yr = 2005; float temp = 0, t=0, x=0, y=0; long time = 0, lastTime = 0; fill(225); textSize(13); text("Chicago", plotX2 - 170, plotY1 + 15); noFill(); strokeWeight(2); stroke(224); //if (chkMonthView.checked || chkAvg[2].checked) strokeWeight(3); // bolder lines line(plotX2 - 140, plotY1 + 15, plotX2 - 120, plotY1 + 15); if (chkMonthView.checked) { for (int i =yearOptions.length-1; i>=0; i--) if (yearOptions[i].selected) { yr += i; break; // draw only for latest year } timeMin = new Date(yr - 1900, selectedMonth, 1).getTime(); timeMax = new Date(yr - 1900, selectedMonth, daysOfMonth, 23, 59).getTime(); } for (int i = 0; i < chicagoDates.length; i++) { time = chicagoDates[i].getTime(); if (time < timeMin || time > timeMax) continue; if (chicagoTempData.isValid(i, 0)) { hr = chicagoDates[i].getHours() ; //println(dayHourLow + " " + hr + " " + dayHourHigh); if (hr < dayHourLow || hr > dayHourHigh) continue; float value = chicagoTempData.getFloat(i, 0); if (value > dataMax) continue; // consider them error if (chkAvg[1].checked) // get daily average { // 1 - 31 if (day != chicagoDates[i].getDate()) // new day beginning { t = value; if (dataCount > 0) // 0 for firsttime, other times plot previous { Date d = new Date(chicagoDates[i].getYear(), month, day); time = d.getTime(); value = temp / dataCount; } dataCount = 1; temp = t; day = chicagoDates[i].getDate(); month = chicagoDates[i].getMonth(); if (time == 0) continue; } else { lastTime = time; temp += value; dataCount++; continue; } } else if (chkAvg[2].checked) // get monthly average { // 0 - 11 if (month != chicagoDates[i].getMonth()) // new day beginning { t = value; if (dataCount > 0) // 0 for firsttime, other times plot previous { Date d = new Date(year, month, getDaysOfMonth(month));//day, 23, 59); time = d.getTime(); value = temp / dataCount; } dataCount = 1; temp = t; year = chicagoDates[i].getYear(); month =chicagoDates[i].getMonth(); if (time == 0) continue; // first time starting with a new date } else { lastTime = time; temp += value; dataCount++; continue; } } else { // normally calcuate time time = chicagoDates[i].getTime();// / MILIS_PER_MIN; } if (value < dataMin) value = dataMin; // clip; continue skips x axis x = map(time, timeMin, timeMax, plotX1, plotX2); y = map(value, dataMin, dataMax, plotY2, plotY1); vertex(x, y); } } if (lastTime != 0) // so date aggregation used, plot the last point, it is not ploted as date has not changed past it. { if (temp/dataCount < dataMin) temp = dataMin*dataCount; // clip; continue skips x axis x = map(lastTime, timeMin, timeMax, plotX1, plotX2); y = map(temp/dataCount, dataMin, dataMax, plotY2, plotY1); vertex(x, y); } endShape(); } void loadChicagoTemperature() // separated to save starting time { if (chicagoTempData != null) return; println("loading chicago temparature..."); //chicago outdoor temp chicagoTempData = new FloatTable("chicagotemp.txt"); String[] ctd_titles = chicagoTempData.getRowNames(); chicagoDates = new Date[ctd_titles.length]; try { for (int i=0; i < ctd_titles.length; i++) { chicagoDates[i] = stampFormat.parse(ctd_titles[i]);//.getTime() ; // / MILIS_PER_MIN; } } catch (ParseException e) { die("Problem while setting up dates", e); } } // sliders void drawSliders() { sliderHoursOfDay.update(); sliderHoursOfDay.display(); fill(#FFFFFF); textSize(13); textLeading(10); textAlign(LEFT, TOP);//, CENTER); text("Hours", sliderHoursOfDay.x-38, sliderHoursOfDay.y); // } /// check boxes void drawCheckBoxes() { chkMultipleRooms.display(); fill(#FFFFFF); textSize(13); textLeading(10); textAlign(LEFT, TOP);//, CENTER); text("Multiple Rooms", chkMultipleRooms.x+15, chkMultipleRooms.y); // chkOutdoor.display(); text("Compare Outdoor", chkOutdoor.x+15, chkOutdoor.y); // chkMonthView.display(); text("Month View", chkMonthView.x+15, chkMonthView.y); chkAvg[0].display(); text("No Average", chkAvg[0].x+15, chkAvg[0].y); chkAvg[1].display(); text("Daily Average", chkAvg[1].x+15, chkAvg[1].y); chkAvg[2].display(); text("Monthly Average", chkAvg[2].x+15, chkAvg[2].y); chkF_C[0].display(); chkF_C[1].display(); text("F", chkF_C[0].x+15, chkF_C[0].y); // text("C", chkF_C[1].x+15, chkF_C[1].y); // textAlign(CENTER); text("Temperature", chkF_C[0].x + 13, chkF_C[0].y - 10); } /// label options void drawOptionLabels() { for (int i=0; i=0; i--) { if (i ==7) fill(#1F1F1F); // boundary else if ((chkMultipleRooms.checked && visibleColumns[i]) || (!chkMultipleRooms.checked && currentColumn == i) ) fill(color_room[i]); else fill(color_room_inactive); rect(roomX1[i], roomY1[i], roomX2[i], roomY2[i]); fill(#F0F0F0); textFont(plotFont); textSize(13); textLeading(15); textAlign(CENTER, CENTER); String title = ""; switch(i) { case 0: title = "meeting room"; break; case 1: title = "main lab"; break; case 2: title = "machine room"; break; case 3: title = "lounge"; break; case 4: title = "proto-\ntype\nspace"; break; case 5: title = "class room"; break; case 6: title = "office"; break; } text(title, (roomX1[i]+roomX2[i])/2, (roomY1[i]+roomY2[i])/2); } } /////////////////////////// void loadData() { dates = new Date[times.length]; try { for (int i=0; i= x && mouseX <= x+width && mouseY >= y && mouseY <= y+height) { return true; } else { return false; } } boolean overRectCorners(float x1, float y1, float x2, float y2) { if (x1 > x2) { x2 = x1 + x2; x1 = x2 - x1; x2 = x2 - x1; } if (y1 > y2) { y2 = y1 + y2; y1 = y2 - y1; y2 = y2 - y1; } if (mouseX >= x1 && mouseX <= x2 && mouseY >= y1 && mouseY <= y2) { return true; } else { return false; } } int getDaysOfMonth(int month) { int d =0; switch(month) { case 1: d = 29; // include the leapYear in the graph break; case 0: case 2: case 4: case 6: case 7: case 9: case 11: d = 31; break; case 3: case 5: case 8: case 10: d = 30; break; } return d; }