Public
Edited
Mar 28, 2024
Insert cell
Insert cell
Insert cell
Insert cell
viewof txt = 'Hotel has a total of ' + floors*rooms+' rooms, using ' + Math.round(bond[2].value + bond[3].value+(36.25*rooms*floors))+ ' liters of water each day.'
Insert cell
bond5 = bond
Insert cell
Insert cell
Insert cell
chart3 = SankeyChart({
nodes: node4,
links: bond4
}, {
//nodeGroup: d => d.id.split(/\W/)[0], // take first word for color
nodeGroup: d => d.id,
nodeAlign, // e.g., d3.sankeyJustify; set by input above
linkColor, // e.g., "source" or "target"; set by input above
format: (f => d => `${f(d)} L/D`)(d3.format(",.1~f")),
//nodeTitle,
//linkColor:.50,
nodeStrokeWidth:1,
width,
height: 550
})
Insert cell
proposed = md`#### Aera New York Proposed Hotel Room Water Usage`
Insert cell
chart = SankeyChart({
nodes: node1,
links: bond5
}, {
//nodeGroup: d => d.id.split(/\W/)[0], // take first word for color
nodeGroup: d => d.id,
nodeAlign, // e.g., d3.sankeyJustify; set by input above
linkColor, // e.g., "source" or "target"; set by input above
format: (f => d => `${f(d)} L/D`)(d3.format(",.1~f")),
//nodeTitle,
//linkColor:.50,
nodeStrokeWidth:1,
width,
height: 550
}

)
Insert cell
Insert cell
totalWaterSavings = md ` #### Daily Water Savings: ${savings} liters`
Insert cell
totalWaterCreated = md ` #### Total amount remediated for watering: ${waterSavings} liters`
Insert cell
//difference5 = bond4[4].value
Insert cell
viewof rooms = Inputs.range([15, 25], {step: 1, label: "Rooms per Floor", value:'20'})
Insert cell
newrooms = rooms
Insert cell
viewof floors = Inputs.range([10, 20], {step: 1, label: "Total Floors", value: 15})
Insert cell
viewof flush1 = Inputs.range([3, 18], {step: 1, label: "Flush Volume", value: 6})
Insert cell
viewof showerVolume = Inputs.range([6, 12], {step: .5, label: "Shower L/Min", value: 9.5})
Insert cell
viewof showerLength = Inputs.range([6, 12], {step: 1, label: "Average Shower Length (Min)", value: 8})
Insert cell
viewof sinkVolume = Inputs.range([5, 10], {step: .5, label: "Sink L/Min", value: 7.5})
Insert cell
viewof sinkUsage = Inputs.range([5, 15], {step: .5, label: "Sink Daily Use Time (Min)", value: 8})
Insert cell
viewof graywater = Inputs.range([80, 100], {step: 1, label: "Gray Water Throughput (L/d/m^2)", value: 93})
Insert cell
//viewof sinkUsage
Insert cell
viewof radios = Inputs.radio(["1", "2", "3","4"], {label: "Showers/Day", value: "2"})
Insert cell
viewof city = Inputs.radio(["New York", "Dubai"], {label: "City", value: "New York"})
Insert cell
bond[4].value
Insert cell
difference1 =6
Insert cell
mutable newTotal = 0
Insert cell
//mutable sinkUsage4 = 5
Insert cell
mutable sinkUsage4 = Inputs.range([5, 15], {step: .5, label: "Sink Daily Use Time (Min)", value: 8})
Insert cell
mutable watering = 0
Insert cell
savings = round(newTotal,0)
Insert cell
waterSavings = round(watering,0)
Insert cell
mutable potableTotal = 0
Insert cell
mutable remediated = 0
Insert cell
mutable normWatering = 0
Insert cell
mutable normPotable = 0
Insert cell
mutable proposedBlack = 0
Insert cell
mutable normGray = 0
Insert cell
function updateValues(floors,newrooms){ var something = sinkUsage3Copy*5


//bond[1].value = floors3*2
var showerUsers = radios*64705
//console.log(showerUsers)
//bond[3].value = showerUsers
//bond[5].value = showerUsers
bond[3].value = showerLength*showerVolume*newrooms*floors*radios//
bond[5].value = showerLength*showerVolume*newrooms*floors*radios
//bond[1].value = showerUsers+bond[2].value

bond4[3].value = showerLength*showerVolume*newrooms*floors*radios//current shower
bond4[8].value = showerLength*showerVolume*newrooms*floors*radios// current shower to gray

//var potable = rooms*floors*332
//bond[1].value = potable
bond[4].value = newrooms*floors*sinkVolume*sinkUsage//sink to remediation
bond[2].value = newrooms*floors*sinkVolume*sinkUsage//washing to sink

bond4[7].value = newrooms*floors*sinkVolume*sinkUsage//current sink to gray
bond4[2].value = newrooms*floors*sinkVolume*sinkUsage//current washing to sink

bond[1].value = bond[2].value + bond[3].value//washing = sink+shower
//bond[0].value = bond[1].value + 31000
bond[0].value = 36.25*newrooms*floors//ice

bond4[1].value = bond[2].value + bond[3].value//current washing = sink+shower
mutable remediated = bond4[1].value//remdiated total in proposed
//bond[0].value = bond[1].value + 31000
bond4[0].value = 36.25*newrooms*floors// current ice

mutable potableTotal = bond4[0].value+bond4[1].value
var flush3 = flush1*7*newrooms*floors
//console.log(flush3)
bond[7].value = flush3//new flush size
bond[8].value = flush3//new blackwater size
var remediation = bond[4].value+bond[5].value//compute remediation by adding washing and shower
bond[6].value = remediation - bond[7].value//compute watering quantity by subtracting flush from remediation


bond4[5].value = flush3//current new flush size
bond4[6].value = flush3//current new black water
bond4[4].value = 16857//water requirement for 1200 occupants
if(city=="Dubai"){bond4[4].value=46918}
bond4[9].value = bond4[4].value

mutable normWatering = bond4[4].value
mutable normPotable = bond4[5].value+bond4[0].value+bond4[1].value+bond4[4].value
mutable normGray = bond4[7].value+bond4[8].value+bond4[4].value

mutable proposedBlack = bond[8].value
mutable watering = bond[6].value
mutable newTotal = (bond4[0].value+bond4[1].value+bond4[4].value+bond4[5].value)-(bond[1].value+bond[0].value)

}
Insert cell
// Copyright 2021 Observable, Inc.
// Released under the ISC license.
// https://observablehq.com/@d3/sankey-diagram
function SankeyChart({
nodes, // an iterable of node objects (typically [{id}, …]); implied by links if missing
links // an iterable of link objects (typically [{source, target}, …])
}, {
format = ",", // a function or format specifier for values in titles
align = "justify", // convenience shorthand for nodeAlign
nodeId = d => d.id, // given d in nodes, returns a unique identifier (string)
nodeGroup, // given d in nodes, returns an (ordinal) value for color
nodeGroups, // an array of ordinal values representing the node groups
nodeLabel, // given d in (computed) nodes, text to label the associated rect
//nodeTitle = d => `${d.id}\n${format(d.value)}`, // given d in (computed) nodes, hover text
nodeTitle = d => `${format(d.value)}`, // given d in (computed) nodes, hover text
nodeAlign = align, // Sankey node alignment strategy: left, right, justify, center
nodeWidth = 45, // width of node rects
nodePadding = 10, // vertical separation between adjacent nodes
nodeLabelPadding = 6, // horizontal separation between node and label
nodeStroke = "currentColor", // stroke around node rects
nodeStrokeWidth, // width of stroke around node rects, in pixels
nodeStrokeOpacity, // opacity of stroke around node rects
nodeStrokeLinejoin, // line join for stroke around node rects
linkSource = ({source}) => source, // given d in links, returns a node identifier string
linkTarget = ({target}) => target, // given d in links, returns a node identifier string
linkValue = ({value}) => value, // given d in links, returns the quantitative value
linkPath = d3Sankey.sankeyLinkHorizontal(), // given d in (computed) links, returns the SVG path
linkTitle = d => `${d.source.id} → ${d.target.id}\n${format(d.value)}`, // given d in (computed) links
linkColor = "source-target", // source, target, source-target, or static color
linkStrokeOpacity = 0.5, // link stroke opacity
linkMixBlendMode = "multiply", // link blending mode
colors = d3.schemeBlues[6], // array of colors
width = 640, // outer width, in pixels
height = 500, // outer height, in pixels
marginTop = 5, // top margin, in pixels
marginRight = 1, // right margin, in pixels
marginBottom = 5, // bottom margin, in pixels
marginLeft = 1, // left margin, in pixels
} = {}) {

var flr
var rms
if(city=="New York"){
flr= floors
rms = rooms
}else{
flr = floorsDubai
rms = roomsDubai
}
updateValues(flr,rms)

//var remediation = bond[4].value+bond[5].value//compute remediation by adding washing and shower
//bond4[6].value = remediation - bond[7].value
//difference1 = 40
//difference1 + bond4[0].value+bond4[1].value+bond4[4].value+bond4[5].value
//difference5 = bond4[0].value+bond4[1].value+bond4[4].value+bond4[5].value



// Convert nodeAlign from a name to a function (since d3-sankey is not part of core d3).
if (typeof nodeAlign !== "function") nodeAlign = {
left: d3Sankey.sankeyLeft,
right: d3Sankey.sankeyRight,
center: d3Sankey.sankeyCenter
}[nodeAlign] ?? d3Sankey.sankeyJustify;

// Compute values.
const LS = d3.map(links, linkSource).map(intern);
const LT = d3.map(links, linkTarget).map(intern);
const LV = d3.map(links, linkValue);
if (nodes === undefined) nodes = Array.from(d3.union(LS, LT), id => ({id}));
const N = d3.map(nodes, nodeId).map(intern);
const G = nodeGroup == null ? null : d3.map(nodes, nodeGroup).map(intern);

// Replace the input nodes and links with mutable objects for the simulation.
nodes = d3.map(nodes, (_, i) => ({id: N[i]}));
links = d3.map(links, (_, i) => ({source: LS[i], target: LT[i], value: LV[i]}));

// Ignore a group-based linkColor option if no groups are specified.
if (!G && ["source", "target", "source-target"].includes(linkColor)) linkColor = "currentColor";

// Compute default domains.
if (G && nodeGroups === undefined) nodeGroups = G;

// Construct the scales.
const color = nodeGroup == null ? null : d3.scaleOrdinal(nodeGroups, colors);

// Compute the Sankey layout.
d3Sankey.sankey()
.nodeSort((a, b) => a.index - b.index)
.nodeId(({index: i}) => N[i])
.nodeAlign(nodeAlign)
.nodeWidth(nodeWidth)
.nodePadding(nodePadding)
.extent([[marginLeft, marginTop], [width - marginRight, height - marginBottom]])
({nodes, links});

// Compute titles and labels using layout nodes, so as to access aggregate values.
if (typeof format !== "function") format = d3.format(format);
const Tl = nodeLabel === undefined ? N : nodeLabel == null ? null : d3.map(nodes, nodeLabel);
const Tt = nodeTitle == null ? null : d3.map(nodes, nodeTitle);
const Lt = linkTitle == null ? null : d3.map(links, linkTitle);
const Lv = linkValue == null ? null : d3.map(links, linkValue);

// A unique identifier for clip paths (to avoid conflicts).
const uid = `O-${Math.random().toString(16).slice(2)}`;

const svg = d3.create("svg")
.attr("width", width)
.attr("height", height)
.attr("viewBox", [0, 0, width, height])
.attr("style", "max-width: 100%; height: auto; height: intrinsic;");

const node = svg.append("g")
.attr("stroke", nodeStroke)
.attr("stroke-width", nodeStrokeWidth)
.attr("stroke-opacity", nodeStrokeOpacity)
.attr("stroke-linejoin", nodeStrokeLinejoin)
.selectAll("rect")
.data(nodes)
.join("rect")
.attr("x", d => d.x0)
.attr("y", d => d.y0)
.attr("height", d => d.y1 - d.y0)
.attr("width", d => d.x1 - d.x0);

if (G) node.attr("fill", ({index: i}) => color(G[i]));
if (Tt) node.append("title").text(({index: i}) => Tt[i]);

const link = svg.append("g")
.attr("fill", "none")
.attr("stroke-opacity", linkStrokeOpacity)
.selectAll("g")
.data(links)
.join("g")
.style("mix-blend-mode", linkMixBlendMode);

if (linkColor === "source-target") link.append("linearGradient")
.attr("id", d => `${uid}-link-${d.index}`)
.attr("gradientUnits", "userSpaceOnUse")
.attr("x1", d => d.source.x1)
.attr("x2", d => d.target.x0)
.call(gradient => gradient.append("stop")
.attr("offset", "0%")
.attr("stop-color", ({source: {index: i}}) => color(G[i])))
.call(gradient => gradient.append("stop")
.attr("offset", "100%")
.attr("stop-color", ({target: {index: i}}) => color(G[i])));

link.append("path")
.attr("d", linkPath)
.attr("stroke", linkColor === "source-target" ? ({index: i}) => `url(#${uid}-link-${i})`
: linkColor === "source" ? ({source: {index: i}}) => color(G[i])
: linkColor === "target" ? ({target: {index: i}}) => color(G[i])
: linkColor)
.attr("stroke-width", ({width}) => Math.max(1, width))
.call(Lt ? path => path.append("title").text(({index: i}) => Lt[i]) : () => {});

if (Tl) svg.append("g")
.attr("font-family", "sans-serif")
.attr("font-size", 24)
.selectAll("text")
.data(nodes)
.join("text")
.attr("x", d => d.x0 < width / 2 ? d.x1 + nodeLabelPadding : d.x0 - nodeLabelPadding)
.attr("y", d => (d.y1 + d.y0) / 2)
.attr("dy", "0.35em")
.attr("text-anchor", d => d.x0 < width / 2 ? "start" : "end")
.text(({index: i}) => Tl[i]);
//.text(({index: i}) => Lv[i]);

if (Tt) svg.append("g")
.attr("font-family", "sans-serif")
.attr("font-size", 24)
.selectAll("text")
.data(nodes)
.join("text")
.attr("x", d => d.x0 < width / 2 ? d.x1 + nodeLabelPadding : d.x0 - nodeLabelPadding)
.attr("y", d => ((d.y1 + d.y0) / 2)+26)
.attr("dy", "0.35em")
.attr("text-anchor", d => d.x0 < width / 2 ? "start" : "end")
.text(({index: i}) => Tt[i]);
//.text(({index: i}) => bond[i].value)

function intern(value) {
return value !== null && typeof value === "object" ? value.valueOf() : value;
}
return Object.assign(svg.node(), {scales: {color}});
}
Insert cell
sheet = 'https://docs.google.com/spreadsheets/d/e/2PACX-1vRoczva03XZk0-WCbNiL4ihA4kPxXX19LOkpOL9hdADkoRNXn7_EVgX12VKqf8nk1ZdXOZ_pZt09BL7/pub?output=csv'
Insert cell
node2 = 'https://docs.google.com/spreadsheets/d/e/2PACX-1vTdiEd9YrA-qOZTkv2qYDFfLKOdTcRLIAUNZH5hm3sXoRD6ctaLAanU9jwDsmakFV7L7-ZzGAuqIq5B/pub?output=csv'
Insert cell
bond = d3.csv(sheet, d3.autoType)
Insert cell
node1 = d3.csv(node2, d3.autoType)
Insert cell
//howto("SankeyChart", {imports: {d3: "d3", d3Sankey: "d3-sankey"}})
Insert cell
Insert cell
d3Sankey = require.alias({"d3-array": d3, "d3-shape": d3, "d3-sankey": "d3-sankey@0.12.3/dist/d3-sankey.min.js"})("d3-sankey")
Insert cell
import {howto} from "@d3/example-components"
Insert cell
node3 = 'https://docs.google.com/spreadsheets/d/e/2PACX-1vR5xJzEBNwWOz8C5Cgqduzhk01449DsVMZmTpCc3JGGXQN4d_Rl-Qq1KMBlNl_M4u0wnNjiQOA-nnhr/pub?output=csv'
Insert cell
sheet3 = 'https://docs.google.com/spreadsheets/d/e/2PACX-1vTtiPjXi7VaHdWY_vGaI6GZofVHGE19LMhm5xYvRlWAn-vPa4olHNQ39NjcIc03YxESirb-wIQrvxix/pub?output=csv'
Insert cell
node4 = d3.csv(node3, d3.autoType)
Insert cell
bond4 = d3.csv(sheet3, d3.autoType)
Insert cell
round = (n, places) => {
if (!places) return Math.round(n);
const d = 10 ** places;
return Math.round(n * d) / d;
}
Insert cell
viewof water_air = Inputs.radio(["Gray Water Remediation", "Air Supply Requirements"], {value: "Gray Water Remediation"})
Insert cell
water_air
Insert cell
bool={
var retur
if(water_air=="Gray Water Remediation"){retur = option1}else{retur = option2}

return retur
}
Insert cell
boolDash = {
var retur
if(water_air=="Gray Water Remediation"){retur = waterDash}else{retur = airDash}

return retur
}
Insert cell
import {LineChart} from "153f45f086ac8d1c"
Insert cell
Insert cell
Insert cell
data = d3.csv(dataLink,d3.autoType)
Insert cell
data2 = d3.csv(data2Link,d3.autoType)
Insert cell
Insert cell
focus = Generators.input(chart1)
Insert cell
chartCopy =

