The ROI seem to forgot to update its states after rotate and resulting in errors of setPosition - pyqtgraph

Code to reproduce
import pyqtgraph as pg
from pyqtgraph.Qt import QtCore, QtWidgets
from pyqtgraph import PolyLineROI
app = pg.mkQApp("Arrow Example")
w = QtWidgets.QMainWindow()
cw = pg.GraphicsLayoutWidget()
w.show()
w.resize(1600, 900)
w.setCentralWidget(cw)
p = cw.addPlot(row=0, col=0)
ls = PolyLineROI([[0, 0], [1, 1], [2, 0]])
p.addItem(ls)
print(ls.getState())
ls.rotate(angle=90, center=[1, 1])
print(ls.getState())
p.setRange(QtCore.QRectF(-20, -10, 60, 20))
ls.setPoints([[0, 0], [1, 1], [2, 9]])
if __name__ == '__main__':
pg.exec()
Expected behavior
the result of getState should update after rotate. And the follow-up setPoints should be functional.
Real behavior
the ROI become strange after setPoints
image

Related

Why does the screen offset to left while updating kivy garden graph?

I am trying to create a kivy application with live graph using 'garden graph'. There seems a bug which offset the screen to left while updating the graph. What could be the possible reason?
graph.py
from kivy.config import Config
Config.set('graphics', 'width', '1024')
Config.set('graphics', 'height', '600')
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.core.window import Window
from kivy.lang import Builder
from kivy.clock import Clock, mainthread
from kivy.uix.screenmanager import ScreenManager, Screen
"""
Graph References:
https://github.com/kivy-garden/graph
https://stackoverflow.com/questions/30821127/using-kivy-garden-graph-in-kv-language#answer-46522799
"""
from math import sin
import random
from kivy_garden.graph import Graph, MeshLinePlot
"""
Class to manage Testing Screen
"""
class WindowGraph(Screen, Widget):
def __init__(self, **kw):
super().__init__(**kw)
self.graph = None
self.plot = None
self.x = 101
self.generate_graph()
# Clock.schedule_interval(self.update_graph, 1/10)
#mainthread
def generate_graph(self):
self.graph = self.ids['graph_test']
self.plot = MeshLinePlot(color=[1, 0, 0, 1])
# self.plot.points = [(x, sin(x / 10.)) for x in range(0, 101)]
self.graph.add_plot(self.plot)
#mainthread
def update_graph(self, *args):
self.plot.points.append((self.x, random.random()))
self.graph.xmin = max(self.x - 50, 0)
self.graph.xmax = self.x + 1
self.x += 10
def control_graph(self):
self.update_graph()
"""
Class to manage all screens
"""
class WindowManager(ScreenManager):
pass
# Load kv builder file
kv = Builder.load_file("graph.kv")
class CTControlApp(App):
def build(self):
Window.clearcolor = (205/255, 205/255, 205/255, 1)
return kv
CTControlApp().run()
graph.kv
WindowManager:
WindowGraph:
<WindowGraph>
name: "layout_graph"
FloatLayout:
size: root.width, root.height
canvas.before :
Color:
rgba: 1, 1, 1, 1
Line:
width: 0.5
rectangle: self.x, self.y, self.width, self.height
Label:
text: "TESTING"
font_size : 22
pos_hint : {"x":0.01369*14, "y":0.03448*27}
size_hint:0.01369*45, 0.03448*2
background_color :1, 1, 1, 0
color : 1, 1, 1, 1
Graph:
id: graph_test
xlabel:'X'
ylabel:'Y'
x_ticks_minor:5
x_tics_major:25
y_ticks_major:1
y_grid_label:True
x_grid_label:True
padding:5
x_grid:True
y_grid:True
xmin:-0
xmax:100
ymin:-1
ymax:1
pos_hint: {"x":0.01369*2, "y":0.03448*2}
size_hint: 0.01369*56, 0.03448*25
Button :
id: button_graph_control
text: "UPDATE"
on_press: root.control_graph()
font_size : 24
pos_hint : {"x":0.01369*60, "y":0.03448*10}
size_hint:0.01369*10, 0.03448*3
background_color :0.5, 0.5, 0.5, 0.3
color : 1, 1, 1, 1
Screen before updating graph
Screen after updating graph
Please help me resolve this issue dear friends

