Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/JuliaPlots/VennEuler.jl

Venn/Euler Diagrams for Julia
https://github.com/JuliaPlots/VennEuler.jl

Last synced: 3 months ago
JSON representation

Venn/Euler Diagrams for Julia

Awesome Lists containing this project

README

        

[![][travis-img]][travis-url] [![][codecov-img]][codecov-url] [![][slack-img]][slack-url]

[travis-img]: http://img.shields.io/travis/com/JuliaPlots/VennEuler.jl.svg
[travis-url]: https://travis-ci.com/JuliaPlots/VennEuler.jl
[codecov-img]: https://codecov.io/gh/JuliaPlots/VennEuler.jl/branch/master/graph/badge.svg
[codecov-url]: https://codecov.io/gh/JuliaPlots/VennEuler.jl
[slack-img]: https://img.shields.io/badge/chat-on%20slack-yellow.svg
[slack-url]: https://julialang.slack.com

VennEuler.jl
============

Generate area-proportional Venn/Euler diagrams in Julia. This is based, in part, on
algorithms from [Leland Wilkinson](http://www.cs.uic.edu/~wilkinson/Publications/venneuler.pdf).

Wilkinson, Leland. "Exact and approximate area-proportional circular Venn and Euler diagrams." _IEEE Transactions on Visualization and Computer Graphics_ 18, no. 2 (2012): 321-331.

GitHub: [HarlanH/VennEuler.jl](https://github.com/HarlanH/VennEuler.jl)

See LICENSE.md for the MIT license.

What It Does
============

Area-proportional Venn/Euler Diagrams show the overlap between sets in such a way that the size of the shapes
is proportional to the size of the sets, and the size of the overlaps on the page
is proportional to the size of the overlaps of the sets. In general, using circles, you can only do
this perfectly if you have two sets -- there will always be some residual error, where the sizes are
not perfectly proportional.

Wilkinson developed a straightforward method of approximately fitting area-proportional diagrams, but
the code was written in Java and was difficult to extend. This Julia package re-implements the
algorithm, with the following additions:

1. You can use other shapes -- currently squares, triangles, and rectangles, in addition to circles.
2. You can use 3-parameter (X, Y, Q) shapes, such as axis-parallel rectangles, in addition to
2-parameter (X, Y) shapes, such as squares.
3. There is a relatively easy-to-use specification structure that lets you mix and match shapes.
4. You can lock any parameters you'd like and prevent them from being improved, which is handy for
putting the largest shape in the middle.
5. It should be easy/easier for others to collaborate and extend.

How It Works
============

You define a structure that specifies the shapes and additional constraints you'd like on the fitting. That
gets translated into a "state" vector, which has 2 (or more) values per shape. A set of lower and upper
bounds is defined that keeps the shapes all inside the lines. Then the state vector and bounds are
optimized, currently with a rather brute-force optimizer. To compute the cost function, the shapes are
drawn onto in-memory bitmaps, the number of overlapping pixels is counted, and the distance between
the resulting counts and the actual target overlap vector is computed. That cost function is minimized.

The results can be rendered as an SVG file.

How To Use It
=============

```
(v1.2) pkg> add VennEuler

julia> using VennEuler

julia> data = Bool[
0 1 0
1 1 0
0 0 1
0 1 0
0 1 0
0 1 1
0 0 1
1 0 1
1 1 0
1 0 1
];

julia> eo = make_euler_object(["a","b","c"], data, EulerSpec(:circle), sizesum=0.5)
EulerObject(6, ["a", "b", "c"], [0.2060129077457011, 0.2060129077457011, 0.252313252202016, 0.252313252202016, 0.23032943298089031, 0.23032943298089031], [0.7939870922542989, 0.7939870922542989, 0.747686747797984, 0.747686747797984, 0.7696705670191097, 0.7696705670191097], [0.2060129077457011, 0.252313252202016, 0.23032943298089031], VennEuler.DisjointSet(["a", "b", "c"], [0, 2, 3, 1, 0, 2, 2, 0]), EulerSpec[EulerSpec(:circle, [NaN, NaN], [1, 2]), EulerSpec(:circle, [NaN, NaN], [3, 4]), EulerSpec(:circle, [NaN, NaN], [5, 6])], getfield(VennEuler, Symbol("##6#9")){EulerObject}(EulerObject(#= circular reference @-2 =#)))

julia> loss, state, result = optimize(eo, random_state(eo))
(0.024647421240312717, [0.5307496857847521, 0.3158423607955026, 0.747686747797984, 0.2905651018373946, 0.3429581864192766, 0.33534561404792806], :XTOL_REACHED)

julia> render("three-circles.svg", eo, state)
```

![readme-example-image](/docs/three-circles.svg)

For more examples see the unit tests.

How To Make It Better
=====================

Pull requests welcome! See the [issues list](https://github.com/HarlanH/VennEuler.jl/issues?state=open)!