//{
//var curChart = chart
//if(city=="New York"){curChart = chart}
//}

html`
<div class='outer' style='height:800px;'>
<div class='title' style='position:absolute;top:0px;left:0px;font-family:helvetica'>
${md ` ### AERA Air, Water, Energy and Cost Modeling`}

</div>

<div class="water_air" style='position:absolute;top:35px;left:0px;'>
${viewof water_air}
</div>



${boolDash}


${bool}

</div>
`


/*
<div class="map-embed" style='position:absolute;height:600px;top:120px;width:700px;left:400px;'>

${bool}



</div>
<div class="map-embed" style='position:absolute;top:530px;left:400px;'>
${md ` #### Proposed Model`}
</div>
<div class="map-embed" style='position:absolute;height:500px;top:475px;width:700px;left:400px;'>
${chart}
</div>

<div class="treemap" style='position:absolute;top:140px;width:400px;left:1150px;'>
${treemapChart2}
</div>

<div class="treemap" style=position:absolute;top:600px;width:400px;left:1150px;'>
${treemapChart}
</div>
</div>
*/

//viewof sinkUgssbgage2 = Inputs.range([5, 15], {step: .5, label: "gafgf", value: 8}

Insert cell




<div class="input" style='position:absolute;top:73px;left:0px;font-family:helvetica'>