synchronize selection of > 1 chart

How do I synchronize the selection in the 2 charts below? Also, how do I get the bounds of the box selection?
import holoviews as hv
import hvplot.pandas
from bokeh.sampledata.autompg import autompg
hv.extension('bokeh')
hv.Layout([autompg.hvplot.scatter(x='mpg', y='yr', tools=['box_select']), autompg.hvplot.scatter(x='mpg', y='yr', tools=['box_select'])]).cols(1)
The linked selection is easy:
import holoviews as hv
import hvplot.pandas
from bokeh.sampledata.autompg import autompg
hv.extension('bokeh')
from holoviews.plotting.links import DataLink
a = autompg.hvplot.scatter(x='mpg', y='yr', tools=['box_select'])
b = autompg.hvplot.scatter(x='mpg', y='yr', tools=['box_select'])
DataLink(a, b)
hv.Layout([a, b]).cols(1)
Documentation: https://www.holoviews.org/user_guide/Linking_Plots.html
Now for retrieving the bounds. You can use BoundsXY for that:
import numpy as np
import holoviews as hv
from holoviews.streams import BoundsXY
data = np.random.multivariate_normal((0, 0), [[1, 0.1], [0.1, 1]], (1000,))
points = hv.Points(data).opts(tools=['box_select'])
sel = BoundsXY(source=points)
def cog(bounds):
'Center of gravity'
if bounds is None:
bounds=(0, 0, 0, 0)
index = points.dframe().x.between(*bounds[::2]) & points.dframe().y.between(*bounds[1::2])
x = points.dframe().loc[index, 'x'].mean() if index.any() else []
y = points.dframe().loc[index, 'y'].mean() if index.any() else []
return hv.Points((x, y)).opts(size=10)
mean_sel = hv.DynamicMap(cog, kdims=[], streams=[sel])
points * mean_sel
(modelled on http://holoviews.org/reference/apps/bokeh/selection_stream.html)

What problems can lead to a CuDNNError with ConvolutionND

I am using three-dimensional convolution links (with ConvolutionND) in my chain.
The forward computation run smoothly (I checked intermediate result shapes to be sure I understood correctly the meaning of the parameters of convolution_nd), but during the backward a CuDNNError is raised with the message CUDNN_STATUS_NOT_SUPPORTED.
The cover_all parameter of ConvolutionND as its default value of False, so from the doc I don't see what can be the cause of the error.
Here is how I defind one of the convolution layers :
self.conv1 = chainer.links.ConvolutionND(3, 1, 4, (3, 3, 3)).to_gpu(self.GPU_1_ID)
And the call stack is
File "chainer/function_node.py", line 548, in backward_accumulate
gxs = self.backward(target_input_indexes, grad_outputs)
File "chainer/functions/connection/convolution_nd.py", line 118, in backward
gy, W, stride=self.stride, pad=self.pad, outsize=x_shape)
File "chainer/functions/connection/deconvolution_nd.py", line 310, in deconvolution_nd
y, = func.apply(args)
File chainer/function_node.py", line 258, in apply
outputs = self.forward(in_data)
File "chainer/functions/connection/deconvolution_nd.py", line 128, in forward
return self._forward_cudnn(x, W, b)
File "chainer/functions/connection/deconvolution_nd.py", line 105, in _forward_cudnn
tensor_core=tensor_core)
File "cupy/cudnn.pyx", line 881, in cupy.cudnn.convolution_backward_data
File "cupy/cuda/cudnn.pyx", line 975, in cupy.cuda.cudnn.convolutionBackwardData_v3
File "cupy/cuda/cudnn.pyx", line 461, in cupy.cuda.cudnn.check_status
cupy.cuda.cudnn.CuDNNError: CUDNN_STATUS_NOT_SUPPORTED
So are there special points to take care of when using ConvolutionND ?
A failing code is for instance :
import chainer
from chainer import functions as F
from chainer import links as L
from chainer.backends import cuda
import numpy as np
import cupy as cp
chainer.global_config.cudnn_deterministic = False
NB_MASKS = 60
NB_FCN = 3
NB_CLASS = 17
class MFEChain(chainer.Chain):
"""docstring for Wavelphasenet."""
def __init__(self,
FCN_Dim,
gpu_ids=None):
super(MFEChain, self).__init__()
self.GPU_0_ID, self.GPU_1_ID = (0, 1) if gpu_ids is None else gpu_ids
with self.init_scope():
self.conv1 = chainer.links.ConvolutionND(3, 1, 4, (3, 3, 3)).to_gpu(
self.GPU_1_ID
)
def __call__(self, inputs):
### Pad input ###
processed_sequences = []
for convolved in inputs:
## Transform to sequences)
copy = convolved if self.GPU_0_ID == self.GPU_1_ID else F.copy(convolved, self.GPU_1_ID)
processed_sequences.append(copy)
reprocessed_sequences = []
with cuda.get_device(self.GPU_1_ID):
for convolved in processed_sequences:
convolved = F.expand_dims(convolved, 0)
convolved = F.expand_dims(convolved, 0)
convolved = self.conv1(convolved)
reprocessed_sequences.append(convolved)
states = F.vstack(reprocessed_sequences)
logits = states
ret_logits = logits if self.GPU_0_ID == self.GPU_1_ID else F.copy(logits, self.GPU_0_ID)
return ret_logits
def mfe_test():
mfe = MFEChain(150)
inputs = list(
chainer.Variable(
cp.random.randn(
NB_MASKS,
11,
in_len,
dtype=cp.float32
)
) for in_len in [53248]
)
val = mfe(inputs)
grad = cp.ones(val.shape, dtype=cp.float32)
val.grad = grad
val.backward()
for i in inputs:
print(i.grad)
if __name__ == "__main__":
mfe_test()
cupy.cuda.cudnn.convolutionBackwardData_v3 is incompatible with some specific parameters, as described in an issue in official github.
Unfortunately, the issue only dealt with deconvolution_2d.py (not deconvolution_nd.py), therefore the decision-making about whether cudnn is used or not failed in your case, I guess.
you can check your parameter by confirming
check whether dilation parameter (!=1) or group parameter (!=1) is passed to the convolution.
print chainer.config.cudnn_deterministic, configuration.config.autotune, and configuration.config.use_cudnn_tensor_core.
Further support may be obtained by raising an issue in the official github.
The code you showed is much complicated.
To clarify the problem, the code below would help.
from chainer import Variable, Chain
from chainer import links as L
from chainer import functions as F
import numpy as np
from six import print_
batch_size = 1
in_channel = 1
out_channel = 1
class MyLink(Chain):
def __init__(self):
super(MyLink, self).__init__()
with self.init_scope():
self.conv = L.ConvolutionND(3, 1, 1, (3, 3, 3), nobias=True, initialW=np.ones((in_channel, out_channel, 3, 3, 3)))
def __call__(self, x):
return F.sum(self.conv(x))
if __name__ == "__main__":
my_link = MyLink()
my_link.to_gpu(0)
batch = Variable(np.ones((batch_size, in_channel, 3, 3, 3)))
batch.to_gpu(0)
loss = my_link(batch)
loss.backward()
print_(batch.grad)

