Skip to content

Commit

Permalink
Added variable chooser for lda:
Browse files Browse the repository at this point in the history
  • Loading branch information
andresnowak committed Dec 20, 2024
1 parent be80299 commit 1241b42
Showing 6 changed files with 377 additions and 138 deletions.
237 changes: 117 additions & 120 deletions app/bubble_chart.js
Original file line number Diff line number Diff line change
@@ -1,130 +1,127 @@
"use client";

import dynamic from "next/dynamic";
const Plot = dynamic(() => import("react-plotly.js"), { ssr: false });
import { useEffect, useRef, useState } from "react";
import Papa from "papaparse";
import { useEffect, useState } from "react";
import {
Chart,
BubbleController,
LinearScale,
Title,
Tooltip,
Legend,
PointElement,
} from "chart.js";

function BubbleChart({ datapath, colors }) {
const [bubbleData, setBubbleData] = useState([]);
const [years, setYears] = useState([]);
const [columns, setColumns] = useState([]);
Chart.register(
BubbleController,
LinearScale,
Title,
Tooltip,
Legend,
PointElement
);

useEffect(() => {
fetch(datapath)
.then((res) => res.text())
.then((csv) => {
Papa.parse(csv, {
complete: (result) => {
const header = result.data[0].map((c) => c.trim());
const rows = result.data.slice(1).map((r) => r.map((c) => c.trim()));
const uniqueYears = [...new Set(rows.map((r) => r[0]))];
const traces = uniqueYears.map((year) => {
const yearData = rows.filter((row) => row[0] === year);
return {
name: year,
x: yearData.map((d) => parseFloat(d[1])),
y: yearData.map((d) => parseFloat(d[2])),
text: yearData.map((d) => d[3]),
mode: "markers",
marker: {
size: yearData.map((d) => parseFloat(d[4])),
color: colors,
sizemode: "area",
},
};
});
setColumns(header);
setYears(uniqueYears);
setBubbleData(traces);
},
});
})
.catch((err) => console.error("CSV load error:", err));
}, [datapath, colors]);
function BubbleChart() {
const chartRef = useRef(null);

// Each frame corresponds to one year
const frames = bubbleData.map((trace) => ({
name: trace.name,
data: [trace],
}));
useEffect(() => {
const ctx = chartRef.current.getContext("2d");

// Create slider steps for each year
const sliderSteps = bubbleData.map((trace, i) => ({
label: trace.name,
method: "animate",
args: [
[trace.name],
{
mode: "immediate",
transition: { duration: 500 },
frame: { duration: 500, redraw: false },
},
],
}));
new Chart(ctx, {
type: "bubble",
data: {
labels: "Africa",
datasets: [
{
label: ["China"],
backgroundColor: "rgba(255,221,50,0.2)",
borderColor: "rgba(255,221,50,1)",
data: [
{
x: 21269017,
y: 5.245,
r: 9,
},
],
},
{
label: ["Denmark"],
backgroundColor: "rgba(60,186,159,0.2)",
borderColor: "rgba(60,186,159,1)",
data: [
{
x: 258702,
y: 7.526,
r: 10,
},
],
},
{
label: ["Germany"],
backgroundColor: "rgba(0,0,0,0.2)",
borderColor: "#000",
data: [
{
x: 3979083,
y: 6.994,
r: 80,
},
],
},
{
label: ["Japan"],
backgroundColor: "rgba(193,46,12,0.2)",
borderColor: "rgba(193,46,12,1)",
data: [
{
x: 4931877,
y: 5.921,
r: 15,
},
],
},
],
},
options: {
title: {
display: true,
text: "Predicted world population (millions) in 2050",
},
scales: {
y: {
title: {
display: true,
text: "Happiness",
},
},
x: {
title: {
display: true,
text: "GDP (PPP)",
},
},
},
},
});

const layout = {
title: "Animated Bubble Chart",
xaxis: { title: columns[1] },
yaxis: { title: columns[2] },
showlegend: false,
updatemenus: [
{
type: "buttons",
x: 0.1,
y: 1.15,
xanchor: "left",
yanchor: "top",
showactive: false,
buttons: [
{
label: "Play",
method: "animate",
args: [
null,
{
fromcurrent: true,
frame: { duration: 500, redraw: false },
transition: { duration: 500 },
},
],
},
{
label: "Pause",
method: "animate",
args: [
[null],
{
mode: "immediate",
frame: { duration: 0, redraw: false },
},
],
},
],
},
],
sliders: [
{
active: 0,
steps: sliderSteps,
x: 0.1,
y: 0,
len: 0.9,
},
],
};
// Cleanup function to destroy the chart instance
return () => {
if (ctx) {
ctx.chart && ctx.chart.destroy();
}
};
}, []);

return (
<div className="w-full max-w-2xl">
<Plot
data={[bubbleData[0]]}
layout={layout}
frames={frames}
config={{ scrollZoom: false }}
style={{ width: "100%", height: "600px" }}
/>
</div>
);
}
return (
<div className="w-full max-w-2xl">
<canvas
id="bubble-chart"
ref={chartRef}
width={800}
height={800}
></canvas>
</div>
);
};

