Skip to content

Commit d1e82b7

Browse files
committed
heatmaps side by side : real vs synth
1 parent 092d54a commit d1e82b7

File tree

6 files changed

+162
-90
lines changed

6 files changed

+162
-90
lines changed

src/assets/synthetic-data.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,7 @@ def run():
274274
'dataTypes': json.dumps(dtypes_dict),
275275
'combined_data' : combined_data.to_json(orient="records"),
276276
'realCorrelations': real_data.corr().to_json(orient="records"),
277+
'synthDataCorrelations': synthetic_data.corr().to_json(orient="records"),
277278
'syntheticCorrelations': np.abs(df_numeric.corr() - synth_df_numeric.corr()).to_json(orient="records"),
278279
'reports' : [
279280
# {
@@ -283,6 +284,7 @@ def run():
283284
# {'reportType': 'univariateDistributionRealData'},
284285
# {'reportType': 'bivariateDistributionRealData'},
285286
# {'reportType': 'correlationRealData'},
287+
# {'reportType': 'correlationSynthData'},
286288
{
287289
'reportType': 'heading',
288290
'headingKey': 'syntheticData.cartModelTitle' if sdgMethod == 'cart' else 'syntheticData.gaussianCopulaModelTitle'

src/components/DistributionReport.tsx

Lines changed: 78 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -16,22 +16,21 @@ interface CorrelationMatrixProps {
1616
columns: string[];
1717
data: number[][];
1818
};
19+
title: string;
20+
showLegend?: boolean;
1921
}
2022

2123
function CorrelationMatrix(props: CorrelationMatrixProps) {
2224
return (
23-
<div className="grid lg:grid-cols-[50%_50%] grid-cols-[100%]">
24-
<div className="col-[1]">
25-
<HeatMapChart
26-
columns={props.heatmapData.columns}
27-
data={props.heatmapData.data}
28-
title={t('heatmap.syntheticdata')}
29-
rangeMax={2}
30-
rangeMin={0}
31-
colors="LtRd"
32-
/>
33-
</div>
34-
</div>
25+
<HeatMapChart
26+
columns={props.heatmapData.columns}
27+
data={props.heatmapData.data}
28+
title={props.title}
29+
rangeMax={2}
30+
rangeMin={0}
31+
colors="LtRd"
32+
showLegend={props.showLegend}
33+
/>
3534
);
3635
}
3736

@@ -76,6 +75,7 @@ export interface DistributionReportProps {
7675
synthetic: string;
7776
reports: DistributionReport[];
7877
realCorrelations: string;
78+
synthDataCorrelations: string;
7979
syntheticCorrelations: string;
8080
combined_data: string;
8181
}
@@ -189,12 +189,40 @@ export const DistributionReport = (
189189
'correlationSyntheticData'
190190
) {
191191
return (
192-
<CorrelationMatrix
193-
key={index}
194-
heatmapData={createHeatmapdata(
195-
distributionReportProps.syntheticCorrelations
196-
)}
197-
/>
192+
<div className="grid lg:grid-cols-[50%_50%] grid-cols-[100%]">
193+
<div className="col-[1] lg:col-[1]">
194+
<CorrelationMatrix
195+
key={
196+
index
197+
}
198+
title={t(
199+
'heatmap.realdata'
200+
)}
201+
heatmapData={createHeatmapdata(
202+
distributionReportProps.realCorrelations
203+
)}
204+
showLegend={
205+
false
206+
}
207+
/>
208+
</div>
209+
<div className="col-[1] lg:col-[2]">
210+
<CorrelationMatrix
211+
key={
212+
index
213+
}
214+
title={t(
215+
'heatmap.synthData'
216+
)}
217+
heatmapData={createHeatmapdata(
218+
distributionReportProps.synthDataCorrelations
219+
)}
220+
showLegend={
221+
true
222+
}
223+
/>
224+
</div>
225+
</div>
198226
);
199227
}
200228
}
@@ -538,6 +566,38 @@ export const DistributionReport = (
538566
</div>
539567
);
540568
}
569+
570+
if (report.reportType === 'correlationSynthData') {
571+
const { columns: realColumns, data: convertedData } =
572+
createHeatmapdata(
573+
distributionReportProps.synthDataCorrelations
574+
);
575+
return (
576+
<div key={indexReport} className="mb-4">
577+
<Accordion
578+
title={t(
579+
'syntheticData.correlationSynthData'
580+
)}
581+
content={
582+
<div className="grid lg:grid-cols-[50%_50%] grid-cols-[100%]">
583+
<div className="col-[1]">
584+
<HeatMapChart
585+
columns={realColumns}
586+
data={convertedData}
587+
title={t(
588+
'heatmap.synthData'
589+
)}
590+
rangeMax={1}
591+
rangeMin={-1}
592+
colors="RdYlBu"
593+
/>
594+
</div>
595+
</div>
596+
}
597+
/>
598+
</div>
599+
);
600+
}
541601
if (
542602
report.reportType ===
543603
'univariateDistributionSyntheticData'
@@ -628,24 +688,6 @@ export const DistributionReport = (
628688
);
629689
}
630690

