SmarAct UI overhaul#1320
Conversation
…ick behavior from TyphosPositionerRow
…ude optional picoscale
|
I know this is a really large PR due to the size of the pyqt scripts/uis, so feel free to break it up (perhaps I should've submitted 2 different PRs, honestly) |
| def __init__(self, parent=None, **kwargs): | ||
| super().__init__(parent=parent) | ||
|
|
||
| self.ui = typing.cast(_SmarActDetailedUI, uic.loadUi(self.ui_template, self)) |
There was a problem hiding this comment.
I'm a little surprised you'd need to invoke the uic loader manually here. Naively I'd expect PyDM to do this for you in the super call:
https://github.com/slaclab/pydm/blob/ba4125d479a2e6adb033e9ab1a05ab2bab2fdf84/pydm/display.py#L315-L316
There was a problem hiding this comment.
Perhaps this is why your macros aren't being expanded?
There was a problem hiding this comment.
Definitely why the macro isn't being expanded, but also I can't omit this line or else self.ui never populates. Not sure why the super() call doesn't proc it
There was a problem hiding this comment.
Okay figured out why pydm.Display wasn't loading the UI correctly. Got that remedied, but now I can't quite grab my object names. Might need to fenagle a bit more of the code to fix that
There was a problem hiding this comment.
This sadly isn't why the macro isn't being expanded. Got the super call to work with:
class SmarActDetailedWidget(Display, utils.TyphosBase):
"""
Custom widget for managing the SmarAct detailed screen
"""
ui: _SmarActDetailedUI
ui_template = path.join(path.dirname(path.realpath(__file__)), 'SmarAct.detailed.ui')
def __init__(self, parent=None, ui_filename=ui_template, **kwargs):
super().__init__(parent=parent, ui_filename=ui_filename)
but still get greeted with the complaints when the expert screen opens:
[2025-01-30 16:17:39] - INFO - Loading Tools ...
[2025-01-30 16:17:39] - INFO - Adding devices ...
[2025-01-30 16:17:42] - INFO - Launching application ...
[2025-01-30 16:17:45] - INFO - Loading Tools ...
[2025-01-30 16:17:45] - INFO - Adding devices ...
[2025-01-30 16:17:45] - ERROR - Unable to find signal for <PyDMChannel (sig://${name}_motor_egu)> in signal registry.Use typhos.plugins.register_signal()
[2025-01-30 16:17:45] - ERROR - Unable to find signal for <PyDMChannel (sig://${name}_description)> in signal registry.Use typhos.plugins.register_signal()
:sadge:
slactjohnson
left a comment
There was a problem hiding this comment.
This is pretty cool. Some of this Typhos stuff is a bit beyond me, but reading through this, things generally make sense. I'd be interested to understand if this is a good template to base other, similar screens off of. I imagine there's a lot of nice things that we could do with many of our devices if we put in a little time.
| class _SmarActDetailedUI(QtWidgets.QWidget): | ||
| """Annotations helper for SmarAct.detailed.ui. Do not instantiate.""" | ||
| # Status bar | ||
| calibrated_bool: pydm.widgets.byte.PyDMByteIndicator |
There was a problem hiding this comment.
Generally we don't add the type to the signal name; is there a reason you're doing that here?
There was a problem hiding this comment.
If you make a stub class with annotations and apply it like this, you get really good autocomplete/api lookup help in e.g. vscode because it knows that self.ui.calibrated_bool is a PyDMByteIndicator
|
|
||
| def add_device(self, device): | ||
| """Typhos hook for adding a new device.""" | ||
| super().add_device(device) |
There was a problem hiding this comment.
Should this occur after the check for None?
There was a problem hiding this comment.
I think that will always kill the screen, because I have to wait for typhos to grab add_device and link the ophyd.device back to the display. Let me try it out at the very least!
There was a problem hiding this comment.
I checked a bit and I think the ordering doesn't matter (based on the code for TyphosBase)
|
|
||
| def add_device(self, device): | ||
| """Typhos hook for adding a new device.""" | ||
| super().add_device(device) |
There was a problem hiding this comment.
Same comment as above.
|
To my quick-ish readthrough of the python file everything looks kosher, I can go again later with a more critical eye if you'd like to make sure there aren't any potential smaller issues. The results look good! I can try to nitpick ui layout stuff too (resize behavior, whitespace) if that's desirable. |
I think some of the As long as the method hooks the typhos magic and you get the |
…n checks for TipTilt
christina-pino
left a comment
There was a problem hiding this comment.
So far looks good! Albeit that it has been a while since I have had to work with typhos/pydm and never got this far. Two questions/comments.
- when released, will the *.ui and *.py "screens" join to be just *.ui like the rest?
- what command did you use to open the detailed screen with the pico scale check? I tried running
typhos "pcdsdevices.epics_motor.SmarAct[{'prefix':'LAS:FTL:MCS:01:m1', 'name':'LAS:FTL:MCS:01:m1'}]"
but it never shows the pico scale tab and has the EGU/description error
Both the
That's expected! A The egu and description signal error seems to be tied to how the |
|
I might consider refactoring these screens given the ease of pcdshub/typhos#627. I think I'd still need to do something janky to get the ordering the way I want for the tabs, but it does cut down on a lot of hard coding since I can just add things like: To the |
I wonder if this is worth a typhos patch itself, or if there are cases where one might want to avoid the py file. |
… as a byte indicator
… epics_motor device
|
These screenshots look really great! |
|
This does look amazing. I will mention that this seems to have a merge conflict, hopefully that's not too painful |
ZLLentz
left a comment
There was a problem hiding this comment.
Mostly nitpicks! Can ignore if you like!
I think this is pretty great.
| def __init__(self, *args, **kwargs): | ||
| super().__init__(*args, **kwargs) | ||
| # Long name shenanigans | ||
| self.step_voltage.long_name = 'Step Voltage' |
There was a problem hiding this comment.
side note: the long_name ophyd PR churned a little bit recently (rebase?) so these are pretty safe for the future.
| def __init__(self, parent=None, ui_filename=ui_template, **kwargs): | ||
| super().__init__(parent=parent, ui_filename=ui_filename) |
There was a problem hiding this comment.
nitpick: this might be redundant now, unless you intend to block the kwargs pass-through
| def __init__(self, parent=None, ui_filename=ui_template, **kwargs): | |
| super().__init__(parent=parent, ui_filename=ui_filename) |
There was a problem hiding this comment.
It breaks if I change it 🤷
I think if I just manually call out the template anyway it's superfluous, but I deleted that and went the super().__init__ route. I remember it only being able to catch my template if I did it this way (still doesn't expand my macros) but let me tinker
There was a problem hiding this comment.
Yeah I don't really gain or lose anything by blocking the **kwargs or not, least as far as I can tell. Still need to super().__init__ though. Maintainer's choice on whether or not I should pass the **kwargs 🤷
| """ | ||
| ui: _SmarActDetailedUI | ||
| # Seems confusing, but really just cleans up the call to pydm for setting self.ui | ||
| ui_template = path.join(path.dirname(path.realpath(__file__)), 'SmarAct.detailed.ui') |
There was a problem hiding this comment.
Question: In the past I was able to just give e.g. SmarAct.detailed.ui without any path handling and pydm knew to check the same dir. Does it behave differently here? (same for the embedded widget)
There was a problem hiding this comment.
You're absolutely right! This is probably a relic of previous fenagling I was doing. I can update this across the .py files
|
|
||
| def add_device(self, device): | ||
| """Typhos hook for adding a new device.""" | ||
| super().add_device(device) |
There was a problem hiding this comment.
I checked a bit and I think the ordering doesn't matter (based on the code for TyphosBase)
| def fix_pvs(self): | ||
| """ | ||
| Fix all the channel access and signal linking to various pydm objects in the screen, | ||
| since the macros aren't expanded when the UI is initialized. |
There was a problem hiding this comment.
nit: it'd be nice to figure out and clean the root cause here but it's not strictly required
There was a problem hiding this comment.
Yeah the lack of macro expansion is very annoying considering the tedium of adding it in designer in the first place, but c'est la vie. I can't figure out why pydm isn't expanding the ui before opening the .py screen.
A little hacky for me to just handle the egu and desc signals this way, but it got rid of the terminal spam on start-up complaining about how the sig//${name}_egu etc. didn't exist
| self.maybe_add_pico() | ||
| self.add_tool_tips() | ||
| # Only start this timer if PicoScale exists | ||
| if hasattr(self.device, 'pico_exists'): |
There was a problem hiding this comment.
nitpick: possibly this belongs in maybe_add_pico
There was a problem hiding this comment.
Oh! Good point, I'll move this there, not sense in having it out here if the check is already done in maybe_add_pico
Co-authored-by: Zachary Lentz <ZLLentz@users.noreply.github.com>


Description
Adding new SmarAct screens to help with day-to-day ops:
I made the bulk of the UI in designer and (mostly) manually labeled the signals 🤮. Noticed in #430 that the discussion for naming signals with human-readable text has come up a few times. I think Ken had a good point that I should probably put the
dotted_namesignals back in as a tooltip for hutch-python friendlinessMotivation and Context
While fixing #1275 we realized it was time to update the SmarAct screens to improve user readability.
How Has This Been Tested?
I've tested this on some live devices for linear & tip-tilt (open-loop) in the LRL as well as the picoscale devices in the FTL (with permission). Everything appears to work as intended with the live devices.
One small hang-up is that launching the
SmarAct.detailed.pyscreen from typhos using CLI triggers some complaints:Since the
uifile isn't having the macros expanded before it opens. I have to wait untiladd_deviceprocesses for the macros to be expanded, so none of the other signals appear to trigger it.Both the
EGUandDESCfields read/write regardless of this complaint.Now I could fix this by emptying out all the channel slots on all the elements in the
uifile then just slot the signals in the.pybut it would be super annoying and messy, I think. Also, theuiworks by itself for any non-picoscale related system, so I'd hate to break it.Where Has This Been Documented?
This PR
Screenshots (if appropriate):
Some vids showing off the GUI
smaract_embedded_tip_tilt.mp4
smaract_picoscale_screen.mp4
Pre-merge checklist