First, I tried plotting histogram using visuals.HistogramVisual
, I am getting some weird window. Here is the code :
from vispy import app, visuals
import numpy as np
import sys
import time
from PyQt5.QtWidgets import *
class snrHistogram(app.Canvas):
def __init__(self, *args, **kwargs):
app.Canvas.__init__(self, title='histogram fail',
keys="interactive", size=(300, 300))
self.snr_hist = visuals.HistogramVisual(
np.repeat([0, 1, 1, 20, 20, 40, 40, 80, 80, 90], 400), bins=1, color='r', orientation='h')
self.label = visuals.TextVisual("hi", color='blue', pos=[50, 50, 0])
self.configure_transforms()
#self.show()
def configure_transforms(self):
vp = (0, 0, self.physical_size[0], self.physical_size[1])
self.context.set_viewport(*vp)
self.label.transforms.configure(canvas=self, viewport=vp)
self.snr_hist.transforms.configure(canvas=self, viewport=vp)
def on_resize(self, event):
self.configure_transforms()
def on_mouse_wheel(self, event):
self.update()
def on_draw(self, event):
self.snr_hist.draw()
self.label.draw()
self.update()
def on_close(self, event):
self.close()
class Window(QWidget):
def __init__(self):
super().__init__()
self.layout = QHBoxLayout(self)
start_time= time.time()
s = snrHistogram()
self.layout.addWidget(s.native)
self.setLayout(self.layout)
end_time = time.time()
elapsed_time = end_time-start_time
print("Elapsed time to plot hist is: ", elapsed_time)
#self.setCentralWidget(self)
self.show()
App= QApplication(sys.argv)
window = Window()
sys.exit(App.exec_())
here is the output of it, Why I am getting like this? Where am I wrong?,
Further, I have 1D data which was computed in GPU and stored in GPU memory and I want to plot histogram using the same data(which stored in GPU memory). since vispy has access to GPU, is it directly take data or should I download data to GPU and plot again? How exactly it will work?
Any leads will be appreciated.
UPDATE
I want to plot something like this, two histogram plots in single figure. I can do it in matplot and also in pyqtgraph. Here is the sample of it,
Do you have an example of what you're expecting to see?
I ran your example code and it looks like VisPy's histogram orientation is actually backwards. This is drawing a vertical histogram (bins axis on the bottom, number on the side). I just filed a bug in the VisPy repository on this here. I'm not sure how it went this long without being noticed...unless I'm missing something.
Anyway, the main issue seems to be the transform(s) of your Visual. What you're seeing is actually one large single bin histogram that starts in the lower-left and goes outside the Canvas/viewport. I'll be honest that I rarely use the HistogramVisual or numpy's histogram functions (which the Visual is using underneath). It is possible that since this Visual was written things have changed in numpy.
Anyway, here are the changes I made:
from vispy.visuals.transforms import STTransform
bins
to 5 and orientation to
v`.configure_transforms
: self.snr_hist.transform = STTransform(scale=(300 / 1200.0, 300 / 90.0, 1.0))
The 300
values in this line come from the size of your canvas. The 1200.0
and 90.0
I got from printing out the values that numpy gave from calling np.histogram
here: https://github.com/vispy/vispy/blob/main/vispy/visuals/histogram.py
In my opinion this Visual needs a major rewrite so that you can control more of the histogram keyword arguments, but probably most importantly control the normalization of the bin sizes.
Further, I have 1D data which was computed in GPU and stored in GPU memory and I want to plot histogram using the same data(which stored in GPU memory). since vispy has access to GPU, is it directly take data or should I download data to GPU and plot again? How exactly it will work?
How was your data computed/generated in the GPU? CUDA? OpenCL? The short answer is that no there is no way to draw with vispy without copying the data to the CPU and resending it to the GPU through VisPy. The longer answer is that this is something I'm working on with PyCUDA in my free time...I just don't have much free time.
Here's the top part of my updated code
from vispy import app, visuals
import numpy as np
import sys
import time
from PyQt5.QtWidgets import *
from vispy.visuals.transforms import STTransform
class snrHistogram(app.Canvas):
def __init__(self, *args, **kwargs):
app.Canvas.__init__(self, title='histogram fail',
keys="interactive", size=(300, 300))
self.snr_hist = visuals.HistogramVisual(
np.repeat([0, 1, 1, 20, 20, 40, 40, 80, 80, 90], 400), bins=5, color='r', orientation='v')
#np.repeat([0, 1, 1, 20, 20, 40, 40, 80, 80, 90], 400), bins=5, color='r', orientation='h')
self.label = visuals.TextVisual("hi", color='blue', pos=[50, 50, 0])
self.configure_transforms()
#self.show()
def configure_transforms(self):
vp = (0, 0, self.physical_size[0], self.physical_size[1])
self.context.set_viewport(*vp)
self.label.transforms.configure(canvas=self, viewport=vp)
self.snr_hist.transforms.configure(canvas=self, viewport=vp)
self.snr_hist.transform = STTransform(scale=(300 / 1200.0, 300 / 90.0, 1.0))
Running this (with the bottom portion of your original code) gives me:
Where the red portion on the top is the first "bin", the portion below that is the second bin, and so on for a total of 5 bins. So the "bin" axis is "Y" axis, the quantity/amount axis is the "X" axis.