Giter Site home page Giter Site logo

cetz-plot's Introduction

Note: cetz-plot has not been released yet! Use cetz 0.2.2 's internal plotting module.

CeTZ-Plot

CeTZ-Plot is a library that adds plots and charts to CeTZ, a library for drawing with Typst.

Examples

Plot Pie Chart Clustered Barchart

Click on the example image to jump to the code.

Usage

For information, see the manual (stable).

To use this package, simply add the following code to your document:

#import "@preview/cetz:0.2.2"
#import "@preview/cetz-plot:0.1.0": plot, chart

#cetz.canvas({
  // Your plot/chart code goes here
})

Installing

To install the CeTZ-Plot package under your local typst package dir you can use the install script from the repository.

Just

This project uses just, a handy command runner.

You can run all commands without having just installed, just have a look into the justfile. To install just on your system, use your systems package manager. On Windows, Cargo (cargo install just), Chocolatey (choco install just) and some other sources can be used. You need to run it from a sh compatible shell on Windows (e.g git-bash).

Testing

This package comes with some unit tests under the tests directory. To run all tests you can run the just test target. You need to have typst-test in your PATH: cargo install typst-test --git https://github.com/tingerrr/typst-test.

cetz-plot's People

Contributors

johannes-wolf avatar jamesxx avatar

Stargazers

Bauke avatar Steven Morad avatar Michael Schubert avatar Thomas N Atkins avatar  avatar Max Brown avatar Mackev avatar Bay avatar Sébastien d'Herbais de Thun avatar Florent Michel avatar Naivy Pujol Méndez avatar  avatar Li WeiHua avatar Mattéo Delabre avatar Je Sian Keith Herman avatar Mathemensch avatar _ivaquero_ avatar Andrea PIERRÉ avatar Gabriel Francisco avatar

Watchers

 avatar  avatar Christopher Marcotte avatar Jack avatar

Forkers

jamesxx

cetz-plot's Issues

[feature request] Provide set origin and anchor capabilities to `plot`

AFAIK we cannot set an origin to plot.plot. It is automatically set to (0,0), let alone set an anchor with respect to that origin. Although we can workaround it by translate the coordinate system within a group, it would be interesting to be able to set the origin as we do with content, circle, ...

Moreover, in addition to the anchors we can set via add-anchor, having built-in named compass anchors ("west", "north", etc.) is very effective when putting stuffs around the plot axis.

plot: Manual legend manipulation

I have a plot like so:
image

Which is constructed sort of like this:

#cetz.chart({
  plot.add(label: $n'_min$, ...)
  plot.add(label: $n'_max$, ...)
  for value in values {
    plot.add(style: palette.purple, label: if value.t == 1 { $n$ })
  }
})

This is obviously simplified, but it should across what kind of structure the data has that I'm visualizing.

I would like to add an entry to the legend which more clearly communicates that n is every line in the purple palette, without actually adding 7 different lines.

Currently, there doesn't seem to be a way to easily add some entry to the legend of a plot manually, or for a group of elements in the plot. Ideally, I would manually add an item to the plot at the end, such that it renders a gradient of the palette. Alternatively, I could somehow tell the plot that they all share a label, and it would figure it out from their chosen colors.

[Tracking] Refactor

When implementing logarithmic plots, and then when implementing polar plots, I ran into the challenge that the axis style has no control over how the data is plotted. This make sense if you treat axis styles as a purely visual element, however, this PR turns them into "drivers" that can change more behaviour of the underlying plot.

This is the initial PR, to allow people a better chance at collaborating on the refactor as well as to give maintainers a better chance at reviewing changes in smaller chunks rather than one hefty PR

Firstly, axis styles have been moved out of axes.typ (like in a previous draft PR), and instead are located in plot/axis-styles/. They become modules which must currently provide 3 functions: make-ctx (responsible for constructing the context within which data is prepared), data-viewport (responsible for transforming data along any number of axes, and onto the plot itself), and draw-axes (responsible for drawing the axes).

make-ctx now supplies an array axes rather than separately providing x and y, as a more general solution for when higher dimensional plots are implemented. It must also provide compute-fill-paths and compute-stroke-paths (previously supplied by the util.typ module) to allow for a finer grained control over clipping (of note: path computation occurs PRIOR to data-viewport transformations)

Plot elements (previously plot.add-<name>()) are now under plot.add.<name>, and plot.add has become plot.add.xy to disambiguate.

The school-book axis style remains unimplemented but I hope to bring it back at a later stage