631-
if (report.reportType === 'correlationSyntheticData') {
632-
return (
633-
<div className="mb-4" key={indexReport}>
634-
<Accordion
635-
title={t(
636-
'syntheticData.correlationSyntheticData'
637-
)}
638-
content={
639-
<CorrelationMatrix
640-
heatmapData={createHeatmapdata(
641-
distributionReportProps.syntheticCorrelations
642-
)}
643-
/>
644-
}
645-
></Accordion>
646-
</div>
647-
);
648-
}
649691
return null;
650692
}
651693
)}

src/components/componentMapper.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,9 @@ export default function ComponentMapper({
169169
synthetic={resultItem.synthetic}
170170
reports={resultItem.reports}
171171
realCorrelations={resultItem.realCorrelations}
172+
synthDataCorrelations={
173+
resultItem.synthDataCorrelations
174+
}
172175
syntheticCorrelations={
173176
resultItem.syntheticCorrelations
174177
}

src/components/graphs/HeatMap.tsx

Lines changed: 75 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@ interface HeatMapChartProps {
88
rangeMin: number;
99
rangeMax: number;
1010
colors: 'RdYlBu' | 'LtRd';
11+
showLegend?: boolean;
1112
}
1213

1314
// Define margins for the chart
14-
const margin = { top: 10, right: 0, bottom: 40, left: 0 };
15+
const margin = { top: 50, right: 0, bottom: 40, left: 0 };
1516
// Define height for the chart, adjusting for margins
1617
const height = 300 - margin.top - margin.bottom;
1718

@@ -22,6 +23,7 @@ const HeatMapChart = ({
2223
rangeMin,
2324
rangeMax,
2425
colors,
26+
showLegend = true,
2527
}: HeatMapChartProps) => {
2628
const svgRef = useRef(null); // Reference to the SVG element
2729
const containerRef = useRef(null); // Reference to the container div
@@ -37,10 +39,11 @@ const HeatMapChart = ({
3739
Math.floor(Math.min(widthForHeatmap, 500) / data[0].length)
3840
);
3941
const barHeight = barWidth;
42+
const heatMapTop = 50;
4043
const svg = d3
4144
.select(svgRef.current)
4245
.attr('width', containerWidth)
43-
.attr('height', 50 + data.length * barHeight)
46+
.attr('height', heatMapTop + 50 + data.length * barHeight)
4447
.append('g');
4548

4649
svg.append('defs')
@@ -94,7 +97,7 @@ const HeatMapChart = ({
9497
dataRow.forEach((dataCell, cellIndex) => {
9598
svg.append('rect')
9699
.attr('x', 50 + cellIndex * barWidth)
97-
.attr('y', rowIndex * barHeight)
100+
.attr('y', heatMapTop + rowIndex * barHeight)
98101
.attr('width', barWidth)
99102
.attr('height', barHeight)
100103
.style('fill', function () {
@@ -113,7 +116,10 @@ const HeatMapChart = ({
113116
const textColor = luminance < 0.5 ? 'white' : 'black';
114117
svg.append('text')
115118
.attr('x', barWidth / 2 + 50 + cellIndex * barWidth)
116-
.attr('y', barHeight / 2 + rowIndex * barHeight)
119+
.attr(
120+
'y',
121+
heatMapTop + barHeight / 2 + rowIndex * barHeight
122+
)
117123
.attr('text-anchor', 'middle')
118124
.attr('dominant-baseline', 'middle')
119125
.style('fill', textColor)
@@ -127,7 +133,7 @@ const HeatMapChart = ({
127133
.data(data[0])
128134
.join('text')
129135
.attr('x', (_, i) => 50 + i * barWidth + barWidth / 2)
130-
.attr('y', 20 + barHeight * data.length)
136+
.attr('y', heatMapTop + 20 + barHeight * data.length)
131137
.attr('text-anchor', 'middle')
132138
.style('font-size', '12px')
133139
.text((_, i) => `${columns?.[i]}`);
@@ -137,60 +143,77 @@ const HeatMapChart = ({
137143
.data(data)
138144
.join('text')
139145
.attr('x', 40)
140-
.attr('y', (_, i) => i * barHeight + barHeight / 2)
146+
.attr('y', (_, i) => heatMapTop + i * barHeight + barHeight / 2)
141147
.attr('dy', '0.35em')
142148
.attr('text-anchor', 'end')
143149
.style('font-size', '12px')
144150
.text((_, i) => `${columns?.[i]}`);
145-
146-
const svgBar = autoBandwidth(seriesSvgBar())
147-
.xScale(xScale)
148-
.yScale(yScale)
149-
.crossValue(0)
150-
.baseValue((_: unknown, i: number) =>
151-
i > 0 ? expandedDomain[i - 1] : 0
152-
)
153-
.mainValue((d: number) => d)
154-
.decorate(
155-
(
156-
selection: d3.Selection<
157-
SVGGElement,
158-
unknown,
159-
null,
160-
undefined
161-
>
162-
) => {
163-
selection
164-
.selectAll('path')
165-
.style('fill', d =>
166-
colorScale(d as unknown as d3.NumberValue)
167-
);
168-
}
151+
if (showLegend) {
152+
const svgBar = autoBandwidth(seriesSvgBar())
153+
.xScale(xScale)
154+
.yScale(yScale)
155+
.crossValue(0)
156+
.baseValue((_: unknown, i: number) =>
157+
i > 0 ? expandedDomain[i - 1] : 0
158+
)
159+
.mainValue((d: number) => d)
160+
.decorate(
161+
(
162+
selection: d3.Selection<
163+
SVGGElement,
164+
unknown,
165+
null,
166+
undefined
167+
>
168+
) => {
169+
selection
170+
.selectAll('path')
171+
.style('fill', d =>
172+
colorScale(d as unknown as d3.NumberValue)
173+
);
174+
}
175+
);
176+
177+
const axisLabel = d3
178+
.axisRight(yScale)
179+
.tickValues(
180+
colors === 'RdYlBu'
181+
? [...domain, (domain[1] + domain[0]) / 2]
182+
: [...domain]
183+
)
184+
.tickSizeOuter(0);
185+
186+
const legendBar = svg
187+
.append('g')
188+
.datum(expandedDomain)
189+
.call(svgBar);
190+
legendBar.attr(
191+
'transform',
192+
`translate(${legendWidth - 50 + barWidth * data.length},${heatMapTop})`
169193
);
170194

171-
const axisLabel = d3
172-
.axisRight(yScale)
173-
.tickValues(
174-
colors === 'RdYlBu'
175-
? [...domain, (domain[1] + domain[0]) / 2]
176-
: [...domain]
177-
)
178-
.tickSizeOuter(0);
179-
180-
const legendBar = svg.append('g').datum(expandedDomain).call(svgBar);
181-
legendBar.attr(
182-
'transform',
183-
`translate(${legendWidth - 50 + barWidth * data.length},0)`
184-
);
185-
svg.append('g')
195+
svg.append('g')
196+
.attr(
197+
'transform',
198+
`translate(${legendWidth - 50 + barWidth * data.length + 20},${heatMapTop})`
199+
)
200+
.datum(expandedDomain)
201+
.call(axisLabel)
202+
.select('.domain')
203+
.attr('visibility', 'hidden');
204+
}
205+
d3.select(svgRef.current)
206+
.append('text')
186207
.attr(
187-
'transform',
188-
`translate(${legendWidth - 50 + barWidth * data.length + 20})`
208+
'x',
209+
50 + (barWidth * data.length) / 2
210+
//showLegend ? containerWidth / 2 : containerWidth / 2 - 50
189211
)
190-
.datum(expandedDomain)
191-
.call(axisLabel)
192-
.select('.domain')
193-
.attr('visibility', 'hidden');
212+
.attr('y', 20)
213+
.attr('text-anchor', 'middle')
214+
.style('font-size', '16px')
215+
.style('font-weight', 'bold')
216+
.text(`${title}`);
194217
}, [data, title, containerWidth]);
195218

196219
useEffect(() => {
@@ -217,7 +240,7 @@ const HeatMapChart = ({
217240
// Render the chart container and SVG element with horizontal scroll if needed
218241
return (
219242
<div className="flex flex-col gap-4">
220-
<h3 className="text-center font-semibold text-base">{title}</h3>
243+
{/* <h3 className="text-center font-semibold text-base">{title}</h3> */}
221244
<div
222245
ref={containerRef}
223246
style={{ width: '100%', display: 'flex', overflowX: 'auto' }}

src/locales/en.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,8 @@
166166
},
167167
"heatmap": {
168168
"realdata": "Correlation matrix of attached data",
169-
"syntheticdata": "Absolute difference in correlation matrix, i.e., |attached data - synthetic data|"
169+
"syntheticdata": "Absolute difference in correlation matrix, i.e., |attached data - synthetic data|",
170+
"synthData": "Correlation matrix of synthetic data"
170171
},
171172
"distribution": {
172173
"distributionFor": "Distribution for",

src/locales/nl.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,8 @@
164164
},
165165
"heatmap": {
166166
"realdata": "Correlatie matrix van gekoppelde data",
167-
"syntheticdata": "Absoluut verschil in correlation matrix, m.a.w., |gekoppelde data - synthetische data|"
167+
"syntheticdata": "Absoluut verschil in correlation matrix, m.a.w., |gekoppelde data - synthetische data|",
168+
"synthData": "Correlatie matrix van synthetische data"
168169
},
169170
"distribution": {
170171
"distributionFor": "Distributie voor",

0 commit comments

Comments
 (0)