Source code for kf.QtOrbits

"""PyQt5 widgets to render a particle orbit system.
"""
################################################################
# Written in 2019 by Garth Zeglin <garthz@cmu.edu>

# To the extent possible under law, the author has dedicated all copyright
# and related and neighboring rights to this software to the public domain
# worldwide. This software is distributed without any warranty.

# You should have received a copy of the CC0 Public Domain Dedication along with this software.
# If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.

################################################################
import math, logging
import numpy as np

# for documentation on the PyQt5 API, see http://pyqt.sourceforge.net/Docs/PyQt5/index.html
from PyQt5 import QtCore, QtGui, QtWidgets

# set up logger for module
log = logging.getLogger('QtOrbits')

# filter out most logging; the default is NOTSET which passes along everything
# log.setLevel(logging.WARNING)

################################################################
[docs]class QtOrbits(QtWidgets.QWidget): """Custom widget representing a particle orbit system generator.""" def __init__(self, channels=4): super().__init__() self.setMinimumSize(QtCore.QSize(100, 100)) self.setAutoFillBackground(True) # graphical state variables self.channels = channels self.positions = [[0,0,0]]*self.channels # spatial positions, unit scaling [-1,1] self.attractors = [[0,0,0]]*4 # finish initialization self.show() return
[docs] def update_positions(self, positions): self.positions = positions self.repaint()
[docs] def update_attractors(self, attractors): self.attractors = attractors self.repaint()
# === element drawing methods ============================================================ # === Qt API methods ============================================================
[docs] def paintEvent(self, e): """Subclass implementation of parent QWidget class callback to repaint the graphics.""" geometry = self.geometry() view_width = geometry.width() view_height = geometry.height() # clear the background qp = QtGui.QPainter() qp.begin(self) qp.fillRect(QtCore.QRectF(0, 0, view_width, view_height), QtCore.Qt.white) # qp.setRenderHint(QtGui.QPainter.Antialiasing) # Set up a coordinate system scaled to real-world millimeters, centered # in the visible area, keeping the minimum visible area in view. # define minimum visible area scene_width = 3.5 scene_height = scene_width scene_aspect = scene_width / scene_height view_aspect = view_width / view_height if scene_aspect > view_aspect: scaling = view_width / scene_width else: scaling = view_height/scene_height qp.save() qp.translate(QtCore.QPointF(view_width/2, view_height/2)) qp.scale(scaling, scaling) # draw the bounds pen = QtGui.QPen(QtCore.Qt.black) pen.setWidthF(0.01) qp.setPen(pen) qp.drawEllipse(QtCore.QPointF(0.0,0.0),math.sqrt(3),math.sqrt(3)) # draw the attractors in black brush = QtGui.QBrush(QtGui.QColor(240, 240, 240, 255)) qp.setBrush(brush) for pos in self.attractors: qp.drawEllipse(QtCore.QPointF(pos[0], pos[1]), 0.2, 0.2) # draw the particles in a color derived from their coordinates color = QtGui.QColor() for pos in self.positions: color.setRgbF(min(1.0, abs(pos[0])), min(1.0, abs(pos[1])), min(1.0, abs(pos[2])), 1.0) brush = QtGui.QBrush(color) qp.setBrush(brush) qp.drawEllipse(QtCore.QPointF(pos[0], pos[1]), 0.05, 0.05) # restore the initial unscaled coordinates qp.restore() qp.end()
################################################################