DropEvent does not work when dragging and dropping between widgets - pyqt5

I'm trying to get the behavior that when I drag and drop a MyButton, the dropEvent will be triggered in any part of the interface. Right now it works pretty much as needed, except for one thing. The dropEvent doesn't work if the mouse button is released between widgets, and I don't know how to fix this problem. For me it is very important that the dropEvent is always triggered, at the moment when the drag is finished, because at that moment I send a message to the server about the move made, and if at that moment the mouse was between the widgets, this message is not sent.
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'DS_Test.ui'
#
# Created by: PyQt5 UI code generator 5.15.7
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtGui import QDragEnterEvent, QDropEvent
class MyButton(QtWidgets.QPushButton):
def mouseMoveEvent(self, event):
btn_img = self.grab()
painter = QtGui.QPainter(btn_img)
painter.setCompositionMode(painter.CompositionMode_DestinationIn)
painter.fillRect(btn_img.rect(), QtGui.QColor(0, 0, 0, 150))
painter.end()
data = QtCore.QMimeData()
drag = QtGui.QDrag(self)
drag.setMimeData(data)
drag.setPixmap(btn_img)
drag.setHotSpot(event.pos())
self._pos = event.pos()
drag.exec_(QtCore.Qt.CopyAction)
super(MyButton, self).mouseMoveEvent(event)
class MyFrame(QtWidgets.QFrame):
def __init__(self, parent):
super().__init__(parent)
self.setAcceptDrops(True)
def dragEnterEvent(self, e: QDragEnterEvent):
e.accept()
def dragMoveEvent(self, e):
e.accept()
def dropEvent(self, e: QDropEvent):
self.parent().dropEvent(e)
class MyQDialog(QtWidgets.QDialog):
def __init__(self):
super().__init__()
self.setAcceptDrops(True)
def dropEvent(self, e: QDropEvent):
print("dropEvent - is done")
e.accept()
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(1051, 800)
self.verticalLayout = QtWidgets.QVBoxLayout(Dialog)
self.verticalLayout.setObjectName("verticalLayout")
self.horizontalFrame = MyFrame(Dialog)
self.horizontalFrame.setStyleSheet("background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(255, 0, 0, 211), stop:0.166 rgba(255, 255, 0, 211), stop:0.333 rgba(0, 255, 0, 211), stop:0.5 rgba(0, 255, 255, 211), stop:0.666 rgba(0, 0, 255, 211), stop:0.833 rgba(255, 0, 255, 211), stop:1 rgba(255, 0, 0, 211));")
self.horizontalFrame.setObjectName("horizontalFrame")
self.horizontalLayout_6 = QtWidgets.QHBoxLayout(self.horizontalFrame)
self.horizontalLayout_6.setObjectName("horizontalLayout_6")
self.pushButton_3 = MyButton(self.horizontalFrame)
self.pushButton_3.setObjectName("pushButton_3")
self.horizontalLayout_6.addWidget(self.pushButton_3)
self.pushButton_2 = MyButton(self.horizontalFrame)
self.pushButton_2.setObjectName("pushButton_2")
self.horizontalLayout_6.addWidget(self.pushButton_2)
self.pushButton = MyButton(self.horizontalFrame)
self.pushButton.setObjectName("pushButton")
self.horizontalLayout_6.addWidget(self.pushButton)
self.verticalLayout.addWidget(self.horizontalFrame)
self.horizontalFrame_2 = MyFrame(Dialog)
self.horizontalFrame_2.setStyleSheet("background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(9, 41, 4, 255), stop:0.085 rgba(2, 79, 0, 255), stop:0.19 rgba(50, 147, 22, 255), stop:0.275 rgba(236, 191, 49, 255), stop:0.39 rgba(243, 61, 34, 255), stop:0.555 rgba(135, 81, 60, 255), stop:0.667 rgba(121, 75, 255, 255), stop:0.825 rgba(164, 255, 244, 255), stop:0.885 rgba(104, 222, 71, 255), stop:1 rgba(93, 128, 0, 255));")
self.horizontalFrame_2.setObjectName("horizontalFrame_2")
self.horizontalLayout_7 = QtWidgets.QHBoxLayout(self.horizontalFrame_2)
self.horizontalLayout_7.setObjectName("horizontalLayout_7")
self.verticalLayout.addWidget(self.horizontalFrame_2)
self.horizontalFrame_3 = MyFrame(Dialog)
self.horizontalFrame_3.setStyleSheet("background-color: qlineargradient(spread:pad, x1:0, y1:1, x2:0, y2:0, stop:0 rgba(0, 0, 0, 255), stop:0.05 rgba(14, 8, 73, 255), stop:0.36 rgba(28, 17, 145, 255), stop:0.6 rgba(126, 14, 81, 255), stop:0.75 rgba(234, 11, 11, 255), stop:0.79 rgba(244, 70, 5, 255), stop:0.86 rgba(255, 136, 0, 255), stop:0.935 rgba(239, 236, 55, 255));")
self.horizontalFrame_3.setObjectName("horizontalFrame_3")
self.horizontalLayout_8 = QtWidgets.QHBoxLayout(self.horizontalFrame_3)
self.horizontalLayout_8.setObjectName("horizontalLayout_8")
self.verticalLayout.addWidget(self.horizontalFrame_3)
self.retranslateUi(Dialog)
QtCore.QMetaObject.connectSlotsByName(Dialog)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
self.pushButton_3.setText(_translate("Dialog", "PushButton"))
self.pushButton_2.setText(_translate("Dialog", "PushButton"))
self.pushButton.setText(_translate("Dialog", "PushButton"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
Dialog = MyQDialog()
ui = Ui_Dialog()
ui.setupUi(Dialog)
Dialog.show()
sys.exit(app.exec_())

As recommended in the comment, I added dragEnterEvent and dragMoveEvent to MyQDialog. Now everything works the way I want it to. Here is the corrected code
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'DS_Test.ui'
#
# Created by: PyQt5 UI code generator 5.15.7
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtGui import QDragEnterEvent, QDropEvent
class MyButton(QtWidgets.QPushButton):
def mouseMoveEvent(self, event):
btn_img = self.grab()
painter = QtGui.QPainter(btn_img)
painter.setCompositionMode(painter.CompositionMode_DestinationIn)
painter.fillRect(btn_img.rect(), QtGui.QColor(0, 0, 0, 150))
painter.end()
data = QtCore.QMimeData()
drag = QtGui.QDrag(self)
drag.setMimeData(data)
drag.setPixmap(btn_img)
drag.setHotSpot(event.pos())
self._pos = event.pos()
drag.exec_(QtCore.Qt.CopyAction)
super(MyButton, self).mouseMoveEvent(event)
class MyFrame(QtWidgets.QFrame):
def __init__(self, parent):
super().__init__(parent)
self.setAcceptDrops(True)
def dragEnterEvent(self, e: QDragEnterEvent):
e.accept()
def dragMoveEvent(self, e):
e.accept()
def dropEvent(self, e: QDropEvent):
self.parent().dropEvent(e)
class MyQDialog(QtWidgets.QDialog):
def __init__(self):
super().__init__()
self.setAcceptDrops(True)
def dragEnterEvent(self, e: QDragEnterEvent):
e.accept()
def dragMoveEvent(self, e):
e.accept()
def dropEvent(self, e: QDropEvent):
print("dropEvent - is done")
e.accept()
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(1051, 800)
self.verticalLayout = QtWidgets.QVBoxLayout(Dialog)
self.verticalLayout.setObjectName("verticalLayout")
self.horizontalFrame = MyFrame(Dialog)
self.horizontalFrame.setStyleSheet("background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(255, 0, 0, 211), stop:0.166 rgba(255, 255, 0, 211), stop:0.333 rgba(0, 255, 0, 211), stop:0.5 rgba(0, 255, 255, 211), stop:0.666 rgba(0, 0, 255, 211), stop:0.833 rgba(255, 0, 255, 211), stop:1 rgba(255, 0, 0, 211));")
self.horizontalFrame.setObjectName("horizontalFrame")
self.horizontalLayout_6 = QtWidgets.QHBoxLayout(self.horizontalFrame)
self.horizontalLayout_6.setObjectName("horizontalLayout_6")
self.pushButton_3 = MyButton(self.horizontalFrame)
self.pushButton_3.setObjectName("pushButton_3")
self.horizontalLayout_6.addWidget(self.pushButton_3)
self.pushButton_2 = MyButton(self.horizontalFrame)
self.pushButton_2.setObjectName("pushButton_2")
self.horizontalLayout_6.addWidget(self.pushButton_2)
self.pushButton = MyButton(self.horizontalFrame)
self.pushButton.setObjectName("pushButton")
self.horizontalLayout_6.addWidget(self.pushButton)
self.verticalLayout.addWidget(self.horizontalFrame)
self.horizontalFrame_2 = MyFrame(Dialog)
self.horizontalFrame_2.setStyleSheet("background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(9, 41, 4, 255), stop:0.085 rgba(2, 79, 0, 255), stop:0.19 rgba(50, 147, 22, 255), stop:0.275 rgba(236, 191, 49, 255), stop:0.39 rgba(243, 61, 34, 255), stop:0.555 rgba(135, 81, 60, 255), stop:0.667 rgba(121, 75, 255, 255), stop:0.825 rgba(164, 255, 244, 255), stop:0.885 rgba(104, 222, 71, 255), stop:1 rgba(93, 128, 0, 255));")
self.horizontalFrame_2.setObjectName("horizontalFrame_2")
self.horizontalLayout_7 = QtWidgets.QHBoxLayout(self.horizontalFrame_2)
self.horizontalLayout_7.setObjectName("horizontalLayout_7")
self.verticalLayout.addWidget(self.horizontalFrame_2)
self.horizontalFrame_3 = MyFrame(Dialog)
self.horizontalFrame_3.setStyleSheet("background-color: qlineargradient(spread:pad, x1:0, y1:1, x2:0, y2:0, stop:0 rgba(0, 0, 0, 255), stop:0.05 rgba(14, 8, 73, 255), stop:0.36 rgba(28, 17, 145, 255), stop:0.6 rgba(126, 14, 81, 255), stop:0.75 rgba(234, 11, 11, 255), stop:0.79 rgba(244, 70, 5, 255), stop:0.86 rgba(255, 136, 0, 255), stop:0.935 rgba(239, 236, 55, 255));")
self.horizontalFrame_3.setObjectName("horizontalFrame_3")
self.horizontalLayout_8 = QtWidgets.QHBoxLayout(self.horizontalFrame_3)
self.horizontalLayout_8.setObjectName("horizontalLayout_8")
self.verticalLayout.addWidget(self.horizontalFrame_3)
self.retranslateUi(Dialog)
QtCore.QMetaObject.connectSlotsByName(Dialog)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
self.pushButton_3.setText(_translate("Dialog", "PushButton"))
self.pushButton_2.setText(_translate("Dialog", "PushButton"))
self.pushButton.setText(_translate("Dialog", "PushButton"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
Dialog = MyQDialog()
ui = Ui_Dialog()
ui.setupUi(Dialog)
Dialog.show()
sys.exit(app.exec_())

Related

is it possible to pad a numpy array with a tuple?

I'm trying to pad a numpy array with a tuple (the array itself has only tuples)...all I can find is padding an array with 0s or 1s, which I can get to work, but that doesn't help me. Is it possible to pad with a tuple?
The crucial line is :
cells = np.pad(cells, pad_width=1, mode='constant', constant_values=material)
Replacing material, which is a 4-tuple, with a 0 works fine...but I really need it to be a tuple.
I get the error message:
operands could not be broadcast together with remapped shapes [original->remapped]: (4,) and requested shape (2,2)
Here is the code I am using, but using 0s and 1s instead:
import numpy as np
side_len = 3
a = [1 for x in range(9)]
a = np.array(a)
a = a.reshape(side_len,side_len)
a = np.pad(a, pad_width=1, mode='constant', constant_values=0)
The goal is instead of a list of 1s, to pass a list of tuples, and instead of a constant_values=0, to have constant_values=material, where material is an arbitrary 4-tuple.
A flat list of tuples are passed to this function (the function is not shown here), eg:
[(0, 0, 255, 255), (0, 0, 255, 255), (0, 0, 255, 255), (0, 0, 255, 255), (0, 0, 255, 255), (0, 0, 255, 255), (0, 0, 255, 255), (0, 0, 255, 255), (0, 0, 255, 255)]
Which I convert to a numpy array using:
cells = np.array(cells, dtype='i,i,i,i').reshape(side_len,side_len)
Perhaps this is wonky, but the rest of my program just uses lists, I don't need numpy for it; but for this padding issue, I originally was manually iterating over my flat list and doing the padding, which took forever as the list grew, so I thought I'd try numpy because it might be faster.
the solution was:
import numpy as np
side_len = 3
material = (0,0,0,255)
a = [(255,0,0,255) for x in range(9)]
a = np.array(a,dtype='i,i,i,i').reshape(side_len,side_len)
_material = np.array(material,dtype='i,i,i,i')
a = np.pad(a, pad_width=1, mode='constant', constant_values=_material)
a
array([[( 0, 0, 0, 255), ( 0, 0, 0, 255), ( 0, 0, 0, 255),
( 0, 0, 0, 255), ( 0, 0, 0, 255)],
[( 0, 0, 0, 255), (255, 0, 0, 255), (255, 0, 0, 255),
(255, 0, 0, 255), ( 0, 0, 0, 255)],
[( 0, 0, 0, 255), (255, 0, 0, 255), (255, 0, 0, 255),
(255, 0, 0, 255), ( 0, 0, 0, 255)],
[( 0, 0, 0, 255), (255, 0, 0, 255), (255, 0, 0, 255),
(255, 0, 0, 255), ( 0, 0, 0, 255)],
[( 0, 0, 0, 255), ( 0, 0, 0, 255), ( 0, 0, 0, 255),
( 0, 0, 0, 255), ( 0, 0, 0, 255)]],
dtype=[('f0', '<i4'), ('f1', '<i4'), ('f2', '<i4'), ('f3', '<i4')])

How i can add QFrame in QScrollArea?

I was doing this by creating QFrame() object in loop and it add in QFormLayout to get multiple Frame but it shows nothing .
scr = QScrollArea()
frame = QFrame()
frame.setStyleSheet("background:'black'")
lbl= QLabel(f"{name_playlist[details]}",frame)
lbl.setStyleSheet('''background-color: qradialgradient(spread:pad, cx:0.5, cy:0.5, radius:1.772, fx:0.5, fy:0.5, stop:0 rgba(216, 106, 126, 255), stop:1 rgba(255, 255, 255, 255));
color:#fff;
font: 63 12pt "Bahnschrift SemiBold";border-radius:10px''')
lbl.setGeometry(QRect(0,170,201,31))
lbl_1 = QLabel(frame)
pixmap = QPixmap(f"{thumbnails_playlist[details]}")
pixmap= pixmap.scaled(191,161)
lbl_1.setStyleSheet("border-radius: 15px")
lbl_1.setPixmap(pixmap)
# nm_songs.append(lbl)
thumbnail.append(frame)
formlayout.addRow(thumbnail[details])
groupbox.setLayout(formlayout)
self.scroll.setWidget(groupbox)```

How can I keep a subplot table from stretching?

How should I alter the following script to keep the subplot (on right_ from stretching? Is there a way to set either plot area of the subplot? Frustrating as I go thru the row/column sizing in the function, but when plot it just expands to fill the area. In the left subplot is the full list (22 rows). In the right I just pass half the df rows, and it fills vertically? Thx.
import pandas as pd
import matplotlib.pyplot as plt
import six
plt.rcParams['font.family'] = "Lato"
raw_data = dict(TF_001=[42, 39, 86, 15, 23, 57, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
21, 22, 23, 24, 25],
SP500=[52, 41, 79, 80, 34, 47, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
23, 24, 25],
Strategy=[62, 37, 84, 51, 67, 32, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
22,
23, 24, 25],
LP_Port=[72, 43, 36, 26, 53, 88, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
22, 23, 24, 25])
df = pd.DataFrame(raw_data, index=pd.Index(
['Sharpe Ratio', 'Sortino Ratio', 'Calmars Ratio', 'Ulcer Index', 'Max Drawdown', 'Volatility',
'VaR', 'CVaR', 'R-Squared', 'CAGR', 'Risk-of-Ruin', 'Gain-Pain Ratio', 'Pitfall Indicator',
'Serentity Ratio', 'Common Sense Ratio', 'Kelly Criteria', 'Payoff Ratio', 'Ratio-A',
'Ratio-B', 'Ratio-C', 'Ratio-D', 'Ratio-E'], name='Metric'),
columns=pd.Index(['TF_001', 'SP500', 'Strategy', 'LP_Port'], name='Series'))
def create_table(data,
ax=None,
col_width=None,
row_height=None,
font_size=8,
header_color='#E5E5E5',
row_colors=None,
edge_color='w',
header_columns=0,
bbox=None):
if row_colors is None:
row_colors = ['#F1F8E9', 'w']
if bbox is None:
bbox = [0, 0, 1, 1]
data_table = ax.table(cellText=data.values,
colLabels=data.columns,
rowLabels=data.index,
bbox=bbox,
cellLoc='center',
rowLoc='left',
colLoc='center',
colWidths=([col_width] * len(data.columns)))
cell_map = data_table.get_celld()
for i in range(0, len(data.columns)):
cell_map[(0, i)].set_height(row_height * 0.2)
data_table.auto_set_font_size(False)
data_table.set_fontsize(font_size)
for k, cell in six.iteritems(data_table._cells):
cell.set_edgecolor(edge_color)
if k[0] == 0 or k[1] < header_columns:
cell.set_text_props(weight='heavy', color='black')
cell.set_facecolor(header_color)
else:
cell.set_facecolor(row_colors[k[0] % len(row_colors)])
for row, col in data_table._cells:
if (row == 0) or (col == -1):
data_table._cells[(row, col)].set_alpha(0.8)
return ax
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 7), constrained_layout=False)
create_table(df, ax1, col_width=1.1, row_height=0.25, font_size=8)
create_table(df.iloc[0:11, ], ax2, col_width=1.1, row_height=0.25, font_size=8)
ax1.set_title("- Conventional Risk Measures -",
fontsize=10,
fontweight='heavy',
loc='center')
ax1.axis('off')
ax2.set_title("- Second Order Risk Measures -",
fontsize=10,
fontweight='heavy',
loc='center')
ax2.axis('off')
plt.suptitle('EF QuantOne - Performance and Risk Assessment ("PaRA")',
x=0.0175,
y=0.9775,
ha='left',
fontsize=12,
weight='heavy')
plt.tight_layout()
plt.savefig('risk_parameter_table[1].pdf',
orientation='portrait',
pad_inches=0.5)
plt.show()
Figured it out ...
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import six
plt.rcParams['font.family'] = "Lato"
raw_data = dict(TF_001=[42, 39, 86, 15, 23, 57, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
21, 22, 23, 24, 25],
SP500=[52, 41, 79, 80, 34, 47, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
23, 24, 25],
Strategy=[62, 37, 84, 51, 67, 32, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
22,
23, 24, 25],
LP_Port=[72, 43, 36, 26, 53, 88, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
22, 23, 24, 25])
df = pd.DataFrame(raw_data, index=pd.Index(
['Sharpe Ratio', 'Sortino Ratio', 'Calmars Ratio', 'Ulcer Index', 'Max Drawdown', 'Volatility',
'VaR', 'CVaR', 'R-Squared', 'CAGR', 'Risk-of-Ruin', 'Gain-Pain Ratio', 'Pitfall Indicator',
'Serentity Ratio', 'Common Sense Ratio', 'Kelly Criteria', 'Payoff Ratio', 'Ratio-A',
'Ratio-B', 'Ratio-C', 'Ratio-D', 'Ratio-E'], name='Metric'),
columns=pd.Index(['TF_001', 'SP500', 'Strategy', 'LP_Port'], name='Series'))
def create_table(data,
ax=None,
col_width=None,
row_height=None,
font_size=8,
header_color='#E5E5E5',
row_colors=None,
edge_color='w',
header_columns=0,
bbox=None):
if row_colors is None:
row_colors = ['#F1F8E9', 'w']
if bbox is None:
bbox = [0, 0, 1, 1]
data_table = ax.table(cellText=data.values,
colLabels=data.columns,
rowLabels=data.index,
bbox=bbox,
cellLoc='center',
rowLoc='left',
colLoc='center',
colWidths=([col_width] * len(data.columns)))
cell_map = data_table.get_celld()
for i in range(0, len(data.columns)):
cell_map[(0, i)].set_height(row_height * 0.2)
data_table.auto_set_font_size(False)
data_table.set_fontsize(font_size)
for k, cell in six.iteritems(data_table._cells):
cell.set_edgecolor(edge_color)
if k[0] == 0 or k[1] < header_columns:
cell.set_text_props(weight='heavy', color='black')
cell.set_facecolor(header_color)
else:
cell.set_facecolor(row_colors[k[0] % len(row_colors)])
for row, col in data_table._cells:
if (row == 0) or (col == -1):
data_table._cells[(row, col)].set_alpha(0.8)
return ax
# fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(11, 8.5), constrained_layout=False)
fig = plt.figure(figsize=(12, 10))
w, h = fig.get_size_inches()
div = np.array([w, h, w, h])
col_width = 1.1
row_height = 0.25
ax1_subplot_size = (np.array(df.shape[::-1]) + np.array([0, 1])) * np.array(
[col_width, row_height])
ax1 = fig.add_axes(np.array([1.6, 1, 4.4, 5.75]) / div)
ax2_subplot_size = (np.array(df.shape[::-1]) + np.array([0, 1])) * np.array(
[col_width, row_height])
ax2 = fig.add_axes(np.array([7.5, 3.75, 4.4, 3]) / div)
create_table(df, ax1, col_width, row_height, font_size=8)
create_table(df.iloc[0:11, ], ax2, col_width, row_height, font_size=8)
ax1.set_title("- Conventional Risk Measures -",
fontsize=10,
fontweight='heavy',
loc='center')
ax1.axis('off')
ax2.set_title("- Second Order Risk Measures -",
fontsize=10,
fontweight='heavy',
loc='center')
ax2.axis('off')
plt.suptitle('EF QuantOne - Performance and Risk Assessment ("PaRA")',
x=0.0175,
y=0.9775,
ha='left',
fontsize=12,
weight='heavy')
# plt.tight_layout()
plt.savefig('risk_parameter_table[1].pdf',
orientation='portrait',
pad_inches=0.5)
plt.show()

how to decode png with tensorflow 2.x API without using the palette contained in the png file

png files are usually index values assosiated with a default palette. by default, index values can be read by PIL image, for example:
import tensorflow as tf
from PIL import Image
import numpy as np
path = '1.png'
image1 = Image.open(path)
print(image1.mode)
array1 = np.array(image1)
print(array1.shape)
print(set(list(array1.reshape(-1))))
the results:
P
(1024, 543)
{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}
index can be converted to palette colors:
image2 = image1.convert('RGB')
print(image2.mode)
array2 = np.array(image2)
print(array2.shape)
print(set([tuple(x) for x in list(array2.reshape(-1, 3))]))
the results are
RGB
(1024, 543, 3)
{(0, 255, 255), (255, 255, 0), (0, 0, 255), (85, 255, 170), (170, 255, 85), (255, 0, 0), (255, 170, 0), (0, 170, 255), (0, 85, 255), (255, 85, 0), (0, 0, 170)}
the question is, by default, tensorflow 2.x API read palette colors, is there a way to read the index values?
tensor = tf.io.read_file(path)
tensor = tf.image.decode_png(tensor, channels=3)
array3 = tensor.numpy()
print(array3.shape)
print(set([tuple(x) for x in list(array3.reshape(-1, 3))]))
(1024, 543, 3)
{(0, 255, 255), (255, 255, 0), (0, 0, 255), (85, 255, 170), (170, 255, 85), (255, 0, 0), (255, 170, 0), (0, 170, 255), (0, 85, 255), (255, 85, 0), (0, 0, 170)}
my temporary solution is to remove all the palette assosiated with png files. Still looking for more efficient solutions
from PIL import Image
import numpy as np
img = Image.open('1.png')
img = np.array(img)
img = Image.fromarray(img)
img.save('2.png')
Ideal solution
A clean solution would be to re-implement a custom op to decode a PNG without palette conversion.
Currently, the palette conversion in TF for the decode_png-op is done at core level:
// convert palette to rgb(a) if needs be.
if (context->color_type == PNG_COLOR_TYPE_PALETTE)
png_set_palette_to_rgb(context->png_ptr);
Work-around solution
(TF2.X)
As you've mentioned PIL in your sample code, you could wrap the PIL-call with tf.py_function in order to get the desired behavior, like:
def read_png(mask):
def read_fn(p):
return np.asarray(Image.open(p.numpy().decode()))
return tf.py_function(read_fn, [mask], tf.uint8)
and then read a paletted PNG-image without automatic palette application, like:
img = read_png(path)
img= img.numpy()
print(img.shape)
print(set(list(img.reshape(-1))))
Sample output
(1024, 543)
{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}
Note: in TF1.X this works only in graph-mode, and you would have to use tf.py_func to wrap the TF around PIL-function (+ some minor changes).

MatPlotLib PyQt5 Layout Problems

MatPlotLib PyQt5 Layout Problems:
Using horizontal and vertical layouts, it seems to be very difficult to get the widgets where I want them. Maybe there is another way of doing it, for instance:
If one can put the canvas and toolbar in a container or some kind of widget. Then you can size it and put it where you want.
If one can limit the size of the plot so that the UI in the background is visible. This seems impossible though.
What about using QGridLayout?
I have tried many things, but am very confused and nothing seems to work.
The problems I have (using the current horizontal and vertical layouts) are:
The labels drift and are not aligned with the widgets.
The buttonbox is too wide. Can the buttons be split between the last two columns?
Here is some code. Sorry for the formatting. (It's hard to get the 4 spaces right):
import sys
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
import matplotlib.pyplot as plt
import random
from PyQt5.QtWidgets import QPushButton, QVBoxLayout, QHBoxLayout, QApplication, QDialog, QGridLayout, QLayout
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Dialog(QDialog):
def __init__(self, parent=None):
super(Ui_Dialog, self).__init__(parent)
self.setupUi(self)
self.setupPlot()
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(719, 353)
Dialog.setWindowTitle("Task")
self.buttonBox = QtWidgets.QDialogButtonBox(Dialog)
self.buttonBox.setGeometry(QtCore.QRect(590, 310, 121, 32))
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
self.buttonBox.setObjectName("buttonBox")
self.label1 = QtWidgets.QLabel(Dialog)
self.label1.setGeometry(QtCore.QRect(590, 40, 51, 16))
self.label1.setText("label1:")
self.label1.setObjectName("label1")
self.label2 = QtWidgets.QLabel(Dialog)
self.label2.setGeometry(QtCore.QRect(590, 70, 41, 16))
self.label2.setText("label2:")
self.label2.setObjectName("label2")
self.cBox1 = QtWidgets.QComboBox(Dialog)
self.cBox1.setGeometry(QtCore.QRect(650, 40, 61, 22))
self.cBox1.setLayoutDirection(QtCore.Qt.LeftToRight)
self.cBox1.setEditable(False)
self.cBox1.setCurrentText("Option0")
self.cBox1.setMaxVisibleItems(2)
self.cBox1.setObjectName("cBox1")
self.cBox1.addItem("")
self.cBox1.setItemText(0, "Option0")
self.cBox1.addItem("")
self.cBox1.setItemText(1, "Option1")
self.label5 = QtWidgets.QLabel(Dialog)
self.label5.setGeometry(QtCore.QRect(590, 160, 51, 16))
self.label5.setText("label5:")
self.label5.setObjectName("label5")
self.dSpinBox5 = QtWidgets.QDoubleSpinBox(Dialog)
self.dSpinBox5.setGeometry(QtCore.QRect(650, 160, 62, 22))
self.dSpinBox5.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.dSpinBox5.setMaximum(1999.99)
self.dSpinBox5.setObjectName("dSpinBox5")
self.dSpinBox4 = QtWidgets.QDoubleSpinBox(Dialog)
self.dSpinBox4.setGeometry(QtCore.QRect(650, 130, 62, 22))
self.dSpinBox4.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.dSpinBox4.setMaximum(1999.99)
self.dSpinBox4.setObjectName("dSpinBox4")
self.label0 = QtWidgets.QLabel(Dialog)
self.label0.setGeometry(QtCore.QRect(590, 10, 41, 16))
self.label0.setText("label0:")
self.label0.setObjectName("label0")
self.dSpinBox3 = QtWidgets.QDoubleSpinBox(Dialog)
self.dSpinBox3.setGeometry(QtCore.QRect(650, 100, 62, 22))
self.dSpinBox3.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.dSpinBox3.setMaximum(1999.99)
self.dSpinBox3.setObjectName("dSpinBox3")
self.label3 = QtWidgets.QLabel(Dialog)
self.label3.setGeometry(QtCore.QRect(590, 100, 61, 16))
self.label3.setText("label3:")
self.label3.setObjectName("label3")
self.lineEdit0 = QtWidgets.QLineEdit(Dialog)
self.lineEdit0.setGeometry(QtCore.QRect(650, 10, 61, 20))
self.lineEdit0.setInputMask("")
self.lineEdit0.setText("")
self.lineEdit0.setObjectName("lineEdit0")
self.label4 = QtWidgets.QLabel(Dialog)
self.label4.setGeometry(QtCore.QRect(590, 130, 41, 16))
self.label4.setText("label4:")
self.label4.setObjectName("label4")
self.spinBox2 = QtWidgets.QSpinBox(Dialog)
self.spinBox2.setGeometry(QtCore.QRect(650, 70, 61, 22))
self.spinBox2.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.spinBox2.setMaximum(999)
self.spinBox2.setSingleStep(10)
self.spinBox2.setProperty("value", 50)
self.spinBox2.setObjectName("spinBox2")
self.label6 = QtWidgets.QLabel(Dialog)
self.label6.setGeometry(QtCore.QRect(590, 190, 41, 16))
self.label6.setText("label6:")
self.label6.setObjectName("label6")
self.dSpinBox6 = QtWidgets.QDoubleSpinBox(Dialog)
self.dSpinBox6.setGeometry(QtCore.QRect(650, 190, 62, 22))
self.dSpinBox6.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.dSpinBox6.setReadOnly(True)
self.dSpinBox6.setButtonSymbols(QtWidgets.QAbstractSpinBox.NoButtons)
self.dSpinBox6.setObjectName("dSpinBox6")
self.label7 = QtWidgets.QLabel(Dialog)
self.label7.setGeometry(QtCore.QRect(590, 220, 47, 16))
self.label7.setText("label7:")
self.label7.setObjectName("label7")
self.spinBox7 = QtWidgets.QSpinBox(Dialog)
self.spinBox7.setGeometry(QtCore.QRect(650, 220, 61, 22))
self.spinBox7.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.spinBox7.setMaximum(999)
self.spinBox7.setProperty("value", 50)
self.spinBox7.setObjectName("spinBox7")
self.checkBox8 = QtWidgets.QCheckBox(Dialog)
self.checkBox8.setGeometry(QtCore.QRect(650, 250, 61, 20))
self.checkBox8.setLayoutDirection(QtCore.Qt.RightToLeft)
self.checkBox8.setText("")
self.checkBox8.setCheckable(False)
self.checkBox8.setObjectName("checkBox8")
self.checkBox9 = QtWidgets.QCheckBox(Dialog)
self.checkBox9.setGeometry(QtCore.QRect(650, 280, 61, 20))
self.checkBox9.setLayoutDirection(QtCore.Qt.RightToLeft)
self.checkBox9.setText("")
self.checkBox9.setCheckable(False)
self.checkBox9.setObjectName("checkBox9")
self.label8 = QtWidgets.QLabel(Dialog)
self.label8.setGeometry(QtCore.QRect(590, 250, 51, 16))
self.label8.setText("label8")
self.label8.setObjectName("label8")
self.label9 = QtWidgets.QLabel(Dialog)
self.label9.setGeometry(QtCore.QRect(590, 276, 47, 16))
self.label9.setText("label9")
self.label9.setObjectName("label9")
self.buttonBox.accepted.connect(Dialog.accept)
self.buttonBox.rejected.connect(Dialog.reject)
QtCore.QMetaObject.connectSlotsByName(Dialog)
def setupPlot(self):
self.setLayout(QHBoxLayout())
self.layout().setContentsMargins(0, 0, 0, 0)
self.figure = plt.figure()
self.figure.set_facecolor("none")
self.canvas = FigureCanvas(self.figure)
self.toolbar = NavigationToolbar(self.canvas, self)
self.widget = QtWidgets.QWidget()
layout = QVBoxLayout()
self.widget.setLayout(layout)
layout.addWidget(self.toolbar)
layout.addWidget(self.canvas)
self.layout().addWidget(self.widget)
self.widget = QtWidgets.QWidget()
layout = QVBoxLayout()
self.widget.setLayout(layout)
layout.addWidget(self.label0)
layout.addWidget(self.label1)
layout.addWidget(self.label2)
layout.addWidget(self.label3)
layout.addWidget(self.label4)
layout.addWidget(self.label5)
layout.addWidget(self.label6)
layout.addWidget(self.label7)
layout.addWidget(self.label8)
layout.addWidget(self.label9)
self.layout().addWidget(self.widget)
self.widget = QtWidgets.QWidget()
layout = QVBoxLayout()
self.widget.setLayout(layout)
layout.addWidget(self.lineEdit0)
layout.addWidget(self.cBox1)
layout.addWidget(self.spinBox2)
layout.addWidget(self.dSpinBox3)
layout.addWidget(self.dSpinBox4)
layout.addWidget(self.dSpinBox5)
layout.addWidget(self.dSpinBox6)
layout.addWidget(self.spinBox7)
layout.addWidget(self.checkBox8)
layout.addWidget(self.checkBox9)
layout.addWidget(self.buttonBox)
self.layout().addWidget(self.widget)
self.plot()
def plot(self):
data = [random.random() for i in range(10)]
self.figure.clear()
ax = self.figure.add_subplot(111)
ax.plot(data, '*-')
self.canvas.draw()
if __name__ == '__main__':
app = QApplication(sys.argv)
main = Ui_Dialog()
main.show()
sys.exit(app.exec_())
#ImportanceOfBeingErnest Your comment is what solved the question. Appreciated:
Removed all the setGeometry calls.
Created a QGridLayout .
Added widgets to the gridLayout like this:
self.layout().addWidget(self.checkBoxDone, 3, 4, 1, 1)
NB: Be careful not to confuse the parameters:
widget
start row (from 0 at the top)
start column (from 0 on the left)
number of rows to span (downwards)
number of columns to span (to the right)