<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Calibration | OpenStudio</title> <link href="http://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.3.2/css/bootstrap.min.css" rel="stylesheet"> <link href="file:///C:/openstudio_git/OpenStudio/openstudiocore/resources/web_assets/bootstrap.min.css" rel="stylesheet"> <style type="text/css"> body { font: 10px sans-serif; min-width: 750px; } table { max-width:700px; } .axis path, .axis line { fill: none; stroke: #000; shape-rendering: crispEdges; } .bar { fill: steelblue; } .x.axis path { display: none; } .d3-tip { line-height: 1; font-weight: bold; padding: 12px; background: rgba(0, 0, 0, 0.8); color: #fff; border-radius: 2px; } /* Creates a small triangle extender for the tooltip */ .d3-tip:after { box-sizing: border-box; display: inline; font-size: 10px; width: 100%; line-height: 1; color: rgba(0, 0, 0, 0.8); content:"\25BC"; position: absolute; text-align: center; } /* Style northward tooltips differently */ .d3-tip.n:after { margin: -1px 0 0 0; top: 100%; left: 0; } .chartInfo h6 { display: inline; } </style> <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script> <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/d3/3.3.9/d3.min.js"></script> <script type="text/javascript" src="file:///C:/openstudio_git/OpenStudio/openstudiocore/resources/web_assets/jquery.min.js"></script> <script type="text/javascript" src="file:///C:/openstudio_git/OpenStudio/openstudiocore/resources/web_assets/d3.min.js"></script> <script type="text/javascript"> // http://labratrevenge.com/d3-tip/javascripts/d3.tip.min.js d3.tip=function(){function t(t){v=m(t),w=v.createSVGPoint(),document.body.appendChild(x)}function e(){return"n"}function n(){return[0,0]}function r(){return" "}function o(){var t=p();return{top:t.n.y-x.offsetHeight,left:t.n.x-x.offsetWidth/2}}function s(){var t=p();return{top:t.s.y,left:t.s.x-x.offsetWidth/2}}function l(){var t=p();return{top:t.e.y-x.offsetHeight/2,left:t.e.x}}function u(){var t=p();return{top:t.w.y-x.offsetHeight/2,left:t.w.x-x.offsetWidth}}function f(){var t=p();return{top:t.nw.y-x.offsetHeight,left:t.nw.x-x.offsetWidth}}function i(){var t=p();return{top:t.ne.y-x.offsetHeight,left:t.ne.x}}function a(){var t=p();return{top:t.sw.y,left:t.sw.x-x.offsetWidth}}function c(){var t=p();return{top:t.se.y,left:t.e.x}}function d(){var t=d3.select(document.createElement("div"));return t.style({position:"absolute",opacity:0,pointerEvents:"none",boxSizing:"border-box"}),t.node()}function m(t){return t=t.node(),"svg"==t.tagName.toLowerCase()?t:t.ownerSVGElement}function p(){var t=d3.event.target,e={},n=t.getScreenCTM(),r=t.getBBox(),o=r.width,s=r.height,l=r.x,u=r.y,f=document.body.scrollTop,i=document.body.scrollLeft;return document.documentElement&&document.documentElement.scrollTop&&(f=document.documentElement.scrollTop,i=document.documentElement.scrollLeft),w.x=l+i,w.y=u+f,e.nw=w.matrixTransform(n),w.x+=o,e.ne=w.matrixTransform(n),w.y+=s,e.se=w.matrixTransform(n),w.x-=o,e.sw=w.matrixTransform(n),w.y-=s/2,e.w=w.matrixTransform(n),w.x+=o,e.e=w.matrixTransform(n),w.x-=o/2,w.y-=s/2,e.n=w.matrixTransform(n),w.y+=s,e.s=w.matrixTransform(n),e}var y=e,g=n,h=r,x=d(),v=null,w=null;t.show=function(){var e,n=h.apply(this,arguments),r=g.apply(this,arguments),o=y.apply(this,arguments),s=d3.select(x),l=0;for(s.html(n).style({opacity:1,pointerEvents:"all"});l--;)s.classed(E[l],!1);return e=T.get(o).apply(this),s.classed(o,!0).style({top:e.top+r[0]+"px",left:e.left+r[1]+"px"}),t},t.hide=function(){return nodel=d3.select(x),nodel.style({opacity:0,pointerEvents:"none"}),t},t.attr=function(e){if(2>arguments.length&&"string"==typeof e)return d3.select(x).attr(e);var n=Array.prototype.slice.call(arguments);return d3.selection.prototype.attr.apply(d3.select(x),n),t},t.style=function(e){if(2>arguments.length&&"string"==typeof e)return d3.select(x).style(e);var n=Array.prototype.slice.call(arguments);return d3.selection.prototype.style.apply(d3.select(x),n),t},t.direction=function(e){return arguments.length?(y=null==e?e:d3.functor(e),t):y},t.offset=function(e){return arguments.length?(g=null==e?e:d3.functor(e),t):g},t.html=function(e){return arguments.length?(h=null==e?e:d3.functor(e),t):h};var T=d3.map({n:o,s:s,e:l,w:u,nw:f,ne:i,sw:a,se:c}),E=T.keys();return t}; </script> </head> <body> <div style="width:250px;display:inline-block;"> <label>Calibration Method</label> <select id="calibrationMethodSelect"> </select> </div> <div style="width:400px;display:inline-block;"> <h6 id="calibrationString"></h6> </div> <div id="consumptionString-0" class="chartInfo"></div> <div id="chart-0"></div> <div id="table-0" ></div> <div id="consumptionString-1" class="chartInfo"></div> <div id="chart-1"></div> <div id="table-1" ></div> <div id="consumptionString-2" class="chartInfo"></div> <div id="chart-2"></div> <div id="table-2" ></div> <script type="text/javascript"> function numFormat(n) { var parts = n.toString().split("."); return parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",") + (parts[1] ? "." + parts[1] : ""); } <%= energy %> $.each(calibrationGuidelines, function (index, value) { $('#calibrationMethodSelect') .append($("<option></option>") .attr("value", index) .text(value)); }); $("#calibrationMethodSelect").change(onMethodChange); var maxNMBE = 0; var maxCVRMSE = 0; function onMethodChange() { if ($('#calibrationMethodSelect').val() == "0") { maxNMBE = ashraeMaxNMBE; maxCVRMSE = ashraeMaxCVRMSE; } else { maxNMBE = fempMaxNMBE; maxCVRMSE = fempMaxCVRMSE; } $('#calibrationString').text("NMBE of " + maxNMBE + "% or less and CV(RMSE) of " + maxCVRMSE + "% relative to monthly data. Must contain all utility data for one year and real weather data. Check the guideline for additional requirements."); $('.table').each(function(i) { $(this).find('tr:last td:not(:first)').each(function(j) { var value = $(this).text().replace(/%/g, ''); if (value != "—") { var num = parseFloat(value); if (Math.abs(num) > maxNMBE) { num = "<font color=\"red\">" + num; } num = num + "%"; $(this).html(num); } }); }) for (var c in charts) { if(consumption[charts[c]]){ cvrmseString = "<h6>CV(RMSE) = </h6>" num = consumption[charts[c]].cvrsme; if (Math.abs(num) > maxCVRMSE) { num = "<font color=\"red\">" + num + "<font color=\"black\">"; } cvrmseString = cvrmseString + num; nmbeString = "<h6>NMBE = </h6>" num = consumption[charts[c]].nmbe; if (Math.abs(num) > maxNMBE) { num = "<font color=\"red\">" + num; } nmbeString = nmbeString + num; string = "<h4 style=\"margin-bottom:-10px;\">" + charts[c] + " (" + consumption[charts[c]].units + ")</h4>"; if(charts[c] != "Electricity Demand"){ string = string + "<br>" + cvrmseString + "<br>" + nmbeString; } $('#consumptionString-' + c).html(string); } } } onMethodChange(); function outputTable(name, units, obj, id) { var $table = $('<table id="' + name.toLowerCase().replace(/ /g, '-') + '">').addClass("table table-striped table-bordered table-condensed"); var headers = ''; for (var i = 1; i <= obj.Start.length; i++) headers += '<th>' + i + '</th>'; $table.append('<thead>').children('thead').append('<tr />').children('tr').append('<th> </th>').append(headers); var $tbody = $table.append('<tbody />').children('tbody'); var key; for (key in obj) { if (obj.hasOwnProperty(key)) { if (key == "Start" | key == "End" | key == "Actual" | key == "Model" | key == "NMBE") { var $row = $tbody.append('<tr />').children('tr:last'); $row.append("<td>" + key + "</td>"); for (i = 0; i < obj.Start.length; i++) { var num = obj[key][i] === 0 ? "—" : numFormat(obj[key][i]); if (num != "—") { if (key == "NMBE") { if (Math.abs(num) > maxNMBE) { num = "<font color=\"red\">" + num; } num = num + "%"; } } $row.append("<td>" + num + "</td>"); } } } } $table.appendTo('#' + id); } var margin = { top: 20.5, right: 20, bottom: 30, left: 40.5 }, width = 560 - margin.left - margin.right, height = 300 - margin.top - margin.bottom; var x0 = d3.scale.ordinal() .rangeRoundBands([0, width], 0.1); var x1 = d3.scale.ordinal(); var y = d3.scale.linear() .range([height, 0]); var color = d3.scale.ordinal() .range(["#8CC739", "#29AAE7"]); var xAxis = d3.svg.axis() .scale(x0) .orient("bottom"); var yAxis = d3.svg.axis() .scale(y) .orient("left") .tickFormat(d3.format(".2s")); var tip = d3.tip() .attr('class', 'd3-tip') .offset([-10, 0]) .html(function (d) { return "<strong>" + d3.event.target.__data__.name + ":</strong> <span style='color:red'>" + d3.event.target.__data__.value + "</span>"; }); var charts = ["Electricity Consumption", "Electricity Demand", "Natural Gas Consumption"]; for (var c in charts) { if(consumption[charts[c]]){ if (c == 0) { margin.right = 125; } cvrmseString = "<h6>CV(RMSE) = </h6>" num = consumption[charts[c]].cvrsme; if (Math.abs(num) > maxCVRMSE) { num = "<font color=\"red\">" + num + "<font color=\"black\">"; } cvrmseString = cvrmseString + num; nmbeString = "<h6>NMBE = </h6>" num = consumption[charts[c]].nmbe; if (Math.abs(num) > maxNMBE) { num = "<font color=\"red\">" + num; } nmbeString = nmbeString + num; string = "<h4 style=\"margin-bottom:-10px;\">" + charts[c] + " (" + consumption[charts[c]].units + ")</h4>"; if(charts[c] != "Electricity Demand"){ string = string + "<br>" + cvrmseString + "<br>" + nmbeString; } $('#consumptionString-' + c).html(string); var svg = d3.select("#chart-" + c).append("svg") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom) .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); svg.call(tip); data = []; for (var enduse in consumption[charts[c]].data) { if (enduse == "Actual" | enduse == "Model") { var enduse_data = consumption[charts[c]].data[enduse]; for (var i = 1; i <= enduse_data.length; i++) { if (data.length < enduse_data.length) { var temp = { "Month": i }; temp[enduse] = enduse_data[i - 1]; data.push(temp); } else { data[i - 1][enduse] = enduse_data[i - 1]; } } } } var comparison = d3.keys(data[0]).filter(function (key) { return key !== "Month"; }); data.forEach(function (d) { d.consumption = comparison.map(function (name) { return { name: name, value: +d[name] }; }); }); x0.domain(data.map(function (d) { return d.Month; })); x1.domain(comparison).rangeRoundBands([0, x0.rangeBand()]); y.domain([0, d3.max(data, function (d) { return d3.max(d.consumption, function (d) { return d.value; }); })]); //data.sort(function(a, b) { return b.total - a.total; }); svg.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") .call(xAxis); svg.append("g") .attr("class", "y axis") .call(yAxis) .append("text") .attr("transform", "rotate(-90)") .attr("y", -36) .attr("dy", ".71em") .style("text-anchor", "end") .text(consumption[charts[c]].units); var month = svg.selectAll(".month") .data(data) .enter().append("g") .attr("class", "g") .on('mouseover', tip.show) .on('mouseout', tip.hide) .attr("transform", function (d) { return "translate(" + x0(d.Month) + ",0)"; }); month.selectAll("rect") .data(function (d) { return d.consumption; }) .enter().append("rect") .attr("width", x1.rangeBand()) .attr("x", function (d) { return x1(d.name); }) .attr("y", function (d) { return y(d.value); }) .attr("height", function (d) { return height - y(d.value); }) .style("fill", function (d) { return color(d.name); }); var legend = svg.selectAll(".legend") .data(comparison.slice().reverse()) .enter().append("g") .attr("class", "legend") .attr("transform", function (d, i) { return "translate(0," + i * 20 + ")"; }); legend.append("rect") .attr("x", width + 105) .attr("width", 18) .attr("height", 18) .style("fill", color); legend.append("text") .attr("x", width + 105 - 3) .attr("y", 9) .attr("dy", ".35em") .style("text-anchor", "end") .text(function (d) { return d; }); svg.selectAll(".g").attr("stroke", "black"); outputTable(charts[c], consumption[charts[c]].units, consumption[charts[c]].data, "table-" + c); } } </script> </body> </html>