Bokeh - get updated data when using Edit Tools

Recently, multi-gesture edit tools have been added to Bokeh. For example, using the script below, I can interactively draw points in a jupyter notebook using the PointDrawTool. My question is, how do I get the updated data for the points that I generate or edit into a numpy array or a similar data structure?
from bokeh.plotting import figure, output_file, show, Column
from bokeh.models import DataTable, TableColumn, PointDrawTool, ColumnDataSource
from bokeh.io import output_notebook
# Direct output to notebook
output_notebook()
p = figure(x_range=(0, 10), y_range=(0, 10), tools=[],
title='Point Draw Tool')
p.background_fill_color = 'lightgrey'
source = ColumnDataSource({
'x': [1, 5, 9], 'y': [1, 5, 9], 'color': ['red', 'green', 'yellow']
})
renderer = p.scatter(x='x', y='y', source=source, color='color', size=10)
columns = [TableColumn(field="x", title="x"),
TableColumn(field="y", title="y"),
TableColumn(field='color', title='color')]
table = DataTable(source=source, columns=columns, editable=True, height=200)
draw_tool = PointDrawTool(renderers=[renderer], empty_value='black')
p.add_tools(draw_tool)
p.toolbar.active_tap = draw_tool
handle = show(Column(p, table), notebook_handle=True)
Using such method of showing plot does not provide synchronization between Python and JS. To solve this you can use bookeh server, as described here. Usualy you use commnad:
bokeh serve --show myapp.py
Then you can embed this application in your jupyter. For me it was very inconvinient so I started to look for other solutions.
It is possible to run bookeh app from jupyter notebook, you can find example here.
Sample code for your problem would look like this:
from bokeh.plotting import figure, output_notebook, show, Column
from bokeh.models import DataTable, TableColumn, PointDrawTool, ColumnDataSource
output_notebook()
def modify_doc(doc):
p = figure(x_range=(0, 10), y_range=(0, 10), tools=[],
title='Point Draw Tool')
p.background_fill_color = 'lightgrey'
source = ColumnDataSource({
'x': [1, 5, 9], 'y': [1, 5, 9], 'color': ['red', 'green', 'yellow']
})
renderer = p.scatter(x='x', y='y', source=source, color='color', size=10)
columns = [TableColumn(field="x", title="x"),
TableColumn(field="y", title="y"),
TableColumn(field='color', title='color')]
table = DataTable(source=source, columns=columns, editable=True, height=200)
draw_tool = PointDrawTool(renderers=[renderer], empty_value='black')
p.add_tools(draw_tool)
p.toolbar.active_tap = draw_tool
doc.add_root(Column(p, table))
show(modify_doc)

