Public
Edited
Jun 22, 2022
1 star
Insert cell
Insert cell
ind = dates.indexOf(time1)
Insert cell
<style>
/* match the scrubber's width to our race chart */
/* input[type="range"][name="i"] {
width: ${width-90}px !important;
} */
</style>
Insert cell
style = html`
<style>
.button {
color:lightgrey;
border: 0;
background: transparent;
box-sizing: border-box;
width: 100;
height: 74px;
border-color: transparent transparent transparent lightgrey;
transition: 100ms all ease;
cursor: pointer;
border-style: solid;
border-width: 37px 0 37px 60px;
}
.paused {
border-style: double;
border-width: 0px 0 0px 60px;
}
.button:hover {
border-color: transparent transparent transparent #404040;
}
input{
accent-color:white
}

</style>
`
Insert cell
test === null
Insert cell
test = null
Insert cell
today = d3.timeDay.offset(d3.utcDay(), -2) //d3.utcDay()
Insert cell
start = d3.timeDay.offset(today, -365)
Insert cell
textures = require("textures@1.2.0/dist/textures.js")
Insert cell
Insert cell
Insert cell
limitsDelayed = {
await Promises.delay(1500, ""); // delay returning
return limits;
}
Insert cell
limits
Insert cell
viewof limits = {
// document.querySelector('[name="b"]').disabled = true;
return brushFilterX(d3.extent(dates), {
defaultExtent: [start, d3.timeDay.offset(today, -1)]
});
}
Insert cell
Insert cell
(1 * 21) / 200
Insert cell
ns = Inputs.text().classList[0]
Insert cell
viewof colorView = Inputs.radio(["Anomaly", "Heatwaves"], {
value: "Anomaly",
format: (x) => html`<span style="color: white">${x}`
})
Insert cell
colorView
Insert cell
datesToPlot = datesCopy.filter(
(d) => d >= limitsDelayed[0] && d <= limitsDelayed[1]
)
Insert cell
// d3.timeDay.offset(limits[1], 1)
Insert cell
Insert cell
datesCopy = [...dates]
Insert cell
dateExtent = [new Date("2013-01-01"), new Date()] //d3.extent(HWStatus, (d) => new Date(d.date_start1))
Insert cell
Insert cell
Math.min(755, width - 1)
Insert cell
viewof time1 = Scrubber(datesToPlot, {
width: 0,
delay: 100,
autoplay: false,
loop: false,
format: (d) => ""
})
Insert cell
limits
Insert cell
curDate = md`# ${textcolor(timeFormat(new Date(time1)), "black")}`
Insert cell
leg = {
return colorView === "Anomaly"
? Plot.legend({
marginLeft: 10,
marginRight: 10,

style: {
backgroundColor: "#000000",
color: "#e0f5ee",
fontSize: "16px",
fontWeight: "normal"
},
color: {
type: "diverging",
domain: [-4, 4],
pivot: 0,
reverse: true,
legend: true,
label: "SSTA (°C) →"
}
})
: Plot.legend({
color: {
type: "categorical",
domain: ["Moderate", "Strong", "Severe", "Extreme"],
range: ["#FEDB67", "#f26722", "#cd3728", "#7E1416"] // use the "accent" scheme
},
style: {
backgroundColor: "#000000",
color: "#e0f5ee",
fontSize: "16px",
fontWeight: "normal"
}
});
}
Insert cell
Plot.legend({
style: {
fontSize: "16px",
backgroundColor: "#000000",
color: "#e0f5ee"
},
color: {
type: "categorical",
domain: ["Moderate", "Strong", "Severe", "Extreme"],
range: ["#FEDB67", "#f26722", "#cd3728", "#7E1416"] // use the "accent" scheme
}
})
Insert cell
// new Date(time1)
Insert cell
mutable siteClicked = 8
Insert cell
viewof lineChart = {
const HWlineChart = Plot.plot({
style: {
backgroundColor: "#000000",
color: "#e0f5ee",

// fontFamily: "system-ui",
fontSize: 20
// title: "stuff"
// overflow: "visible"
},
// height: "auto",
// height: 400,
marginTop: 50,
className: "hwclass",

marks: [
Plot.line(clickedSite, {
x: "date",
y: "sst",
stroke: colors.get("sst"),

curve: "step",
strokeWidth: 2
}),
Plot.line(clickedSite, {
x: "date",
y: "thresh",
stroke: colors.get("thresh"),
opacity: 0.7,
// curve: "step",
strokeWidth: 2
}),
Plot.line(clickedSite, {
x: "date",
y: "seas",
stroke: colors.get("seas"),
opacity: 0.7,
// curve: "step",
strokeWidth: 2
}),
Plot.areaY(clickedSite, {
x: "date",
y1: "thresh",
y2: "diff",
sort: "date",
curve: "step",
fill: colors.get("moderate")
}),

Plot.areaY(clickedSite, {
x: "date",
y1: "thresh",
y2: "diffStrong",
sort: "date",
curve: "step",
fill: colors.get("Strong")
}),
Plot.areaY(clickedSite, {
x: "date",
y1: "thresh",
y2: "diffExtreme",
sort: "date",
curve: "step",
fill: colors.get("Extreme")
}),

Plot.areaY(clickedSite, {
x: "date",
y1: "thresh",
y2: "diffSevere",
sort: "date",
curve: "step",
fill: colors.get("Severe")
}),

// rule at bottom of chart marking y=0;
Plot.ruleY([0]),

// vertical rule to mark date/time of event
Plot.ruleX([time1], {
stroke: "gray",
y1: 0,
y2: d3.max(clickedSite, (d) => d.sst)
}),
Plot.text(
[
{
x: dateForLabel,
y: yValueForLabel,
text: buoyClicked
}
],
{
x: "x",
y: "y",
text: "text",
fontSize: 24
}
)
],

color: {
domain: ["above", "below", "avg", "thresh"],
range: [
colors.get("above"),
colors.get("below"),
colors.get("actuals"),
colors.get("forecast")
]
// legend: true
},
y: {
label: "↑ (°C)"
},

marginLeft: 60,
width: 500,
height: 300
});

const SSTAlineChart = Plot.plot({
x: {
domain: [limitsDelayed[0], limitsDelayed[1]]
},
y: {
label: "↑ SST (°C)",
domain: [0, yMaxDomainToUse]
},
style: {
backgroundColor: "#000000",
color: "#e0f5ee",
// fontFamily: "system-ui",
fontSize: 20
// overflow: "visible"
},
height: 500,
marginTop: 50,
className: "hwclass",
// y: {
// nice: true
// },
// x: {
// nice: true
// },
marks: [
Plot.dot(clickedSite, {
x: "date",
y: "sst",
stroke: "ssta",
fill: "ssta"
}),
Plot.line(clickedSite, {
x: "date",
y: "sst",
stroke: "#ccc",
curve: "step",
strokeWidth: 0.5
}),
// vertical rule to mark date/time of event
Plot.ruleX([time1], {
stroke: "white",
y1: 0,
y2: d3.max(clickedSite, (d) => d.sst)
}),
Plot.text(
[
{
x: dateForLabel,
y: yValueForLabel,
text: buoyClicked
}
],
{
x: "x",
y: "y",
text: "text",
fontSize: 24
}
)
],
color: {
type: "diverging",
domain: [-4, 4],
pivot: 0,
reverse: true
// legend: true,
// label: "SSTA (°C) →"
},

width: 500,
height: 300
// marginBottom: 70,
// label: buoyClicked
// title: "some stie"
});
if (siteClicked !== null) {
return colorView === "Anomaly" ? SSTAlineChart : HWlineChart;
} else {
return md``;
}
}
Insert cell
width
Insert cell
clickedSite.length
Insert cell
d3.max(clickedSite, (d) => d.sst) * 1.1
Insert cell
Insert cell
buoys
Insert cell
yMaxDomainToUse = {
return clickedSite[Math.floor(clickedSite.length / 1.2)] === undefined ?
18 : d3.max(clickedSite, (d) => d.sst) * 1.1
}
Insert cell
yValueForLabel = {
return clickedSite[Math.floor(clickedSite.length / 1.2)] === undefined
? 18
: d3.max(clickedSite, (d) => d.sst) * 1.1;
}
Insert cell
dateForLabel = {
return clickedSite[Math.floor(clickedSite.length / 1.2)] === undefined
? d3.timeDay.offset(limitsDelayed[0], 30)
: clickedSite[Math.floor(clickedSite.length * 0.2)].date;
}
Insert cell
Math.floor(clickedSite.length * 0.1)
Insert cell
buoyClicked = buoys.find((d) => d.pk === siteClicked).long_name
Insert cell
Insert cell
viewof table = Inputs.table(clickedSite, {})
Insert cell
clickedSite = buoyDailyData.filter((d) => d.station === siteClicked)
Insert cell
sstaColors = d3.scaleSequential(d3.interpolateRdBu).domain([4, -4])
Insert cell
coloursForSSTA = clickedSite.map((d) => sstaColors(d.ssta))
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
r = "mapbox://styles/hakai/ckwpei0yq08cj15nthgd4ql45" //"mapbox://styles/hakai/ckwuxmze164c314pe8hs0s1on" //"mapbox://styles/hakai/ckwpei0yq08cj15nthgd4ql45" //"mapbox://styles/mapbox/dark-v10" //mapbox://styles/hakai/ckwp8ahbx2u0w15o5zwx3odtn"
Insert cell
Insert cell
Type JavaScript, then Shift-Enter. Ctrl-space for more options. Arrow ↑/↓ to switch modes.