${md ` #### IAQ Modeling`}
${viewof energyCosts}
${viewof taoh}

</div>

<div class="results" style='position:absolute;left:0px;top:175px;margin-top:5px;font-family:helvetica;font-size:15px'>

${md `**Total Greenwall Area:**`}
${md ` ## ${(m2)} m2`}
${md ` `}
</div>
<div class="results" style='position:absolute;left:0px;top:275px;margin-top:5px;font-family:helvetica;font-size:15px'>
${md `**Annual Air Energy Savings** (ASHRAE MIN):`}
${md ` ## ${round((taoh*kwh0)-(taoh*kwh1))} kWh`}
</div>
<div class="results" style='position:absolute;left:0px;top:375px;margin-top:5px;font-family:helvetica;font-size:15px'>
${md `**Annual Air Energy Savings** (10X ASHRAE):`}
${md ` ## ${round((taoh*kwh10)-(taoh*kwh2))} kWh`}
</div>
<div class="results" style='position:absolute;left:0px;top:475px;margin-top:5px;font-family:helvetica;font-size:15px'>
${md `**Annual Air Energy Costs Savings** (ASHRAE MIN):`}
${md ` ## $${round(((taoh*kwh0)-(taoh*kwh1))*energyCosts)}`}
</div>
<div class="results" style='position:absolute;left:0px;top:575px;margin-top:5px;font-family:helvetica;font-size:15px'>
${md `**Annual Air Energy Costs Savings** (10X ASHRAE):`}
${md ` ## $${round(((taoh*kwh10)-(taoh*kwh2))*energyCosts)}`}


</div>




Insert cell
taoh1 = round(74900/10.764)
Insert cell
kwh0 = 205
Insert cell
kwh10=431
Insert cell
m2 ={
var value = 1

if(focus!=null){value=focus.m2}

return value
}
Insert cell
kwh1={
var value = 1

if(focus!=null){value=focus.kwh}

return value
}
Insert cell
kwh1*10000
Insert cell
kwh2={
var value = 0
if(kwh1==205){value = 431}
if(kwh1==203.7){value = 407.1}
if(kwh1==202.4){value = 383.2}
if(kwh1==201.1){value = 359.3}
if(kwh1==199.8){value = 339.4}
if(kwh1==198.5){value = 311.5}
if(kwh1==197.2){value = 287.6}
if(kwh1==195.9){value = 263.6}
if(kwh1==194.6){value = 240}
if(kwh1==193.3){value = 215}
if(kwh1==192){value = 282}


return value
}
Insert cell
number = {

return 5
}
Insert cell
number
Insert cell
viewof energyCosts = Inputs.range([.1, .2], {step: .01, label: "Energy Cost $/kWh", value: .15})
Insert cell
viewof taoh = Inputs.range([2000, 9000], {step: 5, label: "Total Area of Hotel m2", value: 74905/10.764})
Insert cell
waterDash = `<div class="input" style='position:absolute;top:55px;left:0px;font-family:helvetica'>

${md ` #### Spatial Scenario`}
${controls()[0]}
${controls()[1]}
${controls()[2]}


${viewof sinkUsage}
${viewof sinkVolume}
${viewof showerLength}
${viewof showerVolume}
${viewof radios}
${viewof graywater}
${viewof city}


</div>

<div class="results" style='position:absolute;left:0px;top:450px;font-family:helvetica'>

${md `#### Available Gray Water:`}
${md ` ## ${waterSavings} L/d`}
</div>
<div class="results" style='position:absolute;left:0px;top:550px;font-family:helvetica'>
${md `#### Total Required Planting Area (m^2):`}
${md ` ## ${round(waterSavings/graywater,0)} m^2`}
</div>





`


Insert cell
`<div class="map-embed" style='position:absolute;top:75px;left:400px;font-family:helvetica'>
${md ` #### Normative Model`}
</div>

<div class="map-embed" style='position:absolute;height:550px;top:100px;width:700px;left:400px;'>
${chart3}
</div>

<div class="map-embed" style='position:absolute;top:425px;left:400px;font-family:helvetica'>
${md ` #### Proposed Model`}
</div>

<div class="map-embed" style='position:absolute;height:600px;top:450px;width:700px;left:400px;'>
${chart}
</div>

<div class="treemap" style='position:absolute;top:100px;width:400px;left:1150px;'>
${treemapChart2}
</div>

<div class="treemap" style='position:absolute;top:450px;width:400px;left:1150px;'>
${treemapChart}
</div>

