Skip to content

Instantly share code, notes, and snippets.

@noc0lour
Created November 3, 2023 12:36
Show Gist options
  • Save noc0lour/1f17a0efaacc5ca310f3f30a886227c8 to your computer and use it in GitHub Desktop.
Save noc0lour/1f17a0efaacc5ca310f3f30a886227c8 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3
"""Plot Constellation and animate it."""
from PySide6.QtWidgets import (
QWidget,
QLabel,
QGridLayout,
QApplication,
QMainWindow,
QSlider,
)
import numpy as np
import pyqtgraph as pg
from PySide6.QtGui import QIcon
from PySide6.QtCore import Qt, QPropertyAnimation
import argparse
import sys
import os
import pandas as pd
vhex = np.vectorize(hex)
def ints2bits(ints, m):
"""Convert integers to their bit representations MSB first.
:param ints: array of ints
:param m: bit-width per int
:returns: array of bit arrays
"""
b = np.expand_dims(ints, 1)
B = np.flip(
np.unpackbits(b.view(np.uint8), axis=1, count=m, bitorder="little"), axis=1
)[:, :m]
return B
def hex2bits(hexs, m):
"""Convert list of hex strings to their bit representation MSB first.
:param hexs: list of hex strings
:param m: bit-width per hex
:returns: array of bit arrays
"""
ints = np.array([int("0x" + h, 0) for h in hexs])
bits = ints2bits(ints, m)
return bits
class Window(QMainWindow):
def __init__(self, min_epoch, max_epoch, constellations, constellation_size):
super().__init__()
# setting title
self.setWindowTitle("Constellations")
# Set parameters
self.min_epoch = min_epoch
self.max_epoch = max_epoch
self.constellations = constellations
self.constellation_size = constellation_size
# setting geometry
self.setGeometry(100, 100, 600, 500)
# icon
icon = QIcon("skin.png")
# setting icon to the window
self.setWindowIcon(icon)
# calling method
self.UiComponents()
# showing all the widgets
self.show()
def plotPoints(self, epoch):
constellation_df = self.constellations[self.constellations["epoch"] == epoch]
constellation = constellation_df["constellation"].iloc[0]
labels = constellation_df["labels"].iloc[0]
bitstrings = [str(s) for s in hex2bits(labels, 6)]
self.scatter.setData(pos=constellation)
for bitstring, point, label in zip(bitstrings, constellation, self.labeltexts):
label.setText(bitstring)
label.setPos(float(point[0]), float(point[1]))
def slider_valuechanged(self):
epoch = self.slider.value()
self.plotPoints(epoch)
self.epoch_text.setText(f"Epoch: {epoch}")
information_rate = self.constellations[self.constellations["epoch"] == epoch][
"information_rate"
].iloc[0]
self.informationrate_text.setText(f"IR: {information_rate}")
# method for components
def UiComponents(self):
# creating a widget object
widget = QWidget()
# creating a plot window
plot = pg.plot()
# creating a scatter plot item
# of size = 10
# using brush to enlarge the of white color with transparency is 50%
self.scatter = pg.ScatterPlotItem(size=10, brush=pg.mkBrush(255, 255, 255, 120))
self.labeltexts = [pg.TextItem() for _ in range(self.constellation_size)]
self.epoch_text = QLabel("Epoch: 0")
self.informationrate_text = QLabel("IR: ")
self.slider = QSlider(Qt.Orientation.Horizontal, self)
self.slider.setGeometry(50, 50, 200, 50)
self.slider.setMinimum(self.min_epoch)
self.slider.setMaximum(self.max_epoch)
self.slider.setTickPosition(QSlider.TickPosition.TicksBelow)
self.slider.setTickInterval(1)
self.slider.valueChanged.connect(self.slider_valuechanged)
self.anim = QPropertyAnimation(self.slider, b"value")
self.anim.setStartValue(self.min_epoch)
self.anim.setEndValue(self.max_epoch)
self.anim.setDuration(10000)
self.anim.start()
self.plotPoints(0)
# add item to plot window
# adding scatter plot item to the plot window
plot.addItem(self.scatter)
for label in self.labeltexts:
plot.addItem(label)
# Creating a grid layout
layout = QGridLayout()
# setting this layout to the widget
widget.setLayout(layout)
# plot window goes on right side, spanning 3 rows
layout.addWidget(plot, 0, 0, 3, 6)
layout.addWidget(self.slider, 4, 1, 1, 3)
layout.addWidget(self.epoch_text, 4, 4, 1, 1)
layout.addWidget(self.informationrate_text, 4, 5, 1, 1)
# setting this widget as central widget of the main window
self.setCentralWidget(widget)
if __name__ == "__main__":
constellations_df = pd.DataFrame(
(
{
"constellation": np.random.normal(size=(64,2)),
"epoch": e,
"information_rate": "0.1",
"labels": list(str(v)[2:].upper() for v in vhex(np.arange(64))),
}
for e in range(1000)
),
dtype=object,
)
start_epoch = int(constellations_df["epoch"].min())
end_epoch = int(constellations_df["epoch"].max())
constellation_size = (
constellations_df[constellations_df["epoch"] == 1]["constellation"]
.iloc[0]
.shape[0]
)
# create pyqt5 app
App = QApplication(sys.argv)
# create the instance of our Window
window = Window(start_epoch, end_epoch, constellations_df, constellation_size)
# start the app
sys.exit(App.exec())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment