@@ -7,6 +7,7 @@ interface ViolinChartProps {
77 numericColumn : string ;
88 realData : Array < { [ key : string ] : any } > ;
99 syntheticData : Array < { [ key : string ] : any } > ;
10+ comparison : boolean ;
1011}
1112
1213const formatTick = ( value : number ) => {
@@ -26,6 +27,7 @@ const ViolinChart = ({
2627 numericColumn,
2728 realData,
2829 syntheticData,
30+ comparison,
2931} : ViolinChartProps ) => {
3032 const svgRef = useRef < SVGSVGElement > ( null ) ;
3133 const containerRef = useRef < HTMLDivElement > ( null ) ;
@@ -37,10 +39,12 @@ const ViolinChart = ({
3739
3840 // Get unique categories
3941 const categories = Array . from (
40- new Set ( [
41- ...realData . map ( d => d [ categoricalColumn ] ) ,
42- ...syntheticData . map ( d => d [ categoricalColumn ] ) ,
43- ] )
42+ comparison
43+ ? new Set ( [
44+ ...realData . map ( d => d [ categoricalColumn ] ) ,
45+ ...syntheticData . map ( d => d [ categoricalColumn ] ) ,
46+ ] )
47+ : new Set ( [ ...realData . map ( d => d [ categoricalColumn ] ) ] )
4448 ) ;
4549
4650 // Process data for violin plots
@@ -73,7 +77,10 @@ const ViolinChart = ({
7377 // Reserve space for legend (120px width + 20px padding)
7478 const legendWidth = 140 ;
7579 const plotWidth =
76- containerWidth - margin . left - margin . right - legendWidth ;
80+ containerWidth -
81+ margin . left -
82+ margin . right -
83+ ( comparison ? legendWidth : 0 ) ;
7784
7885 // Create scales
7986 const xScale = d3
@@ -86,16 +93,18 @@ const ViolinChart = ({
8693 const bandwidth = Math . min ( xScale . bandwidth ( ) / 2 , 50 ) ;
8794
8895 // Calculate min and max with padding
89- const minValue =
90- d3 . min ( [
91- ...realData . map ( d => + d [ numericColumn ] ) ,
92- ...syntheticData . map ( d => + d [ numericColumn ] ) ,
93- ] ) || 0 ;
94- const maxValue =
95- d3 . max ( [
96- ...realData . map ( d => + d [ numericColumn ] ) ,
97- ...syntheticData . map ( d => + d [ numericColumn ] ) ,
98- ] ) || 0 ;
96+ const minValue = comparison
97+ ? d3 . min ( [
98+ ...realData . map ( d => + d [ numericColumn ] ) ,
99+ ...syntheticData . map ( d => + d [ numericColumn ] ) ,
100+ ] ) || 0
101+ : d3 . min ( [ ...realData . map ( d => + d [ numericColumn ] ) ] ) || 0 ;
102+ const maxValue = comparison
103+ ? d3 . max ( [
104+ ...realData . map ( d => + d [ numericColumn ] ) ,
105+ ...syntheticData . map ( d => + d [ numericColumn ] ) ,
106+ ] ) || 0
107+ : d3 . max ( [ ...realData . map ( d => + d [ numericColumn ] ) ] ) || 0 ;
99108
100109 // Add padding and ensure domain includes zero
101110 const range = Math . abs ( maxValue - minValue ) ;
@@ -279,20 +288,22 @@ const ViolinChart = ({
279288 . attr ( 'd' , path )
280289 . attr ( 'transform' , `translate(${ centerPos } , 0)` )
281290 . style ( 'fill' , 'steelblue' )
291+ . style ( 'stroke' , 'darkblue' )
282292 . style ( 'opacity' , 0.5 ) ;
283293
284294 drawQuartileLines ( real , 'left' , 'steelblue' ) ;
285295 }
286296 }
287297
288298 // Draw synthetic data violin (right side)
289- if ( synthetic . length > 0 ) {
299+ if ( comparison && synthetic . length > 0 ) {
290300 const path = createViolin ( synthetic , 'right' ) ;
291301 if ( path ) {
292302 svg . append ( 'path' )
293303 . attr ( 'd' , path )
294304 . attr ( 'transform' , `translate(${ centerPos } , 0)` )
295305 . style ( 'fill' , 'orange' )
306+ . style ( 'stroke' , '#ff6200' )
296307 . style ( 'opacity' , 0.5 ) ;
297308
298309 drawQuartileLines ( synthetic , 'right' , 'orange' ) ;
@@ -322,59 +333,61 @@ const ViolinChart = ({
322333 . attr ( 'font-size' , '12px' )
323334 . text ( numericColumn ) ;
324335
325- // Add legend at fixed position relative to plot area
326- const legend = svg
327- . append ( 'g' )
328- . attr ( 'class' , 'legend' )
329- . attr ( 'transform' , `translate(${ plotWidth + 20 } , 30)` ) ;
330-
331- // No need to adjust SVG width since we reserved space for legend
336+ if ( comparison ) {
337+ // Add legend at fixed position relative to plot area
338+ const legend = svg
339+ . append ( 'g' )
340+ . attr ( 'class' , 'legend' )
341+ . attr ( 'transform' , `translate(${ plotWidth + 20 } , 30)` ) ;
342+
343+ // No need to adjust SVG width since we reserved space for legend
344+
345+ // Add background rectangle for legend
346+ legend
347+ . append ( 'rect' )
348+ . attr ( 'x' , - 10 )
349+ . attr ( 'y' , - 10 )
350+ . attr ( 'width' , 110 )
351+ . attr ( 'height' , 55 )
352+ . attr ( 'rx' , 5 )
353+ . style ( 'fill' , 'white' )
354+ . style ( 'opacity' , 0.7 )
355+ . style ( 'stroke' , '#e2e8f0' )
356+ . style ( 'stroke-width' , 1 ) ;
332357
333- // Add background rectangle for legend
334- legend
335- . append ( 'rect' )
336- . attr ( 'x' , - 10 )
337- . attr ( 'y' , - 10 )
338- . attr ( 'width' , 110 )
339- . attr ( 'height' , 55 )
340- . attr ( 'rx' , 5 )
341- . style ( 'fill' , 'white' )
342- . style ( 'opacity' , 0.7 )
343- . style ( 'stroke' , '#e2e8f0' )
344- . style ( 'stroke-width' , 1 ) ;
345-
346- // Add legend items
347- legend
348- . append ( 'rect' )
349- . attr ( 'x' , 0 )
350- . attr ( 'y' , 0 )
351- . attr ( 'width' , 15 )
352- . attr ( 'height' , 15 )
353- . style ( 'fill' , 'steelblue' )
354- . style ( 'opacity' , 0.5 ) ;
355-
356- legend
357- . append ( 'text' )
358- . attr ( 'x' , 20 )
359- . attr ( 'y' , 12 )
360- . style ( 'font-size' , '12px' )
361- . text ( t ( 'distribution.realData' ) ) ;
362-
363- legend
364- . append ( 'rect' )
365- . attr ( 'x' , 0 )
366- . attr ( 'y' , 20 )
367- . attr ( 'width' , 15 )
368- . attr ( 'height' , 15 )
369- . style ( 'fill' , 'orange' )
370- . style ( 'opacity' , 0.5 ) ;
371-
372- legend
373- . append ( 'text' )
374- . attr ( 'x' , 20 )
375- . attr ( 'y' , 32 )
376- . style ( 'font-size' , '12px' )
377- . text ( t ( 'distribution.syntheticData' ) ) ;
358+ // Add legend items
359+ legend
360+ . append ( 'rect' )
361+ . attr ( 'x' , 0 )
362+ . attr ( 'y' , 0 )
363+ . attr ( 'width' , 15 )
364+ . attr ( 'height' , 15 )
365+ . style ( 'fill' , 'steelblue' )
366+ . style ( 'opacity' , 0.5 ) ;
367+
368+ legend
369+ . append ( 'text' )
370+ . attr ( 'x' , 20 )
371+ . attr ( 'y' , 12 )
372+ . style ( 'font-size' , '12px' )
373+ . text ( t ( 'distribution.realData' ) ) ;
374+
375+ legend
376+ . append ( 'rect' )
377+ . attr ( 'x' , 0 )
378+ . attr ( 'y' , 20 )
379+ . attr ( 'width' , 15 )
380+ . attr ( 'height' , 15 )
381+ . style ( 'fill' , 'orange' )
382+ . style ( 'opacity' , 0.5 ) ;
383+
384+ legend
385+ . append ( 'text' )
386+ . attr ( 'x' , 20 )
387+ . attr ( 'y' , 32 )
388+ . style ( 'font-size' , '12px' )
389+ . text ( t ( 'distribution.syntheticData' ) ) ;
390+ }
378391 } , [
379392 containerWidth ,
380393 categoricalColumn ,
0 commit comments