expand Widget in pyqt

I am trying to force my QTextEdit widget to span the whole cell of the QGridLayout.
I tried a lot of different combinations of QSizePolicy and sizeHint(), but nothing has the desired effect.
In the example below I have a main widget of minimum size 800x600 and another widget 'blue' of size 100x100 in column 1. So I want the QTextEdit in column 0 to be 700x600.
In general I want 'edit' to be (n-blue.width())xm if my main widget is resized to nxm.
import sys
from PyQt5 import QtWidgets, QtCore
if __name__ == '__main__':
qApp = QtWidgets.QApplication(sys.argv)
mainWidget = QtWidgets.QWidget()
mainWidget.setMinimumSize(800, 600)
mainLayout = QtWidgets.QGridLayout(mainWidget)
blue = QtWidgets.QWidget(mainWidget)
blue.setStyleSheet('background-color: blue')
blue.setFixedSize(100, 100)
edit = QtWidgets.QTextEdit(mainWidget)
### what to do here?
policy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding,
QtWidgets.QSizePolicy.Expanding)
edit.setSizePolicy(policy)
###
mainLayout.addWidget(edit, 0, 0, 1, 1, QtCore.Qt.AlignCenter)
mainLayout.addWidget(blue, 0, 1, 1, 1, QtCore.Qt.AlignCenter)
mainLayout.setColumnStretch(0, 1)
mainLayout.setColumnStretch(1, 0)
mainWidget.setLayout(mainLayout)
mainWidget.show()
sys.exit(qApp.exec_())
I think you're just placing too many constraints on the QGridLayout. Try adding the widgets to the layout with just...
mainLayout.addWidget(edit, 0, 0)
mainLayout.addWidget(blue, 0, 1)
Also, you probably don't need to set the sizing policy explicitly -- it should just work as-is (it does for me).
The full, minimal working example would be something like...
import sys
from PyQt5 import QtWidgets, QtCore
if __name__ == '__main__':
qApp = QtWidgets.QApplication(sys.argv)
mainWidget = QtWidgets.QWidget()
mainWidget.setMinimumSize(800, 600)
mainLayout = QtWidgets.QGridLayout(mainWidget)
blue = QtWidgets.QWidget(mainWidget)
blue.setStyleSheet('background-color: blue')
blue.setFixedSize(100, 100)
edit = QtWidgets.QTextEdit(mainWidget)
mainLayout.addWidget(edit, 0, 0)
mainLayout.addWidget(blue, 0, 1)
mainWidget.show()
sys.exit(qApp.exec_())

Resources