Insert cell
Insert cell
buoyDailyData
Insert cell
// selected = hexbyLocation.get(
// map.selected ? map.selected.data.lng + "|" + map.selected.data.lat : ""
// ) || []
Insert cell
// hexbyLocation = d3.group(hex, (d) => d.lng + "|" + d.lat)
Insert cell
// HWStatus.filter((d) => d.station === "7")
Insert cell
new Date(time1).toISOString().substring(0, 10) === "2021-01-01"
Insert cell
HWsForDate = buoyDailyData.filter(
(d) =>
new Date(time1).toISOString().substring(0, 10) ===
new Date(d.result_time).toISOString().substring(0, 10)
)
Insert cell
buoyDailyData.filter((d) => d.category === "Strong")
Insert cell
new Date(dateExtent[1])
Insert cell
center = projection.invert([width/2, height/2])
Insert cell
metersToPixelsAtMaxZoom = (meters, latitude) =>
meters / 0.075 / Math.cos(latitude * Math.PI / 180)
Insert cell
limits[0]
Insert cell
dayBeforeStart = {
const b = Object.assign(limits[0]);
const fistDate = new Date(b);

return new Date(fistDate.setDate(fistDate.getDate() - 1))
.toISOString()
.substring(0, 10);
}
Insert cell
limits[0]
Insert cell
// buoyDailyData = {
// const buoyDailyData = await FileAttachment(
// "buoysHWStatusDaily-2.json"
// ).json();
// buoyDailyData.forEach((d) => {
// d.ssta = d.sst - d.seas;
// d.diffStrong = d.thresh;
// d.diffExtreme = d.thresh;
// d.diffSevere = d.thresh;
// if (d.category === "Strong") {
// d.diffStrong = Math.max(d.thresh, d.sst);
// }
// if (d.category === "Extreme") {
// d.diffExtreme = Math.max(d.thresh, d.sst);
// }
// if (d.category === "Severe") {
// d.diffSevere = Math.max(d.thresh, d.sst);
// }
// d.diff = Math.max(d.thresh, d.sst);
// d.date = new Date(d.result_time);
// });
// let outdate = buoyDailyData.filter(
// (d) =>
// new Date(limits[0].toISOString().substring(0, 10)) <= d.date &&
// new Date(limits[1].toISOString().substring(0, 10)) >= d.date
// );
// return outdate;
// }
Insert cell
limits
Insert cell
dayBeforeStart
Insert cell
buoyDailyData = {
// let daysago = new Date().getDate() - 7;
// let st = new Date(new Date().setDate(daysago));

return fetch(
"https://t6r95rekqe.execute-api.us-east-1.amazonaws.com/dev/getDailySSTStats?startDate=" +
dayBeforeStart +
"&endDate=" +
limitsDelayed[1].toISOString().substring(0, 10) +
""
)
.then((resp) => resp.json())
.then((data) => {
data.forEach((d) => {
d.ssta = d.sst - d.seas;
d.diff = d.thresh;
d.diffStrong = d.thresh;
d.diffExtreme = d.thresh;
d.diffSevere = d.thresh;
if (d.category === "Strong") {
d.diffStrong = Math.max(d.thresh, d.sst);
}
if (d.category === "Extreme") {
d.diffExtreme = Math.max(d.thresh, d.sst);
}
if (d.category === "Severe") {
d.diffSevere = Math.max(d.thresh, d.sst);
}
if (d.category === "Moderate") {
d.diff = Math.max(d.thresh, d.sst);
}
// d.diff = Math.max(d.thresh, d.sst);
d.date = new Date(d.result_time);
});
return data;
});
}
Insert cell
// dateExtent[0].toISOString().substring(0, 10)
Insert cell
// updateMapbox = {
// // This allows us to update the map with data without re-rendering the whole cell
// // There is a bit of weirdness around adding and removing the layer to make sure mapbox rerenders
// let fc = {
// type: "FeatureCollection",
// features: hexgeo
// };
// if (map._loaded) {
// if (!map.getSource("hexbins")) {
// map.addSource("hexbins", {
// type: "geojson",
// data: fc
// });
// } else {
// // console.log("setting source")
// map.getSource("hexbins").setData(fc);
// }
// if (map.getLayer(hexbinLayer.id)) {
// map.removeLayer(hexbinLayer.id);
// }
// // console.log("adding layer")
// map.addLayer(hexbinLayer);
// // map.flyTo(projection.invert([100,1000]))
// // console.log("flying")
// // }
// return true;
// }
// return false;
// }
Insert cell
// map._loaded
Insert cell
// map.getSource("hexbins")
Insert cell
// import {california, countyShapes} with {height as height, hexbin as hexbin} from "@enjalot/air-quality-explorations"
Insert cell
originalScale = 25355.18980109889
Insert cell
scaleRatio = projection.scale() / originalScale
Insert cell
widthRatio = width / 955
Insert cell
heightRatio = height / 500
Insert cell
projection = d3
.geoAlbers()
.rotate([126, 0])
.fitSize(
[width, height],
topojson.feature(BC_Midres, BC_Midres.objects.BC_Midres_latlng)
)
Insert cell
pixelRadius = 100 * scaleRatio * d3.min([widthRatio, heightRatio])
Insert cell
hexbin = d3
.hexbin()
.extent([
[0, 0],
[width, height]
])
.radius(100)
Insert cell
numOfDates = d3.timeDay.count(...dateExtent)
Insert cell
height = 500
Insert cell
colorMHW = d3
.scaleOrdinal()
.domain(["none", "Moderate", "Strong", "Extreme", "Severe"])
.range(["#31a354", "#FEDB67", "#f26722", "#7E1416", "#cd3728"])
Insert cell
opacityMHW("none")
Insert cell
opacityMHW = d3
.scaleOrdinal()
.domain(["none", "Moderate", "Strong", "Extreme", "Severe"])
// .range([0.9, 0.9, 0.9, 0.9, 0.9])
Insert cell
colorPM1 = d3.scaleLinear()
.domain([0,50, 100, 150, 200, 250])
.range(["green", "yellow", "orange", "red", "maroon", "maroon"])
Insert cell
opacityPM1 = d3.scaleLinear()
.domain([0,50, 100, 150, 200, 250])
.range([0.1, 0.5, 0.9, 0.9, 0.9, 0.9])
Insert cell
colorP03 = d3.scaleLinear()
.domain([1,1000, 5000, 10000, 20000, 25000])
.range(["green", "yellow", "orange", "red", "maroon", "maroon"])
Insert cell
opacityP03 = d3
.scaleLinear()
.domain([1, 1000, 5000, 10000, 20000, 25000])
.range([0.1, 0.75, 0.75, 0.9, 0.9, 0.9])
Insert cell
numFormat = d3.format(",d")
Insert cell
timeFormat = d3.timeFormat("%Y-%m-%d")
Insert cell
import { Scrubber } from "@mbrownshoes/stylized-scrubber"
Insert cell
import {legend} from "@d3/color-legend"
Insert cell
import { BC_Midres } from "@mbrownshoes/how-i-start-maps-in-d3"
Insert cell
d3 = require("d3@6.0.0-rc.3", "d3-hexbin@0.2")
Insert cell
// token = "pk.eyJ1IjoiaGFrYWkiLCJhIjoiY2lyNTcwYzY5MDAwZWc3bm5ubTdzOWtzaiJ9.6QhxH6sQEgK634qO7a8MoQ"
Insert cell
// mapboxgl = {
// const gl = await require("mapbox-gl");
// if (!gl.accessToken) {
// gl.accessToken =
// "pk.eyJ1IjoiaGFrYWkiLCJhIjoiY2lyNTcwYzY5MDAwZWc3bm5ubTdzOWtzaiJ9.6QhxH6sQEgK634qO7a8MoQ";
// const href = await require.resolve("mapbox-gl/dist/mapbox-gl.css");
// document.head.appendChild(html`<link href=${href} rel=stylesheet>`);
// }
// return gl;
// }
Insert cell
import { textcolor } from "@observablehq/text-color-annotations-in-markdown"
Insert cell
Insert cell
alldates = d3.timeMonth
.range(new Date(dateExtent[0]), new Date(dateExtent[1]))
.map((d) => d.toISOString().substring(0, 10))
Insert cell
// import { brushFilterX } from "921d584bd92a9817"
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