puzzlepiece.puzzle module
- class puzzlepiece.puzzle.Puzzle(app=None, name='Puzzle', debug=True, bottom_buttons=True, style='Fusion', *args, **kwargs)[source]
Bases:
QWidgetA container for
puzzlepiece.piece.Pieceobjects, meant to be the main QWidget (window) of an automation application. It keeps track of thePieceobjects it contains and lets them communicate.A simple set up will look like this:
import puzzlepiece as pzp from puzzlepiece.pieces import random_number # Create a Qt app that will run our GUI, and the Puzzle app = pzp.QApp() puzzle = pzp.Puzzle(name="Basic example") # Add Pieces to the Puzzle puzzle.add_piece("random", random_number.Piece, row=0, column=0) # Show the Puzzle window and execute the Qt application puzzle.show() app.exec()
The Qt app creation and call to
execcan be skipped when running in IPython / Jupyter, but the%gui qtmagic has to be used first to enable the GUI integration.When adding multiple
Pieces, the Puzzle can be used as a context manager, ensuring that any loaded APIs will be correctly unloaded in case any of the Pieces raises an exception duringsetup():with Puzzle(debug=False) as puzzle: # Any exceptions raised in this setup context will cause the Puzzle to shut down # gracefully, calling handle_close() on the Pieces added so far puzzle.add_piece("laser", laser.Piece, row=0, column=0) puzzle.add_piece("stage", stage.Piece, row=1, column=0) puzzle.show() # Note that the Puzzle object can still be used outside of the setup context puzzle["laser:power].set_value(10)
- Parameters:
app – A QtApp created to contain this QWidget.
name – A name for the window.
debug (bool) – Sets the Puzzle.debug property, if True the app should launch in debug mode and Pieces shouldn’t communicate with hardware.
bottom_buttons (bool) – Whether the bottom buttons of the Puzzle (Tree, Export, STOP) should be shown.
style – A Qt style to apply to the QApplication. puzzlepiece defaults to Fusion for cross-platform consistency, and adds some tweaks to make it look better. Set to None to maintain system-specific styling.
- property pieces
A
PieceDict, effectively a dictionary ofPieceobjects. Can be used to access Pieces from within other Pieces.You can also directly index the Puzzle object with the
Piecename, or even with aPieceand aBaseParam:# These two are equivalent puzzle.pieces["piece_name"] puzzle["piece_name"] # These three are equivalent puzzle.pieces["piece_name"].params["piece_name"] puzzle["piece_name"]["param_name"] puzzle["piece_name:param_name"]
The valid keys for indexing a Puzzle object are available when autocompleting the key in IPython.
- property globals
A
puzzlepiece.puzzle.Globalsobject, effectively a dictionary, can be used for API modules that need to be shared by multiple Pieces.See
puzzlepiece.puzzle.Globals.require()andpuzzlepiece.puzzle.Globals.release()for advanced use.
- property debug
A bool flag set on Puzzle creation. Pieces should act in debug mode if True.
- add_piece(name, piece, row, column, rowspan=1, colspan=1, param_defaults=None)[source]
Adds a
Pieceto the grid layout, and registers it with the Puzzle.- Parameters:
name – Identifying string for the Piece.
piece – A
Pieceobject or a class defining one (which will be automatically instantiated).row – Row index for the grid layout.
column – Column index for the grid layout.
rowspan – Height in rows.
colspan – Width in columns.
param_defaults – An optional dictionary of default param values. These will be set without calling the corresponding param setters or
changedsignals.
- Return type:
- replace_piece(name, new_piece)[source]
Replace a named
Piecewith a new one. Can be combined withimportlib.reloadto do live development on Pieces.This method is experimental and can sometimes fail. It’s useful for development, but shouldn’t really be used in production applications.
- Parameters:
name – Name of the Piece to be replaced.
piece – A
Pieceobject or a class defining one (which will be automatically instantiated).
- add_folder(row, column, rowspan=1, colspan=1)[source]
Adds a tabbed
Folderto the grid layout, and returns it.- Parameters:
row – Row index for the grid layout.
column – Column index for the grid layout.
rowspan – Height in rows.
column – Width in columns.
- Return type:
- register_piece(name, piece)[source]
Registers a
Pieceobject with the Puzzle. This is done by default when aPieceis added withadd_piece(),puzzlepiece.puzzle.Folder.add_piece(), orpuzzlepiece.puzzle.Grid.add_piece(), so this method should rarely be called manually.
- process_events()[source]
Forces the QApplication to process events that happened while a callback was executing. Can for example update plots while a long process is running, or run any keyboard shortcuts pressed while proecessing.
- run_worker(worker)[source]
Add a Worker to the Puzzle’s Threadpool and runs it. See
puzzlepiece.threadsfor more details on how to set up a Worker.
- custom_excepthook(exctype, value, traceback)[source]
Override or replace this method to call a custom handler whenever an exception is raised. This will run after the defatult exception handler (
sys.__excepthook__), but before a GUI alert is displayed.
- run(text)[source]
Execute script commands for this Puzzle as described in
puzzlepiece.parse.run().
- get_values(text)[source]
Get the values from multiple params as a list.
- Parameters:
text – A string of comma-separated param strings as described in
puzzlepiece.parse.parse_params().- Return type:
list
- record_values(text, dictionary=None)[source]
Get the values from multiple params and record them in a dictionary. Useful for storing metadata about a measurement.
- Parameters:
text – A string of comma-separated param strings as described in
puzzlepiece.parse.parse_params().dictionary – If provided, this function will write the param names and values to this dictionary. Otherwise, a new one is created and returned.
- Return type:
dict
- puzzlepiece.puzzle.QApp(args=None)[source]
A QApplication has to be constructed before any Qt objects (including the Puzzle and the Pieces), so this is a convenient shortcut to instance the QApplication class (see https://doc.qt.io/qt-6/qapplication.html).
Only one QApplication can exist at a time, so if there is already an instance, this function returns it instead of creating a new one.
- Parameters:
args – list of strings to pass as arguments when creating the QApplication
- class puzzlepiece.puzzle.Folder(puzzle, *args, **kwargs)[source]
Bases:
QTabWidgetA tabbed group of
PieceorGridobjects within thePuzzle.Best created with
puzzlepiece.puzzle.Puzzle.add_folder().- add_piece(name, piece, param_defaults=None)[source]
Adds a
Pieceas a tab to this Folder, and registers it with the parentPuzzle.- Parameters:
- Return type:
- class puzzlepiece.puzzle.Grid(puzzle, *args, **kwargs)[source]
Bases:
QWidgetA grid layout for
Pieceobjects. For when you need multiple Pieces within a singleFoldertab.Best created with
puzzlepiece.puzzle.Puzzle.add_folder().- add_piece(name, piece, row, column, rowspan=1, colspan=1, param_defaults=None)[source]
Adds a
Pieceto the grid layout, and registers it with the parentPuzzle.- Parameters:
name – Identifying string for the Piece.
piece – A
Pieceobject or a class defining one (which will be automatically instantiated).row – Row index for the grid layout.
column – Column index for the grid layout.
rowspan – Height in rows.
colspan – Width in columns.
param_defaults – An optional dictionary of default param values. These will be set without calling the corresponding param setters or
changedsignals.
- Return type:
- class puzzlepiece.puzzle.PieceDict[source]
Bases:
objectA dictionary wrapper that enforces single-use of keys, and raises a more useful error when a Piece tries to use another Piece that hasn’t been registered.
It also allows indexing params directly by using this key format:
[piece_name]:[param_name].
- class puzzlepiece.puzzle.Globals[source]
Bases:
QObjectA dictionary wrapper used for
puzzlepiece.puzzle.Puzzle.globals. It behaves like a dictionary, allowingpuzzlepiece.piece.Pieceobjects to share device APIs with each other.Additionally,
require()andrelease()can be used to keep track of the Pieces using a given variable, so that the API can be loaded once and then unloaded once all the Pieces are done with it.- require(name)[source]
Register that a Piece is using the variable with a given name. This will increase an internal counter to indicate the Piece having a hold on the variable.
Returns False if this is the first time a variable is being registered (and thus setup is needed) or True if the variable has been registered already.
For example, this can be used within
setup():def setup(self): if not self.puzzle.globals.require('sdk'): # Load the SDK if not done already by a different Piece self.puzzle.globals['sdk'] = self.load_sdk()
- Parameters:
name – a dictionary key for the required variable
- Return type:
bool
- release(name)[source]
Indicate that a Piece is done using the variable with a given name. This will decrease an internal counter to indicate the Piece is releasing its hold on the variable.
Returns False if the counter is non-zero (so different Pieces are still using this variable) or True if all Pieces are done with the variable (in that case the SDK can be safely shut down for example).
For example, this can be used within
handle_close():def handle_close(self): if self.puzzle.globals.release('sdk'): # Unload the SDK if all Pieces are done with it self.puzzle.globals['sdk'].stop()
- Parameters:
name – a dictionary key for the variable being released
- Return type:
bool
- deleted
A Qt signal called when a Globals key is deleted. The key is passed as the argument. You can use this when multiple Pieces share the same API instance - the other Pieces can connect to this Signal and handle the API being deleted.