`

Insert cell


<div class="map-embed" style='position:absolute;top:75px;left:400px;font-family:helvetica'>
${md ` #### Baseline Case (ASHRAE minimum Outdoor Air Supply)`}
</div>

<div class="map-embed" style='position:absolute;top:425px;left:400px;font-family:helvetica'>
${md ` #### Parity Case (10x ASHRAE minimum Outdoor Air Supply)`}
</div>
<div class="map-embed" style='position:absolute;height:600px;top:60px;width:1200px;left:400px;'>


${chart1}

</div>




Insert cell
circleChart = {

const width2 = 360,
height2 = 500;
const svg2 = d3.create("svg")
.attr("height", '1400')
.attr("width", '330');
//.attr("viewBox", [0,0,width2,height2]);

svg2.selectAll("circle")
.data(icons) //get data to define path
.enter() //there are more data than elements, this selects them
.append("circle") //appends path to data
.attr('cx',function(d,i){return (d[0]*32)+15})
.attr('cy',function(d,i){return (d[1]*32)+25})
.attr('r','12')
.attr('fill','rgb(100,200,100)')
//.attr('stroke-width','1')
//.attr('stroke-dasharray','4,4')
//.attr('stroke','rgb(100,100,100)')

return svg2.node();
}
Insert cell
function controls(){

var rm = viewof rooms
if(city=="Dubai"){rm = viewof roomsDubai}
var flr = viewof floors
if(city=="Dubai"){flr = viewof floorsDubai}
var flu = viewof flush1
if(city=="Dubai"){flu = viewof flushDubai}


return [rm,flr,flu]
}
Insert cell
function chooseChart(){
var curChart = chart3
if(city=="New York"){return chart3}
if(city=="Dubai"){return chart4}

}
Insert cell
function chooseChart1(){
//var curChart = chart3
//if(city=="New York"){curChart = chart}
//if(city=="Dubai"){console.log('hellooo')
//return chart3}

///return curChart
return chart
}
Insert cell
html`
${viewof rooms}
${Inputs.bind(htl.html`<input type=number style="width: 80px;">`, viewof sinkUsage3)}
${Inputs.bind(htl.html`<input type=range style="width: 80px;">`, viewof sinkUsage3)}
`
Insert cell
viewof sinkUsage3 = Inputs.range([5, 15], {step: .5, label: "Sink Daily Use Time (Min)", value: 8})
Insert cell
function rounded(){
var number = round((waterSavings/graywater)/100,0)
var savings = []
for (let index = 0; index < number; ++index) {
var yval = 0
if(index>9){yval=1}
if(index>19){yval=2}
if(index>29){yval=3}
if(index>39){yval=4}
if(index>49){yval=5}
if(index>59){yval=6}
if(index>69){yval=7}
if(index>79){yval=8}
if(index>89){yval=9}
if(index>99){yval=10}
if(index>109){yval=11}
if(index>108){yval=12}
savings.push([index%10,yval])
//console.log('hello')
}
return savings
}
Insert cell
icons = rounded()
Insert cell
radios
Insert cell
sinkUsage3Copy = sinkUsage3
Insert cell
viewof floors2 = Inputs.range([10, 20], {step: 1, label: "Total Floors", value: 15})
Insert cell
//${Inputs.bind(htl.html`<input type=number min=8 max=15 style="width: 80px;">`, viewof sinkUsage3)}
//${Inputs.bind(htl.html`<input type=range style="width: 80px;">`, viewof sinkUsage3)}
//<label for="oi-ec050e-2">Hotel Occupants - Aera Dubai</label>
//<input type=number name=g min=0 max=255 step=1 value=127>
//<input type=range name=g min=0 max=255 step=1 value=127>
Insert cell
floors3 = floors2.valueOf()
Insert cell
chart4 = SankeyChart({
nodes: node4,
links: bond4
}, {
//nodeGroup: d => d.id.split(/\W/)[0], // take first word for color
nodeGroup: d => d.id,
nodeAlign, // e.g., d3.sankeyJustify; set by input above
linkColor, // e.g., "source" or "target"; set by input above
format: (f => d => `${f(d)} L/D`)(d3.format(",.1~f")),
//nodeTitle,
//linkColor:.50,
nodeStrokeWidth:1,
width,
height: 400
})
Insert cell
viewof roomsDubai = Inputs.range([3, 18], {step: 1, label: "Rooms per Floor", value:'11'})
Insert cell
viewof floorsDubai = Inputs.range([50, 80], {step: 1, label: "Total Floors", value: 69})
Insert cell
viewof flushDubai = Inputs.range([3, 18], {step: 1, label: "Flush Volume", value: 6})
Insert cell
viewof showersDubai = Inputs.radio(["1", "2", "3","4"], {label: "Shower Users", value: "4"})
Insert cell
flare = FileAttachment("flare-2.csv").csv({typed: true})
Insert cell
waterType = [{name:"water.Watering",size:watering},{name:"water.Remediated Water",size:remediated},{name:"water.Potable Water",size:potableTotal},{name:"water.Black Water",size:proposedBlack}]
Insert cell
treemapChart = Treemap(waterType, {
path: d => d.name.replace(/\./g, "/"), // e.g., "flare/animate/Easing"
value: d => d?.size, // size of each node (file); null for internal nodes (folders)
group: d => d.name.split(".")[1], // e.g., "animate" in "flare.animate.Easing"; for color
label: (d, n) => [...d.name.split(".").pop().split(/(?=[A-Z][a-z])/g), n.value.toLocaleString("en")].join("\n"),
title: (d, n) => `${d.name}\n${n.value.toLocaleString("en")}`, // text to show on hover
link: (d, n) => `https://github.com/prefuse/Flare/blob/master/flare/src${n.id}.as`,
//tile, // e.g., d3.treemapBinary; set by input above
width: 270,
height: 270
})
Insert cell
normativeWaterType = [{name:"water.Watering",size:normWatering},{name:"water.Gray Water",size:normGray},{name:"water.Potable Water",size:normPotable},{name:"water.Black Water",size:proposedBlack}]
Insert cell
treemapChart2 = Treemap(normativeWaterType, {
path: d => d.name.replace(/\./g, "/"), // e.g., "flare/animate/Easing"
value: d => d?.size, // size of each node (file); null for internal nodes (folders)
group: d => d.name.split(".")[1], // e.g., "animate" in "flare.animate.Easing"; for color
label: (d, n) => [...d.name.split(".").pop().split(/(?=[A-Z][a-z])/g), n.value.toLocaleString("en")].join("\n"),
title: (d, n) => `${d.name}\n${n.value.toLocaleString("en")}`, // text to show on hover
link: (d, n) => `https://github.com/prefuse/Flare/blob/master/flare/src${n.id}.as`,
//tile, // e.g., d3.treemapBinary; set by input above
width: 270,
height: 270
})
Insert cell
// Copyright 2021 Observable, Inc.
// Released under the ISC license.
// https://observablehq.com/@d3/treemap
function Treemap(data, { // data is either tabular (array of objects) or hierarchy (nested objects)
path, // as an alternative to id and parentId, returns an array identifier, imputing internal nodes
id = Array.isArray(data) ? d => d.id : null, // if tabular data, given a d in data, returns a unique identifier (string)
parentId = Array.isArray(data) ? d => d.parentId : null, // if tabular data, given a node d, returns its parent’s identifier
children, // if hierarchical data, given a d in data, returns its children
value, // given a node d, returns a quantitative value (for area encoding; null for count)
sort = (a, b) => d3.descending(a.value, b.value), // how to sort nodes prior to layout
label, // given a leaf node d, returns the name to display on the rectangle
group, // given a leaf node d, returns a categorical value (for color encoding)
title, // given a leaf node d, returns its hover text
link, // given a leaf node d, its link (if any)
linkTarget = "_blank", // the target attribute for links (if any)
tile = d3.treemapBinary, // treemap strategy
width = 640, // outer width, in pixels
height = 400, // outer height, in pixels
margin = 0, // shorthand for margins
marginTop = margin, // top margin, in pixels
marginRight = margin, // right margin, in pixels
marginBottom = margin, // bottom margin, in pixels
marginLeft = margin, // left margin, in pixels
padding = 1, // shorthand for inner and outer padding
paddingInner = padding, // to separate a node from its adjacent siblings
paddingOuter = padding, // shorthand for top, right, bottom, and left padding
paddingTop = paddingOuter, // to separate a node’s top edge from its children
paddingRight = paddingOuter, // to separate a node’s right edge from its children
paddingBottom = paddingOuter, // to separate a node’s bottom edge from its children
paddingLeft = paddingOuter, // to separate a node’s left edge from its children
round = true, // whether to round to exact pixels
colors = d3.schemeBlues[4], // array of colors
zDomain, // array of values for the color scale
fill = "#ccc", // fill for node rects (if no group color encoding)
fillOpacity = group == null ? null : 0.6, // fill opacity for node rects
stroke, // stroke for node rects
strokeWidth, // stroke width for node rects
strokeOpacity, // stroke opacity for node rects
strokeLinejoin, // stroke line join for node rects
} = {}) {

// If id and parentId options are specified, or the path option, use d3.stratify
// to convert tabular data to a hierarchy; otherwise we assume that the data is
// specified as an object {children} with nested objects (a.k.a. the “flare.json”
// format), and use d3.hierarchy.
const root = path != null ? d3.stratify().path(path)(data)
: id != null || parentId != null ? d3.stratify().id(id).parentId(parentId)(data)
: d3.hierarchy(data, children);

// Compute the values of internal nodes by aggregating from the leaves.
value == null ? root.count() : root.sum(d => Math.max(0, value(d)));

// Prior to sorting, if a group channel is specified, construct an ordinal color scale.
const leaves = root.leaves();
const G = group == null ? null : leaves.map(d => group(d.data, d));
if (zDomain === undefined) zDomain = G;
zDomain = new d3.InternSet(zDomain);
const color = group == null ? null : d3.scaleOrdinal(zDomain, colors);

// Compute labels and titles.
const L = label == null ? null : leaves.map(d => label(d.data, d));
const T = title === undefined ? L : title == null ? null : leaves.map(d => title(d.data, d));

// Sort the leaves (typically by descending value for a pleasing layout).
if (sort != null) root.sort(sort);

// Compute the treemap layout.
d3.treemap()
.tile(tile)
.size([width - marginLeft - marginRight, height - marginTop - marginBottom])
.paddingInner(paddingInner)
.paddingTop(paddingTop)
.paddingRight(paddingRight)
.paddingBottom(paddingBottom)
.paddingLeft(paddingLeft)
.round(round)
(root);

const svg = d3.create("svg")
.attr("viewBox", [-marginLeft, -marginTop, width, height])
.attr("width", width)
.attr("height", height)
.attr("style", "max-width: 100%; height: auto; height: intrinsic;")
.attr("font-family", "sans-serif")
.attr("font-size", 10);

const node = svg.selectAll("a")
.data(leaves)
.join("a")
.attr("xlink:href", link == null ? null : (d, i) => link(d.data, d))
.attr("target", link == null ? null : linkTarget)
.attr("transform", d => `translate(${d.x0},${d.y0})`);

node.append("rect")
.attr("fill", color ? (d, i) => color(G[i]) : fill)
.attr("fill-opacity", fillOpacity)
.attr("stroke", stroke)
.attr("stroke-width", strokeWidth)
.attr("stroke-opacity", strokeOpacity)
.attr("stroke-linejoin", strokeLinejoin)
.attr("width", d => d.x1 - d.x0)
.attr("height", d => d.y1 - d.y0);

if (T) {
node.append("title").text((d, i) => T[i]);
}

if (L) {
// A unique identifier for clip paths (to avoid conflicts).
const uid = `O-${Math.random().toString(16).slice(2)}`;

node.append("clipPath")
.attr("id", (d, i) => `${uid}-clip-${i}`)
.append("rect")
.attr("width", d => d.x1 - d.x0)
.attr("height", d => d.y1 - d.y0);

node.append("text")
.attr("clip-path", (d, i) => `url(${new URL(`#${uid}-clip-${i}`, location)})`)
.selectAll("tspan")
.data((d, i) => `${L[i]}`.split(/\n/g))
.join("tspan")
.attr("x", 3)
.attr("y", (d, i, D) => `${(i === D.length - 1) * 0.3 + 1.1 + i * 0.9}em`)
.attr("fill-opacity", (d, i, D) => i === D.length - 1 ? 0.7 : null)
.text(d => d);
}

return Object.assign(svg.node(), {scales: {color}});
}
Insert cell
import {Swatches} from "@d3/color-legend"
Insert cell
import {howto} from "@d3/example-components"
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more