-
+
-
-
+
-
+
function updateChartInner(g, x, y, linesGroup, color, line, data) {
- // Update axes with transitions
- x.domain(d3.extent(data, d => d.x));
- g.select(".x-axis").transition().duration(1500).call(d3.axisBottom(x).ticks(10));
- y.domain([0, d3.max(data, d => d.y)]);
- g.select(".y-axis").transition().duration(1500).call(d3.axisLeft(y).ticks(5));
-
- // Group data by basis function
- const dataByFunction = Array.from(d3.group(data, d => d.b));
- const keyFn = d => d[0];
-
- // Update basis function lines
- const u = linesGroup.selectAll("path").data(dataByFunction, keyFn);
- u.join(
- enter => enter.append("path").attr("fill","none").attr("stroke-width",3)
- .attr("stroke", (_, i) => color(i)).attr("d", d => line(d[1].map(pt => ({x: pt.x, y: 0}))))
- .style("opacity",0),
- update => update,
- exit => exit.transition().duration(1000).style("opacity",0).remove()
- )
- .transition().duration(1000)
- .attr("d", d => line(d[1]))
- .attr("stroke", (_, i) => color(i))
- .style("opacity",1);
-}
-
-chart = {
- // State variable for selected mu parameter
- let selectedMu = 1;
-
- const filteredData = () => cdf_data.filter(d =>
- Math.abs(selectedMu - d.mu) < 0.001
- );
-
- const container = d3.create("div")
- .style("max-width", "none")
- .style("width", "100%");
-
- const controlsContainer = container.append("div")
- .style("display", "flex")
- .style("gap", "20px")
- .style("align-items", "center");
-
- // Single slider control for mu
- const sliderContainer = controlsContainer.append('div')
- .style('display','flex')
- .style('align-items','center')
- .style('gap','10px')
- .style('flex','1');
-
- sliderContainer.append('label')
- .text('Naive:')
- .style('font-size','20px');
-
- const muSlider = sliderContainer.append('input')
- .attr('type','range')
- .attr('min', 0)
- .attr('max', 1)
- .attr('step', 0.1)
- .property('value', selectedMu)
- .on('input', function(event) {
- selectedMu = +this.value;
- muDisplay.text(selectedMu.toFixed(1));
- updateChart(filteredData());
- })
- .style('width', '100%')
- //.style('-webkit-appearance', 'none')
- .style('appearance', 'none')
- .style('height', '8px')
- .style('background', '#BDBDBDFF');
-
- const muDisplay = sliderContainer.append('span')
- .text(selectedMu.toFixed(1))
- .style('font-size','20px');
-
- // Add Reset button
- controlsContainer.append('button')
- .text('Reset')
- .style('font-size', '20px')
- .style('align-self', 'center')
- .style('margin-left', 'auto')
- .on('click', () => {
- selectedMu = 1;
- muSlider.property('value', selectedMu);
- muDisplay.text(selectedMu.toFixed(1));
- updateChart(filteredData());
- });
-
- // Build SVG
- const width = 600;
- const height = 450;
- const margin = {top: 40, right: 20, bottom: 40, left: 40};
- const innerWidth = width - margin.left - margin.right;
- const innerHeight = height - margin.top - margin.bottom;
-
- // Set controls container width to match SVG plot width
- controlsContainer.style("max-width", "none").style("width", "100%");
- // Distribute each control evenly and make sliders full-width
- controlsContainer.selectAll("div").style("flex", "1").style("min-width", "0px");
- controlsContainer.selectAll("input").style("width", "100%").style("box-sizing", "border-box");
+function updateChartInner(g, x, y, linesGroup, color, line, data) {
+ // Update axes with transitions
+ x.domain(d3.extent(data, d => d.x));
+ g.select(".x-axis").transition().duration(1500).call(d3.axisBottom(x).ticks(10));
+ y.domain([0, d3.max(data, d => d.y)]);
+ g.select(".y-axis").transition().duration(1500).call(d3.axisLeft(y).ticks(5));
+
+ // Group data by basis function
+ const dataByFunction = Array.from(d3.group(data, d => d.b));
+ const keyFn = d => d[0];
+
+ // Update basis function lines
+ const u = linesGroup.selectAll("path").data(dataByFunction, keyFn);
+ u.join(
+ enter => enter.append("path").attr("fill","none").attr("stroke-width",3)
+ .attr("stroke", (_, i) => color(i)).attr("d", d => line(d[1].map(pt => ({x: pt.x, y: 0}))))
+ .style("opacity",0),
+ update => update,
+ exit => exit.transition().duration(1000).style("opacity",0).remove()
+ )
+ .transition().duration(1000)
+ .attr("d", d => line(d[1]))
+ .attr("stroke", (_, i) => color(i))
+ .style("opacity",1);
+}
+
+chart = {
+ // State variable for selected mu parameter
+ let selectedMu = 1;
+
+ const filteredData = () => cdf_data.filter(d =>
+ Math.abs(selectedMu - d.mu) < 0.001
+ );
+
+ const container = d3.create("div")
+ .style("max-width", "none")
+ .style("width", "100%");
+
+ const controlsContainer = container.append("div")
+ .style("display", "flex")
+ .style("gap", "20px")
+ .style("align-items", "center");
+
+ // Single slider control for mu
+ const sliderContainer = controlsContainer.append('div')
+ .style('display','flex')
+ .style('align-items','center')
+ .style('gap','10px')
+ .style('flex','1');
+
+ sliderContainer.append('label')
+ .text('Naive:')
+ .style('font-size','20px');
+
+ const muSlider = sliderContainer.append('input')
+ .attr('type','range')
+ .attr('min', 0)
+ .attr('max', 1)
+ .attr('step', 0.1)
+ .property('value', selectedMu)
+ .on('input', function(event) {
+ selectedMu = +this.value;
+ muDisplay.text(selectedMu.toFixed(1));
+ updateChart(filteredData());
+ })
+ .style('width', '100%')
+ //.style('-webkit-appearance', 'none')
+ .style('appearance', 'none')
+ .style('height', '8px')
+ .style('background', '#BDBDBDFF');
+
+ const muDisplay = sliderContainer.append('span')
+ .text(selectedMu.toFixed(1))
+ .style('font-size','20px');
+
+ // Add Reset button
+ controlsContainer.append('button')
+ .text('Reset')
+ .style('font-size', '20px')
+ .style('align-self', 'center')
+ .style('margin-left', 'auto')
+ .on('click', () => {
+ selectedMu = 1;
+ muSlider.property('value', selectedMu);
+ muDisplay.text(selectedMu.toFixed(1));
+ updateChart(filteredData());
+ });
+
+ // Build SVG
+ const width = 600;
+ const height = 450;
+ const margin = {top: 40, right: 20, bottom: 40, left: 40};
+ const innerWidth = width - margin.left - margin.right;
+ const innerHeight = height - margin.top - margin.bottom;
+
+ // Set controls container width to match SVG plot width
+ controlsContainer.style("max-width", "none").style("width", "100%");
+ // Distribute each control evenly and make sliders full-width
+ controlsContainer.selectAll("div").style("flex", "1").style("min-width", "0px");
+ controlsContainer.selectAll("input").style("width", "100%").style("box-sizing", "border-box");
+
+ // Create scales
+ const x = d3.scaleLinear()
+ .range([0, innerWidth]);
+
+ const y = d3.scaleLinear()
+ .range([innerHeight, 0]);
+
+ // Create a color scale for the basis functions
+ const color = d3.scaleOrdinal(["#80C684FF", "#FFD44EFF", "#D81A5FFF"]);
+
+ // Create SVG
+ const svg = d3.create("svg")
+ .attr("width", "100%")
+ .attr("height", "auto")
+ .attr("viewBox", [0, 0, width, height])
+ .attr("preserveAspectRatio", "xMidYMid meet")
+ .attr("style", "max-width: 100%; height: auto;");
- // Create scales
- const x = d3.scaleLinear()
- .range([0, innerWidth]);
-
- const y = d3.scaleLinear()
- .range([innerHeight, 0]);
-
- // Create a color scale for the basis functions
- const color = d3.scaleOrdinal(["#80C684FF", "#FFD44EFF", "#D81A5FFF"]);
-
- // Create SVG
- const svg = d3.create("svg")
- .attr("width", "100%")
- .attr("height", "auto")
- .attr("viewBox", [0, 0, width, height])
- .attr("preserveAspectRatio", "xMidYMid meet")
- .attr("style", "max-width: 100%; height: auto;");
-
- // Create the chart group
- const g = svg.append("g")
- .attr("transform", `translate(${margin.left},${margin.top})`);
-
- // Add axes
- const xAxis = g.append("g")
- .attr("transform", `translate(0,${innerHeight})`)
- .attr("class", "x-axis")
- .call(d3.axisBottom(x).ticks(10))
- .style("font-size", "20px");
-
- const yAxis = g.append("g")
- .attr("class", "y-axis")
- .call(d3.axisLeft(y).ticks(5))
- .style("font-size", "20px");
-
- // Add a horizontal line at y = 0
- g.append("line")
- .attr("x1", 0)
- .attr("x2", innerWidth)
- .attr("y1", y(0))
- .attr("y2", y(0))
- .attr("stroke", "#000")
- .attr("stroke-opacity", 0.2);
-
- // Add gridlines
- g.append("g")
- .attr("class", "grid-lines")
- .selectAll("line")
- .data(y.ticks(5))
- .join("line")
- .attr("x1", 0)
- .attr("x2", innerWidth)
- .attr("y1", d => y(d))
- .attr("y2", d => y(d))
- .attr("stroke", "#ccc")
- .attr("stroke-opacity", 0.5);
+ // Create the chart group
+ const g = svg.append("g")
+ .attr("transform", `translate(${margin.left},${margin.top})`);
+
+ // Add axes
+ const xAxis = g.append("g")
+ .attr("transform", `translate(0,${innerHeight})`)
+ .attr("class", "x-axis")
+ .call(d3.axisBottom(x).ticks(10))
+ .style("font-size", "20px");
+
+ const yAxis = g.append("g")
+ .attr("class", "y-axis")
+ .call(d3.axisLeft(y).ticks(5))
+ .style("font-size", "20px");
+
+ // Add a horizontal line at y = 0
+ g.append("line")
+ .attr("x1", 0)
+ .attr("x2", innerWidth)
+ .attr("y1", y(0))
+ .attr("y2", y(0))
+ .attr("stroke", "#000")
+ .attr("stroke-opacity", 0.2);
+
+ // Add gridlines
+ g.append("g")
+ .attr("class", "grid-lines")
+ .selectAll("line")
+ .data(y.ticks(5))
+ .join("line")
+ .attr("x1", 0)
+ .attr("x2", innerWidth)
+ .attr("y1", d => y(d))
+ .attr("y2", d => y(d))
+ .attr("stroke", "#ccc")
+ .attr("stroke-opacity", 0.5);
+
+ // Create a line generator
+ const line = d3.line()
+ .x(d => x(d.x))
+ .y(d => y(d.y))
+ .curve(d3.curveBasis);
+
+ // Group to contain the basis function lines
+ const linesGroup = g.append("g")
+ .attr("class", "basis-functions");
+
+ // Store the current basis functions for transition
+ let currentBasisFunctions = new Map();
+
+ // Function to update the chart with new data
+ function updateChart(data) {
+ updateChartInner(g, x, y, linesGroup, color, line, data);
+ }
- // Create a line generator
- const line = d3.line()
- .x(d => x(d.x))
- .y(d => y(d.y))
- .curve(d3.curveBasis);
+ // Store the update function
+ svg.node().update = updateChart;
+
+ // Initial render
+ updateChart(filteredData());
- // Group to contain the basis function lines
- const linesGroup = g.append("g")
- .attr("class", "basis-functions");
-
- // Store the current basis functions for transition
- let currentBasisFunctions = new Map();
-
- // Function to update the chart with new data
- function updateChart(data) {
- updateChartInner(g, x, y, linesGroup, color, line, data);
- }
-
- // Store the update function
- svg.node().update = updateChart;
-
- // Initial render
- updateChart(filteredData());
-
- container.node().appendChild(svg.node());
- return container.node();
-}
+ container.node().appendChild(svg.node());
+ return container.node();
+}Â
@@ -26275,7 +26287,7 @@ w_{t,k}^{\text{Naive}} = \frac{1}{K}\label{eq:naive_combination}
@@ -26600,7 +26612,7 @@ w_{t,k}^{\text{smooth}} = \sum_{l=1}^L \beta_l \varphi_l = \beta'\varphi
-
Â
+Â
@@ -27220,7 +27232,7 @@ Y_{t} = \mu + Y_{t-1} + \varepsilon_t \quad \text{with} \quad \varepsilon_t = \
-
+
@@ -27228,194 +27240,194 @@ Y_{t} = \mu + Y_{t-1} + \varepsilon_t \quad \text{with} \quad \varepsilon_t = \
-
// Defined above
-// function updateChartInner(g, x, y, linesGroup, color, line, data) {
-// // Update axes with transitions
-// x.domain([0, d3.max(data, d => d.x)]);
-// g.select(".x-axis").transition().duration(1500).call(d3.axisBottom(x).ticks(10));
-// y.domain([0, d3.max(data, d => d.y)]);
-// g.select(".y-axis").transition().duration(1500).call(d3.axisLeft(y).ticks(5));
-
-// // Group data by basis function
-// const dataByFunction = Array.from(d3.group(data, d => d.b));
-// const keyFn = d => d[0];
-
-// // Update basis function lines
-// const u = linesGroup.selectAll("path").data(dataByFunction, keyFn);
-// u.join(
-// enter => enter.append("path").attr("fill","none").attr("stroke-width",3)
-// .attr("stroke", (_, i) => color(i)).attr("d", d => line(d[1].map(pt => ({x: pt.x, y: 0}))))
-// .style("opacity",0),
-// update => update,
-// exit => exit.transition().duration(1000).style("opacity",0).remove()
-// )
-// .transition().duration(1000)
-// .attr("d", d => line(d[1]))
-// .attr("stroke", (_, i) => color(i))
-// .style("opacity",1);
-// }
-
-chart0 = {
- // State variables for selected parameters
- let selectedMu = 0.5;
- let selectedSig = 1;
- let selectedNonc = 0;
- let selectedTailw = 1;
- const filteredData = () => bsplineData.filter(d =>
- Math.abs(selectedMu - d.mu) < 0.001 &&
- d.sig === selectedSig &&
- d.nonc === selectedNonc &&
- d.tailw === selectedTailw
- );
- const container = d3.create("div")
- .style("max-width", "none")
- .style("width", "100%");;
- const controlsContainer = container.append("div")
- .style("display", "flex")
- .style("gap", "20px");
- // slider controls
- const sliders = [
- { label: 'Mu', get: () => selectedMu, set: v => selectedMu = v, min: 0.1, max: 0.9, step: 0.2 },
- { label: 'Sigma', get: () => Math.log2(selectedSig), set: v => selectedSig = 2 ** v, min: -2, max: 2, step: 1 },
- { label: 'Noncentrality', get: () => selectedNonc, set: v => selectedNonc = v, min: -4, max: 4, step: 2 },
- { label: 'Tailweight', get: () => Math.log2(selectedTailw), set: v => selectedTailw = 2 ** v, min: -2, max: 2, step: 1 }
- ];
- // Build slider controls with D3 data join
- const sliderCont = controlsContainer.selectAll('div').data(sliders).join('div')
- .style('display','flex').style('align-items','center').style('gap','10px')
- .style('flex','1').style('min-width','0px');
- sliderCont.append('label').text(d => d.label + ':').style('font-size','20px');
- sliderCont.append('input')
- .attr('type','range').attr('min', d => d.min).attr('max', d => d.max).attr('step', d => d.step)
- .property('value', d => d.get())
- .on('input', function(event, d) {
- const val = +this.value; d.set(val);
- d3.select(this.parentNode).select('span').text(d.label.match(/Sigma|Tailweight/) ? 2**val : val);
- updateChart(filteredData());
- })
- .style('width', '100%');
- sliderCont.append('span').text(d => (d.label.match(/Sigma|Tailweight/) ? d.get() : d.get()))
- .style('font-size','20px');
-
- // Add Reset button to clear all sliders to their defaults
- controlsContainer.append('button')
- .text('Reset')
- .style('font-size', '20px')
- .style('align-self', 'center')
- .style('margin-left', 'auto')
- .on('click', () => {
- // reset state vars
- selectedMu = 0.5;
- selectedSig = 1;
- selectedNonc = 0;
- selectedTailw = 1;
- // update input positions
- sliderCont.selectAll('input').property('value', d => d.get());
- // update displayed labels
- sliderCont.selectAll('span')
- .text(d => d.label.match(/Sigma|Tailweight/) ? (2**d.get()) : d.get());
- // redraw chart
- updateChart(filteredData());
- });
-
- // Build SVG
- const width = 1200;
- const height = 450;
- const margin = {top: 40, right: 20, bottom: 40, left: 40};
- const innerWidth = width - margin.left - margin.right;
- const innerHeight = height - margin.top - margin.bottom;
-
- // Set controls container width to match SVG plot width
- controlsContainer.style("max-width", "none").style("width", "100%");
- // Distribute each control evenly and make sliders full-width
- controlsContainer.selectAll("div").style("flex", "1").style("min-width", "0px");
- controlsContainer.selectAll("input").style("width", "100%").style("box-sizing", "border-box");
-
- // Create scales
- const x = d3.scaleLinear()
- .domain([0, 1])
- .range([0, innerWidth]);
-
- const y = d3.scaleLinear()
- .domain([0, 1])
- .range([innerHeight, 0]);
-
- // Create a color scale for the basis functions
- const color = d3.scaleOrdinal(["#9B26B0FF", "#3F51B4FF", "#02A9F3FF", "#009687FF", "#8BC34AFF", "#FFEB3AFF", "#FF9800FF", "#795447FF"]);
-
- // Create SVG
- const svg = d3.create("svg")
- .attr("width", "100%")
- .attr("height", "auto")
- .attr("viewBox", [0, 0, width, height])
- .attr("preserveAspectRatio", "xMidYMid meet")
- .attr("style", "max-width: 100%; height: auto;");
-
- // Create the chart group
- const g = svg.append("g")
- .attr("transform", `translate(${margin.left},${margin.top})`);
-
- // Add axes
- const xAxis = g.append("g")
- .attr("transform", `translate(0,${innerHeight})`)
- .attr("class", "x-axis")
- .call(d3.axisBottom(x).ticks(10))
- .style("font-size", "20px");
-
- const yAxis = g.append("g")
- .attr("class", "y-axis")
- .call(d3.axisLeft(y).ticks(5))
- .style("font-size", "20px");
-
- // Add a horizontal line at y = 0
- g.append("line")
- .attr("x1", 0)
- .attr("x2", innerWidth)
- .attr("y1", y(0))
- .attr("y2", y(0))
- .attr("stroke", "#000")
- .attr("stroke-opacity", 0.2);
-
- // Add gridlines
- g.append("g")
- .attr("class", "grid-lines")
- .selectAll("line")
- .data(y.ticks(5))
- .join("line")
- .attr("x1", 0)
- .attr("x2", innerWidth)
- .attr("y1", d => y(d))
- .attr("y2", d => y(d))
- .attr("stroke", "#ccc")
- .attr("stroke-opacity", 0.5);
+// Defined above
+// function updateChartInner(g, x, y, linesGroup, color, line, data) {
+// // Update axes with transitions
+// x.domain([0, d3.max(data, d => d.x)]);
+// g.select(".x-axis").transition().duration(1500).call(d3.axisBottom(x).ticks(10));
+// y.domain([0, d3.max(data, d => d.y)]);
+// g.select(".y-axis").transition().duration(1500).call(d3.axisLeft(y).ticks(5));
+
+// // Group data by basis function
+// const dataByFunction = Array.from(d3.group(data, d => d.b));
+// const keyFn = d => d[0];
+
+// // Update basis function lines
+// const u = linesGroup.selectAll("path").data(dataByFunction, keyFn);
+// u.join(
+// enter => enter.append("path").attr("fill","none").attr("stroke-width",3)
+// .attr("stroke", (_, i) => color(i)).attr("d", d => line(d[1].map(pt => ({x: pt.x, y: 0}))))
+// .style("opacity",0),
+// update => update,
+// exit => exit.transition().duration(1000).style("opacity",0).remove()
+// )
+// .transition().duration(1000)
+// .attr("d", d => line(d[1]))
+// .attr("stroke", (_, i) => color(i))
+// .style("opacity",1);
+// }
+
+chart0 = {
+ // State variables for selected parameters
+ let selectedMu = 0.5;
+ let selectedSig = 1;
+ let selectedNonc = 0;
+ let selectedTailw = 1;
+ const filteredData = () => bsplineData.filter(d =>
+ Math.abs(selectedMu - d.mu) < 0.001 &&
+ d.sig === selectedSig &&
+ d.nonc === selectedNonc &&
+ d.tailw === selectedTailw
+ );
+ const container = d3.create("div")
+ .style("max-width", "none")
+ .style("width", "100%");;
+ const controlsContainer = container.append("div")
+ .style("display", "flex")
+ .style("gap", "20px");
+ // slider controls
+ const sliders = [
+ { label: 'Mu', get: () => selectedMu, set: v => selectedMu = v, min: 0.1, max: 0.9, step: 0.2 },
+ { label: 'Sigma', get: () => Math.log2(selectedSig), set: v => selectedSig = 2 ** v, min: -2, max: 2, step: 1 },
+ { label: 'Noncentrality', get: () => selectedNonc, set: v => selectedNonc = v, min: -4, max: 4, step: 2 },
+ { label: 'Tailweight', get: () => Math.log2(selectedTailw), set: v => selectedTailw = 2 ** v, min: -2, max: 2, step: 1 }
+ ];
+ // Build slider controls with D3 data join
+ const sliderCont = controlsContainer.selectAll('div').data(sliders).join('div')
+ .style('display','flex').style('align-items','center').style('gap','10px')
+ .style('flex','1').style('min-width','0px');
+ sliderCont.append('label').text(d => d.label + ':').style('font-size','20px');
+ sliderCont.append('input')
+ .attr('type','range').attr('min', d => d.min).attr('max', d => d.max).attr('step', d => d.step)
+ .property('value', d => d.get())
+ .on('input', function(event, d) {
+ const val = +this.value; d.set(val);
+ d3.select(this.parentNode).select('span').text(d.label.match(/Sigma|Tailweight/) ? 2**val : val);
+ updateChart(filteredData());
+ })
+ .style('width', '100%');
+ sliderCont.append('span').text(d => (d.label.match(/Sigma|Tailweight/) ? d.get() : d.get()))
+ .style('font-size','20px');
+
+ // Add Reset button to clear all sliders to their defaults
+ controlsContainer.append('button')
+ .text('Reset')
+ .style('font-size', '20px')
+ .style('align-self', 'center')
+ .style('margin-left', 'auto')
+ .on('click', () => {
+ // reset state vars
+ selectedMu = 0.5;
+ selectedSig = 1;
+ selectedNonc = 0;
+ selectedTailw = 1;
+ // update input positions
+ sliderCont.selectAll('input').property('value', d => d.get());
+ // update displayed labels
+ sliderCont.selectAll('span')
+ .text(d => d.label.match(/Sigma|Tailweight/) ? (2**d.get()) : d.get());
+ // redraw chart
+ updateChart(filteredData());
+ });
+
+ // Build SVG
+ const width = 1200;
+ const height = 450;
+ const margin = {top: 40, right: 20, bottom: 40, left: 40};
+ const innerWidth = width - margin.left - margin.right;
+ const innerHeight = height - margin.top - margin.bottom;
+
+ // Set controls container width to match SVG plot width
+ controlsContainer.style("max-width", "none").style("width", "100%");
+ // Distribute each control evenly and make sliders full-width
+ controlsContainer.selectAll("div").style("flex", "1").style("min-width", "0px");
+ controlsContainer.selectAll("input").style("width", "100%").style("box-sizing", "border-box");
+
+ // Create scales
+ const x = d3.scaleLinear()
+ .domain([0, 1])
+ .range([0, innerWidth]);
+
+ const y = d3.scaleLinear()
+ .domain([0, 1])
+ .range([innerHeight, 0]);
+
+ // Create a color scale for the basis functions
+ const color = d3.scaleOrdinal(["#9B26B0FF", "#3F51B4FF", "#02A9F3FF", "#009687FF", "#8BC34AFF", "#FFEB3AFF", "#FF9800FF", "#795447FF"]);
+
+ // Create SVG
+ const svg = d3.create("svg")
+ .attr("width", "100%")
+ .attr("height", "auto")
+ .attr("viewBox", [0, 0, width, height])
+ .attr("preserveAspectRatio", "xMidYMid meet")
+ .attr("style", "max-width: 100%; height: auto;");
+
+ // Create the chart group
+ const g = svg.append("g")
+ .attr("transform", `translate(${margin.left},${margin.top})`);
+
+ // Add axes
+ const xAxis = g.append("g")
+ .attr("transform", `translate(0,${innerHeight})`)
+ .attr("class", "x-axis")
+ .call(d3.axisBottom(x).ticks(10))
+ .style("font-size", "20px");
+
+ const yAxis = g.append("g")
+ .attr("class", "y-axis")
+ .call(d3.axisLeft(y).ticks(5))
+ .style("font-size", "20px");
+
+ // Add a horizontal line at y = 0
+ g.append("line")
+ .attr("x1", 0)
+ .attr("x2", innerWidth)
+ .attr("y1", y(0))
+ .attr("y2", y(0))
+ .attr("stroke", "#000")
+ .attr("stroke-opacity", 0.2);
+
+ // Add gridlines
+ g.append("g")
+ .attr("class", "grid-lines")
+ .selectAll("line")
+ .data(y.ticks(5))
+ .join("line")
+ .attr("x1", 0)
+ .attr("x2", innerWidth)
+ .attr("y1", d => y(d))
+ .attr("y2", d => y(d))
+ .attr("stroke", "#ccc")
+ .attr("stroke-opacity", 0.5);
+
+ // Create a line generator
+ const line = d3.line()
+ .x(d => x(d.x))
+ .y(d => y(d.y))
+ .curve(d3.curveBasis);
+
+ // Group to contain the basis function lines
+ const linesGroup = g.append("g")
+ .attr("class", "basis-functions");
+
+ // Store the current basis functions for transition
+ let currentBasisFunctions = new Map();
+
+ // Function to update the chart with new data
+ function updateChart(data) {
+ updateChartInner(g, x, y, linesGroup, color, line, data);
+ }
- // Create a line generator
- const line = d3.line()
- .x(d => x(d.x))
- .y(d => y(d.y))
- .curve(d3.curveBasis);
+ // Store the update function
+ svg.node().update = updateChart;
+
+ // Initial render
+ updateChart(filteredData());
- // Group to contain the basis function lines
- const linesGroup = g.append("g")
- .attr("class", "basis-functions");
-
- // Store the current basis functions for transition
- let currentBasisFunctions = new Map();
-
- // Function to update the chart with new data
- function updateChart(data) {
- updateChartInner(g, x, y, linesGroup, color, line, data);
- }
-
- // Store the update function
- svg.node().update = updateChart;
-
- // Initial render
- updateChart(filteredData());
-
- container.node().appendChild(svg.node());
- return container.node();
-}
+ container.node().appendChild(svg.node());
+ return container.node();
+}
diff --git a/index.qmd b/index.qmd
index 9b441c0..2ffa3ee 100644
--- a/index.qmd
+++ b/index.qmd
@@ -36,12 +36,9 @@ revealjs-plugins:
# - drop
---
-# High-Level View {.center visibility="uncounted"}
+## The beginning: June 2020 {visibility="uncounted"}
-
-
+](assets/allisonhorst/the_beginning_cropped.png)
::: {.hidden}
$$
@@ -49,21 +46,6 @@ $$
$$
:::
-
-
-
```{r, setup, include=FALSE}
# Compile with: rmarkdown::render("crps_learning.Rmd")
library(latex2exp)
@@ -97,9 +79,9 @@ col_orange <- "#ffa600"
col_yellow <- "#FCE135"
```
-## The beginning: June 2020
+## {.placeholder-for-titleSlide}
-](assets/allisonhorst/the_beginning_cropped.png)
+# High-Level View {.center visibility="uncounted"}
## Motivation