diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7e3be18..b9d36a9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,15 +18,15 @@ jobs: strategy: fail-fast: false matrix: - branch: [version-1-4, devel] + branch: [version-1-6, version-2-0, devel] target: [linux, macos, windows] include: - target: linux - builder: ubuntu-18.04 + builder: ubuntu-latest - target: macos - builder: macos-10.15 + builder: macos-latest - target: windows - builder: windows-2019 + builder: windows-latest name: '${{ matrix.target }} (${{ matrix.branch }})' runs-on: ${{ matrix.builder }} steps: diff --git a/changelog.org b/changelog.org index 4dce8ac..685d7f6 100644 --- a/changelog.org +++ b/changelog.org @@ -1,3 +1,10 @@ +* v0.3.3 +- add ~hideLine~ for ~Trace~ object for scatter plots, in order to set + the line width to 0. Used for backwards compatibility, because + setting a value of 0 would be the default. +- add ~FillMode~ value of ~toSelf~ to allow colored bands / filled + polygons +- add example for a manual error band * v0.3.2 - fix behavior of =show= when =--threads:on= for =Grid= usage, in particular for example 18. =filename= argument is now optional, diff --git a/examples/all.nim b/examples/all.nim index 9f691d5..9c0f0ea 100644 --- a/examples/all.nim +++ b/examples/all.nim @@ -14,3 +14,4 @@ import fig15_horizontalBarPlot import fig16_plotly_sugar import fig17_color_font_legend import fig18_subplots +import fig21_error_band diff --git a/examples/fig21_error_band.nim b/examples/fig21_error_band.nim new file mode 100644 index 0000000..49fe121 --- /dev/null +++ b/examples/fig21_error_band.nim @@ -0,0 +1,43 @@ +import sequtils +import plotly +import chroma +from std / algorithm import reversed + +# simple example showcasing error bands (by hand) + +let + d = Trace[float](mode: PlotMode.LinesMarkers, `type`: PlotType.Scatter) + size = @[16.float] +d.marker = Marker[float](size: size) +d.xs = @[1'f64, 2, 3, 4, 5] +d.ys = @[1'f64, 2, 1, 9, 5] + +# Create a Trace for the error band +let + dBand = Trace[float](mode: PlotMode.Lines, `type`: PlotType.Scatter, + opacity: 0.75, # opacity 75% to be prettier + fill: ToSelf, # `ToSelf` means the filling is done to its own data + hideLine: true) # line width 0 disables the outline +# Create X data that is first increasing and then decreasing +dBand.xs = concat(d.xs, d.xs.reversed) +# Assign the actual ribbon band. Currently needs to be a seq +dBand.marker = Marker[float](color: @[color(0.6, 0.6, 0.6)]) + +# define some errors we will use (symmetric) +let yErr = d.ys.mapIt(0.25) +# now create the first upper band range +var yErrs = newSeqOfCap[float](d.ys.len * 2) # first upper, then lower +for i in 0 ..< d.ys.len: # upper errors + yErrs.add(d.ys[i] + yErr[i]) +# and now the lower +for i in countdown(d.ys.high, 0): # lower errors + yErrs.add(d.ys[i] - yErr[i]) +dBand.ys = yErrs + +let + layout = Layout(title: "testing", width: 1200, height: 400, + xaxis: Axis(title: "my x-axis"), + yaxis: Axis(title: "y-axis too"), autosize: false) + p = Plot[float](layout: layout, traces: @[d, dBand]) # assign both traces +echo p.save() +p.show() diff --git a/src/plotly/api.nim b/src/plotly/api.nim index 413850f..072538c 100644 --- a/src/plotly/api.nim +++ b/src/plotly/api.nim @@ -342,8 +342,10 @@ func `%`*(t: Trace): JsonNode = if t.xs.len > 0: fields.parseBarFields(t) of PlotType.Scatter, PlotType.ScatterGL: - if t.lineWidth > 0: + if not t.hideLine and t.lineWidth > 0: fields["line"] = %* {"width": t.lineWidth} + elif t.hideLine: + fields["line"] = %* {"width": 0} else: discard diff --git a/src/plotly/plotly_types.nim b/src/plotly/plotly_types.nim index e44bb99..1110705 100644 --- a/src/plotly/plotly_types.nim +++ b/src/plotly/plotly_types.nim @@ -43,6 +43,7 @@ type Unset = "" ToNextY = "tonexty" ToZeroY = "tozeroy" + ToSelf = "toself" PlotMode* {.pure.} = enum Lines = "lines" @@ -219,6 +220,7 @@ type orientation*: Orientation of Scatter, ScatterGL: lineWidth*: int + hideLine*: bool # can be used to force line to be width 0 (for backwards compatiblity) else: discard diff --git a/tests/plotly/test_api.nim b/tests/plotly/test_api.nim index b8355b9..6be6163 100644 --- a/tests/plotly/test_api.nim +++ b/tests/plotly/test_api.nim @@ -495,20 +495,21 @@ suite "show w/ filename without threads fails compilation": xs: xs, ys: ys) let plt = Plot[float](layout: layout, traces: @[d]) - ## NOTE: the following tests assume the test is compiled without `--threads:on`! - test "Plot - saveImage fails": - check compileFails(plt.saveImage("test.svg")) + when not compileOption("threads"): + ## NOTE: the following tests assume the test is compiled without `--threads:on`! + test "Plot - saveImage fails": + check compileFails(plt.saveImage("test.svg")) - test "PlotJson - saveImage fails": - check compileFails(plt.toPlotJson.saveImage("test.svg")) + test "PlotJson - saveImage fails": + check compileFails(plt.toPlotJson.saveImage("test.svg")) - test "Plot - show w/ filename w/o threads:on fails": - check compileFails(plt.show("test.svg")) + test "Plot - show w/ filename w/o threads:on fails": + check compileFails(plt.show("test.svg")) - test "PlotJson - show w/ filename w/o threads:on fails": - check compileFails(plt.toPlotJson.show("test.svg")) + test "PlotJson - show w/ filename w/o threads:on fails": + check compileFails(plt.toPlotJson.show("test.svg")) - test "Grid - show w/ filename w/o threads:on fails": - var grid = createGrid(1) - grid[0] = plt - check compileFails(grid.show("test.svg")) + test "Grid - show w/ filename w/o threads:on fails": + var grid = createGrid(1) + grid[0] = plt + check compileFails(grid.show("test.svg"))