Skip to content

Commit 5d2c7c5

Browse files
committed
heatmaps real vs synth
1 parent 5740966 commit 5d2c7c5

File tree

5 files changed

+129
-16
lines changed

5 files changed

+129
-16
lines changed

src/assets/synthetic-data.tsx

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -619,11 +619,15 @@ def run():
619619
setResult(json.dumps({'type': 'table', 'data': synthetic_data.head().to_json(orient="records")}))
620620
621621
np.random.seed(42)
622-
heatmap = np.random.rand(100, 10)
622+
# heatmap = np.random.rand(100, 10)
623623
624-
# Compute the correlation matrix
625-
correlation_matrix = np.corrcoef(heatmap, rowvar=False)
626-
setResult(json.dumps({'type': 'heatmap', 'data': correlation_matrix.tolist()}))
624+
# Compute the (test) correlation matrix
625+
# correlation_matrix = np.corrcoef(heatmap, rowvar=False)
626+
# setResult(json.dumps({'type': 'heatmap', 'data': correlation_matrix.tolist()}))
627+
628+
setResult(json.dumps({'type': 'heatmap', 'real': real_data.corr().to_json(orient="records"), 'synthetic': synthetic_data.corr().to_json(orient="records")}))
629+
630+
# setResult(json.dumps({'type': 'heatmap', 'data': synthetic_data.corr().to_json(orient="records")}))
627631
return
628632
629633

src/components/componentMapper.tsx

Lines changed: 87 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,50 @@ const createArrayFromPythonDictionary = (dict: Record<string, number>) => {
2323
return resultArray;
2424
};
2525

