Published
Edited
Mar 8, 2021
1 fork
Importers
Insert cell
md`# MIT Model Input Calibration`
Insert cell
xlsx = require('https://bundle.run/xlsx@0.14.1')
Insert cell
Insert cell
Insert cell
chart = {
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height]);
svg.append("g")
.call(yAxis_ticks);

const g = svg.selectAll(".vars")
.data(counts)
.join("g")
.attr("class", "vars")
.attr("transform", d => `translate(0,${y(d.variable) + y.bandwidth()/2})`);
g.each(function(d, i) {
const x = d3.scaleLinear()
// .domain([0, 3]).nice()
.domain([0, 3]).nice()
.range([margin.left, width - margin.right]);
const xAxis = g => g
// .call(d3.axisBottom(x).tickValues([0, 1, 2, 3]).tickFormat(dd => x_lookup[d.variable] [dd]).tickPadding(12))
.call(d3.axisBottom(x).tickValues([0, 1, 2, 3]).tickFormat(dd => x_lookup[d.variable][dd]).tickPadding(12))
.call(g => g.select(".domain").remove())
.call(g => g.selectAll(".tick line").remove())
.call(g => g.selectAll("text").attr("font-weight", "bold"))
.call(g => g.selectAll("text").attr("color", (dd, i) => highlight(d, i)))
.call(g => g.selectAll("text").style("mix-blend-mode", "multiply"));
d3.select(this).selectAll(".dots")
// .data([0, 1, 2, 3])
.data([0, 1, 2, 3])
.join("circle")
.attr("class", "dots")
.style("mix-blend-mode", "multiply")
.attr("stroke", "#00a1b0")
.attr("stroke-width", 1)
.attr("fill", chroma("#00a1b0").brighten(1.5).desaturate())
.attr("fill-opacity", .5)
.attr("cy", 0)
.attr("cx", (d, i) => x(i))
.attr("r", dd => scale(d[dd.toString(16)]))
d3.select(this).selectAll(".points")
// .data([0, 1, 2, 3])
.data([0, 1, 2, 3])
.join("circle")
.attr("class", "points")
.style("mix-blend-mode", "multiply")
// .attr("stroke", "#00a1b0")
// .attr("stroke-width", 2)
.attr("fill", (dd, i) => highlight(d, i))
.attr("cy", 0)
.attr("cx", (d, i) => x(i))
.attr("r", 4)
d3.select(this).append("g").call(xAxis);

})

svg.append("g")
.call(xAxis);

svg.append("g")
.call(yAxis);
svg.selectAll("text").attr("font-size", 16).attr("font-family", "Open Sans")

return svg.node();
}
Insert cell
filename = binary.name.split(".")[0]
Insert cell
input = new Uint8Array(await Files.buffer(binary))
Insert cell
wb = xlsx.read(input, {type: 'array'})
Insert cell
sheets = wb.SheetNames.filter(d => d != "Building_Design_Space_Original" && d != "Building Information" && d != "Baseline")
Insert cell
// data must be structured with typical input fields as column headers, with one column calling out building name
// data = FileAttachment("UT Baseline Inputs@1.csv").csv({typed: true})

