Skip to content

Commit 0cf9dc3

Browse files
committed
Docs violin plot update
1 parent b0ae2db commit 0cf9dc3

8 files changed

Lines changed: 70 additions & 84 deletions

File tree

docs/.vitepress/config.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,9 @@ export default defineConfig({
8787
items: [
8888
{ text: '2D Scatter Plot', link: './scatter_plot_2D' },
8989
{ text: '3D Scatter Plot', link: './scatter_plot_3D' },
90-
{ text: 'Embellished Chart', link: './embellished_chart' },
90+
{ text: 'Vector Field', link: './vector_field' },
9191
{ text: 'Dimensionality Reduction Plot', link: './dimensionality_reduction_plot' },
92-
{ text: 'Vector Field', link: './vector_field' }
92+
{ text: 'Embellished Chart', link: './embellished_chart' },
9393
]
9494
},
9595
{
@@ -119,9 +119,10 @@ export default defineConfig({
119119
items: [
120120
{ text: '2D Area Chart', link: './area_chart_2D' },
121121
{ text: '2D Stacked Area Chart', link: './area_chart_stacked' },
122+
{ text: 'Violin Plot', link: './violin_plot' },
123+
{ text: 'Surface Chart', link: './surface_chart' },
122124
{ text: 'Pie Chart', link: './pie_chart' },
123125
{ text: 'Donut Chart', link: './donut_chart' },
124-
{ text: 'Surface Chart', link: './surface_chart' }
125126
]
126127
},
127128
{
@@ -155,6 +156,7 @@ export default defineConfig({
155156
{ text: 'Multiple Interactions', link: './multiple_interactions' },
156157
{ text: 'Single Selection', link: './brushing_linking_single' },
157158
{ text: 'Multiple Selection', link: './brushing_linking_multiple' },
159+
{ text: 'Filtering Selection', link: './brushing_linking_filter' },
158160
{ text: 'Layouts', link: './layout' },
159161
{ text: 'ImAxes Simplified', link: './imaxes_simplified'}
160162
]

docs/anu-examples/Scatterplot2D.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ export function scatterplot2D(engine){
1212
//Create an empty Scene
1313
const scene = new BABYLON.Scene(engine);
1414
//Add some lighting
15-
new BABYLON.HemisphericLight('light1', new BABYLON.Vector3(0, 10, -5), scene);
15+
const fillLight = new BABYLON.HemisphericLight('fillLight', new BABYLON.Vector3(0, 1, 0), scene);
16+
fillLight.intensity = 1.25;
17+
fillLight.groundColor = new BABYLON.Color3(0.5, 0.5, 0.5);
1618
//Add a camera that rotates around the origin and adjust its properties
1719
const camera = new BABYLON.ArcRotateCamera('Camera', 0, 0, 0, new BABYLON.Vector3(0, 0, 0), scene);
1820
camera.position = new BABYLON.Vector3(0, 0, -3);

docs/anu-examples/Scatterplot3D.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ export function scatterplot3D(engine){
1212
//Create an empty Scene
1313
const scene = new BABYLON.Scene(engine);
1414
//Add some lighting
15-
new BABYLON.HemisphericLight('light1', new BABYLON.Vector3(0, 10, 0), scene);
15+
const fillLight = new BABYLON.HemisphericLight('fillLight', new BABYLON.Vector3(0, 1, 0), scene);
16+
fillLight.intensity = 1.25;
17+
fillLight.groundColor = new BABYLON.Color3(0.5, 0.5, 0.5);
1618
//Add a camera that rotates around the origin and adjust its properties
1719
const camera = new BABYLON.ArcRotateCamera('Camera', 0, 0, 0, new BABYLON.Vector3(0, 0, 0), scene);
1820
camera.position = new BABYLON.Vector3(2, 2, -3.5);
Lines changed: 40 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import * as d3 from 'd3';
77
import data from './data/penguins.json';
88

99
//Create and export a function that takes a Babylon engine and returns a Babylon Scene
10-
export function violinChart(engine) {
10+
export function violinPlot(engine) {
1111

1212
//Create an empty Scene
1313
const scene = new BABYLON.Scene(engine);
@@ -16,70 +16,66 @@ export function violinChart(engine) {
1616
fillLight.intensity = 1.25;
1717
fillLight.groundColor = new BABYLON.Color3(0.5, 0.5, 0.5);
1818
//Add a camera that rotates around the origin and adjust its properties
19-
const camera = new BABYLON.ArcRotateCamera('Camera', 0, 0, 0, new BABYLON.Vector3(0, 0.5, 0), scene);
20-
camera.position = new BABYLON.Vector3(0, 0.5, -3);
19+
const camera = new BABYLON.ArcRotateCamera('Camera', 0, 0, 0, new BABYLON.Vector3(0, 0.75, 0), scene);
20+
camera.position = new BABYLON.Vector3(0, 0.75, -2.5);
2121
camera.wheelPrecision = 20;
2222
camera.minZ = 0;
2323
camera.attachControl(true);
2424

2525
// Kernel density estimation functions (adapted from D3 gallery example)
2626
function kernelDensityEstimator(kernel, ticks) {
27-
return function(values) {
28-
return ticks.map(function(x) {
29-
return [x, d3.mean(values, function(v) { return kernel(x - v); })];
27+
return function (values) {
28+
return ticks.map(function (x) {
29+
return [
30+
x,
31+
d3.mean(values, function (v) {
32+
return kernel(x - v);
33+
}),
34+
];
3035
});
3136
};
3237
}
33-
38+
3439
function kernelEpanechnikov(bandwidth) {
35-
return function(v) {
36-
return Math.abs(v /= bandwidth) <= 1 ? 0.75 * (1 - v * v) / bandwidth : 0;
40+
return function (v) {
41+
return Math.abs((v /= bandwidth)) <= 1 ? (0.75 * (1 - v * v)) / bandwidth : 0;
3742
};
3843
}
3944

4045
// Get unique species
41-
const species = Array.from(new Set(data.map(d => d.Species)));
42-
46+
const species = Array.from(new Set(data.map((d) => d.Species)));
47+
4348
// Create scales for the visualization
4449
// Y scale for the beak length values
45-
const beakLengths = data.map(d => d['Beak Length (mm)']).filter(d => d != null);
46-
const scaleY = d3.scaleLinear()
47-
.domain(d3.extent(beakLengths))
48-
.range([0, 1.5])
49-
.nice();
50-
50+
const beakLengths = data.map((d) => d['Beak Length (mm)']).filter((d) => d != null);
51+
const scaleY = d3.scaleLinear().domain(d3.extent(beakLengths)).range([0, 1.5]).nice();
52+
5153
// X scale for positioning the violins (one for each species)
52-
const scaleX = d3.scaleBand()
53-
.domain(species)
54-
.range([-1, 1])
55-
.paddingInner(1).paddingOuter(0.5);
56-
54+
const scaleX = d3.scaleBand().domain(species).range([-1, 1]).paddingInner(1).paddingOuter(0.5);
5755

5856
// Create kernel density estimator
5957
const kde = kernelDensityEstimator(kernelEpanechnikov(0.7), scaleY.ticks(50));
60-
58+
6159
// Compute density for each species
62-
const densityData = species.map(sp => {
60+
const densityData = species.map((sp) => {
6361
const values = data
64-
.filter(d => d.Species === sp && d['Beak Length (mm)'] != null)
65-
.map(d => d['Beak Length (mm)']);
62+
.filter((d) => d.Species === sp && d['Beak Length (mm)'] != null)
63+
.map((d) => d['Beak Length (mm)']);
6664
return {
6765
species: sp,
68-
density: kde(values)
66+
density: kde(values),
6967
};
7068
});
7169

7270
// Find the maximum density value across all species for scaling
7371
let maxDensity = 0;
74-
densityData.forEach(d => {
75-
const max = d3.max(d.density, v => v[1]);
72+
densityData.forEach((d) => {
73+
const max = d3.max(d.density, (v) => v[1]);
7674
if (max > maxDensity) maxDensity = max;
7775
});
7876

7977
// Scale for the width of the violins based on density
80-
const scaleWidth = d3.scaleLinear()
81-
.domain([0, maxDensity])
82-
.range([0, 0.25]); // 0.25 to leave some space between violins
78+
const scaleWidth = d3.scaleLinear().domain([0, maxDensity]).range([0, 0.25]); // 0.25 to leave some space between violins
8379

8480
// Color scale for different species using Anu helper function
8581
const scaleC = d3.scaleOrdinal(anu.ordinalChromatic('d310').toColor3());
@@ -91,50 +87,36 @@ export function violinChart(engine) {
9187
// Function to create the path array for a violin shape
9288
// All violins are created at x=0 and will be positioned later
9389
const createViolinPath = (speciesData) => {
90+
9491
// Create the path for the violin shape (right half) - from bottom to top
95-
const rightPath = speciesData.density.map(d =>
96-
new BABYLON.Vector3(scaleWidth(d[1]), scaleY(d[0]), 0)
97-
);
98-
92+
const rightPath = speciesData.density.map((d) => new BABYLON.Vector3(scaleWidth(d[1]), scaleY(d[0]), 0));
93+
9994
// Create the left half (mirror of right half) - from top to bottom
100-
const leftPath = speciesData.density.map(d =>
101-
new BABYLON.Vector3(-scaleWidth(d[1]), scaleY(d[0]), 0)
102-
).reverse();
103-
95+
const leftPath = speciesData.density.map((d) => new BABYLON.Vector3(-scaleWidth(d[1]), scaleY(d[0]), 0)).reverse();
96+
10497
// Combine both halves to create a closed shape
10598
const fullPath = [...rightPath, ...leftPath];
106-
99+
107100
// Smooth the path for better visual appearance
108101
const smoothPath = BABYLON.Curve3.CreateCatmullRomSpline(fullPath, 30, true).getPoints();
109-
102+
110103
// Create center line path at the same points for ribbon fill
111-
const centerPath = smoothPath.map(p => new BABYLON.Vector3(0, p.y, 0));
112-
104+
const centerPath = smoothPath.map((p) => new BABYLON.Vector3(0, p.y, 0));
105+
113106
// Return the path array for ribbon creation - from center to outline
114107
return [centerPath, smoothPath];
115108
};
116109

117110
// Create violin shapes using anu.bind for each species
118-
let violins = chart.bind('ribbon',
119-
{
120-
pathArray: (d) => createViolinPath(d),
121-
closeArray: true,
122-
closePath: true,
123-
sideOrientation: BABYLON.Mesh.DOUBLESIDE
124-
},
125-
densityData)
111+
let violins = chart.bind('ribbon', { pathArray: (d) => createViolinPath(d), sideOrientation: BABYLON.Mesh.DOUBLESIDE }, densityData)
126112
.positionX((d) => scaleX(d.species))
127113
.positionZ(-0.01) // Slightly adjust z to prevent Z-fighting
128114
.material((d, n, i) => new BABYLON.StandardMaterial('violinMaterial_' + i, scene))
129115
.diffuseColor((d) => scaleC(d.species));
130-
131116

132117
// Create axes with custom labels
133-
anu.createAxes('myAxes', {
134-
scale: {
135-
x: scaleX,
136-
y: scaleY
137-
},
118+
anu.createAxes('myAxes', {
119+
scale: { x: scaleX, y: scaleY },
138120
parent: chart,
139121
});
140122

docs/examples/index.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ layout: page
1717
<div class="cards">
1818
<cardImg title="2D Scatter Plot" img="/anu/assets/example-images/scatterplot2D.webp" link="/anu/examples/scatter_plot_2D"></cardImg>
1919
<cardImg title="3D Scatter Plot" img="/anu/assets/example-images/scatterplot3D.webp" link="/anu/examples/scatter_plot_3D"></cardImg>
20-
<cardImg title="Embellished Chart" img="/anu/assets/example-images/embellishedChart.webp" link="/anu/examples/embellished_chart"></cardImg>
21-
<cardImg title="Dimensionality Reduction Plot" img="/anu/assets/example-images/dimensionalityReductionPlot.webp" link="/anu/examples/dimensionality_reduction_plot"></cardImg>
2220
<cardImg title="Vector Field" img="/anu/assets/example-images/vectorField.webp" link="/anu/examples/vector_field"></cardImg>
21+
<cardImg title="Dimensionality Reduction Plot" img="/anu/assets/example-images/dimensionalityReductionPlot.webp" link="/anu/examples/dimensionality_reduction_plot"></cardImg>
22+
<cardImg title="Embellished Chart" img="/anu/assets/example-images/embellishedChart.webp" link="/anu/examples/embellished_chart"></cardImg>
2323
</div>
2424
</div>
2525
<div class='section'>
@@ -49,10 +49,10 @@ layout: page
4949
<div class="cards">
5050
<cardImg title="2D Area Chart" img="/anu/assets/example-images/areachart2D.webp" link="/anu/examples/area_chart_2D"></cardImg>
5151
<cardImg title="2D Stacked Area Chart" img="/anu/assets/example-images/areachartStacked.webp" link="/anu/examples/area_chart_stacked"></cardImg>
52+
<cardImg title="Violin Plot" img="/anu/assets/example-images/violinPlot.webp" link="/anu/examples/violin_plot"></cardImg>
53+
<cardImg title="Surface Chart" img="/anu/assets/example-images/surfaceChart.webp" link="/anu/examples/surface_chart"></cardImg>
5254
<cardImg title="Pie Chart" img="/anu/assets/example-images/pieChart.webp" link="/anu/examples/pie_chart"></cardImg>
5355
<cardImg title="Donut Chart" img="/anu/assets/example-images/donutChart.webp" link="/anu/examples/donut_chart"></cardImg>
54-
<cardImg title="Surface Chart" img="/anu/assets/example-images/surfaceChart.webp" link="/anu/examples/surface_chart"></cardImg>
55-
<cardImg title="Violin Chart" img="/anu/assets/example-images/violinChart.webp" link="/anu/examples/violin_chart"></cardImg>
5656
</div>
5757
</div>
5858
<div class='section'>

docs/examples/violin_chart.md

Lines changed: 0 additions & 17 deletions
This file was deleted.

docs/examples/violin_plot.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
aside: false
3+
---
4+
<script setup>
5+
import { violinPlot } from '../anu-examples/violinPlot.js'
6+
</script>
7+
8+
# Violin Plot
9+
Violin plot using [Ribbon](https://doc.babylonjs.com/features/featuresDeepDive/mesh/creation/param/ribbon/) adapted from the [violin plot from kernel density estimate](https://d3-graph-gallery.com/graph/violin_basicDens.html) example from the D3 Graph Gallery.
10+
11+
<singleView :scene="violinPlot" />
12+
13+
::: code-group
14+
<<< @/./anu-examples/violinPlot.js
15+
:::
File renamed without changes.

0 commit comments

Comments
 (0)