26+
function createHeatmapdata(resultItem: unknown) {
27+
const columns: string[] = [];
28+
const heatmapList =
29+
typeof resultItem === 'string'
30+
? JSON.parse(resultItem as string)
31+
: (resultItem as Record<string, unknown>);
32+
const convertedData: number[][] = [];
33+
let createdColumns = false;
34+
if (heatmapList) {
35+
heatmapList.forEach(
36+
(heatmapRow: number[] | object, rowIndex: number) => {
37+
if (Array.isArray(heatmapRow)) {
38+
columns.push(`${rowIndex + 1}`);
39+
convertedData.push(heatmapRow);
40+
} else {
41+
if (typeof heatmapRow === 'object') {
42+
const temp = [];
43+
for (const key in heatmapRow) {
44+
temp.push(
45+
(
46+
heatmapRow as unknown as Record<
47+
string,
48+
number
49+
>
50+
)[key]
51+
);
52+
if (!createdColumns) {
53+
columns.push(key);
54+
}
55+
}
56+
createdColumns = true;
57+
convertedData.push(temp);
58+
}
59+
}
60+
}
61+
);
62+
}
63+
64+
return {
65+
columns,
66+
data: convertedData,
67+
};
68+
}
69+
2670
export default function ComponentMapper({
2771
items,
2872
data,
@@ -129,22 +173,59 @@ export default function ComponentMapper({
129173
);
130174
}
131175
case 'heatmap': {
132-
console.log('heatmap data', resultItem.data);
133176
/*
177+
resultItem.real
178+
resultItem.synthetic
179+
134180
Array in Array
135181
136182
[
137183
[1,2,3],
138184
[4,5,6],
139185
[7,8,9]
140186
]
187+
188+
of
189+
190+
Object in Array
191+
192+
[
193+
{a: 1, b: 2, c: 3},
194+
{a: 4, b: 5, c: 6},
195+
{a: 7, b: 8, c: 9}
196+
]
141197
*/
198+
const { columns: realColumns, data: convertedData } =
199+
createHeatmapdata(resultItem.real);
200+
const {
201+
columns: synthticColumns,
202+
data: syntheticData,
203+
} = createHeatmapdata(resultItem.synthetic);
142204
return (
143-
<HeatMapChart
144-
key={index}
145-
data={resultItem.data}
146-
title={resultItem.title ?? ''}
147-
/>
205+
<div className="grid lg:grid-cols-[50%_50%] grid-cols-[100%]">
206+
<div className="col-[1]">
207+
<h2 className="pb-2">
208+
{t('heatmap.realdata')}
209+
</h2>
210+
<HeatMapChart
211+
columns={realColumns}
212+
key={index}
213+
data={convertedData}
214+
title={resultItem.title ?? ''}
215+
/>
216+
</div>
217+
<div className="col-[1] lg:col-[2]">
218+
<h2 className="pb-2">
219+
{t('heatmap.syntheticdata')}
220+
</h2>
221+
<HeatMapChart
222+
columns={synthticColumns}
223+
key={index}
224+
data={syntheticData}
225+
title={resultItem.title ?? ''}
226+
/>
227+
</div>
228+
</div>
148229
);
149230
}
150231
case 'barchart': {

src/components/graphs/HeatMap.tsx

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,23 @@ import { autoBandwidth, extentLinear, seriesSvgBar } from 'd3fc';
44
interface HeatMapChartProps {
55
title: string;
66
data: number[][];
7+
columns: string[];
78
}
89

910
// Define margins for the chart
1011
const margin = { top: 10, right: 0, bottom: 40, left: 0 };
1112
// Define height for the chart, adjusting for margins
1213
const height = 300 - margin.top - margin.bottom;
1314

14-
const HeatMapChart = ({ title, data }: HeatMapChartProps) => {
15+
const HeatMapChart = ({ title, data, columns }: HeatMapChartProps) => {
1516
const svgRef = useRef(null); // Reference to the SVG element
1617
const containerRef = useRef(null); // Reference to the container div
1718
const [containerWidth, setContainerWidth] = useState(800); // Default container width
1819

1920
useEffect(() => {
2021
// Clear any previous SVG content to avoid overlapping elements
2122
d3.select(svgRef.current).selectAll('*').remove();
22-
const legendWidth = 100;
23+
const legendWidth = 150;
2324
const widthForHeatmap = containerWidth - 50 - legendWidth;
2425
const barWidth = Math.max(
2526
10,
@@ -73,6 +74,25 @@ const HeatMapChart = ({ title, data }: HeatMapChartProps) => {
7374
.style('fill', function () {
7475
return colorScale(dataCell);
7576
});
77+
78+
const color = d3.color(colorScale(dataCell));
79+
if (!color) return 'black';
80+
81+
// Get RGB values using d3.rgb() ..
82+
const rgb = d3.rgb(color);
83+
84+
// Calculate perceived brightness
85+
const luminance =
86+
(0.299 * rgb.r + 0.587 * rgb.g + 0.114 * rgb.b) / 255;
87+
const textColor = luminance < 0.5 ? 'white' : 'black';
88+
svg.append('text')
89+
.attr('x', barWidth / 2 + 50 + cellIndex * barWidth)
90+
.attr('y', barHeight / 2 + rowIndex * barHeight)
91+
.attr('text-anchor', 'middle')
92+
.attr('dominant-baseline', 'middle')
93+
.style('fill', textColor)
94+
.style('font-size', '10px')
95+
.text(dataCell.toFixed(2));
7696
});
7797
});
7898

@@ -81,10 +101,10 @@ const HeatMapChart = ({ title, data }: HeatMapChartProps) => {
81101
.data(data[0])
82102
.join('text')
83103
.attr('x', (_, i) => 50 + i * barWidth + barWidth / 2)
84-
.attr('y', 50 + barHeight * data.length)
104+
.attr('y', 20 + barHeight * data.length)
85105
.attr('text-anchor', 'middle')
86106
.style('font-size', '12px')
87-
.text((_, i) => `Cell ${i + 1}`);
107+
.text((_, i) => `${columns?.[i]}`);
88108

89109
svg.append('g')
90110
.selectAll('text')
@@ -95,7 +115,7 @@ const HeatMapChart = ({ title, data }: HeatMapChartProps) => {
95115
.attr('dy', '0.35em')
96116
.attr('text-anchor', 'end')
97117
.style('font-size', '12px')
98-
.text((_, i) => `Row ${i + 1}`);
118+
.text((_, i) => `${columns?.[i]}`);
99119

100120
const svgBar = autoBandwidth(seriesSvgBar())
101121
.xScale(xScale)
@@ -130,7 +150,7 @@ const HeatMapChart = ({ title, data }: HeatMapChartProps) => {
130150
const legendBar = svg.append('g').datum(expandedDomain).call(svgBar);
131151
legendBar.attr(
132152
'transform',
133-
`translate(${legendWidth + barWidth * data.length},0)`
153+
`translate(${legendWidth - 50 + barWidth * data.length},0)`
134154
);
135155
const legendBarWidth = Math.abs(
136156
legendBar.node()!.getBoundingClientRect().x

src/locales/en.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,5 +114,9 @@
114114
"distribution": {
115115
"heading": "The \"{{variable}}\" variable distribution across the different clusters:"
116116
}
117+
},
118+
"heatmap": {
119+
"realdata": "Correlation matrix of real data",
120+
"syntheticdata": "Correlation matrix of synthetic data"
117121
}
118122
}

src/locales/nl.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,5 +114,9 @@
114114
"distribution": {
115115
"heading": "De \"{{variable}}\" variabele verdeling over de verschillende clusters:"
116116
}
117+
},
118+
"heatmap": {
119+
"realdata": "Correlatie matrix van echte data",
120+
"syntheticdata": "Correlatie matrix van synthetische data"
117121
}
118122
}

0 commit comments

Comments
 (0)