export { BubbleChart };
export { BubbleChart };
2 changes: 1 addition & 1 deletion app/iframe_charts.js
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@ const IframeChart = ({ src }) => {
console.log("IframeChart component mounted with datapath:", src);
return (
<div style={{ height: '900px', width: "100%", display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
<div style={{ width: '90%', height: '100%' }}>
<div style={{ width: '100%', height: '100%' }}>
<iframe
src={src}
style={{ border: 'none', width: '100%', height: '100%' }}
74 changes: 63 additions & 11 deletions app/page.js
Original file line number Diff line number Diff line change
@@ -57,6 +57,40 @@ function VariableChooserComponent({ Title, variables, children }) {
);
}

function VariableChooserComponentLDA({ Title, variables, children }) {
const [selectedVariable, setSelectedVariable] = useState(
variables[0].datapath
);

const handleChange = (e) => {
setSelectedVariable(e.target.value);
};

return (
<div className="flex justify-center w-full max-w-7xl align-center flex-col">
<h3 className="text-2xl font-bold mb-2 text-center">{Title}</h3>
{variables.length > 1 && (
<select
value={selectedVariable}
onChange={handleChange}
className="p-2 border border-gray-300 rounded-md"
>
{variables.map((variable, index) => (
<option key={index} value={variable.datapath}>
{variable.name}
</option>
))}
</select>
)}
<div className="flex justify-center w-full align-center flex-col">
{children(selectedVariable)}
</div>
</div>
);
}



export default function Home() {
return (
<>
@@ -193,15 +227,32 @@ export default function Home() {
/>
)}
</VariableChooserComponent>
<div className="flex justify-center w-full align-center flex-col">
<h3 className="text-2xl font-bold mb-2 text-center p-4">
Topic modeling LDA
</h3>
<IframeChart
title="Iframe Chart"
src="lda_world_cup_football.html"
/>
</div>
<VariableChooserComponentLDA
Title="Topic modeling LDA"
variables={[
{
datapath: "lda_world_cup_football.html",
name: "LDA World Cup Football",
},
{
datapath: "lda_olympics.html",
name: "LDA Olympics",
},
{
datapath: "lda_nba.html",
name: "LDA NBA",
},
]}
>

{(variable) => (
<IframeChart
src={variable}
loading={<LoadingSpinner />}
/>
)}

</VariableChooserComponentLDA>
<VariableChooserComponent
Title="Line plot of delta view"
variables={[
@@ -241,14 +292,15 @@ export default function Home() {
Title="Line plot of delta view"
variables={[
{
datapath: "bubble_data.csv",
datapath: "data/bubble_data.csv",
name: "Bubble Chart",
},
]}
>
{(variable) => (
<BubbleChart
datapath={variable}
dataPath={variable}
colors={["#165B33"]}
loading={<LoadingSpinner />}
/>
)}
95 changes: 95 additions & 0 deletions public/lda_nba.html

Large diffs are not rendered by default.

Loading

0 comments on commit 1241b42

Please sign in to comment.