Skip to content

Commit

Permalink
STY: Apply changes from pre-commit for tutorial files
Browse files Browse the repository at this point in the history
  • Loading branch information
nstelter-slac committed Sep 14, 2023
1 parent 6288198 commit e80d67f
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 71 deletions.
118 changes: 67 additions & 51 deletions examples/testing_ioc/pydm-tutorial-ioc
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ import time

from pcaspy import Driver, SimpleServer

''' This file provides the server needed for for providing PVs to run the tutorial.
""" This file provides the server needed for for providing PVs to run the tutorial.
You can follow along the tutorial here: https://slaclab.github.io/pydm-tutorial/.
The server mimics variables used by the tutorial, which mimic a simulated camera and motor.
Mimicking this behavior is done (over running simulator programs) in order to minimize the overhead
to get the tutorial up-and-running, and since the simulated data is not necessarily needed to learn
how to make PyDM user-interface.
'''
"""

MAX_POINTS = 1000
FREQUENCY = 1000
Expand All @@ -22,61 +22,74 @@ MIN_UPDATE_TIME = 0.001
IMAGE_SIZE = 512
MESSAGE = "PyDM Rocks!"

prefix = 'IOC:'
prefix = "IOC:"
pvdb = {
'Run' : { 'type' : 'enum',
'enums': ['STOP', 'RUN'], 'asg' : 'default'},
'ReadOnly' : { 'type' : 'enum',
'enums': ['FALSE', 'TRUE'], 'value': 0 },
'XPos' : { 'prec' : 2, 'value' : 0.0, 'asg' : 'default' },
'YPos' : { 'prec' : 2, 'value' : 0.0, 'asg' : 'default' },
'Image' : { 'type' : 'char', 'count': IMAGE_SIZE ** 2, 'value': numpy.zeros(IMAGE_SIZE ** 2, dtype=numpy.uint8), 'asg' : 'default' },
'ImageWidth' : { 'type' : 'int', 'value' : IMAGE_SIZE, 'asg' : 'default' },

'm1.DESC' : { 'type' : 'string', 'value': "Motor X", 'asg' : 'default'},
'm1' : { 'type' : 'float', 'value': 500.0, 'asg' : 'default' },
'm1.VAL' : { 'type' : 'float', 'value': 600.0, 'asg' : 'default' },
'm1.RBV' : { 'type' : 'float', 'value': 500.0, 'asg' : 'default' },
'm1.MOVN' : { 'type' : 'int', 'value': 0, 'asg' : 'default' },
'm1.STOP' : { 'type' : 'int', 'value': 0, 'asg' : 'default' },
'm1.ACCL' : { 'type' : 'float', 'value': 0.002, 'asg' : 'default' },
'm1.VELO' : { 'type' : 'float', 'value': 100.0, 'asg' : 'default' },

'm2.DESC' : { 'type' : 'string', 'value': "Motor Y", 'asg' : 'default'},
'm2' : { 'type' : 'float', 'value': 500.0, 'asg' : 'default' },
'm2.VAL' : { 'type' : 'float', 'value': 700.0, 'asg' : 'default' },
'm2.RBV' : { 'type' : 'float', 'value': 500.0, 'asg' : 'default' },
'm2.MOVN' : { 'type' : 'int', 'value': 0, 'asg' : 'default' },
'm2.STOP' : { 'type' : 'int', 'value': 0, 'asg' : 'default' },
'm2.ACCL' : { 'type' : 'float', 'value': 0.002, 'asg' : 'default' },
'm2.VELO' : { 'type' : 'float', 'value': 100.0, 'asg' : 'default' },

"Run": {"type": "enum", "enums": ["STOP", "RUN"], "asg": "default"},
"ReadOnly": {"type": "enum", "enums": ["FALSE", "TRUE"], "value": 0},
"XPos": {"prec": 2, "value": 0.0, "asg": "default"},
"YPos": {"prec": 2, "value": 0.0, "asg": "default"},
"Image": {
"type": "char",
"count": IMAGE_SIZE**2,
"value": numpy.zeros(IMAGE_SIZE**2, dtype=numpy.uint8),
"asg": "default",
},
"ImageWidth": {"type": "int", "value": IMAGE_SIZE, "asg": "default"},
"m1.DESC": {"type": "string", "value": "Motor X", "asg": "default"},
"m1": {"type": "float", "value": 500.0, "asg": "default"},
"m1.VAL": {"type": "float", "value": 600.0, "asg": "default"},
"m1.RBV": {"type": "float", "value": 500.0, "asg": "default"},
"m1.MOVN": {"type": "int", "value": 0, "asg": "default"},
"m1.STOP": {"type": "int", "value": 0, "asg": "default"},
"m1.ACCL": {"type": "float", "value": 0.002, "asg": "default"},
"m1.VELO": {"type": "float", "value": 100.0, "asg": "default"},
"m2.DESC": {"type": "string", "value": "Motor Y", "asg": "default"},
"m2": {"type": "float", "value": 500.0, "asg": "default"},
"m2.VAL": {"type": "float", "value": 700.0, "asg": "default"},
"m2.RBV": {"type": "float", "value": 500.0, "asg": "default"},
"m2.MOVN": {"type": "int", "value": 0, "asg": "default"},
"m2.STOP": {"type": "int", "value": 0, "asg": "default"},
"m2.ACCL": {"type": "float", "value": 0.002, "asg": "default"},
"m2.VELO": {"type": "float", "value": 100.0, "asg": "default"},
}


def gaussian_2d(x, y, x0, y0, xsig, ysig):
return numpy.exp(-0.5 * (((x - x0) / xsig) ** 2 + ((y - y0) / ysig) ** 2))

class myDriver(Driver):

class myDriver(Driver):
def __init__(self):
Driver.__init__(self)
self.eid = threading.Event()
self.tid = threading.Thread(target=self.runSimScope)
self.tid.setDaemon(True)
self.tid.start()

self.motorXThread = threading.Thread(target=self.updateMotor, args=('m1', 'XPos',))
self.motorXThread = threading.Thread(
target=self.updateMotor,
args=(
"m1",
"XPos",
),
)
self.motorXThread.setDaemon(True)
self.motorXThread.start()

self.motorYThread = threading.Thread(target=self.updateMotor, args=('m2', 'YPos',))
self.motorYThread = threading.Thread(
target=self.updateMotor,
args=(
"m2",
"YPos",
),
)
self.motorYThread.setDaemon(True)
self.motorYThread.start()

def updateMotor(self, motorVarName, axisVarName):
# mimic the functionality of fully-simulated motor and camera
sleepTime = 0.2 # set arbitrarily to match timing when fully-simulated

sleepTime = 0.2 # set arbitrarily to match timing when fully-simulated
motorRbvName = motorVarName + ".RBV"
motorMovingVarName = motorVarName + ".MOVN"
motorStopVarName = motorVarName + ".STOP"
Expand All @@ -86,9 +99,9 @@ class myDriver(Driver):
time.sleep(sleepTime)
motorParam = self.getParam(motorVarName)

if motorParam != motorRbv: # need to move motor
if motorParam != motorRbv: # need to move motor
self.setParam(motorMovingVarName, 1)

# for Motor X: 'Tw +10' = move right, 'Tw -10' = move left
# for Motor Y:'Tw +10' = move up, 'Tw -10' = move down left
motorMoveAmount = 10 if motorRbv < motorParam else -10
Expand All @@ -104,17 +117,17 @@ class myDriver(Driver):
motorRbv = motorRbv + motorMoveAmount
self.setParam(motorRbvName, motorRbv)
axis_pos = self.getParam(axisVarName)
self.setParam(axisVarName, axis_pos + imageMoveAmount)
self.setParam(axisVarName, axis_pos + imageMoveAmount)
self.updatePVs()

time.sleep(sleepTime)

self.setParam(motorStopVarName, 0)
# if stopped, set motorVar line-edit to the motorRBV text-field value
# (motor was stopped before reaching the originally entered value)
if motorParam != motorRbv:
self.setParam(motorVarName, motorRbv)
self.setParam(motorVarName, motorRbv)

self.setParam(motorMovingVarName, 0)
self.updatePVs()

Expand All @@ -126,32 +139,35 @@ class myDriver(Driver):

while True:
# Generate the image data
x0 = 0.5 * (numpy.random.rand() - 0.5) + self.getParam('XPos')
y0 = 0.5 * (numpy.random.rand() - 0.5) - self.getParam('YPos')
x0 = 0.5 * (numpy.random.rand() - 0.5) + self.getParam("XPos")
y0 = 0.5 * (numpy.random.rand() - 0.5) - self.getParam("YPos")
xsig = 0.8 - 0.2 * numpy.random.rand()
ysig = 0.8 - 0.2 * numpy.random.rand()
z = gaussian_2d(xgrid, ygrid, x0, y0, xsig, ysig)
image_data = numpy.abs(256.0 * (z)).flatten(order='C').astype(numpy.uint8, copy=False)
self.setParam('Image', image_data)
image_data = numpy.abs(256.0 * (z)).flatten(order="C").astype(numpy.uint8, copy=False)
self.setParam("Image", image_data)

# do updates so clients see the changes
self.updatePVs()

if __name__ == '__main__':

if __name__ == "__main__":
try:
print('Starting testing-ioc')
print('To start processing records do: caput ' + prefix + 'Run 1')
print("Starting testing-ioc")
print("To start processing records do: caput " + prefix + "Run 1")
server = SimpleServer()
server.initAccessSecurityFile(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'access_rules.as'), P=prefix)
server.initAccessSecurityFile(
os.path.join(os.path.dirname(os.path.realpath(__file__)), "access_rules.as"), P=prefix
)
server.createPV(prefix, pvdb)
driver = myDriver()

# Manually set the ReadOnly PV to force access rule calculation.
# You can set ReadOnly to 1 to disable write access on all PVs.
driver.setParam('ReadOnly', 0)
driver.setParam("ReadOnly", 0)

# process CA transactions
while True:
server.process(0.03)
except KeyboardInterrupt:
print('\nInterrupted... finishing testing-ioc')
print("\nInterrupted... finishing testing-ioc")
45 changes: 28 additions & 17 deletions examples/tutorial/all_motors.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
import os
import json
from pydm import Display
from qtpy.QtWidgets import (QVBoxLayout, QHBoxLayout, QGroupBox,
QLabel, QLineEdit, QPushButton, QScrollArea, QFrame,
QApplication, QWidget)
from qtpy.QtWidgets import (
QVBoxLayout,
QHBoxLayout,
QGroupBox,
QLabel,
QLineEdit,
QPushButton,
QScrollArea,
QFrame,
QApplication,
QWidget,
)
from qtpy import QtCore
from pydm.widgets import PyDMEmbeddedDisplay


class AllMotorsDisplay(Display):
def __init__(self, parent=None, args=[], macros=None):
super(AllMotorsDisplay, self).__init__(parent=parent, args=args, macros=None)
Expand All @@ -27,7 +37,7 @@ def minimumSizeHint(self):
def ui_filepath(self):
# No UI file is being used
return None

def setup_ui(self):
# Create the main layout
main_layout = QVBoxLayout()
Expand All @@ -36,7 +46,8 @@ def setup_ui(self):
# Create a Label to be the title
lbl_title = QLabel("Motors Diagnostic")
# Add some StyleSheet to it
lbl_title.setStyleSheet("\
lbl_title.setStyleSheet(
"\
QLabel {\
qproperty-alignment: AlignCenter;\
border: 1px solid #FF17365D;\
Expand All @@ -47,27 +58,28 @@ def setup_ui(self):
color: rgb(255, 255, 255);\
max-height: 25px;\
font-size: 14px;\
}")
}"
)

# Add the title label to the main layout
main_layout.addWidget(lbl_title)

# Create the Search Panel layout
search_layout = QHBoxLayout()

# Create a GroupBox with "Filtering" as Title
gb_search = QGroupBox(parent=self)
gb_search.setTitle("Filtering")
gb_search.setTitle("Filtering")
gb_search.setLayout(search_layout)

# Create a label, line edit and button for filtering
lbl_search = QLabel(text="Filter: ")
self.txt_filter = QLineEdit()
self.txt_filter.returnPressed.connect(self.do_search)
btn_search = QPushButton()
btn_search.setText("Search")
btn_search.clicked.connect(self.do_search)

# Add the created widgets to the layout
search_layout.addWidget(lbl_search)
search_layout.addWidget(self.txt_filter)
Expand All @@ -81,7 +93,7 @@ def setup_ui(self):
self.results_layout.setContentsMargins(0, 0, 0, 0)

# Create a Frame to host the results of search
self.frm_result = QFrame(parent=self)
self.frm_result = QFrame(parent=self)
self.frm_result.setLayout(self.results_layout)

# Create a ScrollArea so we can properly handle
Expand All @@ -103,7 +115,7 @@ def load_data(self):
# Concatenate the directory with the file name...
data_file = os.path.join(base_dir, "motor_db.txt")
# Open the file so we can read the data...
with open(data_file, 'r') as f:
with open(data_file, "r") as f:
# For each line in the file...
for entry in f.readlines():
# Append to the list of data...
Expand All @@ -114,7 +126,7 @@ def do_search(self):
for widget in self.frm_result.findChildren(QWidget):
widget.setParent(None)
widget.deleteLater()

# Grab the filter text
filter_text = self.txt_filter.text()

Expand All @@ -125,11 +137,10 @@ def do_search(self):
continue
# Create a PyDMEmbeddedDisplay for this entry
disp = PyDMEmbeddedDisplay(parent=self)
disp.macros = json.dumps({"MOTOR":entry})
disp.filename = 'inline_motor.ui'
disp.macros = json.dumps({"MOTOR": entry})
disp.filename = "inline_motor.ui"
disp.setMinimumWidth(700)
disp.setMinimumHeight(40)
disp.setMaximumHeight(100)
# Add the Embedded Display to the Results Layout
self.results_layout.addWidget(disp)

4 changes: 1 addition & 3 deletions examples/tutorial/main.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import time
from os import path
from pydm import Display
from scipy.ndimage.measurements import maximum_position


class BeamPositioning(Display):

def __init__(self, parent=None, args=None):
super(BeamPositioning, self).__init__(parent=parent, args=args)
# Attach our custom process_image method
Expand All @@ -18,7 +16,7 @@ def __init__(self, parent=None, args=None):

def ui_filename(self):
# Point to our UI file
return 'main.ui'
return "main.ui"

def ui_filepath(self):
# Return the full path to the UI file
Expand Down

0 comments on commit e80d67f

Please sign in to comment.