From f94ec0c461b0a17790153ebb2318f66b2e16d301 Mon Sep 17 00:00:00 2001 From: James R Swift Date: Fri, 26 Jul 2024 21:18:46 +0100 Subject: [PATCH 01/11] begin work on violin plot --- src/plot.typ | 1 + src/plot/violin.typ | 71 ++++++++++++++++++++++++++++++++++++++ tests/plot/violin/test.typ | 18 ++++++++++ 3 files changed, 90 insertions(+) create mode 100644 src/plot/violin.typ create mode 100644 tests/plot/violin/test.typ diff --git a/src/plot.typ b/src/plot.typ index 8a062dc..5a1a54f 100644 --- a/src/plot.typ +++ b/src/plot.typ @@ -12,6 +12,7 @@ #import "/src/plot/bar.typ": add-bar #import "/src/plot/errorbar.typ": add-errorbar #import "/src/plot/mark.typ" +#import "/src/plot/violin.typ": violin #import plot-legend: add-legend #let default-colors = (blue, red, green, yellow, black) diff --git a/src/plot/violin.typ b/src/plot/violin.typ new file mode 100644 index 0000000..a9bac57 --- /dev/null +++ b/src/plot/violin.typ @@ -0,0 +1,71 @@ +#import "/src/cetz.typ": draw, process, util, matrix + +#import "util.typ" +#import "sample.typ" + +#let _prepare(self, ctx) = { + let (x, y) = (ctx.x, ctx.y) + + // bin the data + let (min, max) = (calc.min(..self.data),calc.max(..self.data)) + + let binned = self.data.sorted().fold( (0,)*self.bins, (acc, it) => { + let bin = int(calc.rem(5 * (it - min) / (max - min), 5)) + acc.insert(bin, acc.at(bin) + 1) + return acc + }) + + self.line-data = () + + // Generate stroke paths + // self.stroke-paths = util.compute-stroke-paths(self.line-data, + // (x.min, y.min), (x.max, y.max)) + + // Compute fill paths if filling is requested + self.fill = self.at("fill", default: false) + if self.fill { + self.fill-paths = util.compute-fill-paths( + self.line-data, + (x.min, y.min), + (x.max, y.max) + ) + } + + return self +} + +#let _stroke(self, ctx) = { + let (x, y) = (ctx.x, ctx.y) + + // for p in self.stroke-paths { + // draw.line(..p, fill: none) + // } +} + +#let _fill(self, ctx) = { + // fill-segments-to(self.fill-paths, y.min) +} + +#let violin( + data, + style: (:), + axes: ("x", "y"), + bins: 7, +) = { + + (( + type: "violin", + axes: axes, + data: data, + bins: bins, + style: style, + plot-prepare: _prepare, + plot-stroke: _stroke, + plot-fill: _fill, + plot-legend-preview: self => { + draw.rect((0,0), (1,1), ..self.style) + } + ),) + + +} \ No newline at end of file diff --git a/tests/plot/violin/test.typ b/tests/plot/violin/test.typ new file mode 100644 index 0000000..2a1fd33 --- /dev/null +++ b/tests/plot/violin/test.typ @@ -0,0 +1,18 @@ +#set page(width: auto, height: auto) +#import "/src/lib.typ": * +#import "/src/cetz.typ": * +#import "/tests/helper.typ": * + +/* Empty plot */ +#test-case({ + import draw: * + + plot.plot(size: (9, 6), + // x-tick-step: none, + // y-tick-step: none, + { + let vals = (5,4,6,8,5,4,1,5,5,5,4,2,5,4,6,5,4,5,8,4,5,) + cetz-plot.plot.add(vals.map(it=>(0,it)), mark: "x", style: (stroke: none)) + cetz-plot.plot.violin(vals) + }) +}) From 0167627c4441834c5e74418c0730a1f771bd6909 Mon Sep 17 00:00:00 2001 From: James R Swift Date: Fri, 26 Jul 2024 21:36:11 +0100 Subject: [PATCH 02/11] testing --- src/plot/violin.typ | 19 +++++++++++-------- tests/plot/violin/test.typ | 1 + 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/plot/violin.typ b/src/plot/violin.typ index a9bac57..a36f059 100644 --- a/src/plot/violin.typ +++ b/src/plot/violin.typ @@ -8,18 +8,21 @@ // bin the data let (min, max) = (calc.min(..self.data),calc.max(..self.data)) + let range = max - min let binned = self.data.sorted().fold( (0,)*self.bins, (acc, it) => { - let bin = int(calc.rem(5 * (it - min) / (max - min), 5)) - acc.insert(bin, acc.at(bin) + 1) + let bin = int(self.bins * (it - min) / (max - min)) + acc.at(bin - 1) += 1 return acc }) - self.line-data = () + self.line-data = binned.enumerate().map( ((x, y)) => { + (0 + y / 10, min + x) + }) // Generate stroke paths - // self.stroke-paths = util.compute-stroke-paths(self.line-data, - // (x.min, y.min), (x.max, y.max)) + self.stroke-paths = util.compute-stroke-paths(self.line-data, + (x.min, y.min), (x.max, y.max)) // Compute fill paths if filling is requested self.fill = self.at("fill", default: false) @@ -37,9 +40,9 @@ #let _stroke(self, ctx) = { let (x, y) = (ctx.x, ctx.y) - // for p in self.stroke-paths { - // draw.line(..p, fill: none) - // } + for p in self.stroke-paths { + draw.line(..p, fill: none) + } } #let _fill(self, ctx) = { diff --git a/tests/plot/violin/test.typ b/tests/plot/violin/test.typ index 2a1fd33..80e70f1 100644 --- a/tests/plot/violin/test.typ +++ b/tests/plot/violin/test.typ @@ -10,6 +10,7 @@ plot.plot(size: (9, 6), // x-tick-step: none, // y-tick-step: none, + y-max: 10, { let vals = (5,4,6,8,5,4,1,5,5,5,4,2,5,4,6,5,4,5,8,4,5,) cetz-plot.plot.add(vals.map(it=>(0,it)), mark: "x", style: (stroke: none)) From 856fcf5e1f8f77feac221ebdd066b6cf3e2d7dc7 Mon Sep 17 00:00:00 2001 From: James R Swift Date: Tue, 30 Jul 2024 12:35:58 +0100 Subject: [PATCH 03/11] Violin plots (draft) --- src/plot/violin.typ | 103 +++++++++++++++---------------------- tests/plot/violin/test.typ | 19 +++++-- 2 files changed, 57 insertions(+), 65 deletions(-) diff --git a/src/plot/violin.typ b/src/plot/violin.typ index a36f059..3d42990 100644 --- a/src/plot/violin.typ +++ b/src/plot/violin.typ @@ -1,74 +1,55 @@ -#import "/src/cetz.typ": draw, process, util, matrix +#import "line.typ" -#import "util.typ" -#import "sample.typ" - -#let _prepare(self, ctx) = { - let (x, y) = (ctx.x, ctx.y) - - // bin the data - let (min, max) = (calc.min(..self.data),calc.max(..self.data)) - let range = max - min - - let binned = self.data.sorted().fold( (0,)*self.bins, (acc, it) => { - let bin = int(self.bins * (it - min) / (max - min)) - acc.at(bin - 1) += 1 - return acc - }) - - self.line-data = binned.enumerate().map( ((x, y)) => { - (0 + y / 10, min + x) - }) - - // Generate stroke paths - self.stroke-paths = util.compute-stroke-paths(self.line-data, - (x.min, y.min), (x.max, y.max)) - - // Compute fill paths if filling is requested - self.fill = self.at("fill", default: false) - if self.fill { - self.fill-paths = util.compute-fill-paths( - self.line-data, - (x.min, y.min), - (x.max, y.max) - ) - } - - return self -} - -#let _stroke(self, ctx) = { - let (x, y) = (ctx.x, ctx.y) - - for p in self.stroke-paths { - draw.line(..p, fill: none) - } -} - -#let _fill(self, ctx) = { - // fill-segments-to(self.fill-paths, y.min) +#let kernal-normal(x, stdev: 1.5) = { + (1/calc.sqrt(2*calc.pi*calc.pow(stdev,2))) * calc.exp( - (x*x)/(2*calc.pow(stdev,2))) } #let violin( data, + x-key: 0, + y-key: 1, + side: "left", // "left", "right", "both" style: (:), + kernel: kernal-normal.with(stdev: 1.5), + bandwidth: 1, + extend: 0.5, axes: ("x", "y"), - bins: 7, ) = { - (( - type: "violin", - axes: axes, - data: data, - bins: bins, - style: style, - plot-prepare: _prepare, - plot-stroke: _stroke, - plot-fill: _fill, - plot-legend-preview: self => { - draw.rect((0,0), (1,1), ..self.style) + for category in data { + let (x, ys) = (category.at(x-key), category.at(y-key)) + let n = ys.len() + let (min, max) = (calc.min(..ys), calc.max(..ys)) + let domain = (min - (max - min)*extend, max + (max - min)*extend) + + let convolve = (t, side: side)=>{ + let val = ys.map((y)=>kernel((y - t)/bandwidth)).sum() + (x + (1/(n*bandwidth) * val) * if side == "left" {-1} else {1}, t) + } + + if (side in ("left", "both")) { + line.add( + convolve.with(side: "left"), + domain: domain, + line: "raw", + fill-type: "shape", + fill: true, + style: style + ) + } + + if (side in ("right", "both")){ + line.add( + convolve.with(side: "right"), + domain: domain, + line: "raw", + fill-type: "shape", + fill: true, + style: style + ) } - ),) + } + } \ No newline at end of file diff --git a/tests/plot/violin/test.typ b/tests/plot/violin/test.typ index 80e70f1..4abb751 100644 --- a/tests/plot/violin/test.typ +++ b/tests/plot/violin/test.typ @@ -10,10 +10,21 @@ plot.plot(size: (9, 6), // x-tick-step: none, // y-tick-step: none, - y-max: 10, + y-min: -10, y-max: 20, + x-min: -1, x-max: 2, { - let vals = (5,4,6,8,5,4,1,5,5,5,4,2,5,4,6,5,4,5,8,4,5,) - cetz-plot.plot.add(vals.map(it=>(0,it)), mark: "x", style: (stroke: none)) - cetz-plot.plot.violin(vals) + let vals = ( + (0,(5,4,6,8,5.1,4.1,1,5.2,5.3,5.4,4.2,2,5.5,4.3,6,5,4,5,8,4,5,)), + (1,(5,4,6,8,5.1,4.1,1,5.2,5.3,5.4,4.2,2,5.5,4.3,6,5,4,5,8,4,5,)), + ) + // for (x, ys) in vals { + // cetz-plot.plot.add(ys.map(y=>(x,y)), mark: "x", style: (stroke: none)) + // } + cetz-plot.plot.violin( + vals, + extend: 0.35, + side: "right", + bandwidth: 0.5 + ) }) }) From 3892b32e6f63c001d975d1e2873a4ecf82c26b53 Mon Sep 17 00:00:00 2001 From: James R Swift Date: Tue, 30 Jul 2024 14:27:19 +0100 Subject: [PATCH 04/11] Better violin plots --- tests/plot/violin/ref/1.png | Bin 0 -> 21674 bytes tests/plot/violin/test.typ | 24 +++++++++++++++++++----- 2 files changed, 19 insertions(+), 5 deletions(-) create mode 100644 tests/plot/violin/ref/1.png diff --git a/tests/plot/violin/ref/1.png b/tests/plot/violin/ref/1.png new file mode 100644 index 0000000000000000000000000000000000000000..d5d862138cbd19499862aefa0b6add09bed19fb8 GIT binary patch literal 21674 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 I_MeFR7dmzwSO5S3 literal 0 HcmV?d00001 diff --git a/tests/plot/violin/test.typ b/tests/plot/violin/test.typ index 4abb751..0333080 100644 --- a/tests/plot/violin/test.typ +++ b/tests/plot/violin/test.typ @@ -8,23 +8,37 @@ import draw: * plot.plot(size: (9, 6), - // x-tick-step: none, - // y-tick-step: none, + + y-label: [Age], y-min: -10, y-max: 20, - x-min: -1, x-max: 2, + + x-label: [Class], + x-min: -0.5, x-max: 2.5, + x-tick-step: none, + x-ticks: ( (0, [First]), (1, [Second]), (2, [Third])), { let vals = ( (0,(5,4,6,8,5.1,4.1,1,5.2,5.3,5.4,4.2,2,5.5,4.3,6,5,4,5,8,4,5,)), (1,(5,4,6,8,5.1,4.1,1,5.2,5.3,5.4,4.2,2,5.5,4.3,6,5,4,5,8,4,5,)), + (2,(5,4,6,8,5.1,4.1,1,5.2,5.3,5.4,4.2,2,5.5,4.3,6,5,4,5,8,4,5,)), ) // for (x, ys) in vals { // cetz-plot.plot.add(ys.map(y=>(x,y)), mark: "x", style: (stroke: none)) // } cetz-plot.plot.violin( vals, - extend: 0.35, + extents: 0.5, + side: "left", + bandwidth: 0.45, + label: [Male] + ) + + cetz-plot.plot.violin( + vals, + extents: 0.5, side: "right", - bandwidth: 0.5 + bandwidth: 0.45, + label: [Female] ) }) }) From 2006ff736d759fe69b71871e1ac936e7665d88df Mon Sep 17 00:00:00 2001 From: James R Swift Date: Tue, 30 Jul 2024 14:27:30 +0100 Subject: [PATCH 05/11] Better violin plots --- src/plot/violin.typ | 163 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 129 insertions(+), 34 deletions(-) diff --git a/src/plot/violin.typ b/src/plot/violin.typ index 3d42990..949a40c 100644 --- a/src/plot/violin.typ +++ b/src/plot/violin.typ @@ -1,55 +1,150 @@ -#import "line.typ" +#import "/src/cetz.typ": draw + +#import "util.typ" +#import "sample.typ" + #let kernal-normal(x, stdev: 1.5) = { (1/calc.sqrt(2*calc.pi*calc.pow(stdev,2))) * calc.exp( - (x*x)/(2*calc.pow(stdev,2))) } + +#let _violin-render(self, ctx, violin, filling: true) = { + let path = range(self.samples) + .map((t)=>violin.min + (violin.max - violin.min) * (t /self.samples )) + .map((u)=>(u, (violin.convolve)(u))) + .map(((u,v)) => { + (violin.x-position + v, u) + }) + + if self.side == "both"{ + path += path.rev().map(((x,y))=> {(2 * violin.x-position - x,y)}) + } else if self.side == "left"{ + path = path.map( ((x,y))=>{(2 * violin.x-position - x,y)}) + } + + let (x, y) = (ctx.x, ctx.y) + let stroke-paths = util.compute-stroke-paths(path, (x.min, y.min), (x.max, y.max)) + + for p in stroke-paths{ + let args = arguments(..p, closed: self.side == "both") + if filling { + args = arguments(..args, stroke: none) + } else { + args = arguments(..args, fill: none) + } + draw.line(..args) + } +} + +#let _plot-prepare(self, ctx) = { + self.violins = self.data.map(entry=> { + let points = entry.at(self.y-key) + let (min, max) = (calc.min(..points), calc.max(..points)) + let range = calc.abs(max - min) + ( + x-position: entry.at(self.x-key), + points: points, + length: points.len(), + min: min - (self.extents * range), + max: max + (self.extents * range), + convolve: (t) => { + points.map((y)=>(self.kernel)((y - t)/self.bandwidth)).sum() / (points.len() * self.bandwidth) + } + ) + }) + return self +} + +#let _plot-stroke(self, ctx) = { + for violin in self.violins { + _violin-render(self, ctx, violin, filling: false) + } +} + +#let _plot-fill(self, ctx) = { + for violin in self.violins { + _violin-render(self, ctx, violin, filling: true) + } +} + +#let _plot-legend-preview(self) = { + draw.rect((0,0), (1,1), ..self.style) +} + #let violin( data, x-key: 0, y-key: 1, - side: "left", // "left", "right", "both" - style: (:), + side: "right", // "left", "right", "both" kernel: kernal-normal.with(stdev: 1.5), bandwidth: 1, - extend: 0.5, + extents: 0.25, + + samples: 50, + style: (:), + mark-style: (:), axes: ("x", "y"), + label: none, ) = { - for category in data { - let (x, ys) = (category.at(x-key), category.at(y-key)) - let n = ys.len() - let (min, max) = (calc.min(..ys), calc.max(..ys)) - let domain = (min - (max - min)*extend, max + (max - min)*extend) + (( + type: "violins", - let convolve = (t, side: side)=>{ - let val = ys.map((y)=>kernel((y - t)/bandwidth)).sum() - (x + (1/(n*bandwidth) * val) * if side == "left" {-1} else {1}, t) - } + data: data, + x-key: x-key, + y-key: y-key, + side: side, + kernel: kernel, + bandwidth: bandwidth, + extents: extents, - if (side in ("left", "both")) { - line.add( - convolve.with(side: "left"), - domain: domain, - line: "raw", - fill-type: "shape", - fill: true, - style: style - ) - } + samples: samples, + style: style, + mark-style: mark-style, + axes: axes, + label: label, - if (side in ("right", "both")){ - line.add( - convolve.with(side: "right"), - domain: domain, - line: "raw", - fill-type: "shape", - fill: true, - style: style - ) - } + plot-prepare: _plot-prepare, + plot-stroke: _plot-stroke, + plot-fill: _plot-fill, + plot-legend-preview: _plot-legend-preview, + ),) + // for category in data { + // let (x, ys) = (category.at(x-key), category.at(y-key)) + // let n = ys.len() + // let (min, max) = (calc.min(..ys), calc.max(..ys)) + // let domain = (min - (max - min)*extend, max + (max - min)*extend) - } + // let convolve = (t, side: side)=>{ + // let val = ys.map((y)=>kernel((y - t)/bandwidth)).sum() + // (x + (1/(n*bandwidth) * val) * if side == "left" {-1} else {1}, t) + // } + + // if (side in ("left", "both")) { + // line.add( + // convolve.with(side: "left"), + // domain: domain, + // line: "raw", + // fill-type: "shape", + // fill: true, + // style: style + // ) + // } + + // if (side in ("right", "both")){ + // line.add( + // convolve.with(side: "right"), + // domain: domain, + // line: "raw", + // fill-type: "shape", + // fill: true, + // style: style + // ) + // } + + + // } } \ No newline at end of file From e5689c83c3c29a3fae66323a20b92d0f4a93a390 Mon Sep 17 00:00:00 2001 From: James R Swift Date: Tue, 30 Jul 2024 15:16:16 +0100 Subject: [PATCH 06/11] documentation and clean --- src/plot/violin.typ | 63 +++++++++++++++++---------------------------- 1 file changed, 23 insertions(+), 40 deletions(-) diff --git a/src/plot/violin.typ b/src/plot/violin.typ index 949a40c..145968e 100644 --- a/src/plot/violin.typ +++ b/src/plot/violin.typ @@ -1,14 +1,11 @@ #import "/src/cetz.typ": draw - #import "util.typ" #import "sample.typ" - #let kernal-normal(x, stdev: 1.5) = { (1/calc.sqrt(2*calc.pi*calc.pow(stdev,2))) * calc.exp( - (x*x)/(2*calc.pow(stdev,2))) } - #let _violin-render(self, ctx, violin, filling: true) = { let path = range(self.samples) .map((t)=>violin.min + (violin.max - violin.min) * (t /self.samples )) @@ -33,7 +30,7 @@ } else { args = arguments(..args, fill: none) } - draw.line(..args) + draw.line(..self.style, ..args) } } @@ -72,6 +69,28 @@ draw.rect((0,0), (1,1), ..self.style) } + +/// Add a violin plot +/// +/// A violin plot is a chart that can be used to compare the distribution of continuous +/// data between categories. +/// +/// - data (array): Array of data items. An item is an array containing an `x` and one +/// or more `y` values. +/// - x-key (int, string): Key to use for retreiving the `x` position of the violin. +/// - y-key (int, string): Key to use for retreiving values of points within the category. +/// - side (string): The sides of the violin to be rendered: +/// / left: Plot only the left side of the violin. +/// / right: Plot only the right side of the violin. +/// / both: Plot both sides of the violin. +/// - kernel (function): The kernel density estimator function. +/// - bandwidth (float): The smoothing parameter of the kernel. +/// - extents (float): The extension of the domain, expressed as a fraction of spread. +/// - samples (int): The number of samples of the kernel to render. +/// - style (dictionary): Style override dictionary. +/// - mark-style (dictionary): (unused, will eventually be used to render interquartile ranges). +/// - axes (axes): (unstable, documentation to follow once completed). +/// - label (none, content): The name of the category to be shown in the legend. #let violin( data, x-key: 0, @@ -111,40 +130,4 @@ plot-legend-preview: _plot-legend-preview, ),) - // for category in data { - // let (x, ys) = (category.at(x-key), category.at(y-key)) - // let n = ys.len() - // let (min, max) = (calc.min(..ys), calc.max(..ys)) - // let domain = (min - (max - min)*extend, max + (max - min)*extend) - - // let convolve = (t, side: side)=>{ - // let val = ys.map((y)=>kernel((y - t)/bandwidth)).sum() - // (x + (1/(n*bandwidth) * val) * if side == "left" {-1} else {1}, t) - // } - - // if (side in ("left", "both")) { - // line.add( - // convolve.with(side: "left"), - // domain: domain, - // line: "raw", - // fill-type: "shape", - // fill: true, - // style: style - // ) - // } - - // if (side in ("right", "both")){ - // line.add( - // convolve.with(side: "right"), - // domain: domain, - // line: "raw", - // fill-type: "shape", - // fill: true, - // style: style - // ) - // } - - - // } - } \ No newline at end of file From 9d218d5a90cadf91325210a0a5397074e7be39bc Mon Sep 17 00:00:00 2001 From: James R Swift Date: Tue, 30 Jul 2024 15:17:33 +0100 Subject: [PATCH 07/11] update test --- tests/plot/violin/ref/1.png | Bin 21674 -> 21517 bytes tests/plot/violin/test.typ | 29 +++++++++++++++++++++++------ 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/tests/plot/violin/ref/1.png b/tests/plot/violin/ref/1.png index d5d862138cbd19499862aefa0b6add09bed19fb8..2b5eaf1502d8ead8dc6b04bdbb98a6cb81a71fdc 100644 GIT binary patch literal 21517 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 literal 21674 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 I_MeFR7dmzwSO5S3 diff --git a/tests/plot/violin/test.typ b/tests/plot/violin/test.typ index 0333080..bbc2fbc 100644 --- a/tests/plot/violin/test.typ +++ b/tests/plot/violin/test.typ @@ -7,6 +7,20 @@ #test-case({ import draw: * + draw.set-style( + axes: ( + stroke: 0.55pt, + tick: ( + stroke: 0.5pt, + ) + ), + legend: ( + stroke: none, + ) + ) + + let default-colors = (palette.blue-colors.at(3), palette.pink-colors.at(3)) + plot.plot(size: (9, 6), y-label: [Age], @@ -16,29 +30,32 @@ x-min: -0.5, x-max: 2.5, x-tick-step: none, x-ticks: ( (0, [First]), (1, [Second]), (2, [Third])), + + plot-style: (i) => { + let color = default-colors.at(calc.rem(i, default-colors.len())) + (stroke: color + 0.75pt, fill: color.lighten(75%)) + }, { let vals = ( (0,(5,4,6,8,5.1,4.1,1,5.2,5.3,5.4,4.2,2,5.5,4.3,6,5,4,5,8,4,5,)), (1,(5,4,6,8,5.1,4.1,1,5.2,5.3,5.4,4.2,2,5.5,4.3,6,5,4,5,8,4,5,)), (2,(5,4,6,8,5.1,4.1,1,5.2,5.3,5.4,4.2,2,5.5,4.3,6,5,4,5,8,4,5,)), ) - // for (x, ys) in vals { - // cetz-plot.plot.add(ys.map(y=>(x,y)), mark: "x", style: (stroke: none)) - // } + cetz-plot.plot.violin( vals, extents: 0.5, side: "left", bandwidth: 0.45, - label: [Male] + label: [Male], ) cetz-plot.plot.violin( vals, extents: 0.5, side: "right", - bandwidth: 0.45, + bandwidth: 0.5, label: [Female] ) }) -}) +}) \ No newline at end of file From d592d48e30cbaf96f2a056ce657dc74a190b86ce Mon Sep 17 00:00:00 2001 From: James R Swift Date: Tue, 30 Jul 2024 15:26:02 +0100 Subject: [PATCH 08/11] Add to manual and fix typo --- manual.typ | 2 +- src/plot/violin.typ | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/manual.typ b/manual.typ index ad4d930..6a938ce 100644 --- a/manual.typ +++ b/manual.typ @@ -54,7 +54,7 @@ module imported into the namespace. = Plot #doc-style.parse-show-module("/src/plot.typ") -#for m in ("line", "bar", "boxwhisker", "contour", "errorbar", "annotation", "formats") { +#for m in ("line", "bar", "boxwhisker", "contour", "errorbar", "annotation", "formats", "violin") { doc-style.parse-show-module("/src/plot/" + m + ".typ") } diff --git a/src/plot/violin.typ b/src/plot/violin.typ index 145968e..771fcdf 100644 --- a/src/plot/violin.typ +++ b/src/plot/violin.typ @@ -2,7 +2,7 @@ #import "util.typ" #import "sample.typ" -#let kernal-normal(x, stdev: 1.5) = { +#let kernel-normal(x, stdev: 1.5) = { (1/calc.sqrt(2*calc.pi*calc.pow(stdev,2))) * calc.exp( - (x*x)/(2*calc.pow(stdev,2))) } @@ -95,8 +95,8 @@ data, x-key: 0, y-key: 1, - side: "right", // "left", "right", "both" - kernel: kernal-normal.with(stdev: 1.5), + side: "right", + kernel: kernel-normal.with(stdev: 1.5), bandwidth: 1, extents: 0.25, From 9e0a373dee1dfc5b1f8496e739747ce84671a50a Mon Sep 17 00:00:00 2001 From: James R Swift Date: Wed, 31 Jul 2024 11:01:33 +0100 Subject: [PATCH 09/11] rename to `add-violin` --- src/plot.typ | 2 +- src/plot/violin.typ | 2 +- tests/plot/violin/test.typ | 7 +++++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/plot.typ b/src/plot.typ index 43b2553..05640d5 100644 --- a/src/plot.typ +++ b/src/plot.typ @@ -12,7 +12,7 @@ #import "/src/plot/bar.typ": add-bar #import "/src/plot/errorbar.typ": add-errorbar #import "/src/plot/mark.typ" -#import "/src/plot/violin.typ": violin +#import "/src/plot/violin.typ": add-violin #import "/src/plot/formats.typ" #import plot-legend: add-legend diff --git a/src/plot/violin.typ b/src/plot/violin.typ index 771fcdf..744bca1 100644 --- a/src/plot/violin.typ +++ b/src/plot/violin.typ @@ -91,7 +91,7 @@ /// - mark-style (dictionary): (unused, will eventually be used to render interquartile ranges). /// - axes (axes): (unstable, documentation to follow once completed). /// - label (none, content): The name of the category to be shown in the legend. -#let violin( +#let add-violin( data, x-key: 0, y-key: 1, diff --git a/tests/plot/violin/test.typ b/tests/plot/violin/test.typ index bbc2fbc..9af65f7 100644 --- a/tests/plot/violin/test.typ +++ b/tests/plot/violin/test.typ @@ -25,11 +25,14 @@ y-label: [Age], y-min: -10, y-max: 20, + y-tick-step: 10, y-minor-tick-step: 5, + y-grid: "major", x-label: [Class], x-min: -0.5, x-max: 2.5, x-tick-step: none, x-ticks: ( (0, [First]), (1, [Second]), (2, [Third])), + x-grid: "major", plot-style: (i) => { let color = default-colors.at(calc.rem(i, default-colors.len())) @@ -42,7 +45,7 @@ (2,(5,4,6,8,5.1,4.1,1,5.2,5.3,5.4,4.2,2,5.5,4.3,6,5,4,5,8,4,5,)), ) - cetz-plot.plot.violin( + cetz-plot.plot.add-violin( vals, extents: 0.5, side: "left", @@ -50,7 +53,7 @@ label: [Male], ) - cetz-plot.plot.violin( + cetz-plot.plot.add-violin( vals, extents: 0.5, side: "right", From bb654c97fc0e9958d329d410479c66ae31f61f61 Mon Sep 17 00:00:00 2001 From: James R Swift Date: Wed, 31 Jul 2024 11:05:29 +0100 Subject: [PATCH 10/11] document kernal signature --- src/plot/violin.typ | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/plot/violin.typ b/src/plot/violin.typ index 744bca1..3f8f876 100644 --- a/src/plot/violin.typ +++ b/src/plot/violin.typ @@ -83,7 +83,9 @@ /// / left: Plot only the left side of the violin. /// / right: Plot only the right side of the violin. /// / both: Plot both sides of the violin. -/// - kernel (function): The kernel density estimator function. +/// - kernel (function): The kernel density estimator function, which takes a single +/// `x` value relative to the center of a distribution (0) and +/// normalized by the bandwidth /// - bandwidth (float): The smoothing parameter of the kernel. /// - extents (float): The extension of the domain, expressed as a fraction of spread. /// - samples (int): The number of samples of the kernel to render. From 82681930a2c309cbed56432f207599e1913d34f0 Mon Sep 17 00:00:00 2001 From: James R Swift Date: Wed, 31 Jul 2024 11:10:03 +0100 Subject: [PATCH 11/11] update tests --- tests/plot/violin/ref/1.png | Bin 21517 -> 19717 bytes tests/plot/violin/test.typ | 1 - 2 files changed, 1 deletion(-) diff --git a/tests/plot/violin/ref/1.png b/tests/plot/violin/ref/1.png index 2b5eaf1502d8ead8dc6b04bdbb98a6cb81a71fdc..88e6d7d97524cf31d013a0a082bb009767b179b7 100644 GIT binary patch literal 19717 zcmdtK2UJr{+ct{Qlq!n!E((Hx(xnR0tAg}ir57difPx4}6BQ6?(nUh=9i(?5kkBK& zgen9i5I8%a&+~lW_rCxCp0ob7&N?S7vXi}M?z!8{+;h)034f%aNJ>OUgoA@as;nfZ zg@c2;fP-`K%cYCJ9rxjkMI0QpK4m$XC*Bk5FxCse&2M+n39sqGc)pElTKc1mWP^MdIMRFd+Ql9PABq*ae*bapQ~_wgi?Kw#2`u z{#SGVq<+@^zoq_HbN_|5)!eEL0#rq%Xf8F>$psL7e zv78H62yj@cuYKzXBGOkfZzXY1eRG+l{NkHSD!Fy_VTAu))&Ix1`+uP7|0X-n!jnza zckFoq_YHW;21M?Cu!>_>{%S^|+Y7OR-Bf;O&;ktf{R8U zNCjn*-Bz*d=~f`6<(6+(6%2b5KuL&mkiDX6Y||s{Q&Sb{6WQZzhH= zCaZW`}N?1CqGOzIQf}{vFU1X(FHPA1%Rzb zPM^Bdh2B_Vvc5}no9iRl+PQlVqD>99Xi<@}+@ne{m>r{2R`t0m% zrb5(QLTp&ritu^WJlqanAD@~qZ*OnorT~+q`i2I1c1cMSdSerl;NakjIOoaAa3y#5 zdrj};Wbm4f0PEWBhuzbPb|Q9M2^t*D^7rY5}WXsan^7XrDH+}Yl4&+Xk9cE_+h%uJb$ zjSZ_HTBI|fA56Y&eEhH{j(aJZ+A40kN6!p=lMR}q4(<2Dpx}B1hS#4qcTZF}R$Zfb zOjv5u8~^K<_wn1RddwbF^N?szpQA&}3Imf3@>(6f$-$vW4=Xa`V^eZ=E?tjmfq70x zdLh77PX|+@qob!uMP)ECm9!6EldMiwZP}G7KMW}ERHP7u|*WC|09nWrkNP~<7t#y?&f{?o6;&tWaf=K*l6v`?p!@3&D zqO5EuCnvSE`ew8uF2)4~6J<{|?d zPb<{|mntc~5&%>&VqwL2IU40k^3uLoftSq@1{u=*`SYjTLO4gN9V@IehPlXjw39iI zfrh5b_4%a7-pWvkRp-xL^CT4&6#`PaEa%bmhoM*w&y6SWbl^v=R;16+Ye#rtintdU z2QzptHcaAZy=;QW^CnkzYT$`ahwpoSetz45EAo^-pbs!OrN}P-cZ_hHk8K zv1U4bs-vSrF1h!e+RQ&)Juxw{s9~Q@<7<9?o#)1zsCCjM2zPezcyP%;9B8gb%-tph z@PsqFP@y-f5XZ;I-xIFCCZ^^!XHk=r!;25CxDe5HF!em9^6K^LA*2Ez5GWFLi&4}K zN5p5bs>b=7XX)q9EP%qUols{dBv4y5;H$=$AGKgoH^0P{ zKHh%l{OfQzZL9HUlayZgM{V`HB_(P5sZ`mWvXD}ACeJIwdn!||k3 zuN+J?>vOPWL{lK8PkzlW^(Vz?dCmANFZL#YwB4j#B`);pC`L1s+_9~2YJYQG<#wdC zIpmsEO36$P4N^{SB-WDAtvjCP(MIiU?OcuPv49mGR~bHgR;op01*1W>=|2U!Yj{{# z$w`&v^c3Zr`x^WE`ZW26PX`z%!lR>M1^YjH`G8V@Wu8K=QBYW60;5o^q2yNI z4KP3N6VQsxd=Db@+go|rTlG(hGdU%V;G_MltSn8bLpiyn!8C+<^UjSJiJnwiS1pm>VdTq;7cb^JV@~ZMThn#aO;^4B{N`iK4O^q=MgDjumd_b2h!xY0 z_*Q)|x8hdA!Hmmvtx2tia*`IQD6Oy)O=XY1>+?=^C0Kz`E-5Q3>qp1P)efFEUs>6U zQeEv4)JXWx668{Lf+^P1u@Z3r{_U!%I=ZdRv69Rh{mzZ3jrH~YEku#JzOk2^8+MTW2RSL%nfi+otz+Xs z_*=k0W=8*WcbDgyITLvAF$V{SGkQKo8t8hEEt7%|-+IlSmjI@XftzK}UAuOTmbS)w z$5K&Ik>Y;fi3DItjYtsImF~fkqELVv-hfujmUJ>*i%m{uNaiyvzob1@!FuNoiRwJ* zYe?o21wu+nO35dCL|{+?Y78M~6r+4TwZna3)BcUl{-E@!gop_BvatbRNGxe!z(&Pe zGTsDZ(4gMeR1_^g5_)=6>MI&==Y>7d(Xq!ZBsD2EZvp0|k|Tz#fTN8np3d5ch=?%b zI?pJmdD!1B!Pi!sl$3-zp&|)b9nS8BYD!04f!{JF;bI#@Tl!>ct601=e#mXfXfz{_ zCq7O456_#K(C=KQCV4re3xgQkVAFSj>zev3UZ?2p?S;O+eC-xzHm`B@XVUTUac^p{ zD@JBpNkQSY&5y{iNSb>YIXMbRZz3W}G6u1}`A4K%mW-?Q&lXjj6b5^GO4TGgr9cwz z-o49E*DEw`IRR0$pv4Aul$@L(KrgT^zGu5UkaCSfgOZ}pbE?75tL8#cu=mBnn+1i1 z9lOZ2weJUPbE~U~@$vDAiHF~a`F?n+j^X|H_K=IfsF^I}2#cf@xH}}D^mZuhne(?L zkOb*9le?Od5)uqC<_CwsB-9Z}JHNPC;Xbc$=k5ITY-^~ZoLsUL*cZLGnx3BitJqtr zveHO+%pA-}U0hpNHxE+>X%)!I39TGd7p4s{|OaDOWzdi16L$7-<27UoYkFQn*La47_Z@}zNJ|@7{ z!S*{gHit=lMM3HhRf80PU)&)@h80|#oOWv?dC-=ga(n1STwG9+xbGfk#{g&cF$P2X zdlm@~>&mfWyg^M&M8v?r@Ii~lKQ%2aCh48acqzUJL;DSB%-(yK=O2d(KM;|T+5X*o z=%Yc`Im&Ko`|5N*CxYEr4+2l zv;htDQtVWU9T2Zk#Hx4JCL| zMvql38=FPGrsE*YU06xLLRW0ORYOZ>r*u?gWSgMZdRj|-5-`08Q6uSvovu*aITZOt z{Q1{^ad1gqUX9zR4tm!Wg%eMR)l>h2&FO>n@k~-+IB{Zyy?_5+9?$iDZS0>x+?_76 zdy1v-!?(hZ@m7rU28OiA>POeFS!HBo2nsSIt1s!$4@05ycsK0+p&u$M#?~uwTJ7!a zwG?XL7ET(9@k-|;;kXYU{0|osCW z?l_$Zl^r?zbPmYD72DiPPW7*U@HlYZrh9jV9FK5T&Q0_!u8awu`!MDfp(0_6&J~gC zwak~?r~DOfr;(HW+^#R;tN(1qlu8{FJva7*>w4~+*np-$Z*Q6#K!1GS&8|>8y@^g7 zK_Zbm-V8`&U0odzNNjl4jXR|RujFL8h)yDKjdAq*sp;wV1@DFOQHTEJT@)=4)p&Y( z4zGF`KTr!p$KZRH@WLpNmW(f)qfwkFpl9Uf=KflIv$0z8qoHuSDN-R54u_YOm2sjJ zGD`w#JxcW3jypR$MTOsYk2qA&M2c+PNYQv&V|;R-qgHyU?W_Mgc8aM(e<>-KyEMkY z%fv)JPcMJ8I&yh=xjGBran|kE2}fRy@#gWd1Q`U5%pdI$rYVWmr$*u&&+DK5f_IcY zHG$lKwTt1L3c#99(c207if7+noL_782_Kw&w={v^vH<0PYXk_V4SPMSW(gKQKHk~q zIf_TKoj(SONhdBKYq{HM0UFrC=hqT4EX@cI@D-p5T*WLIan5)N17V+0Bg4*~T|u7H zMt8KKTUun^u_vnCO6u3h)jnV_=N3xp2Ud81RXoIa&YN>pgD^8QQxk<~N}@kk`Lysy#QMZNQXCc%d6~!F->wlng5I@y@ro9AL?Kk1xaqPh z4i3T`Xqpiyf8qBP(8}3&tjTcB=wLZz0Za&7&x>KT@s~igSiPPJ@wePJu++}(ojn8O z{rg$OncV+HC;ys6yV!qh4y;)y&batvDy;U;O?76n|Gh=eNmw#s4G)NZW_YX${x_Pz zIt8{2R%=+boVyvIDXhEw3se6a<+lI!7E^?Y>)?D}K@19Tx-+`I_lM@IX8(DomN3bB z*;IC}c1|?9mHAdTFY?E5ig-GR3pLL9i?i`d0Xvt}95<)c9oZ0Q&HJ24QIJh%^I-rrTXkI%@v^|P52$cd zi)M{&wUZYikbR8~m?;1c&1kv6uuc+9$x|&A>hrx88K7DFsH9s;!sUPathQ@;d zO=2nDh(&BMGcpRP3kVDA$}KG~kH#4q8Ch9cUesr%qXQzA-mb1oT}+TxAxrQ@q&edm z?Nis*)>Z=pgX`C?UkHlmnwm8+QVx_S2J#QoOta8=k?SY6XZUP$L)wRFss( zKW3!Dt`P<>`IEXva({+GBo@u`zbY*DmEzSA|S}+LJB0Hi{DiIe0}BEU$|Z$K0dAwv$nA@ z2?m9>?&!iLG+`esQVTX3Zeq|U`RX>7td` z&Us~J4FfYg)MhdDkU6w@s#Dmr`a#yEz;QFcIbfGulj$rdXyBp9V+)lg8NF2}{q zt)nC$Ai(x6F|j)ZReT*BP)MTfL+t|<>RZ%;p>J_yN5>_cmPvX2_6~|~zIu8IVISh+ z^4@lIcFJcJ7hi#d^4z=UZ4SqLODeP&A7ATNG+jK2RZL%2tUxeIb0&}jwm);3SE$8B z8;b71K|NN~{{9;!ZS8CNU8Fdg}68j-6ZK_QLrVw{L(HC;aVVl zI1Z^eiDv%Ywrlm&lraS@1H+R9|ff@~e?N?m~K zXPuH@lJDR6Ls4jp+YyZ5B9{~RYKT0YoentQ;Kp{Tm!RT+8wS)STH4who=4MlUh)e- zvQi^gfR9fzWMpP0_3hg$ZpR%R3XdN@#z6v$TysgM`}fy&tWfZt*k}H^J&NAr6+Iie z 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 WN^e3^{H0g0yei9U$Q8<(2mN1kccRz; literal 21517 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 diff --git a/tests/plot/violin/test.typ b/tests/plot/violin/test.typ index 9af65f7..ed1cbfc 100644 --- a/tests/plot/violin/test.typ +++ b/tests/plot/violin/test.typ @@ -32,7 +32,6 @@ x-min: -0.5, x-max: 2.5, x-tick-step: none, x-ticks: ( (0, [First]), (1, [Second]), (2, [Third])), - x-grid: "major", plot-style: (i) => { let color = default-colors.at(calc.rem(i, default-colors.len()))