Insert cell
excel = wb.Sheets["Baseline"]
Insert cell
data = xlsx.utils.sheet_to_json(excel)
Insert cell
Insert cell
margin = ({top: 80, right: 100, bottom: 50, left: 350})
Insert cell
height = 1400
Insert cell
d3 = require("d3@^6.1")
Insert cell
_ = require('lodash@4.17.15/lodash.js').catch(() => window["_"])
Insert cell
dates = d3.timeMonth.range(new Date(2019, 0, 1), new Date(2019, 11, 30)).map(d3.timeFormat("%b"));
Insert cell
colors = ({"S": "#f79320", "E": "#fed202", "C":"#00a1b0"})
Insert cell
chroma = require('chroma-js')
Insert cell
v_lookup = ({
"WWR": "Window-Wall Ratio (%)",
"WINU": "Window Assembly U (BTU/h-ft2-°F)",
"WINSHGC": "Window SHGC",
"WALLR": "Effective Wall R (h-ft2-°F/BTU)",
"ROOFR": "Effective Roof R (h-ft2-°F/BTU)",
"EQUIPSCHED": "Equipment Usage Schedule",
"LIGHTUSAGE": "Lighting Usage Schedule",
"EPD": "Equipment (Process + Plug) (W/ft2)",
"LPD": "Lighting (W/ft2)",
"HRV": "Sensible ERV Effectiveness",
"ACH": "Air Changes per Hour",
"VENTSCHED": "Ventilation Schedule",
"HUMIDMAX": "Humidity Control Max RH",
"SUPPTEMPRESET": "Max Supply Air Temperature",
"FANPOWER": "Fan Pressure Drop (in. H2O)"
})
Insert cell
counts = {

const count = (d, i) => {
const arr = data.map(dd => dd[d]);
return arr.filter(dd => dd === i).length;
}
const keymap = Object.keys(v_lookup).map(d => ({variable: d, "0": count(d, 0), "1": count(d, 1), "2": count(d, 2), "3": count(d, 3)}));
return keymap;

}
Insert cell
energy = d => {
let r = "Low";
switch(d) {
case 0:
r= "High";
break;
case 1:
r= "Mid-High";
break;
case 2:
r= "Low-High";
break;
default:
r="Low";
}
return r;
}
Insert cell
y = d3.scaleBand()
.domain(Object.keys(v_lookup).reverse())
.range([height - margin.bottom, margin.top])
.padding(.1)
.paddingOuter(.5)
Insert cell
x = d3.scaleLinear()
// .domain([0, 3]).nice()
.domain([0, 3]).nice()
.range([margin.left, width - margin.right])
Insert cell
xAxis = g => g
.attr("transform", `translate(0,${margin.top})`)
// .call(d3.axisTop(x).tickValues([0, 1, 2, 3]).tickFormat((d, i) => energy(i)).tickPadding(10))
.call(d3.axisTop(x).tickValues([0, 1, 2, 3]).tickFormat((d, i) => energy(i)).tickPadding(10))
.call(g => g.select(".domain").remove())
.call(g => g.select(".tick:first-of-type text").clone()
.attr("y", -50)
.attr("x", -18)
.attr("text-anchor", "start")
.attr("font-weight", "bold")
.html("Energy Use Impact"))
Insert cell
yAxis = g => g
.attr("transform", `translate(${5},0)`)
.call(d3.axisRight(y).tickFormat(d => v_lookup[d]))
.call(g => g.select(".domain").remove())
.call(g => g.selectAll(".tick line").remove())
Insert cell
yAxis_ticks = g => g
.attr("transform", `translate(${margin.left},0)`)
.call(d3.axisRight(y).tickFormat(d => v_lookup[d]))
.call(g => g.select(".domain").remove())
.call(g => g.selectAll("text").remove())
.call(g => g.selectAll(".tick line")
.attr("stroke-opacity", 0.1)
.attr("x2", width - margin.left - margin.right))
Insert cell
scale = d3.scaleLinear()
.domain([0, 100])
.range([0, y.bandwidth()/1.5])
Insert cell
x_lookup = ({
"WWR": ["60%", "50%", "40%", "30%"],
"WINU": ["1.0", "0.8", "0.6", "0.4"],
"WINSHGC": ["0.2", "0.3", "0.4", "0.5"],
"WALLR": ["5", "10", "20", "30"],
"ROOFR": ["10", "20", "30", "40"],
"EQUIPSCHED": ["High Intensity", "Uniform Academic", "Seasonal Academic", "Standard"],
"LIGHTUSAGE": ["High Intensity", "Uniform Academic", "Seasonal Academic", "Standard"],
"EPD": ["8", "6", "4", "2"],
"LPD": ["1.6", "1.3", "1", "0.7"],
"HRV": ["0.0", "0.2", "0.4", "0.6"],
"ACH": ["15", "12", "9", "6"],
"VENTSCHED": ["0", "1", "2", "3"],
"HUMIDMAX": ["50", "60", "70", "80"],
"SUPPTEMPRESET": ["68", "64", "60", "56"],
"FANPOWER": ["10", "8", "6", "4"]
})

Insert cell
highlight = (d, i) => {
const objs = Object.entries(d).filter(dd => dd[0] != "variable").sort((a, b) => b[1] - a[1]);
const index = +objs[0][0];
return index === i ? "#00a1b0": "#dfdfdf";

}
Insert cell
serialize = {
const xmlns = "http://www.w3.org/2000/xmlns/";
const xlinkns = "http://www.w3.org/1999/xlink";
const svgns = "http://www.w3.org/2000/svg";
return function serialize(svg) {
svg = svg.cloneNode(true);
const fragment = window.location.href + "#";
const walker = document.createTreeWalker(svg, NodeFilter.SHOW_ELEMENT, null, false);
while (walker.nextNode()) {
for (const attr of walker.currentNode.attributes) {
if (attr.value.includes(fragment)) {
attr.value = attr.value.replace(fragment, "#");
}
}
}
svg.setAttributeNS(xmlns, "xmlns", svgns);
svg.setAttributeNS(xmlns, "xmlns:xlink", xlinkns);
const serializer = new window.XMLSerializer;
const string = serializer.serializeToString(svg);
return new Blob([string], {type: "image/svg+xml"});
};
}
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more