To do and Tracking:

  • Pull current work into aggressive-refactor branch (#27)
  • Refactor the refactor: In moving code around a lot, boilerplate code has become prominent. It has been left in this PR because it does not adversely affect the implementation of features, but it is something that will need seeing to as a final step before merging this branch into main
  • Update the manual: Currently failing CI due to having not updated the manual.
  • Change axis styles from being modules to being dictionaries and a constructor to allow for a finer grained control over how any axis style is rendered

Axis Styles

Currently tracked are orthrect-2d and polar-2d. Wanted are: barycentric-2d, polar-3d, and orthorect-3d.

Orthorect-2d (previously scientific axis style)
  • Reintroduce not drawing unset axes
  • School-book axis style
  • Verify that logarithmic scales are still working
  • Improve clipping function performance (#29)
  • Flipping axes does not appear to work
Polar-2d (previously scientific-polar)
  • Improve clipping function performance (#30)
  • Ticks on axes: I think this can be improved stylistically
  • Grid in example in manual seems broken - needs investigating (addressed by c872366 of #31)

Plot elements

  • add.xy for plotting continuous/continuous data.
    • Add thorough tests
  • Annotations
  • Area chart (#34)
  • Bar/Column (#31)
    • horizontal bars will be supported through swapped axes and a wrapper
    • Stacked100 isn't exposed to public api
      #import "charts/bar/bar.typ" as bar: stacked, clustered, simple
  • Boxplot
  • Bubble plot
  • Contour
  • Error bar
    • Compute stroke paths using clipper
  • Violin plot
  • Series
    • Marks are not drawn within a series - needs investigation

There are many more plot elements to introduce too, so if anything needs adding to the list, we should.

Feature Request: logarithmic scale in plot

I would like to use a logarithmic x-axis in a cetz plot.
One example for a usage is bode plots, where the frequency (x-axis) is normally plotted logarithmically (10^(-3) to 10^3):
image
But it would also be useful for the y-axis, I think.
TikZ supports this via xmode=log, for example, but maybe x-tick-step could be extended for log scaling.

Marks do not display when axes is flipped

Simple one; making the min value for an axis greater than the max value swaps the axis direction, however when you do this the marks disappear.

Example below:

#cetz.canvas({
  import cetz: plot, palette

  let axis-options = (("x", "y"), ("x2", "y"), ("x", "y2"), ("x2", "y2"))
  
  plot.plot(
    size: (5,5),
    x-min: 0,
    x-max: 1,
    y-min: 0,
    y-max: 1,
    x2-min: 1,
    x2-max: 0,
    y2-min: 1,
    y2-max: 0,
    for axes in axis-options {
        plot.add(
        axes: axes,
        mark: "o",
        ((0.1,0.1), (0.4,0.4))
      )
    }
  )
})

Which gives:

image

So the x and y axis are normal, and the x2 and y2 axis are flipped. When I plot the same points for each combination of axes only the marks on the first plot on xy appear- they do not when either or both axes are flipped.

plot: minor ticks disappear when inverting y-axis

Hello,
when I invert the y-axis by swapping y-min and y-max, the minor ticks and the corresponding grid lines disappear. I guess this is a bug and I am the first person to try out that inversion. You can recreate it with the following snippet:

cetz.plot.plot(size: (12,8),
  x-tick-step: none, y-tick-step: 5,  y-minor-tick-step: 1,
  x-min: 0, x-max: 15, x-grid: true,
  y-min: 25, y-max: -1, y-grid: "both", {
    cetz.plot.add(((0,0),))
})

Fill only outside of a circle contour

When using x² + y² + op: ">=" + z: 9 + fill: true it fills outside the circle and inside of it (although it works as expected with hyperbola).

cetz-package/cetz#270 (comment):

This is very complicated to solve as of now. Please create a separate ticket for this. Detecting holes is a contour is currently not supported. We could test if a polygon lies insides another polygon. BUT Typst is currently unable to draw paths with holes in them.

code
#import "@local/cetz:0.1.2"

#cetz.canvas({
  import cetz.draw: *
  import cetz.plot
  let get-style(color) = {
    let (r, g, b, ..) = color.to-rgba()
    (line: (stroke: rgb(r, g, b) + 1pt, fill: color.lighten(25%)))
  }
  let x-min = -10
  let x-max = 10
  let y-min = -10
  let y-max = 10
  let width = x-max - x-min
  let height = y-max - y-min
  plot.plot(size: (15, 15), {
    // circle
    plot.add-contour(
      (x, y) => (calc.pow((x - 1), 2) + calc.pow((y - 1), 2)),
      op: ">=",
      z: 9,
      x-domain: (x-min, x-max),
      y-domain: (y-min, y-max),
      x-samples: 50,
      y-samples: 50,
      fill: true,
      style: get-style(rgb("#2D6FB47F")), // blue
    )
  })
})
screenshot

image

This issue was tested against redesign-internals#742d560.

cetz-plot not in typst universe

README.md suggests that you need to use:

#import "@preview/cetz-plot:0.1.0": plot, chart

to use cetz-plot, but it's not in the typst universe. Compiling a document with the suggested syntax results in the error:

error: package not found (searched for @preview/cetz-plot:0.1.0)

Removing the import producing a working plot. Has cetz-plot been incorporated into cetz? Does README.md need to be updated to reflect that?

Question: linear programming solver and contouring

I'd like to discuss two features which are probably not realistically possible to implement in Typst itself but which may be possible with some kind of rust bindings (which I believe are impossible with Typsts the way it works now).

Countours of surfaces

While I was implementing my own (very simple and totally not extensible) plotting library in Typst, I noticed that most things were very easy as long as I restricted myself to basic shapes, such as circles, rectangles and paths. This allows one to build plots such as pie charts, bar charts, boxplots, filled plots, Kaplan-Meier survival curves, etc. However, sometimes one might want to represent a smothed version of a 3D surface projected into 2D or a density plot, such as this (taken from the Matplotlib docs):

image

The colors themselves can be either discrete (using contours) or smooth (with some kind of linear interpolation between contours). The main algorithm used for those contours is the marching squares algorithm, which is slow and hard to implement in a scripting language like Typst. Fortunately, there seem to be very good implementations in rust for contour drawing.

Linear Programming

Something else which is kinda hard to do and which causes problems in many plotting libraries such as Matplotlib is mixing variable and fixed lengths. For examle, suppose you have a boxplot annotated with p values from comparisons beween groups (drawn in matplotlib):

bitmap

Because matplotlib doesn't handle fixed and variable dimensions inside plots very well, I've had to fix the limits through trial and error. Solving linear constraints for placement of items inside the plot is actually very easy, and doesn't require a real linear programming solver such as the simplex algorithm. However, if you want to take into accound the labels, I believe (but I haven't proved) that you start having to solve general linear programming for it to work. The asymptote library (a C++ program to draw graphics which uses TeX for text rendering actually implements the simplex method to handle these constraints). I believe (but again, I haven't proved) that solving "general" linear programming is required to determine the margins of a plot in more complex layouts such as these:

bitmap

There exists at least one pure rust implementation of the simplex algorithm for linear programming on any number of variables and constraints, and for the layout problem above, in which wahst is needed is a way to determine the margins of the plot, one can get by with only two variables (one can solve for the left and right margin in each axis independently of the other axes, assuming that the total size of the plot is constant, which it often is). The number of constraints is expectedd to be low because even plot with hundreds or thousands of datapoints only contain a couple elements such as legends and annotations which require solving a linear program. I don't know how feasible it would be to implement the simplex algorithm in typst and how performant it would be for small problems such as these.

Given that someone has implemented the simplex algorithm in pure python (https://github.com/dmishin/pylinprog/blob/master/linprog.py) in a very short file, I think that it shouldn't be too hard to implement in typst (everything that can be done with a python class can be done with a typst dictionary).

3D plotting

Plotting smooth 3D surfaces also seems pretty hard for typst, as it requires handling the way light would reflect on general surfaces or at least fine meshes. While this seems easy with a linear algebra package, such linear algebra would have to be performed in rust.

Conclusions

Currently, I believe there is no way of adding rust bindings to a typst package (and rightly so), so if one wants to be able to draw contours efficiently, such functionality would have to be added to typst itself, right? I don't believe that an interpreted language such as typst would be able to draw contours efficiently for a realistic number of points with the marching squares algorithm.

Regarding 3D plotting, it would require bindings to at least a matrix multiplication library and some vectorized functions optimized to work on large multidimensional arrays or at least matrices. This could have to be implemented in typst and not in a package.

Regaring linear programming, I believe it might be possible to implement the simplex algorithm in typst itself, and that may allow us to have more sophisticated layout algotithms and better automated positioning of graphical elements.

I don't know if this is in scope for this library, but these are ideas I'd like to leave here for discussion.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.