Releases: jdranczewski/puzzlepiece
v0.12.1
New features:
- You can now omit
self
in param setter/getter and action definitions. Since these are created in thedefine_params(self)
method of a Piece,self
already exists in the namespace. For example:
def define_params(self):
@pzp.param.readout(self, "digit")
def digit():
return np.random.randint(0, 10)
- Param setter and getters now get unique code object names, meaning that they show up correctly when profiling.
- Thread upgrades:
set_value
andget_value
are now threadsafe (no promises about user-defined setters and getters though!). Threaded versions of the methods are available, and can be invoked by ctrl+clicking the corresponding GUI buttons (or pressing ctrl+enter) to avoid freezing the GUI. Care should be taken with this though, as setting a value multiple times before the operation finishes can confuse hardware for example. - Actions can now return values when called.
- The global STOP is now called on exit to help your Pieces wind down gracefully.
- Keyboard shortcuts for actions now work while focus in Popup, and new
Popup.close()
method added. - New logo! Plus a Q&A section in the documentation.
Fixes:
- The Puzzle and Popups Qt objects are now marked for deletion when closed, avoiding any memory leaks or objects lingering when not expected to.
- ParamSlider no longer emits the
changed
Signal twice whenset_value
is used. - ParamArray spinner now updates correctly for different getter/setter combinations.
self.folder
now set for Pieces beforedefine_params/define_actions
- Assorted fixes to get readthedocs to build again
v0.12.0
Superseded by v0.12.1, see above.
v0.11.0
Added a tutorial! Check it out at https://puzzlepiece.readthedocs.io/en/stable/tutorial.html
New features:
- Puzzles can be indexed in additional ways as a shortcut - you can now directly say
puzzle["piece:param"]
to get a param. This also autocompletes in IPython. - Child params and actions - use
Popup.make_child_params
to easily create settings popups that modify hidden params. replace_piece
- an experimental method to update a Piece in place.done_signal
for the LiveWorker emitted when it finishes.- new extra module:
ipython_shims
adds two convenient magics:%%pzp_script
and%%safe_run
- Improvements to
DataGrid
s, including support for customRow
s inadd_row
andPopup
s for the Rows. - Ability to set a
Popup
's title.
Fixes:
call_stop
stops threads too.- reduced reliance on Qt spreadsheets - param changes should always indicate correctly with a red background now.
v0.10.0 - DataGrids, sliders, shortcuts, fixes
New shortcuts:
- The QApp and Puzzle name arguments are no longer required when creating a Puzzle. The QApp still needs to be created in non-IPython contexts, but it can now be inferred by the Piece.
- You can directly accesss a Piece's params by indexing it like a dictionary:
puzzle["piece"]["param_name"]
# is now equivalent to
puzzle["piece"].params["param_name"]
New features:
- A slider parameter type - displays a slider and a value label. Min and max values, as well as the step size, are defined on creation.
- First
extra
submodule -DataGrid
s allow for storing and interacting with data using theparam
abstractions in a table format. Can be added to a Piece'scustom_layout
to enable new data manipulation tasks.
Fixes and enhancements:
- add_piece now returns the Piece instance (useful if a class is being passed for instantiation)
v_step
argument when creating spinboxes changes the step of the box's buttons.- Popups now close when the Puzzle is closed.
- Default param values are cast to the right type on creation.
- IPython exception handler is now inserted correctly even if
puzzle.process_events()
is called in the cell that creates the Puzzle. - Pieces can now be instantiated without a parent Puzzle. This allows for using the Piece as a standalone Widget in an environment where only one Piece is needed, or a Puzzle cannot be set up, but is in general not advised.
- Option to hide the bottom buttons of a Puzzle (Tree, Export, STOP)
- All code has been re-formatted using ruff.
v0.9.0 - Popups, progress bars, IPython exceptions, fixes
Popups are now available as a convenient way to create a modal window attached to the main Puzzle. Can be used for calibration processes, further settings, or just in general GUI that you don't want cluttering a Piece. See https://puzzlepiece.readthedocs.io/en/latest/puzzlepiece.piece.html#puzzlepiece.piece.Popup for details.
Progress bar params give you a standard way to indicate progress, with tqdm-like iterable wrapping capability:
for i in piece.params['progress'].iter(range(10)):
print(i)
# this will automatically update the progress bar as the iteration goes on
puzzle.process_events() # you may need to refresh the Puzzle to display changes
Exceptions that arise when running in IPython and interacting with the GUI will now display an error dialog just like when running in non-interactive Python. Exceptions that arise during cell execution will still produce a traceback in the Notebook, as before.
Small fixes: all threads now stop when an exception is raised, and a getter result will be cast to the param's type if obtained during a set_value
call (that is if the setter doesn't return a value and a getter is present).
See pull request #2 for full changes
set_value and set_partial updates
set_value()
now returns the new value, as it may be different than the one being set if the setter returns a value or a getter is defined.
ParamArray
has a new property set_partial
which allows you to set values to slices of the stored numpy array. This calls the setter of the param.
puzzle['piece'].params['image'].set_partial[100:200, :] = 128
Convenient shortcuts
You can now access the QApplication class as puzzlepiece.QApp
, and pass Piece classes to add_piece
instead of instantiating them first - this will reduce the clutter when building applications, and bring the minimum viable app to this neater form:
import puzzlepiece as pzp
from puzzlepiece.pieces import random_number
app = pzp.QApp([])
puzzle = pzp.Puzzle(app, "Basic example")
puzzle.add_piece("random", random_number.Piece, 0, 0)
puzzle.show()
app.exec()
Ensurers - capture_exception
Small amendment to v0.6.0: ensurers can now capture the exception when called directly, so they can be used in if
statements easily.
# This will not raise an Exception is the check fails
if self._ensure_connected(capture_exception=True):
print("laser is connected!")
Original v0.6.0 changelog follows:
An ensurer is a decorator that can be placed on getters, setters, and actions, and it will run ahead of these functions. The intended behaviour is performing checks ahead of running the function - for example checking if a laser is connected ahead of trying to set its power. This way one ensurer can be written and used in multiple places easily.
See https://puzzlepiece.readthedocs.io/en/latest/puzzlepiece.piece.html#puzzlepiece.piece.ensurer for examples
Ensurers
An ensurer is a decorator that can be placed on getters, setters, and actions, and it will run ahead of these functions. The intended behaviour is performing checks ahead of running the function - for example checking if a laser is connected ahead of trying to set its power. This way one ensurer can be written and used in multiple places easily.
See https://puzzlepiece.readthedocs.io/en/latest/puzzlepiece.piece.html#puzzlepiece.piece.ensurer for examples
Globals - variable management
It's now easier for multiple Pieces to share a device SDK with each other - they can put a hold on it in puzzle.globals
and release it when done, only setting up and closing the SDK once for all Pieces.
See https://puzzlepiece.readthedocs.io/en/latest/puzzlepiece.puzzle.html#puzzlepiece.puzzle.Globals for examples