olavolav / uniplot Goto Github PK
View Code? Open in Web Editor NEWLightweight plotting to the terminal. 4x resolution via Unicode.
License: MIT License
Lightweight plotting to the terminal. 4x resolution via Unicode.
License: MIT License
In my use-case the list of numbers are dynamically generated, which sometimes create something like this:
plot([[1,2,3,4,3,2,3,4],[3,2,2,4,1,2,1,4],[1,3],[]], lines=True)
Which fails, i think during validation, extracting the max. It also happens with x,y data (which is actually my case).
Looking at the logic I think probably is wise to exclude them from the multi series, but that may also interact with the colors, other possible solution is changing some functions like:
def y_max(self) -> float:
return max([_safe_max(ys_row) for ys_row in self.ys])
#to
def y_max(self) -> float:
return max([_safe_max(ys_row) for ys_row in self.ys if len(self.ys) >0])
This was on the roadmap but have not heard anyone actually request it. So I'll leave the prototypical hack here as an issue in case anyone wants to actually have it.
So in theory we could have an option like y_fill_level
that enables filling the are between the points and a given vertical level, usually the zero line.
It might look something like:
plot(ys, title="Sine wave", y_fill_level=-2.5)
Sine wave
┌────────────────────────────────────────────────────────────┐
│ ▟█▙ │
│ ▗███▌ │
│ ▗██▖ ▟████ │
│ ▟███ ▗█████▌ │ 2
│ ▟█▙ ▗████▌ ▐██████ │
│ ▐███▖ ▟█████ ███████▌ │
│ ▗██▖ █████ ▗██████▌ ▐████████ │
│ ███▙ ▗█████▖ ▐██████▙ ▟████████▌ │
│ ▟█▖ ▐████▖ ▟█████▙ ████████▖ ▗██████████▄│ 1
│ ▐███▖ █████▙ ███████▖ ▗████████▙ ▟███████████│
│ ████▙ ▗██████▖ ▐███████▙ ▟█████████▙▟████████████│
│▐█████▖ ▐██████▌ █████████▖ ▗████████████████████████│
│▟█████▌ ████████ ▗██████████▄█████████████████████████│
│███████────▐████████▙──▟████████████████████████████████████│ 0
│███████▌ ██████████▙▟█████████████████████████████████████│
│████████ ▐█████████████████████████████████████████████████│
│████████▙▄██████████████████████████████████████████████████│
└────────────────────────────────────────────────────────────┘
100 200 300 400 500 600
And then with colors it might look like:
Let me know if this feature would be useful.
I'm working on a tool that I would love to be able to integrate uniplot
into, but I'm running into a problem: I need to capture the output as a string so that I can display it elsewhere. Right now, uniplot.plot
prints directly to stdout: https://github.com/olavolav/uniplot/blob/master/uniplot/uniplot.py#L74
I'm not sure how to square this with the interactive features implemented in that function. Perhaps a helper function could be extracted that returns the plot as a string? Then I could call that function from my tool to get the string that uniplot.plot
would have displayed.
Happy to do the work on this if you can provide some guidance on how you'd like it implemented!
See here, the correct labels are computed in terms of floating point numbers [-1.4 -0.9 -0.4]
but then the string labels are "-0.4", "-0.9" and "-1". The last one is wrong, should of course be "-1.4" so it is cut off at the wrong digit.
See this example:
>>> from uniplot.axis_labels.extended_talbot_labels import extended_talbot_labels
>>> extended_talbot_labels(x_min=-1.846526999372103, x_max=-0.1651564799721942, available_space=17, vertical_direction=True, verbose=True).render()
DEBUG: x_min = -1.846526999372103
DEBUG: x_max = -0.1651564799721942
DEBUG: simplicity = 0.19999999999999996, coverage = 0.9940240106065467, density = -4.666666666666667, grid_alignment = 1 => New best score 😀 = -0.9014939973483634 with labels = [-1.8 -1.7 -1.6 -1.5 -1.4 -1.3 -1.2 -1.1 -1. -0.9 -0.8 -0.7 -0.6 -0.5
-0.4 -0.3 -0.2]
DEBUG: simplicity = 0.0, coverage = 0.549810354275108, density = 0.0, grid_alignment = 1 => New best score 😀 = 0.337452588568777 with labels = [-1.4 -0.9 -0.4]
['', '', '-0.4', '', '', '', '', '-0.9', '', '', '', '', '-1', '', '', '', '']
After using uniplot now for a couple days, I found myself using the interactive mode quite often for some simple EDA on remote resources. However, I've been struggling a bit with the h/j/k/l key combinations for moving the bounding box ("struggling" is perhaps a too strong word here ^^), so I've been wondering if you would be up for having this configurable. If this option existed, I would change it to w/a/s/d.
The Options
dataclass could be a good place for that, however, the question is whether this should be configurable per plot/histogram()
call (1), or a global setting (2).
I don't believe people would need to change this behavior from plot to plot, so option 2 could make more sense here. In this case, a ClassVar
on Options
would already do the trick, allowing for (e.g.)
import uniplot
uniplot.Options.move_keys = "wasd"
uniplot.plot(...)
(just as an example, a proper setter is of course preferable here to change the class var)
This is just the logical continuation of #8.
Should not be a lot of work, now that the groundwork has been done. Thinking about use cases, I assume that datetime for the y-axis is a lot less common.
Sometimes there are gaps at the end of lines.
>>> from uniplot import plot
>>> plot(xs=[0.433,0.6666], ys=[0.8,0.1133], x_min=0, x_max=1, y_min=0, y_max=1, lines=True)
DEBUG indices_slope -0.8571428571428571 slope -2.939640410958905
DEBUG x_index_start 51
DEBUG x_index_stop 79
DEBUG x_indices_of_line [52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
76 77 78]
┌────────────────────────────────────────────────────────────┐
││ │ 1.0
││ │
││ │
││ ▝▖ │
││ ▝▚ │ 0.7
││ ▚ │
││ ▚▖ │
││ ▝▖ │
││ ▝▖ │ 0.5
││ ▝▚ │
││ ▚ │
││ ▚▖ │
││ ▝▖ │ 0.3
││ ▝▖ │
││ ▝▘ │
││ ▝ │
││▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁│ 0.0
└────────────────────────────────────────────────────────────┘
0 1
This is not a bug, but an artifact of the line drawing attempting to be accurate. If the end pixel is drawn because of an end pint that is significantly away from the center of the pixel then this is possible.
Nice project!
So basically I have noticed that plotting has linear speed,
range(10_000_000) took 10x as long to plot as range(1_000_000)
If you are aware of the max resolution, then you could imagine you can compress the data, without resulting in a different plot
One way (probably it's possible to come up with something much better), would be to perhaps fit 1000 linear regressions on sorted data of 10_000_000 data points and use that to e.g. compress 10_000_000 rows into 1_000_000 (or less) - whatever is needed for the solution, basically the sign could be "0=stay equal, -decrease, +increase"
I was able to fit 1000 regressions in 300ms, whereas the naive plotting went from 1s to 10s, so a huge speed-up would be possible if you are able to compress the data
In the example of #15 actually it is curious that the .5
labels are not chosen by the algorithm.
>>> from uniplot.axis_labels.extended_talbot_labels import extended_talbot_labels
>>> extended_talbot_labels(x_min=-1.846526999372103, x_max=-0.1651564799721942, available_space=17, vertical_direction=True, verbose=True).render()
### exponent = 0 ###
(...)
### exponent = -1 ###
### j = 1 ###
### i = 0, q = 1 ###
Testing labels: [-1.8 -1.7 -1.6 -1.5 -1.4 -1.3 -1.2 -1.1 -1. -0.9 -0.8 -0.7 -0.6 -0.5
-0.4 -0.3 -0.2] => simplicity = 0.19999999999999996, coverage = 0.9940240106065467, density = -4.666666666666667, grid_alignment unknown => score_approx = -0.8514939973483636
Testing labels: [-1.8 -1.7 -1.6 -1.5 -1.4 -1.3 -1.2 -1.1 -1. -0.9 -0.8 -0.7 -0.6 -0.5
-0.4 -0.3 -0.2] => simplicity = 0.19999999999999996, coverage = 0.9940240106065467, density = -4.666666666666667, grid_alignment => 1, score = -0.8514939973483636
=> New best score 😀
### i = 1, q = 5 ###
Testing labels: [-1.4 -0.9 -0.4] => simplicity = 0.0, coverage = 0.549810354275108, density = 0.0, grid_alignment unknown => score_approx = 0.337452588568777
Testing labels: [-1.4 -0.9 -0.4] => simplicity = 0.0, coverage = 0.549810354275108, density = 0.0, grid_alignment => 1, score = 0.337452588568777
=> New best score 😀
(...)
### j = 5 ###
### i = 0, q = 1 ###
Testing labels: [-1.4 -0.9 -0.4] => simplicity = -3.8, coverage = 0.549810354275108, density = 0.0, grid_alignment unknown => score_approx = -1.5625474114312228
Testing labels: [-1.8 -1.3 -0.8 -0.3] => simplicity = -3.8, coverage = 0.9640122259435896, density = -0.33333333333333326, grid_alignment unknown => score_approx = -1.5589969435141025
Testing labels: [-1.7 -1.2 -0.7 -0.2] => simplicity = -3.8, coverage = 0.9598794169078467, density = -0.33333333333333326, grid_alignment unknown => score_approx = -1.5600301457730383
Testing labels: [-1.6 -1.1 -0.6] => simplicity = -3.8, coverage = 0.5580759723465938, density = 0.0, grid_alignment unknown => score_approx = -1.5604810069133515
Testing labels: [-1.5 -1. -0.5] => simplicity = -3.8, coverage = 0.5893162650552402, density = 0.0, grid_alignment unknown => score_approx = -1.55267093373619
It seems odd that the simplicity
for the intuitive choice of [-1.5, -1.0, -0.5]
is negative.
Let's investigate, could be a bug.
Hi again,
after playing around a bit more with histograms, I noticed that the x-axis range is ignored in cases where the number of bins as well as min/max values are provided (histogram(data, bins=..., x_min=..., x_max=...)
).
Here is a reproducer:
import numpy as np
from uniplot import histogram
data = np.random.uniform(0, 3, size=1000)
histogram(data, bins=4, x_min=-0.5, x_max=3.5)
# ->
┌────────────────────────────────────────────────────────────┐
│ ▐▀▀▀▀▀▀▀▀▀▀▜ ▐▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▌ │
│ ▐ ▐ ▐ ▌ │
│ ▐ ▝▀▀▀▀▀▀▀▀▀▀▀ ▌ │
│ ▐ ▌ │ 200
│ ▐ ▌ │
│ ▐ ▌ │
│ ▐ ▌ │
│ ▐ ▌ │
│ ▐ ▌ │
│ ▐ ▌ │
│ ▐ ▌ │ 100
│ ▐ ▌ │
│ ▐ ▌ │
│ ▐ ▌ │
│ ▐ ▌ │
│ ▐ ▌ │
│▁▁▁▁▁▁▁▐▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▌▁▁▁▁▁▁▁│ 0
└────────────────────────────────────────────────────────────┘
0 1 2 3
The axis range is of course correct, but I would have expected that the left edge of the first bin and the right edge of the last bin landed on -0.5 and 3.5, respectively.
I could provide a PR, but I first wanted to check if the current behavior was intended.
When ys contain NaN, it will not display.
Thanks.
Options x_max
etc. are not treated correctly when plotting on a log scale.
Hi again @olavolav. If I am not wrong, currently there is support for only using Number Datatypes on both the x and y axes. However, while performing time series analysis and plotting trends for the time, we often need to mention the time(month/ date etc.) as a string. I am looking for something similar to this but on the terminal.
I dont think that you need to perform any sorting for the date and such internally and we can probably mandate that the user itself sorts the list prior to plotting. Can this be supported?
Hello Olav,
I have noticed a small problem when displaying the x axis values. The values seem to be rounded too much making them identical and equal to 0. It seems to happen when one value is positive, the other negative and the values are close to 0 (+-0.01) I included screenshots of it.
PS: uniplot feels great, keep it up!
I'm not familiar with poetry, but in standard python projects this would be fixed by setting the following in pyproject.toml
:
[project.urls]
repository = "https://github.com/olavolav/uniplot"
documentation = <docs website, if any>
Just a small gripe
To Reproduce:
>>> plot(xs=[1,1], ys=[0,1], lines=True, x_min=3, x_max=6)
┌────────────────────────────────────────────────────────────┐
│ ▖ │ 1.0
│ ▌ │
│ ▌ │
│ ▌ │
│ ▌ │ 0.7
│ ▌ │
│ ▌ │
│ ▌ │
│ ▌ │ 0.5
│ ▌ │
│ ▌ │
│ ▌ │
│ ▌ │ 0.3
│ ▌ │
│ ▌ │
│ ▌ │
│▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▌▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁│ 0.0
└────────────────────────────────────────────────────────────┘
3 6
Obviously there should not be anything drawn in this view.
Here, the correct line is drawn, but also weird other ones. In interactive mode this line appears once the real one is out of view.
Hello,
This is an interesting project! Thank you for taking the time to put it together.
Quick question:
When testing out uniplot I'm able to call .plot()
from the python console or through ipython, and get a visualization quite easily. However, it does not work when I include uniplot
in a .py file and I execute the file.
# foo.py
import unipolot as plot
import math
x = [math.sin(i / 20) + i / 300 for i in range(600)]
p = plot(x)
$ python foo.py
Traceback (most recent call last):
File "foo.py", line 4, in <module>
p = plot(x)
TypeError: 'module' object is not callable
Is this expected behaviour, or am I missing something from the docs?
Thanks,
I'd like to plot boxplots on the terminal along with support for multiple boxplots alongside other boxplots
See this example:
>>> plot([1,3,2], height=2)
┌────────────────────────────────────────────────────────────┐
│ ▘ ▗│ 3
│▖ │ 1
└────────────────────────────────────────────────────────────┘
1 2 3
>>> plot([1,3,2], height=2, x_unit=" microns")
┌────────────────────────────────────────────────────────────┐
│ ▘ ▗│ 3
│▖ │ 1
└────────────────────────────────────────────────────────────┘
1 microns 2 microns 3 microns
What should happen is that the labels are centered, including the units.
To reproduce:
from uniplot import plot, histogram
import numpy as np # type: ignore
# Exception when zooming in
xs = np.array(
[
0,
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33,
34,
35,
36,
37,
38,
39,
40,
41,
42,
43,
44,
45,
46,
47,
48,
49,
50,
51,
52,
53,
54,
55,
56,
57,
58,
59,
60,
61,
62,
63,
64,
65,
66,
67,
68,
69,
70,
71,
72,
73,
74,
75,
76,
77,
78,
79,
80,
81,
82,
83,
84,
85,
86,
87,
88,
89,
90,
91,
92,
93,
94,
95,
96,
97,
98,
99,
100,
101,
102,
103,
104,
105,
106,
107,
108,
109,
110,
111,
112,
113,
114,
115,
116,
117,
118,
119,
120,
121,
122,
123,
124,
125,
126,
127,
128,
129,
130,
131,
132,
133,
134,
135,
136,
137,
138,
139,
140,
141,
142,
143,
144,
145,
146,
147,
148,
149,
150,
151,
152,
153,
154,
155,
156,
157,
158,
159,
160,
161,
162,
163,
164,
165,
166,
167,
168,
169,
170,
171,
172,
173,
174,
175,
176,
177,
178,
179,
180,
181,
182,
183,
184,
185,
186,
187,
188,
189,
190,
191,
192,
193,
194,
195,
196,
197,
198,
199,
200,
201,
202,
203,
204,
205,
206,
207,
208,
209,
210,
211,
212,
213,
214,
215,
216,
217,
218,
219,
220,
221,
222,
223,
224,
225,
226,
227,
228,
229,
230,
231,
232,
233,
234,
235,
236,
237,
238,
239,
240,
241,
242,
243,
244,
245,
246,
247,
248,
249,
250,
251,
252,
253,
254,
255,
256,
257,
258,
259,
260,
261,
262,
263,
264,
265,
266,
267,
268,
269,
270,
271,
272,
273,
274,
275,
276,
277,
278,
279,
280,
281,
282,
283,
284,
285,
286,
287,
288,
289,
290,
291,
292,
293,
294,
295,
296,
297,
298,
299,
300,
301,
302,
303,
304,
305,
306,
307,
308,
309,
310,
311,
312,
313,
314,
315,
316,
317,
318,
319,
320,
321,
322,
323,
324,
325,
326,
327,
328,
329,
330,
331,
332,
333,
334,
335,
336,
337,
338,
339,
340,
341,
342,
343,
344,
345,
346,
347,
348,
349,
350,
351,
352,
353,
354,
355,
356,
357,
358,
359,
360,
361,
362,
363,
364,
365,
366,
367,
368,
369,
370,
371,
372,
373,
374,
375,
376,
377,
378,
379,
380,
381,
382,
383,
384,
385,
386,
387,
388,
389,
390,
391,
392,
393,
394,
395,
396,
397,
398,
399,
400,
401,
402,
403,
404,
405,
406,
407,
408,
409,
410,
411,
412,
413,
414,
415,
416,
417,
418,
419,
420,
421,
422,
423,
424,
425,
426,
427,
428,
429,
430,
431,
432,
433,
434,
435,
436,
437,
438,
439,
440,
441,
442,
443,
444,
445,
446,
447,
448,
449,
450,
451,
452,
453,
454,
455,
456,
457,
458,
459,
460,
461,
462,
463,
464,
465,
466,
467,
468,
469,
470,
471,
472,
473,
474,
475,
476,
477,
478,
479,
480,
481,
482,
483,
484,
485,
486,
487,
488,
489,
490,
491,
492,
493,
494,
495,
496,
497,
498,
499,
]
)
ys = np.array(
[
1.26230459e00,
3.59321301e-01,
2.11936647e00,
1.84432132e00,
2.27899071e00,
1.51661172e00,
1.95712695e-01,
1.64582244e00,
1.19080132e00,
1.77906596e00,
2.60834568e00,
4.01352512e00,
1.12257450e00,
-2.38223520e-01,
3.17199023e-01,
2.85413316e-01,
9.91733067e-01,
1.84263384e00,
2.32001561e00,
1.33347914e00,
3.46571661e-01,
1.34794460e00,
1.36144011e00,
2.22913711e00,
2.95592602e00,
3.01213057e00,
1.87905661e00,
4.10827814e-01,
-2.75564854e-01,
1.03768731e00,
-3.97770275e-01,
3.06930582e00,
2.78850709e00,
1.48173807e00,
-4.55744704e-03,
-1.32975609e00,
6.36077517e-02,
1.83738438e00,
1.68082395e00,
1.39683868e00,
-9.97108469e-02,
-9.49959243e-01,
7.88987944e-01,
5.23096813e-01,
1.79377985e00,
2.56523643e00,
1.65300403e00,
1.40698126e00,
7.48265081e-01,
6.23696401e-01,
9.13088969e-01,
7.17841682e-01,
1.76776214e00,
3.85539288e00,
1.44986447e00,
2.91732462e-02,
1.34081560e00,
6.29367473e-01,
1.89256668e00,
-5.01236350e-01,
2.44245545e00,
-3.76219798e-01,
-1.52341955e00,
6.89569262e-02,
3.47522530e-01,
-1.68230067e-01,
1.34471069e00,
1.18431856e00,
1.31349600e00,
7.29997833e-01,
2.89225012e-01,
-2.80413712e00,
7.50533432e-01,
8.71114431e-01,
7.07190831e-01,
3.17740131e00,
5.86036160e-01,
5.90711279e-01,
-7.22011344e-01,
-1.50789690e-01,
1.50888043e00,
3.91049296e-01,
2.35969482e00,
1.08970815e00,
1.42594895e00,
4.96137247e-01,
1.30358513e00,
3.34551072e00,
1.93665667e00,
1.53050683e00,
2.36212454e00,
-5.24698604e-01,
4.42035630e-02,
-9.42400877e-01,
9.51652062e-01,
-6.94684749e-01,
2.91913781e00,
4.31538812e-02,
-1.24747396e00,
7.96053706e-02,
1.87125758e00,
3.24216046e00,
1.21241355e00,
1.18453587e00,
-6.06840947e-01,
-5.66081726e-01,
1.95866564e00,
1.73761292e-01,
1.45443360e00,
3.12741942e00,
2.18546158e00,
3.38033204e-01,
7.39796805e-02,
-4.12367686e-01,
2.09752078e00,
2.94173384e00,
1.43576006e00,
2.35233888e00,
1.75026987e-01,
-7.96761454e-01,
1.16392155e00,
3.95625636e-01,
3.25318881e00,
1.50728811e00,
4.19976468e00,
2.68370507e-01,
2.61967644e00,
-8.89491321e-02,
2.55987916e00,
2.56399322e00,
9.51770979e-01,
6.74653511e-01,
2.33729281e-01,
-7.14686280e-01,
-2.67159716e-01,
1.13894794e00,
3.23252390e00,
1.33774678e00,
1.31868005e00,
1.81951904e-01,
4.79242635e-01,
2.15532864e-01,
6.92885478e-01,
1.70927123e00,
1.32722492e00,
1.44586826e00,
1.29820650e00,
3.99065294e-01,
-5.78380524e-01,
9.27519202e-01,
2.47403927e-01,
1.55674871e00,
-3.25379422e-01,
1.09442721e00,
-4.74897587e-01,
1.93365775e00,
1.41704079e00,
2.91712317e00,
2.66207768e00,
1.84139843e-01,
1.37767813e-01,
1.25142357e00,
4.84057548e-01,
6.07245680e-01,
3.30181350e-01,
2.43432229e00,
2.56402791e00,
-6.93171018e-01,
6.68779033e-01,
-1.94396361e-01,
1.51260020e00,
2.49096620e00,
2.45031139e00,
3.03096170e-01,
-8.18876084e-01,
8.19588735e-01,
-1.17728460e00,
-1.16854500e00,
2.44811633e00,
1.93316841e00,
1.37030049e00,
7.81292142e-01,
4.01495947e-01,
1.47579864e-01,
-2.84856788e-01,
1.98363074e00,
2.19940360e00,
-8.05836667e-01,
1.46269262e00,
-7.71479430e-01,
-4.29736882e-01,
1.49405237e00,
1.83036686e00,
9.27646287e-01,
1.42684947e00,
-1.47479979e00,
-2.83542544e00,
-1.32329789e00,
8.63657805e-01,
1.67849080e00,
2.90746670e-01,
1.21004861e00,
-1.20775413e00,
-5.31279246e-01,
1.56967687e00,
1.83278302e00,
9.72991848e-01,
1.67934543e00,
1.94689352e00,
-1.29059489e00,
-1.66424333e-01,
6.79751734e-01,
1.91516968e00,
1.71575116e00,
1.79466158e00,
5.07323181e-01,
6.24431305e-01,
1.25871938e00,
9.73003775e-01,
1.83284056e00,
7.67068188e-01,
2.16195802e00,
1.97370305e00,
7.27160897e-01,
-9.71488218e-01,
-8.58690312e-01,
-3.67525205e-01,
1.29494233e00,
7.18195673e-02,
1.21326802e00,
-7.58598785e-01,
-1.06418506e-03,
-3.60541127e-01,
5.97630287e-01,
1.16314252e00,
2.79888774e00,
3.17366401e00,
8.46983160e-01,
1.71412642e-02,
-5.94253205e-01,
1.10030645e-01,
8.48605322e-01,
1.60590771e00,
1.51386287e00,
-7.66986890e-01,
3.71606231e-01,
9.31114992e-01,
1.14051595e00,
3.12671250e00,
8.41910255e-01,
1.81572098e00,
7.26485448e-01,
9.54109141e-01,
-7.01049465e-01,
-7.08966723e-01,
1.84269535e00,
2.23904728e00,
1.04671627e00,
3.85234747e-02,
-4.04382967e-01,
7.65336840e-01,
7.72256692e-01,
1.39904849e00,
1.49380494e00,
1.02689147e00,
7.66556348e-01,
6.45355391e-01,
5.92087646e-01,
1.45512657e00,
8.99221323e-01,
2.24730476e00,
1.83258046e00,
1.76767850e00,
-8.32995347e-02,
1.43100675e00,
1.42191705e-01,
2.27576545e00,
3.39549232e00,
3.35252919e00,
1.48749067e00,
-1.17012953e00,
-6.15039264e-01,
9.25848706e-01,
8.39612122e-01,
3.49473756e00,
3.62672699e00,
7.11679401e-01,
-6.21133647e-01,
-1.71974130e-01,
2.19582351e-01,
1.70029203e00,
4.97072898e-01,
3.07661373e00,
5.89705127e-01,
-3.85557180e-01,
-1.21627747e-01,
6.88094658e-01,
2.08683855e00,
2.04800796e00,
3.67022420e-01,
3.03847578e-02,
2.12803068e-01,
1.27382824e00,
2.20525878e00,
2.09729942e00,
2.92745219e00,
1.43501329e00,
-1.00158984e00,
-4.26869441e-01,
2.38459396e-01,
6.18281003e-01,
2.86900336e00,
5.26441897e-01,
1.83471736e00,
5.64276032e-01,
-4.79185498e-02,
1.56645081e00,
1.90975688e00,
1.96805054e00,
1.32437211e00,
1.54723551e00,
2.97027599e00,
8.23747319e-01,
-1.07597824e00,
1.29796781e-01,
3.08261173e00,
1.94024883e00,
1.67053036e00,
7.68453719e-01,
2.53848214e-01,
-2.71074406e-01,
1.11041190e00,
3.06171371e00,
2.88915244e00,
2.00362771e00,
1.67907635e00,
9.25318467e-01,
-6.21558807e-01,
3.77295621e-01,
2.51130485e00,
1.23662523e00,
1.47239092e00,
1.17058209e00,
1.47667951e-01,
1.33386697e-01,
-4.53263981e-01,
1.12631733e00,
3.26298892e00,
2.35568468e00,
3.83027496e-01,
-3.78093690e-02,
6.37261226e-01,
1.72890857e00,
2.57274809e00,
2.60905435e00,
1.56994909e00,
5.17535191e-01,
3.77275665e-01,
-3.45929860e-01,
2.58949535e00,
7.62669260e-01,
3.47958346e00,
1.83376087e00,
3.34759101e-01,
-1.39156268e-01,
1.24690335e-01,
1.07593646e00,
1.77047871e00,
1.18853328e00,
8.68015144e-01,
8.48988929e-01,
-8.95110881e-01,
1.07420642e-01,
3.06363479e00,
7.15866469e-01,
1.66342966e00,
2.57150732e00,
-1.04277245e-01,
-2.90886083e00,
-1.00809760e00,
7.93375194e-01,
2.20504948e00,
2.85967791e00,
2.15743733e00,
2.08510982e00,
3.16493745e-01,
-1.04790522e00,
1.30076686e-01,
1.47648939e00,
9.65983115e-01,
3.03133713e00,
-2.24802033e00,
-1.90839207e-01,
1.41532791e00,
7.77675677e-01,
2.91494777e00,
2.70474727e00,
2.01074236e00,
1.30244225e00,
-4.91068641e-01,
4.32498323e-01,
1.95233060e00,
3.07520214e00,
3.78334096e00,
3.35590562e00,
-8.08053405e-01,
4.51994781e-01,
7.74504797e-01,
3.52334793e-01,
2.44854135e00,
3.34811742e00,
1.82352584e00,
2.26330255e00,
2.77269351e-01,
6.07576157e-02,
-2.01833711e-01,
1.04185052e00,
2.32538242e00,
2.84038167e00,
2.29044210e00,
7.03146152e-01,
-6.01907112e-01,
1.80397234e00,
1.98634086e00,
1.22690644e00,
3.21915541e00,
-1.17284206e00,
-1.54417786e00,
9.18351626e-01,
1.76980729e00,
1.04351305e00,
2.36195029e00,
1.16500774e00,
6.12450462e-01,
-7.08609723e-01,
1.04230824e00,
1.70969447e00,
2.64288913e00,
2.34976952e-01,
1.18716059e00,
-6.61424108e-02,
-1.20049369e00,
-1.12993788e-01,
7.55088949e-01,
1.83416312e00,
2.91320098e00,
2.24328733e00,
2.40555340e00,
-8.20700873e-01,
-2.63662670e-01,
2.94146708e00,
1.04753337e00,
2.53330830e00,
2.32237327e00,
3.59879157e00,
-8.70552383e-02,
-1.59399066e00,
5.19713176e-01,
2.12543089e00,
6.33612253e-01,
6.34693702e-03,
5.60397860e-01,
1.11221859e00,
5.75088199e-01,
1.47442294e00,
1.57493470e00,
2.26755516e00,
1.01931474e00,
8.58035549e-01,
6.32568766e-02,
-9.93171533e-02,
9.53238163e-01,
-7.85355122e-02,
2.21938966e00,
-7.07804875e-01,
1.67680863e00,
-6.63675108e-01,
8.64217983e-02,
6.97749258e-01,
1.31259744e00,
2.59287989e00,
1.56744990e00,
7.89167355e-01,
1.81647380e00,
7.08114108e-02,
4.20118710e-01,
2.17202561e00,
2.82122287e00,
3.27621088e00,
6.30451516e-01,
9.99653246e-01,
1.30341376e00,
5.29974172e-01,
2.89059099e00,
1.37370641e00,
1.23284225e00,
9.20544746e-02,
-2.13971697e00,
6.64817992e-02,
4.62250775e-01,
]
)
After zooming in a few times, it looks something like this:
┌────────────────────────────────────────────────────────────┐
│▐ ▐ █ ▐ ▖ ▟▟ █ ▐█ ▌ ▐▌▐▐ ▌▌▐▐ ▌ ▙▌ ▐ ▌▐ ▌▌▐▐▌▐ │ 1.7
│▐▐ ▐ █ ▐ ▌ ██ ▌▌▐▛▖ ▌ ▌ ▐▌▐▐ ▌▌▐▐ ▌ █▌ ▐ ▌▐▌▌▌▌▐▌▐▌▐│
│▐▐ ▐ █▖▐▙ █ ██ ▌▌▐▌▌ ▌ █ ▐▌▐▐ ▐ ▗▌▙▐▐ ▌ ▜▌ ▐ ▌▐▌▌▌▌▐▌▌▚▐│
│▐▐ ▐▚ █▌▞█ █ ██ ▌▌▐▌▌▗ ▌ █ ▐▌▐▐ ▐▌▐▌█▟▐ ▌▖▐▌ ▐ ▙▐▌▙▌▌▞▚▌▐▐│
│█▝ ▐▐ █▌▌█ █▌██ ▌▌█▌▌▐▌▐▌ █ ▟▌▐▐ ▌▌▐▌██▐ ▌▌▐▌ ▐ █▐▌█▌▌ ▐▌█▐│ 1.2
│█ ▐▐ █▌▌█ █▌▛█▐ █▌▌▌▐▙ ▌ ▐▐▐▐▌▐▐ ▌▌▐▌█▛▐ █▌▐▌ ▝▌█▐▌██▌▌▐▌█▐│
│█ ▐▐ ██▌▜ █▌▌▜▐ █▘▌▌▐█ ▌ ▐▐▐▐█▐▐▖▌▚▐▌█▌▐▐█▌▐▌ ▌█▐▌██▌▌▐▌█▐│
│█ ▐▐▐ ██▌▐ █▌▌▐▐▗█ ▌▌▐█ ▌▌▟▐▐▝▐▐▐▙▌▐▞ █▌▐▐▜▌▐▙ ▌█▐▌█▜▌▌▐▌█▐│
│█ ▐▐▝▖██▌▐ █▌▌▐▐▝█ ▌▌▐█▐ ▚▜▐▞ ▐▐▐█ ▝▌ █▌▐▐▐▌▐█ ▌▌█▐▘█▐▌▌▐▌█▐│ 0.6
│█ ▐▐ ▌██▌▐ █▌▌▐▐ ▌ ▌▌▐█▐ ▐▐▐▌ ▝▟▐█ ▜▌▐▐▐▌▐█▐▌▙▜▐ █▐▌▌▐▌▀▟│
│█ ▐▐ ▌██▌▐ █▌▌▐▐ ▌▌▐█▐ ▐▐▐▌ █▝█ ▐▌▐▐▐▌▐ █▌█▐▐▐ ▐▌▌▐▌ █│
│█▐▐▐ ▚██▌▐▐▛▌▌▐▐ ▌▌▞█▐▐▐▐▐▌ █ █ ▐▌▐▐▐▐▌ █▘█▝▐▐ ▐▌▌▐▌ █│
│█▝▟▐ ▐██▌▐▐▌▌▌▐▐ ▌▙▌█▐▐▐▞▐▌ █ █▗ ▐▘▖█▐▐▌▐█ █ ▐▐ ▐▌▌▐▌ █│ 0.1
│▌▔█▐▔▐▜█▌▐▐▔▌▙▐▐▔▔▔▔█▌▐█▐▐▌▐▌▔▔█▔█▐▔▔▔▐▔▌█▐▐▌▐█▔▌▔▐▐▔▝▌▌▐▌▔█│
│▌ █▌ ▐▐█▌▐▐ █▐ ▌ █▌▐█▐▐▌▐▌ █ █▐ ▌█▐▐▌ █ ▌ ▐▐ ▌▐▌ █│
│▌ █▌ ▝▝█▌▐▐ █▐ ▌ █▌▐█▐▐▌▐▌ █ ▛▐ ▌█▐▐▘ ▌ ▘ ▐▞ ▌▐▌ ▝│
│▌ █▌ █▌▐▐ █▐ ▌ ▐▌▐▘▐ ▌▐▌ █ ▌▐ █▐▐ ▘ ▝▌ ▘▐▌ │ -0.5
└────────────────────────────────────────────────────────────┘
168 332
Move h/j/k/l, zoom u/n, or r to reset. ESC/q to quit
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/olav/Desktop/Development/uniplot/uniplot/uniplot.py", line 48, in plot
xs=series.xs, ys=series.ys, options=options
File "/Users/olav/Desktop/Development/uniplot/uniplot/layer_assembly.py", line 24, in assemble_scatter_plot
pixel_layer = layer_factory.render_points(xs=xs, ys=ys, options=options)
File "/Users/olav/Desktop/Development/uniplot/uniplot/layer_factory.py", line 75, in render_points
lines=options.lines,
File "/Users/olav/Desktop/Development/uniplot/uniplot/pixel_matrix.py", line 125, in render
# DEBUG
IndexError: index -167 is out of bounds for axis 1 with size 120
Is is possible to use different characters instead of colors for plotting multiple series?
It would be nice because I use this library for plotting, and then redirect the python script output to a file, which obviously loses the concept of color, so using like "*" and "+" instead of colors you be nice
Hi Olav. Appreciate the great work with this project. Found this quite useful in logging some data graphically to the terminal in a few of my Data Science projects.
Here is a recommendation for a new feature that can be added. I understand that there is currently support for plotting Scatter Plots and Histograms in Uniplot. Would be great if support for plotting Line Graphs was also added to visualize the trend of data. Kindly look into the possibility of doing this.
Thanks.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.