From 382899ed87d59224ce0cae66e09d5f371fac6dfe Mon Sep 17 00:00:00 2001 From: Johannes Wolf Date: Sun, 8 Sep 2024 14:13:24 +0200 Subject: [PATCH 1/3] plot: Typos & Formatting --- src/axes.typ | 12 +++++++----- src/plot/bar.typ | 6 +++--- src/plot/formats.typ | 2 +- src/plot/util.typ | 4 ++-- src/plot/violin.typ | 22 +++++++++++----------- tests/axes/log-mode/test.typ | 1 - tests/plot/violin/test.typ | 4 ++-- 7 files changed, 26 insertions(+), 25 deletions(-) diff --git a/src/axes.typ b/src/axes.typ index cfd4669..57e3cd5 100644 --- a/src/axes.typ +++ b/src/axes.typ @@ -497,7 +497,7 @@ } // Prepares the axis post creation. The given axis -// must be completely set-up, including its intervall. +// must be completely set-up, including its interval. // Returns the prepared axis #let prepare-axis(ctx, axis, name) = { let style = styles.resolve(ctx.style, root: "axes", @@ -531,15 +531,17 @@ // - vec (vector): Input vector to transform // -> vector #let transform-vec(size, x-axis, y-axis, z-axis, vec) = { + let axes = (x-axis, y-axis) - let (x,y,) = for (dim, axis) in (x-axis, y-axis).enumerate() { - + let (x, y,) = for (dim, axis) in axes.enumerate() { let s = size.at(dim) - axis.inset.sum() let o = axis.inset.at(0) - let transform-func(n) = if (axis.mode == "log") { + let transform-func(n) = if axis.mode == "log" { calc.log(calc.max(n, util.float-epsilon), base: axis.base) - } else {n} + } else { + n + } let range = transform-func(axis.max) - transform-func(axis.min) diff --git a/src/plot/bar.typ b/src/plot/bar.typ index 2c40233..bacd268 100644 --- a/src/plot/bar.typ +++ b/src/plot/bar.typ @@ -143,12 +143,12 @@ /// - data (array): Array of data items. An item is an array containing a x an one or more y values. /// For example `(0, 1)` or `(0, 10, 5, 30)`. Depending on the `mode`, the data items /// get drawn as either clustered or stacked rects. -/// - x-key: (int,string): Key to use for retreiving a bars x-value from a single data entry. +/// - x-key: (int,string): Key to use for retrieving a bars x-value from a single data entry. /// This value gets passed to the `.at(...)` function of a data item. -/// - y-key: (auto,int,string,array): Key to use for retreiving a bars y-value. For clustered/stacked +/// - y-key: (auto,int,string,array): Key to use for retrieving a bars y-value. For clustered/stacked /// data, this must be set to a list of keys (e.g. `range(1, 4)`). If set to `auto`, att but the first /// array-values of a data item are used as y-values. -/// - error-key: (none,int,string): Key to use for retreiving a bars y-error. +/// - error-key: (none,int,string): Key to use for retrieving a bars y-error. /// - mode (string): The mode on how to group data items into bars: /// / basic: Add one bar per data value. If the data contains multiple values, /// group those bars next to each other. diff --git a/src/plot/formats.typ b/src/plot/formats.typ index c51dbc4..8d0a7b5 100644 --- a/src/plot/formats.typ +++ b/src/plot/formats.typ @@ -115,7 +115,7 @@ /// ``` /// /// - value (number): Value to format -/// - digits (int): Number of digits for rouding the factor +/// - digits (int): Number of digits for rounding the factor /// -> Content #let sci(value, digits: 2) = { let exponent = if value != 0 { diff --git a/src/plot/util.typ b/src/plot/util.typ index bff54fc..113a18c 100644 --- a/src/plot/util.typ +++ b/src/plot/util.typ @@ -109,8 +109,8 @@ let is-inside = in-rect(pt) - let (x1, y1) = prev - let (x2, y2) = pt + let (x1, y1, ..) = prev + let (x2, y2, ..) = pt // Ignore lines if both ends are outsides the x-window and on the // same side. diff --git a/src/plot/violin.typ b/src/plot/violin.typ index 3f8f876..2c4291e 100644 --- a/src/plot/violin.typ +++ b/src/plot/violin.typ @@ -3,21 +3,21 @@ #import "sample.typ" #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))) + (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) - }) + .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)}) + path = path.map(((x,y)) => (2 * violin.x-position - x,y)) } let (x, y) = (ctx.x, ctx.y) @@ -46,7 +46,7 @@ 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) + points.map(y => (self.kernel)((y - t) / self.bandwidth)).sum() / (points.len() * self.bandwidth) } ) }) @@ -77,8 +77,8 @@ /// /// - 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. +/// - x-key (int, string): Key to use for retrieving the `x` position of the violin. +/// - y-key (int, string): Key to use for retrieving 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. @@ -132,4 +132,4 @@ plot-legend-preview: _plot-legend-preview, ),) -} \ No newline at end of file +} diff --git a/tests/axes/log-mode/test.typ b/tests/axes/log-mode/test.typ index f732959..57f44f8 100644 --- a/tests/axes/log-mode/test.typ +++ b/tests/axes/log-mode/test.typ @@ -163,4 +163,3 @@ } ) })) - diff --git a/tests/plot/violin/test.typ b/tests/plot/violin/test.typ index ed1cbfc..3822e2f 100644 --- a/tests/plot/violin/test.typ +++ b/tests/plot/violin/test.typ @@ -1,6 +1,6 @@ #set page(width: auto, height: auto) -#import "/src/lib.typ": * #import "/src/cetz.typ": * +#import "/src/lib.typ": * #import "/tests/helper.typ": * /* Empty plot */ @@ -60,4 +60,4 @@ label: [Female] ) }) -}) \ No newline at end of file +}) From 1922d1cb916b92e45d5ec28135fd4d9868f8f07c Mon Sep 17 00:00:00 2001 From: Johannes Wolf Date: Sun, 8 Sep 2024 14:15:00 +0200 Subject: [PATCH 2/3] plot: Cleanup functions --- src/plot/contour.typ | 6 ++---- src/plot/line.typ | 15 +++++---------- src/plot/util.typ | 16 ++++++++-------- src/plot/violin.typ | 3 +-- 4 files changed, 16 insertions(+), 24 deletions(-) diff --git a/src/plot/contour.typ b/src/plot/contour.typ index db611c9..e6c3f20 100644 --- a/src/plot/contour.typ +++ b/src/plot/contour.typ @@ -209,12 +209,10 @@ let (x, y) = (ctx.x, ctx.y) self.contours = self.contours.map(c => { - c.stroke-paths = util.compute-stroke-paths(c.line-data, - (x.min, y.min), (x.max, y.max)) + c.stroke-paths = util.compute-stroke-paths(c.line-data, x, y) if self.fill { - c.fill-paths = util.compute-fill-paths(c.line-data, - (x.min, y.min), (x.max, y.max)) + c.fill-paths = util.compute-fill-paths(c.line-data, x, y) } return c }) diff --git a/src/plot/line.typ b/src/plot/line.typ index 053ae58..be8671d 100644 --- a/src/plot/line.typ +++ b/src/plot/line.typ @@ -86,16 +86,14 @@ let (x, y) = (ctx.x, ctx.y) // 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, y) // Compute fill paths if filling is requested self.hypograph = self.at("hypograph", default: false) self.epigraph = self.at("epigraph", default: false) self.fill = self.at("fill", default: false) if self.hypograph or self.epigraph or self.fill { - self.fill-paths = util.compute-fill-paths(self.line-data, - (x.min, y.min), (x.max, y.max)) + self.fill-paths = util.compute-fill-paths(self.line-data, x, y) } return self @@ -463,15 +461,12 @@ // Generate stroke paths self.stroke-paths = ( - a: util.compute-stroke-paths(self.line-data.a, - (x.min, y.min), (x.max, y.max)), - b: util.compute-stroke-paths(self.line-data.b, - (x.min, y.min), (x.max, y.max)) + a: util.compute-stroke-paths(self.line-data.a, x, y), + b: util.compute-stroke-paths(self.line-data.b, x, y), ) // Generate fill paths - self.fill-paths = util.compute-fill-paths(self.line-data.a + self.line-data.b.rev(), - (x.min, y.min), (x.max, y.max)) + self.fill-paths = util.compute-fill-paths(self.line-data.a + self.line-data.b.rev(), x, y) return self } diff --git a/src/plot/util.typ b/src/plot/util.typ index 113a18c..5c59c80 100644 --- a/src/plot/util.typ +++ b/src/plot/util.typ @@ -173,21 +173,21 @@ /// Compute clipped stroke paths /// /// - points (array): X/Y data points -/// - low (vector): Lower clip-window coordinate -/// - high (vector): Upper clip-window coordinate +/// - x (axis): X-Axis +/// - y (axis): Y-Axis /// -> array List of stroke paths -#let compute-stroke-paths(points, low, high) = { - clipped-paths(points, low, high, fill: false) +#let compute-stroke-paths(points, x, y) = { + clipped-paths(points, (x.min, y.min), (x.max, y.max), fill: false) } /// Compute clipped fill path /// /// - points (array): X/Y data points -/// - low (vector): Lower clip-window coordinate -/// - high (vector): Upper clip-window coordinate +/// - x (axis): X-Axis +/// - y (axis): Y-Axis /// -> array List of fill paths -#let compute-fill-paths(points, low, high) = { - clipped-paths(points, low, high, fill: true) +#let compute-fill-paths(points, x, y) = { + clipped-paths(points, (x.min, y.min), (x.max, y.max), fill: true) } /// Return points of a sampled catmull-rom through the diff --git a/src/plot/violin.typ b/src/plot/violin.typ index 2c4291e..5da01e9 100644 --- a/src/plot/violin.typ +++ b/src/plot/violin.typ @@ -20,8 +20,7 @@ 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)) + let stroke-paths = util.compute-stroke-paths(path, ctx.x, ctx.y) for p in stroke-paths{ let args = arguments(..p, closed: self.side == "both") From e353f2e50177e0e14c5c1acb7e90f6d1d9450391 Mon Sep 17 00:00:00 2001 From: Johannes Wolf Date: Sun, 8 Sep 2024 14:16:39 +0200 Subject: [PATCH 3/3] tests: Add test for rotated annotation --- tests/plot/annotation/ref/1.png | Bin 18920 -> 35926 bytes tests/plot/annotation/test.typ | 21 +++++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/tests/plot/annotation/ref/1.png b/tests/plot/annotation/ref/1.png index 160481af1c55ca425a464bdd4d16b06207eab04e..f2fb296adcd392fad89f7c4b26fa1981fc35988f 100644 GIT binary patch delta 17314 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 U|H`l7A^JrX#YYMya;CxmAI(v~zW@LL delta 227 zcmV<90383;m;&gN0gx6C0x$>y0002x15wxj07Wzsu4^ z49{ZZME0GkP!*^Ov!8Yv_SQ*b(@7qa!F!tTvvk#}AG_^Wkvop53RQusFf&sXs)A~| zUCYDP%*@II%h^woj31LYNGp?&iUpG(i)RFYs&E34u_TkAi&>MqicFI{0T`3e0YQ@> d0R$KP#Rpg3I#Yw@t_c7D002ovPDHLkV1mCTVxIs2 diff --git a/tests/plot/annotation/test.typ b/tests/plot/annotation/test.typ index 917066c..1526a0a 100644 --- a/tests/plot/annotation/test.typ +++ b/tests/plot/annotation/test.typ @@ -23,3 +23,24 @@ }) }) }) + +#test-case({ + import draw: * + set-style(rect: (stroke: none)) + + plot.plot(size: (6, 4), x-horizontal: false, y-horizontal: true, { + plot.add(domain: (-calc.pi, 3*calc.pi), calc.sin) + plot.annotate(background: true, { + rect((0, -1), (calc.pi, 1), fill: blue.lighten(90%)) + rect((calc.pi, -1.1), (2*calc.pi, 1.1), fill: red.lighten(90%)) + rect((2*calc.pi, -1.5), (3.5*calc.pi, 1.5), fill: green.lighten(90%)) + }) + plot.annotate(padding: .1, { + line((calc.pi / 2, 1.1), (rel: (0, .2)), (rel: (2*calc.pi, 0)), (rel: (0, -.2))) + content((calc.pi * 1.5, 1.5), $ lambda $) + }) + plot.annotate(padding: .1, { + line((calc.pi / 2,-.1), (calc.pi / 2, .8), mark: (end: "stealth")) + }) + }) +})