viscose 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- viscose-0.1.0/LICENSE +21 -0
- viscose-0.1.0/PKG-INFO +184 -0
- viscose-0.1.0/README.md +155 -0
- viscose-0.1.0/pyproject.toml +40 -0
- viscose-0.1.0/setup.cfg +4 -0
- viscose-0.1.0/tests/test_viscose.py +943 -0
- viscose-0.1.0/viscose/__init__.py +12 -0
- viscose-0.1.0/viscose/axes.py +1032 -0
- viscose-0.1.0/viscose/figure.py +416 -0
- viscose-0.1.0/viscose/marks.py +409 -0
- viscose-0.1.0/viscose/palettes.py +250 -0
- viscose-0.1.0/viscose/text.py +119 -0
- viscose-0.1.0/viscose.egg-info/PKG-INFO +184 -0
- viscose-0.1.0/viscose.egg-info/SOURCES.txt +15 -0
- viscose-0.1.0/viscose.egg-info/dependency_links.txt +1 -0
- viscose-0.1.0/viscose.egg-info/requires.txt +10 -0
- viscose-0.1.0/viscose.egg-info/top_level.txt +1 -0
viscose-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 BojarLab
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
viscose-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: viscose
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Scientific plots that are pieces of art: palettes with their own special effects, drawn without matplotlib
|
|
5
|
+
Author-email: Daniel Bojar <daniel.bojar@gu.se>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/BojarLab/viscose
|
|
8
|
+
Project-URL: Bug Tracker, https://github.com/BojarLab/viscose/issues
|
|
9
|
+
Keywords: plotting,visualization,figures,palettes,glycowork
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Topic :: Scientific/Engineering :: Visualization
|
|
17
|
+
Requires-Python: >=3.11
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
License-File: LICENSE
|
|
20
|
+
Requires-Dist: numpy
|
|
21
|
+
Requires-Dist: glycorender>=0.5.4
|
|
22
|
+
Provides-Extra: cluster
|
|
23
|
+
Requires-Dist: scipy; extra == "cluster"
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: pytest; extra == "dev"
|
|
26
|
+
Requires-Dist: scipy; extra == "dev"
|
|
27
|
+
Requires-Dist: pandas; extra == "dev"
|
|
28
|
+
Dynamic: license-file
|
|
29
|
+
|
|
30
|
+
<h1 align="center">viscose</h1>
|
|
31
|
+
|
|
32
|
+
<p align="center"><strong>Scientific plots that are pieces of art.</strong><br>
|
|
33
|
+
Pick a palette. It brings its own colors, type, axes, and special effects.</p>
|
|
34
|
+
|
|
35
|
+
<p align="center"><img src="https://raw.githubusercontent.com/BojarLab/viscose/main/examples/readme/hero.png" alt="Ridgeline plots in all four palettes, above an embedding, a clustermap, a volcano plot, and a line and bar figure" width="100%"></p>
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
pip install viscose # numpy and glycorender are all it needs
|
|
39
|
+
pip install "viscose[cluster]" # adds scipy for clustermaps
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## One word changes everything
|
|
43
|
+
|
|
44
|
+
```python
|
|
45
|
+
import viscose as vc
|
|
46
|
+
|
|
47
|
+
fig, ax = vc.subplots(palette = 'aura')
|
|
48
|
+
fig.suptitle('Differential abundance', 'Tumor vs. healthy tissue, 412 glycans')
|
|
49
|
+
ax.scatter(x, y, hue = direction)
|
|
50
|
+
ax.axhline(2)
|
|
51
|
+
ax.set_xlabel('log_{2} fold change')
|
|
52
|
+
ax.set_ylabel('-log_{10} adjusted p')
|
|
53
|
+
fig.save('volcano.pdf')
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Same data, same code, and only `palette` changes. Spheres become rings, gradients become solid shapes, hairline axes become
|
|
57
|
+
heavy rounded ones, and titles go from light and wide to bold and tight. No styling code, no `rcParams`, and no theme files.
|
|
58
|
+
|
|
59
|
+
<p align="center"><img src="https://raw.githubusercontent.com/BojarLab/viscose/main/examples/readme/one_word.png" alt="The same volcano plot in Lumen, Couture, Poster, and Aura" width="100%"></p>
|
|
60
|
+
|
|
61
|
+
## Four palettes, four personalities
|
|
62
|
+
|
|
63
|
+
Each palette has two hues in four shades, and effects to match. Few colors, in shades of those few colors, on white: figures
|
|
64
|
+
that look composed in a paper and striking on a slide.
|
|
65
|
+
|
|
66
|
+
<p align="center"><img src="https://raw.githubusercontent.com/BojarLab/viscose/main/examples/readme/palettes.png" alt="A sample scene and eight shades for each palette" width="100%"></p>
|
|
67
|
+
|
|
68
|
+
### `lumen`: peacock and marigold
|
|
69
|
+
|
|
70
|
+
Gradients run through the marks, points are glossy spheres, lines glow, and everything rests on soft shadows.
|
|
71
|
+
|
|
72
|
+
<p align="center"><img src="https://raw.githubusercontent.com/BojarLab/viscose/main/examples/readme/lumen.png" alt="An embedding, a line and bar figure, and a ridgeline plot in Lumen" width="100%"></p>
|
|
73
|
+
|
|
74
|
+
### `couture`: plum and gold
|
|
75
|
+
|
|
76
|
+
Hairline axes held away from the data, slender needle bars, large light titles, and spaced capitals.
|
|
77
|
+
|
|
78
|
+
<p align="center"><img src="https://raw.githubusercontent.com/BojarLab/viscose/main/examples/readme/couture.png" alt="A mass spectrum, stacked bars, and a volcano plot in Couture" width="100%"></p>
|
|
79
|
+
|
|
80
|
+
### `poster`: forest and vermilion
|
|
81
|
+
|
|
82
|
+
Heavy rounded axes, big bold type, and thick solid marks cut apart by crisp white gaps.
|
|
83
|
+
|
|
84
|
+
<p align="center"><img src="https://raw.githubusercontent.com/BojarLab/viscose/main/examples/readme/poster.png" alt="A volcano plot, stacked bars, and a ridgeline plot in Poster" width="100%"></p>
|
|
85
|
+
|
|
86
|
+
### `aura`: burgundy and teal
|
|
87
|
+
|
|
88
|
+
Marks float on soft shadows in their own color, above rounded heatmap cells, with no axis lines at all.
|
|
89
|
+
|
|
90
|
+
<p align="center"><img src="https://raw.githubusercontent.com/BojarLab/viscose/main/examples/readme/aura.png" alt="A clustermap, a line and bar figure, and an embedding in Aura" width="100%"></p>
|
|
91
|
+
|
|
92
|
+
## Out of the box
|
|
93
|
+
|
|
94
|
+
The same data and the same labels, with no styling on either side: matplotlib and seaborn on the left, viscose on the right.
|
|
95
|
+
|
|
96
|
+
<p align="center"><img src="https://raw.githubusercontent.com/BojarLab/viscose/main/examples/readme/versus.png" alt="A volcano plot from matplotlib and seaborn defaults beside the same plot from viscose in Aura" width="100%"></p>
|
|
97
|
+
|
|
98
|
+
## Glycans in your plots
|
|
99
|
+
|
|
100
|
+
viscose shares its renderer with [glycowork](https://github.com/BojarLab/glycowork)'s GlycoDraw, so a plot can carry real SNFG
|
|
101
|
+
drawings as sharp as the rest of the figure, in PNG, PDF, and SVG.
|
|
102
|
+
|
|
103
|
+
```python
|
|
104
|
+
from glycowork.motif.draw import annotate_figure
|
|
105
|
+
|
|
106
|
+
ax.annotate('Neu5Ac(a2-6)Gal(b1-4)GlcNAc', (x, y), offset = (12, 0), svg_label = True)
|
|
107
|
+
fig.save('volcano.svg')
|
|
108
|
+
annotate_figure('volcano.svg', filepath = 'volcano.pdf', compact = True)
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
<p align="center"><img src="https://raw.githubusercontent.com/BojarLab/viscose/main/examples/readme/glycans.png" alt="A volcano plot and a biosynthetic network with SNFG glycan drawings as labels" width="100%"></p>
|
|
112
|
+
|
|
113
|
+
## Everything you reach for
|
|
114
|
+
|
|
115
|
+
`hue`, `style`, and `size` take one value per point and build the legend for you, as seaborn does.
|
|
116
|
+
|
|
117
|
+
```python
|
|
118
|
+
ax.scatter(x, y, hue = stage, style = source, size = abundance,
|
|
119
|
+
hue_label = 'Stage', style_label = 'Source', size_label = 'Abundance')
|
|
120
|
+
ax.text(0.02, 0.98, 'F = 4.2\np = 0.003', axes_fraction = True, va = 'top')
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
<p align="center"><img src="https://raw.githubusercontent.com/BojarLab/viscose/main/examples/readme/hue_style_size.png" alt="A scatter plot with color, shape, and size mapped to data, with a three-part legend" width="80%"></p>
|
|
124
|
+
|
|
125
|
+
Clustermaps come with both dendrograms and a color bar. Hand over a DataFrame and it brings its own labels.
|
|
126
|
+
|
|
127
|
+
```python
|
|
128
|
+
fig, heat = vc.clustermap(df, palette = 'aura', title = 'Glycan abundance by tissue', colorbar_label = 'z-score')
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
<p align="center"><img src="https://raw.githubusercontent.com/BojarLab/viscose/main/examples/readme/clustermap.png" alt="A clustermap of glycan abundance across tissues in Aura" width="80%"></p>
|
|
132
|
+
|
|
133
|
+
| | |
|
|
134
|
+
|---|---|
|
|
135
|
+
| **Plots** | `plot`, `scatter`, `bar`, `barh`, `stacked_bar`, `hist`, `fill_between`, `errorbar`, `stem`, `hlines`, `arrow`, `heatmap`, `ridgeline`, `dendrogram`, `axhline`, `axvline`, and `vc.clustermap` |
|
|
136
|
+
| **Markers** | `o`, `s`, `D`, `^`, `v`, `X`, `P`, and `*`, all with the palette's effects |
|
|
137
|
+
| **Annotation** | `text`, `annotate`, `legend`, and `colorbar`, with `_{sub}` and `^{super}` in any text |
|
|
138
|
+
| **Layout** | Colliding tick labels turn and thin themselves, labels move to the side with room, legends wrap, and the page grows for anything that needs it |
|
|
139
|
+
| **Output** | `fig.save` writes PNG, PDF, or SVG from the same geometry, with marks, gradients, and text as real vectors in PDF and SVG |
|
|
140
|
+
| **Display** | `fig.show()` works inline in Jupyter and slate, and in the system's image viewer from a terminal, with CI and coding agents kept silent |
|
|
141
|
+
| **SVG hooks** | `gid` on `arrow` and `scatter` names elements for hover text and scripting |
|
|
142
|
+
| **State** | None hidden: a figure is an object, with no current figure and nothing to close |
|
|
143
|
+
|
|
144
|
+
## Light and quick
|
|
145
|
+
|
|
146
|
+
No compiled plotting stack, no backends, and no font cache. For vector output, viscose is often many times faster than
|
|
147
|
+
matplotlib and seaborn, and its files can be far smaller. At 300 dpi, in Poster:
|
|
148
|
+
|
|
149
|
+
| | matplotlib and seaborn | viscose |
|
|
150
|
+
|---|---|---|
|
|
151
|
+
| Dependencies | Nine extra packages, 42.5 MB | numpy and glycorender, with 0.11 MB of its own code |
|
|
152
|
+
| Clustermap, 300 x 100, PDF | 1.57 s, 587 kB | **0.02 s, 79 kB** |
|
|
153
|
+
| Clustermap, 300 x 100, SVG | 1.40 s, 5,943 kB | **0.02 s, 182 kB** |
|
|
154
|
+
| Clustermap, 26 x 16, PDF | 0.11 s, 22 kB | **0.01 s**, 26 kB |
|
|
155
|
+
| Three lines with a legend, PDF | 0.03 s, 12 kB | **under 0.01 s**, 13 kB |
|
|
156
|
+
| Scatter, 100,000 points, PDF | 0.96 s, 1,524 kB | **0.19 s, 644 kB** |
|
|
157
|
+
| Scatter, 412 points, PNG | 0.18 s, 147 kB | 0.20 s, 180 kB |
|
|
158
|
+
|
|
159
|
+
matplotlib's compiled rasterizer is still about twice as fast on most PNGs,
|
|
160
|
+
and the soft shadows of Lumen and Aura add about half a second. To rerun the full comparison, wins and losses alike, use
|
|
161
|
+
[benchmarks/compare_matplotlib.py](https://github.com/BojarLab/viscose/blob/main/benchmarks/compare_matplotlib.py).
|
|
162
|
+
|
|
163
|
+
## Make it yours
|
|
164
|
+
|
|
165
|
+
`vc.set_palette('aura')` changes the default for every figure. A library that builds on viscose calls `vc.default_palette('aura')`
|
|
166
|
+
instead, which gives way to the choice of whoever uses it. In any palette, refer to its shades as `a0` to `a3` and `b0` to `b3`, dark
|
|
167
|
+
to pale, or as `ink`, `muted`, and `faint`; hex and CSS color names work too. `fig.pal.groups(3, 2)` gives categories grouped by hue,
|
|
168
|
+
here three shades of one and two of the other, and `fig.pal.contrast(n)` alternates between the hues for categories that have to stand
|
|
169
|
+
apart, as `scatter(hue = ...)` does.
|
|
170
|
+
|
|
171
|
+
A palette of your own is two hues, three text colors, and whichever effects you like:
|
|
172
|
+
|
|
173
|
+
```python
|
|
174
|
+
vc.register_palette(vc.Palette('midnight', ['#14213D', '#27477E', '#5C85C5', '#C4D5EE'], ['#8F5B00', '#D08C00', '#F2B83B', '#FBE5B0'],
|
|
175
|
+
'#14213D', '#5A6478', '#E6EAF1', point = 'sphere', bar = 'deep', shadow = 0.4))
|
|
176
|
+
fig, ax = vc.subplots(palette = 'midnight')
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Century Gothic is used where it is installed, and glycorender's bundled Comfortaa elsewhere.
|
|
180
|
+
|
|
181
|
+
## More
|
|
182
|
+
|
|
183
|
+
[examples/gallery.py](https://github.com/BojarLab/viscose/blob/main/examples/gallery.py) draws seven standard figures in every palette, [examples/features.py](https://github.com/BojarLab/viscose/blob/main/examples/features.py)
|
|
184
|
+
draws one sheet of features per palette, and [examples/readme_figures.py](https://github.com/BojarLab/viscose/blob/main/examples/readme_figures.py) draws every image on this page.
|
viscose-0.1.0/README.md
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
<h1 align="center">viscose</h1>
|
|
2
|
+
|
|
3
|
+
<p align="center"><strong>Scientific plots that are pieces of art.</strong><br>
|
|
4
|
+
Pick a palette. It brings its own colors, type, axes, and special effects.</p>
|
|
5
|
+
|
|
6
|
+
<p align="center"><img src="https://raw.githubusercontent.com/BojarLab/viscose/main/examples/readme/hero.png" alt="Ridgeline plots in all four palettes, above an embedding, a clustermap, a volcano plot, and a line and bar figure" width="100%"></p>
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
pip install viscose # numpy and glycorender are all it needs
|
|
10
|
+
pip install "viscose[cluster]" # adds scipy for clustermaps
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## One word changes everything
|
|
14
|
+
|
|
15
|
+
```python
|
|
16
|
+
import viscose as vc
|
|
17
|
+
|
|
18
|
+
fig, ax = vc.subplots(palette = 'aura')
|
|
19
|
+
fig.suptitle('Differential abundance', 'Tumor vs. healthy tissue, 412 glycans')
|
|
20
|
+
ax.scatter(x, y, hue = direction)
|
|
21
|
+
ax.axhline(2)
|
|
22
|
+
ax.set_xlabel('log_{2} fold change')
|
|
23
|
+
ax.set_ylabel('-log_{10} adjusted p')
|
|
24
|
+
fig.save('volcano.pdf')
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Same data, same code, and only `palette` changes. Spheres become rings, gradients become solid shapes, hairline axes become
|
|
28
|
+
heavy rounded ones, and titles go from light and wide to bold and tight. No styling code, no `rcParams`, and no theme files.
|
|
29
|
+
|
|
30
|
+
<p align="center"><img src="https://raw.githubusercontent.com/BojarLab/viscose/main/examples/readme/one_word.png" alt="The same volcano plot in Lumen, Couture, Poster, and Aura" width="100%"></p>
|
|
31
|
+
|
|
32
|
+
## Four palettes, four personalities
|
|
33
|
+
|
|
34
|
+
Each palette has two hues in four shades, and effects to match. Few colors, in shades of those few colors, on white: figures
|
|
35
|
+
that look composed in a paper and striking on a slide.
|
|
36
|
+
|
|
37
|
+
<p align="center"><img src="https://raw.githubusercontent.com/BojarLab/viscose/main/examples/readme/palettes.png" alt="A sample scene and eight shades for each palette" width="100%"></p>
|
|
38
|
+
|
|
39
|
+
### `lumen`: peacock and marigold
|
|
40
|
+
|
|
41
|
+
Gradients run through the marks, points are glossy spheres, lines glow, and everything rests on soft shadows.
|
|
42
|
+
|
|
43
|
+
<p align="center"><img src="https://raw.githubusercontent.com/BojarLab/viscose/main/examples/readme/lumen.png" alt="An embedding, a line and bar figure, and a ridgeline plot in Lumen" width="100%"></p>
|
|
44
|
+
|
|
45
|
+
### `couture`: plum and gold
|
|
46
|
+
|
|
47
|
+
Hairline axes held away from the data, slender needle bars, large light titles, and spaced capitals.
|
|
48
|
+
|
|
49
|
+
<p align="center"><img src="https://raw.githubusercontent.com/BojarLab/viscose/main/examples/readme/couture.png" alt="A mass spectrum, stacked bars, and a volcano plot in Couture" width="100%"></p>
|
|
50
|
+
|
|
51
|
+
### `poster`: forest and vermilion
|
|
52
|
+
|
|
53
|
+
Heavy rounded axes, big bold type, and thick solid marks cut apart by crisp white gaps.
|
|
54
|
+
|
|
55
|
+
<p align="center"><img src="https://raw.githubusercontent.com/BojarLab/viscose/main/examples/readme/poster.png" alt="A volcano plot, stacked bars, and a ridgeline plot in Poster" width="100%"></p>
|
|
56
|
+
|
|
57
|
+
### `aura`: burgundy and teal
|
|
58
|
+
|
|
59
|
+
Marks float on soft shadows in their own color, above rounded heatmap cells, with no axis lines at all.
|
|
60
|
+
|
|
61
|
+
<p align="center"><img src="https://raw.githubusercontent.com/BojarLab/viscose/main/examples/readme/aura.png" alt="A clustermap, a line and bar figure, and an embedding in Aura" width="100%"></p>
|
|
62
|
+
|
|
63
|
+
## Out of the box
|
|
64
|
+
|
|
65
|
+
The same data and the same labels, with no styling on either side: matplotlib and seaborn on the left, viscose on the right.
|
|
66
|
+
|
|
67
|
+
<p align="center"><img src="https://raw.githubusercontent.com/BojarLab/viscose/main/examples/readme/versus.png" alt="A volcano plot from matplotlib and seaborn defaults beside the same plot from viscose in Aura" width="100%"></p>
|
|
68
|
+
|
|
69
|
+
## Glycans in your plots
|
|
70
|
+
|
|
71
|
+
viscose shares its renderer with [glycowork](https://github.com/BojarLab/glycowork)'s GlycoDraw, so a plot can carry real SNFG
|
|
72
|
+
drawings as sharp as the rest of the figure, in PNG, PDF, and SVG.
|
|
73
|
+
|
|
74
|
+
```python
|
|
75
|
+
from glycowork.motif.draw import annotate_figure
|
|
76
|
+
|
|
77
|
+
ax.annotate('Neu5Ac(a2-6)Gal(b1-4)GlcNAc', (x, y), offset = (12, 0), svg_label = True)
|
|
78
|
+
fig.save('volcano.svg')
|
|
79
|
+
annotate_figure('volcano.svg', filepath = 'volcano.pdf', compact = True)
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
<p align="center"><img src="https://raw.githubusercontent.com/BojarLab/viscose/main/examples/readme/glycans.png" alt="A volcano plot and a biosynthetic network with SNFG glycan drawings as labels" width="100%"></p>
|
|
83
|
+
|
|
84
|
+
## Everything you reach for
|
|
85
|
+
|
|
86
|
+
`hue`, `style`, and `size` take one value per point and build the legend for you, as seaborn does.
|
|
87
|
+
|
|
88
|
+
```python
|
|
89
|
+
ax.scatter(x, y, hue = stage, style = source, size = abundance,
|
|
90
|
+
hue_label = 'Stage', style_label = 'Source', size_label = 'Abundance')
|
|
91
|
+
ax.text(0.02, 0.98, 'F = 4.2\np = 0.003', axes_fraction = True, va = 'top')
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
<p align="center"><img src="https://raw.githubusercontent.com/BojarLab/viscose/main/examples/readme/hue_style_size.png" alt="A scatter plot with color, shape, and size mapped to data, with a three-part legend" width="80%"></p>
|
|
95
|
+
|
|
96
|
+
Clustermaps come with both dendrograms and a color bar. Hand over a DataFrame and it brings its own labels.
|
|
97
|
+
|
|
98
|
+
```python
|
|
99
|
+
fig, heat = vc.clustermap(df, palette = 'aura', title = 'Glycan abundance by tissue', colorbar_label = 'z-score')
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
<p align="center"><img src="https://raw.githubusercontent.com/BojarLab/viscose/main/examples/readme/clustermap.png" alt="A clustermap of glycan abundance across tissues in Aura" width="80%"></p>
|
|
103
|
+
|
|
104
|
+
| | |
|
|
105
|
+
|---|---|
|
|
106
|
+
| **Plots** | `plot`, `scatter`, `bar`, `barh`, `stacked_bar`, `hist`, `fill_between`, `errorbar`, `stem`, `hlines`, `arrow`, `heatmap`, `ridgeline`, `dendrogram`, `axhline`, `axvline`, and `vc.clustermap` |
|
|
107
|
+
| **Markers** | `o`, `s`, `D`, `^`, `v`, `X`, `P`, and `*`, all with the palette's effects |
|
|
108
|
+
| **Annotation** | `text`, `annotate`, `legend`, and `colorbar`, with `_{sub}` and `^{super}` in any text |
|
|
109
|
+
| **Layout** | Colliding tick labels turn and thin themselves, labels move to the side with room, legends wrap, and the page grows for anything that needs it |
|
|
110
|
+
| **Output** | `fig.save` writes PNG, PDF, or SVG from the same geometry, with marks, gradients, and text as real vectors in PDF and SVG |
|
|
111
|
+
| **Display** | `fig.show()` works inline in Jupyter and slate, and in the system's image viewer from a terminal, with CI and coding agents kept silent |
|
|
112
|
+
| **SVG hooks** | `gid` on `arrow` and `scatter` names elements for hover text and scripting |
|
|
113
|
+
| **State** | None hidden: a figure is an object, with no current figure and nothing to close |
|
|
114
|
+
|
|
115
|
+
## Light and quick
|
|
116
|
+
|
|
117
|
+
No compiled plotting stack, no backends, and no font cache. For vector output, viscose is often many times faster than
|
|
118
|
+
matplotlib and seaborn, and its files can be far smaller. At 300 dpi, in Poster:
|
|
119
|
+
|
|
120
|
+
| | matplotlib and seaborn | viscose |
|
|
121
|
+
|---|---|---|
|
|
122
|
+
| Dependencies | Nine extra packages, 42.5 MB | numpy and glycorender, with 0.11 MB of its own code |
|
|
123
|
+
| Clustermap, 300 x 100, PDF | 1.57 s, 587 kB | **0.02 s, 79 kB** |
|
|
124
|
+
| Clustermap, 300 x 100, SVG | 1.40 s, 5,943 kB | **0.02 s, 182 kB** |
|
|
125
|
+
| Clustermap, 26 x 16, PDF | 0.11 s, 22 kB | **0.01 s**, 26 kB |
|
|
126
|
+
| Three lines with a legend, PDF | 0.03 s, 12 kB | **under 0.01 s**, 13 kB |
|
|
127
|
+
| Scatter, 100,000 points, PDF | 0.96 s, 1,524 kB | **0.19 s, 644 kB** |
|
|
128
|
+
| Scatter, 412 points, PNG | 0.18 s, 147 kB | 0.20 s, 180 kB |
|
|
129
|
+
|
|
130
|
+
matplotlib's compiled rasterizer is still about twice as fast on most PNGs,
|
|
131
|
+
and the soft shadows of Lumen and Aura add about half a second. To rerun the full comparison, wins and losses alike, use
|
|
132
|
+
[benchmarks/compare_matplotlib.py](https://github.com/BojarLab/viscose/blob/main/benchmarks/compare_matplotlib.py).
|
|
133
|
+
|
|
134
|
+
## Make it yours
|
|
135
|
+
|
|
136
|
+
`vc.set_palette('aura')` changes the default for every figure. A library that builds on viscose calls `vc.default_palette('aura')`
|
|
137
|
+
instead, which gives way to the choice of whoever uses it. In any palette, refer to its shades as `a0` to `a3` and `b0` to `b3`, dark
|
|
138
|
+
to pale, or as `ink`, `muted`, and `faint`; hex and CSS color names work too. `fig.pal.groups(3, 2)` gives categories grouped by hue,
|
|
139
|
+
here three shades of one and two of the other, and `fig.pal.contrast(n)` alternates between the hues for categories that have to stand
|
|
140
|
+
apart, as `scatter(hue = ...)` does.
|
|
141
|
+
|
|
142
|
+
A palette of your own is two hues, three text colors, and whichever effects you like:
|
|
143
|
+
|
|
144
|
+
```python
|
|
145
|
+
vc.register_palette(vc.Palette('midnight', ['#14213D', '#27477E', '#5C85C5', '#C4D5EE'], ['#8F5B00', '#D08C00', '#F2B83B', '#FBE5B0'],
|
|
146
|
+
'#14213D', '#5A6478', '#E6EAF1', point = 'sphere', bar = 'deep', shadow = 0.4))
|
|
147
|
+
fig, ax = vc.subplots(palette = 'midnight')
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Century Gothic is used where it is installed, and glycorender's bundled Comfortaa elsewhere.
|
|
151
|
+
|
|
152
|
+
## More
|
|
153
|
+
|
|
154
|
+
[examples/gallery.py](https://github.com/BojarLab/viscose/blob/main/examples/gallery.py) draws seven standard figures in every palette, [examples/features.py](https://github.com/BojarLab/viscose/blob/main/examples/features.py)
|
|
155
|
+
draws one sheet of features per palette, and [examples/readme_figures.py](https://github.com/BojarLab/viscose/blob/main/examples/readme_figures.py) draws every image on this page.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=77"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "viscose"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Scientific plots that are pieces of art: palettes with their own special effects, drawn without matplotlib"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
authors = [
|
|
11
|
+
{name = "Daniel Bojar", email = "daniel.bojar@gu.se"}
|
|
12
|
+
]
|
|
13
|
+
license = "MIT"
|
|
14
|
+
license-files = ["LICENSE"]
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Programming Language :: Python :: 3",
|
|
17
|
+
"Programming Language :: Python :: 3.11",
|
|
18
|
+
"Programming Language :: Python :: 3.12",
|
|
19
|
+
"Programming Language :: Python :: 3.13",
|
|
20
|
+
"Programming Language :: Python :: 3.14",
|
|
21
|
+
"Operating System :: OS Independent",
|
|
22
|
+
"Topic :: Scientific/Engineering :: Visualization",
|
|
23
|
+
]
|
|
24
|
+
keywords = ["plotting", "visualization", "figures", "palettes", "glycowork"]
|
|
25
|
+
dependencies = ["numpy", "glycorender>=0.5.4"]
|
|
26
|
+
requires-python = ">=3.11"
|
|
27
|
+
|
|
28
|
+
[project.optional-dependencies]
|
|
29
|
+
cluster = ["scipy"]
|
|
30
|
+
dev = ["pytest", "scipy", "pandas"]
|
|
31
|
+
|
|
32
|
+
[project.urls]
|
|
33
|
+
"Homepage" = "https://github.com/BojarLab/viscose"
|
|
34
|
+
"Bug Tracker" = "https://github.com/BojarLab/viscose/issues"
|
|
35
|
+
|
|
36
|
+
[tool.setuptools]
|
|
37
|
+
packages = ["viscose"]
|
|
38
|
+
|
|
39
|
+
[tool.pytest.ini_options]
|
|
40
|
+
pythonpath = ["."]
|
viscose-0.1.0/setup.cfg
ADDED