fix: remove deprecated docs
@@ -1,27 +0,0 @@
|
||||
# .readthedocs.yaml
|
||||
# Read the Docs configuration file
|
||||
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
|
||||
|
||||
# Required
|
||||
version: 2
|
||||
|
||||
# Set the version of Python and other tools you might need
|
||||
build:
|
||||
os: ubuntu-22.04
|
||||
tools:
|
||||
python: "3.11"
|
||||
|
||||
# Build documentation in the docs/ directory with Sphinx
|
||||
sphinx:
|
||||
configuration: docs/conf.py
|
||||
|
||||
# If using Sphinx, optionally build your docs in additional formats such as PDF
|
||||
# formats:
|
||||
# - pdf
|
||||
|
||||
# Optionally declare the Python requirements required to build your docs
|
||||
python:
|
||||
install:
|
||||
- requirements: docs/requirements.txt
|
||||
- method: pip
|
||||
path: .[dev]
|
||||
@@ -1,20 +0,0 @@
|
||||
# Minimal makefile for Sphinx documentation
|
||||
#
|
||||
|
||||
# You can set these variables from the command line, and also
|
||||
# from the environment for the first two.
|
||||
SPHINXOPTS ?=
|
||||
SPHINXBUILD ?= sphinx-build
|
||||
SOURCEDIR = .
|
||||
BUILDDIR = _build
|
||||
|
||||
# Put it first so that "make" without argument is like "make help".
|
||||
help:
|
||||
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
|
||||
.PHONY: help Makefile
|
||||
|
||||
# Catch-all target: route all unknown targets to Sphinx using the new
|
||||
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
||||
%: Makefile
|
||||
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
@@ -1,34 +0,0 @@
|
||||
{{ fullname | escape | underline}}
|
||||
|
||||
.. currentmodule:: {{ module }}
|
||||
|
||||
.. autoclass:: {{ objname }}
|
||||
:members:
|
||||
:show-inheritance:
|
||||
:inherited-members:
|
||||
:special-members: __call__, __add__, __mul__
|
||||
|
||||
{% block methods %}
|
||||
{% if methods %}
|
||||
.. rubric:: {{ _('Methods') }}
|
||||
|
||||
.. autosummary::
|
||||
:nosignatures:
|
||||
{% for item in methods %}
|
||||
{%- if not item.startswith('_') %}
|
||||
~{{ name }}.{{ item }}
|
||||
{%- endif -%}
|
||||
{%- endfor %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block attributes %}
|
||||
{% if attributes %}
|
||||
.. rubric:: {{ _('Attributes') }}
|
||||
|
||||
.. autosummary::
|
||||
{% for item in attributes %}
|
||||
~{{ name }}.{{ item }}
|
||||
{%- endfor %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
@@ -1,66 +0,0 @@
|
||||
{{ fullname | escape | underline}}
|
||||
|
||||
.. automodule:: {{ fullname }}
|
||||
|
||||
{% block attributes %}
|
||||
{% if attributes %}
|
||||
.. rubric:: Module attributes
|
||||
|
||||
.. autosummary::
|
||||
:toctree:
|
||||
{% for item in attributes %}
|
||||
{{ item }}
|
||||
{%- endfor %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block functions %}
|
||||
{% if functions %}
|
||||
.. rubric:: {{ _('Functions') }}
|
||||
|
||||
.. autosummary::
|
||||
:toctree:
|
||||
:nosignatures:
|
||||
{% for item in functions %}
|
||||
{{ item }}
|
||||
{%- endfor %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block classes %}
|
||||
{% if classes %}
|
||||
.. rubric:: {{ _('Classes') }}
|
||||
|
||||
.. autosummary::
|
||||
:toctree:
|
||||
:template: custom-class-template.rst
|
||||
:nosignatures:
|
||||
{% for item in classes %}
|
||||
{{ item }}
|
||||
{%- endfor %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block exceptions %}
|
||||
{% if exceptions %}
|
||||
.. rubric:: {{ _('Exceptions') }}
|
||||
|
||||
.. autosummary::
|
||||
:toctree:
|
||||
{% for item in exceptions %}
|
||||
{{ item }}
|
||||
{%- endfor %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block modules %}
|
||||
{% if modules %}
|
||||
.. autosummary::
|
||||
:toctree:
|
||||
:template: custom-module-template.rst
|
||||
:recursive:
|
||||
{% for item in modules %}
|
||||
{{ item }}
|
||||
{%- endfor %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
@@ -1,11 +0,0 @@
|
||||
(api_reference)=
|
||||
# API Reference
|
||||
|
||||
This page contains the auto-generated API documentation for all modules, classes, and functions in the BEC Widgets package.
|
||||
|
||||
```{toctree}
|
||||
:maxdepth: 2
|
||||
:caption: API Documentation
|
||||
|
||||
../autoapi/bec_widgets/index
|
||||
```
|
||||
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="48px" viewBox="0 0 24 24" width="48px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M4 8h4V4H4v4zm6 12h4v-4h-4v4zm-6 0h4v-4H4v4zm0-6h4v-4H4v4zm6 0h4v-4h-4v4zm6-10v4h4V4h-4zm-6 4h4V4h-4v4zm6 6h4v-4h-4v4zm0 6h4v-4h-4v4z"/></svg>
|
||||
|
Before Width: | Height: | Size: 292 B |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 20 20" height="48px" viewBox="0 0 20 20" width="48px" fill="#000000"><g><rect fill="none" height="20" width="20" x="0"/></g><g><g><path d="M16.5,3h-13C2.67,3,2,3.67,2,4.5v9C2,14.33,2.67,15,3.5,15H7v2h6v-2h3.5c0.83,0,1.5-0.67,1.5-1.5v-9 C18,3.67,17.33,3,16.5,3z M16.5,13.5h-13v-9h13V13.5z"/><rect height="1" width="7" x="5" y="7"/><polygon points="14,8 15,8 15,7 14,7 14,6 13,6 13,9 14,9"/><rect height="1" width="7" x="8" y="10"/><polygon points="6,12 7,12 7,9 6,9 6,10 5,10 5,11 6,11"/></g></g></svg>
|
||||
|
Before Width: | Height: | Size: 568 B |
@@ -1,97 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="99.058548mm"
|
||||
height="89.967583mm"
|
||||
viewBox="0 0 99.058554 89.967582"
|
||||
version="1.1"
|
||||
id="svg1040"
|
||||
inkscape:version="0.92.4 (f8dce91, 2019-08-02)"
|
||||
sodipodi:docname="index_api.svg">
|
||||
<defs
|
||||
id="defs1034" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="0.35"
|
||||
inkscape:cx="533.74914"
|
||||
inkscape:cy="10.90433"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
inkscape:window-width="930"
|
||||
inkscape:window-height="472"
|
||||
inkscape:window-x="2349"
|
||||
inkscape:window-y="267"
|
||||
inkscape:window-maximized="0" />
|
||||
<metadata
|
||||
id="metadata1037">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(195.19933,-1.0492759)">
|
||||
<g
|
||||
id="g1008"
|
||||
transform="matrix(1.094977,0,0,1.094977,-521.5523,-198.34055)">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path899"
|
||||
d="M 324.96812,187.09499 H 303.0455 v 72.1639 h 22.67969"
|
||||
style="fill:none;stroke:#5a5a5a;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path899-3"
|
||||
d="m 361.58921,187.09499 h 21.92262 v 72.1639 h -22.67969"
|
||||
style="fill:none;stroke:#5a5a5a;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<g
|
||||
transform="translate(415.87139,46.162126)"
|
||||
id="g944">
|
||||
<circle
|
||||
style="fill:#5a5a5a;fill-opacity:1;stroke:#5a5a5a;stroke-width:4.53704548;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path918"
|
||||
cx="-84.40152"
|
||||
cy="189.84375"
|
||||
r="2.2293637" />
|
||||
<circle
|
||||
style="fill:#5a5a5a;fill-opacity:1;stroke:#5a5a5a;stroke-width:4.53704548;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path918-5"
|
||||
cx="-72.949402"
|
||||
cy="189.84375"
|
||||
r="2.2293637" />
|
||||
<circle
|
||||
style="fill:#5a5a5a;fill-opacity:1;stroke:#5a5a5a;stroke-width:4.53704548;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path918-6"
|
||||
cx="-61.497284"
|
||||
cy="189.84375"
|
||||
r="2.2293637" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.4 KiB |
@@ -1,76 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="89.624855mm"
|
||||
height="89.96759mm"
|
||||
viewBox="0 0 89.62486 89.96759"
|
||||
version="1.1"
|
||||
id="svg1040"
|
||||
inkscape:version="0.92.4 (f8dce91, 2019-08-02)"
|
||||
sodipodi:docname="index_contribute.svg">
|
||||
<defs
|
||||
id="defs1034" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="0.35"
|
||||
inkscape:cx="683.11893"
|
||||
inkscape:cy="-59.078181"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
inkscape:window-width="930"
|
||||
inkscape:window-height="472"
|
||||
inkscape:window-x="2349"
|
||||
inkscape:window-y="267"
|
||||
inkscape:window-maximized="0" />
|
||||
<metadata
|
||||
id="metadata1037">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(234.72009,17.466935)">
|
||||
<g
|
||||
id="g875"
|
||||
transform="matrix(0.99300176,0,0,0.99300176,-133.24106,-172.58804)">
|
||||
<path
|
||||
sodipodi:nodetypes="ccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path869"
|
||||
d="m -97.139881,161.26069 47.247024,40.25446 -47.247024,40.25446"
|
||||
style="fill:none;stroke:#5a5a5a;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path871"
|
||||
d="m -49.514879,241.81547 h 32.505951"
|
||||
style="fill:none;stroke:#5a5a5a;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.5 KiB |
@@ -1,66 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="101.09389mm"
|
||||
height="89.96759mm"
|
||||
viewBox="0 0 101.09389 89.96759"
|
||||
version="1.1"
|
||||
id="svg1040"
|
||||
inkscape:version="0.92.4 (f8dce91, 2019-08-02)"
|
||||
sodipodi:docname="index_getting_started.svg">
|
||||
<defs
|
||||
id="defs1034" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="0.35"
|
||||
inkscape:cx="-93.242129"
|
||||
inkscape:cy="-189.9825"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
inkscape:window-width="1875"
|
||||
inkscape:window-height="1056"
|
||||
inkscape:window-x="1965"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata1037">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(2.9219487,-8.5995374)">
|
||||
<path
|
||||
style="fill:#5a5a5a;fill-opacity:1;stroke-width:0.20233451"
|
||||
d="M 37.270955,98.335591 C 33.358064,97.07991 31.237736,92.52319 32.964256,89.08022 c 0.18139,-0.361738 4.757999,-5.096629 10.17021,-10.521968 l 9.84041,-9.864254 -4.03738,-4.041175 -4.037391,-4.041172 -4.96415,4.916665 c -3.61569,3.581096 -5.238959,5.04997 -5.975818,5.407377 l -1.011682,0.490718 H 17.267525 1.5866055 L 0.65034544,70.96512 C -2.2506745,69.535833 -3.5952145,66.18561 -2.5925745,62.884631 c 0.53525,-1.762217 1.61699004,-3.050074 3.22528014,-3.839847 l 1.15623996,-0.56778 13.2591094,-0.05613 13.259111,-0.05613 11.5262,-11.527539 11.526199,-11.527528 H 40.622647 c -12.145542,0 -12.189222,-0.0046 -13.752801,-1.445851 -2.229871,-2.055423 -2.162799,-5.970551 0.135998,-7.938238 1.475193,-1.262712 1.111351,-1.238469 18.588522,-1.238469 12.899229,0 16.035311,0.05193 16.692589,0.276494 0.641832,0.219264 2.590731,2.051402 9.416301,8.852134 l 8.606941,8.575638 h 6.848168 c 4.837422,0 7.092281,0.07311 7.679571,0.249094 0.48064,0.144008 1.22985,0.634863 1.77578,1.163429 2.383085,2.307333 1.968685,6.539886 -0.804989,8.221882 -0.571871,0.346781 -1.38284,0.687226 -1.80217,0.756523 -0.41933,0.06928 -4.2741,0.127016 -8.56615,0.128238 -6.56998,0.0016 -7.977492,-0.04901 -8.902732,-0.321921 -0.975569,-0.287742 -1.400468,-0.622236 -3.783999,-2.978832 l -2.685021,-2.654679 -5.05411,5.051071 -5.0541,5.051081 3.926292,3.947202 c 2.365399,2.378001 4.114289,4.309171 4.399158,4.857713 0.39266,0.75606 0.47311,1.219412 0.474321,2.731516 0.003,3.083647 0.620779,2.331942 -13.598011,16.531349 -10.273768,10.259761 -12.679778,12.563171 -13.500979,12.92519 -1.267042,0.55857 -3.156169,0.681342 -4.390271,0.285321 z m 40.130741,-65.45839 c -2.212909,-0.579748 -3.782711,-1.498393 -5.51275,-3.226063 -2.522111,-2.518633 -3.633121,-5.181304 -3.633121,-8.707194 0,-3.530699 1.11238,-6.197124 3.631161,-8.704043 4.866751,-4.8438383 12.324781,-4.8550953 17.211791,-0.026 3.908758,3.862461 4.818578,9.377999 2.372188,14.380771 -0.846209,1.730481 -3.39493,4.326384 -5.143839,5.239072 -2.69708,1.407492 -6.042829,1.798628 -8.92543,1.043434 z"
|
||||
id="path1000"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.9 KiB |
@@ -1,67 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="123.72241mm"
|
||||
height="89.96759mm"
|
||||
viewBox="0 0 123.72242 89.96759"
|
||||
version="1.1"
|
||||
id="svg1040"
|
||||
inkscape:version="0.92.4 (f8dce91, 2019-08-02)"
|
||||
sodipodi:docname="index_userguide.svg">
|
||||
<defs
|
||||
id="defs1034" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="0.35"
|
||||
inkscape:cx="332.26618"
|
||||
inkscape:cy="83.744004"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
inkscape:window-width="930"
|
||||
inkscape:window-height="472"
|
||||
inkscape:window-x="2349"
|
||||
inkscape:window-y="267"
|
||||
inkscape:window-maximized="0" />
|
||||
<metadata
|
||||
id="metadata1037">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(141.8903,-20.32143)">
|
||||
<path
|
||||
style="fill:#5a5a5a;fill-opacity:1;stroke-width:0.20483544"
|
||||
d="m -139.53374,110.1657 c -0.80428,-0.24884 -1.71513,-1.11296 -2.07107,-1.96486 -0.23905,-0.57214 -0.28453,-6.28104 -0.28453,-35.720988 0,-38.274546 -0.079,-35.840728 1.19849,-36.91568 0.58869,-0.495345 4.63766,-2.187548 8.47998,-3.544073 l 1.58749,-0.560453 v -3.309822 c 0,-3.025538 0.0396,-3.388179 0.46086,-4.222122 0.68808,-1.362003 1.38671,-1.714455 4.60319,-2.322195 4.12797,-0.779966 5.13304,-0.912766 8.81544,-1.16476 11.80964,-0.808168 22.80911,2.509277 30.965439,9.3392 1.750401,1.465747 3.840861,3.5635 5.0903,5.108065 l 0.659122,0.814805 0.659109,-0.814805 c 1.249431,-1.544565 3.33988,-3.642318 5.09029,-5.108065 8.156331,-6.829923 19.155791,-10.147368 30.965441,-9.3392 3.682389,0.251994 4.68748,0.384794 8.81544,1.16476 3.21647,0.60774 3.91511,0.960192 4.60318,2.322195 0.4213,0.833943 0.46087,1.196584 0.46087,4.222122 v 3.309822 l 1.58748,0.560453 c 4.10165,1.448077 7.98852,3.072753 8.5259,3.563743 1.22643,1.120567 1.15258,-1.245868 1.15258,36.927177 0,34.567591 -0.005,35.083151 -0.40663,35.903991 -0.22365,0.45804 -0.73729,1.05665 -1.14143,1.33024 -1.22281,0.82783 -2.17721,0.70485 -5.86813,-0.7561 -9.19595,-3.63998 -18.956011,-6.38443 -26.791332,-7.53353 -3.02827,-0.44412 -9.26189,-0.61543 -11.77821,-0.3237 -5.19357,0.60212 -8.736108,2.05527 -11.700039,4.79936 -0.684501,0.63371 -1.466141,1.23646 -1.736979,1.33942 -0.63859,0.2428 -4.236521,0.2428 -4.875112,0 -0.27083,-0.10296 -1.05247,-0.70571 -1.73696,-1.33942 -2.96395,-2.74409 -6.50648,-4.19724 -11.700058,-4.79936 -2.516312,-0.29173 -8.749941,-0.12042 -11.778201,0.3237 -7.78194,1.14127 -17.39965,3.83907 -26.73341,7.49883 -3.38325,1.32658 -4.15525,1.50926 -5.11851,1.21125 z m 4.2107,-5.34052 c 5.86759,-2.29858 14.40398,-4.922695 20.2018,-6.210065 6.31584,-1.402418 8.5236,-1.646248 14.91592,-1.647338 4.68699,-7.94e-4 6.013661,0.0632 7.257809,0.3497 0.837332,0.19286 1.561052,0.312028 1.60828,0.264819 0.147111,-0.147119 -1.803289,-1.307431 -4.154879,-2.471801 -8.12511,-4.023029 -18.27311,-4.986568 -29.0861,-2.761718 -1.09536,0.22538 -2.32708,0.40827 -2.73715,0.406418 -1.12787,-0.005 -2.3054,-0.76382 -2.84516,-1.8332 l -0.46086,-0.913098 V 62.99179 35.97471 l -0.56331,0.138329 c -0.30981,0.07608 -1.89985,0.665075 -3.5334,1.308881 -2.27551,0.896801 -2.96414,1.252878 -2.94452,1.522563 0.014,0.193604 0.0372,15.284513 0.0512,33.535345 0.014,18.250839 0.0538,33.183322 0.0884,33.183322 0.0346,0 1.02543,-0.3771 2.20198,-0.83801 z m 113.006991,-32.697216 -0.0518,-33.535203 -3.17495,-1.272156 c -1.74623,-0.699685 -3.33627,-1.278755 -3.53341,-1.286819 -0.33966,-0.01389 -0.35847,1.401778 -0.35847,26.980216 v 26.994863 l -0.46087,0.913112 c -0.53976,1.06939 -1.71729,1.828088 -2.84515,1.833189 -0.41008,0.0021 -1.6418,-0.181031 -2.73716,-0.406421 -11.888201,-2.446089 -22.84337,-1.046438 -31.491022,4.02332 -1.68175,0.985941 -2.216748,1.467501 -1.36534,1.228942 1.575181,-0.441362 4.990592,-0.73864 8.524862,-0.742011 5.954408,-0.005 11.43046,0.791951 19.10874,2.78333 3.9516,1.024874 12.1555,3.687454 15.6699,5.085704 1.23926,0.49306 2.36869,0.90517 2.50985,0.9158 0.20489,0.0155 0.2462,-6.745894 0.20483,-33.515866 z m -59.76135,-2.233777 V 40.065438 l -0.95972,-1.357442 c -1.380522,-1.952627 -5.376262,-5.847994 -7.64336,-7.45136 -3.778692,-2.672401 -9.063392,-4.943324 -13.672511,-5.875304 -3.19731,-0.646503 -5.23069,-0.833103 -9.05886,-0.831312 -4.37716,0.0021 -7.70223,0.349169 -11.83461,1.235469 l -1.07538,0.230645 v 31.242342 c 0,26.565778 0.0426,31.226011 0.28429,31.133261 0.15637,-0.06 1.42379,-0.297169 2.81648,-0.527026 12.37657,-2.042634 23.21658,-0.346861 32.521639,5.087596 2.10018,1.226558 5.20202,3.618878 6.880942,5.30692 0.788609,0.792909 1.502978,1.446609 1.587468,1.452679 0.0845,0.006 0.153622,-13.411893 0.153622,-29.817719 z m 5.80221,28.3766 c 6.21476,-6.141601 15.08488,-10.061509 25.025529,-11.05933 4.262419,-0.427849 11.579921,-0.0054 16.017661,0.924912 0.75932,0.15916 1.45259,0.244888 1.54058,0.190498 0.088,-0.05434 0.16003,-14.060382 0.16003,-31.124436 V 26.176883 l -0.52136,-0.198219 c -0.66893,-0.254325 -4.77649,-0.95482 -7.159981,-1.221048 -2.41372,-0.269605 -8.559851,-0.266589 -10.759229,0.0052 -6.458111,0.798299 -12.584091,3.083792 -17.405651,6.49374 -2.267091,1.603366 -6.262831,5.498733 -7.64336,7.45136 l -0.959721,1.357438 v 29.828747 c 0,16.405812 0.0532,29.828746 0.11802,29.828746 0.065,0 0.77928,-0.65347 1.587482,-1.452149 z"
|
||||
id="path845"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="csscccscsssscsssssscscsccsccsccscsscccccccscccccccccsccscscscccscccsccssccsscccscccccsccccsccscsccsscc" />
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 6.3 KiB |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 20 20" height="48px" viewBox="0 0 20 20" width="48px" fill="#000000"><g><rect fill="none" height="20" width="20" x="0"/></g><g><g><path d="M14.45,10.86l0.26,2.1c0.06,0.46-0.1,0.92-0.43,1.25l-3.55,3.55l-1.41-4.24l-2.83-2.83L2.25,9.27l3.55-3.55 c0.33-0.33,0.79-0.49,1.25-0.43l2.1,0.26C13.92,0.78,17.8,2.2,17.8,2.2C17.8,2.2,19.22,6.08,14.45,10.86z M10.2,6.62 C9.18,7.64,8.37,9.06,7.9,9.97l2.12,2.12c0.91-0.46,2.34-1.27,3.36-2.3C16.18,7,16.54,4.67,16.5,3.5C15.33,3.46,13,3.82,10.2,6.62 z M14,7.5C14,6.68,13.32,6,12.5,6C11.67,6,11,6.68,11,7.5S11.67,9,12.5,9C13.32,9,14,8.33,14,7.5z M7.99,6.92L6.86,6.78L5.02,8.61 l1.62,0.54C6.97,8.52,7.43,7.71,7.99,6.92z M10.85,13.36l0.54,1.62l1.83-1.83l-0.14-1.14C12.29,12.57,11.48,13.03,10.85,13.36z M5.25,12.5c-0.62,0-1.18,0.25-1.59,0.66C2.44,14.38,2,18,2,18s3.62-0.44,4.84-1.66c0.41-0.41,0.66-0.97,0.66-1.59 C7.5,13.51,6.49,12.5,5.25,12.5z M5.78,15.28c-0.44,0.44-1.87,0.81-1.87,0.81s0.37-1.43,0.81-1.87c0.29-0.29,0.77-0.29,1.06,0 S6.07,14.99,5.78,15.28z"/></g></g></svg>
|
||||
|
Before Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 7.0 KiB |
|
Before Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 326 KiB |
|
Before Width: | Height: | Size: 382 KiB |
|
Before Width: | Height: | Size: 94 KiB |
|
Before Width: | Height: | Size: 194 KiB |
|
Before Width: | Height: | Size: 151 KiB |
|
Before Width: | Height: | Size: 1.0 MiB |
|
Before Width: | Height: | Size: 146 KiB |
|
Before Width: | Height: | Size: 432 KiB |
|
Before Width: | Height: | Size: 498 KiB |
|
Before Width: | Height: | Size: 5.0 KiB |
|
Before Width: | Height: | Size: 8.2 KiB |
|
Before Width: | Height: | Size: 131 KiB |
|
Before Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 92 KiB |
|
Before Width: | Height: | Size: 82 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 184 KiB |
|
Before Width: | Height: | Size: 109 KiB |
|
Before Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 81 KiB |
|
Before Width: | Height: | Size: 5.1 KiB |
|
Before Width: | Height: | Size: 168 KiB |
|
Before Width: | Height: | Size: 38 KiB |
@@ -1,116 +0,0 @@
|
||||
# Configuration file for the Sphinx documentation builder.
|
||||
#
|
||||
# For the full list of built-in configuration values, see the documentation:
|
||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html
|
||||
|
||||
# -- Project information -----------------------------------------------------
|
||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
|
||||
|
||||
import datetime
|
||||
import pathlib
|
||||
|
||||
import tomli
|
||||
|
||||
project = "BEC Widgets"
|
||||
copyright = f"{datetime.datetime.today().year}, Paul Scherrer Institute"
|
||||
author = "Paul Scherrer Institute"
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
|
||||
|
||||
current_path = pathlib.Path(__file__).parent.parent.resolve()
|
||||
version_path = f"{current_path}/pyproject.toml"
|
||||
|
||||
|
||||
def get_version():
|
||||
"""load the version from the version file"""
|
||||
with open(version_path, "r", encoding="utf-8") as file:
|
||||
res = tomli.loads(file.read())
|
||||
return res["project"]["version"]
|
||||
|
||||
|
||||
release = get_version()
|
||||
|
||||
extensions = [
|
||||
# "sphinx.ext.coverage",
|
||||
"sphinx.ext.napoleon",
|
||||
"sphinx_toolbox.collapse",
|
||||
"sphinx_copybutton",
|
||||
"myst_parser",
|
||||
"sphinx_design",
|
||||
"sphinx_inline_tabs",
|
||||
"autoapi.extension",
|
||||
"sphinx.ext.viewcode",
|
||||
]
|
||||
|
||||
myst_enable_extensions = [
|
||||
"amsmath",
|
||||
"attrs_inline",
|
||||
"colon_fence",
|
||||
"deflist",
|
||||
"dollarmath",
|
||||
"fieldlist",
|
||||
"html_admonition",
|
||||
"html_image",
|
||||
"replacements",
|
||||
"smartquotes",
|
||||
"strikethrough",
|
||||
"substitution",
|
||||
"tasklist",
|
||||
]
|
||||
|
||||
# AutoAPI configuration
|
||||
autoapi_dirs = ["../bec_widgets"]
|
||||
autoapi_type = "python"
|
||||
autoapi_generate_api_docs = True
|
||||
autoapi_add_toctree_entry = False # We'll control the toctree manually
|
||||
autoapi_keep_files = False
|
||||
autoapi_python_class_content = "both" # Include both class docstring and __init__
|
||||
autoapi_member_order = "groupwise"
|
||||
|
||||
add_module_names = False # Remove namespaces from class/method signatures
|
||||
autodoc_inherit_docstrings = True # If no docstring, inherit from base class
|
||||
set_type_checking_flag = True # Enable 'expensive' imports for sphinx_autodoc_typehints
|
||||
autoclass_content = "both" # Include both class docstring and __init__
|
||||
autodoc_mock_imports = ["pyqtgraph", "qtpy", "PySide6"]
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ["_templates"]
|
||||
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
|
||||
|
||||
language = "Python"
|
||||
|
||||
# -- Options for HTML output -------------------------------------------------
|
||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
|
||||
|
||||
html_theme = "pydata_sphinx_theme"
|
||||
html_static_path = ["_static"]
|
||||
html_css_files = ["custom.css"]
|
||||
html_logo = "../bec_widgets/assets/app_icons/bec_widgets_icon.png"
|
||||
|
||||
|
||||
def skip_submodules(app, what, name, obj, skip, options):
|
||||
if what == "module":
|
||||
if not name.startswith("bec_widgets"):
|
||||
skip = True
|
||||
# print(f"Checking module: {name}")
|
||||
if "bec_widgets.widgets" in name:
|
||||
widget = name.split(".")[-2]
|
||||
submodule = name.split(".")[-1]
|
||||
if submodule in [f"register_{widget}", f"{widget}_plugin"]:
|
||||
# print(f"Skipping submodule: {name}")
|
||||
skip = True
|
||||
elif what in ["data", "attribute"]:
|
||||
obj_name = name.split(".")[-1]
|
||||
if obj_name.startswith("_") or obj_name in ["__all__", "logger", "bec_logger", "app"]:
|
||||
skip = True
|
||||
|
||||
elif what == "class":
|
||||
class_name = name.split(".")[-1]
|
||||
if class_name.startswith("Demo"):
|
||||
skip = True
|
||||
return skip
|
||||
|
||||
|
||||
def setup(app):
|
||||
app.connect("autoapi-skip-member", skip_submodules)
|
||||
@@ -1,52 +0,0 @@
|
||||
(developer)=
|
||||
# Developer
|
||||
|
||||
Welcome to the BEC Widgets developer guide! BEC Widgets is a framework for building graphical user interfaces (GUIs) for [BEC](https://bec.readthedocs.io/en/latest/), a Python package for beamline experiment control.
|
||||
|
||||
This guide targets readers who want to develop new widgets or extend existing ones. If your goal is to use BEC Widgets to build GUIs for your experiments, please refer to the [user guide](#user).
|
||||
|
||||
```{toctree}
|
||||
---
|
||||
maxdepth: 2
|
||||
hidden: true
|
||||
---
|
||||
|
||||
introduction/introduction.md
|
||||
widget_development/widget_development.md
|
||||
api_reference/api_reference.md
|
||||
```
|
||||
|
||||
|
||||
***
|
||||
|
||||
````{grid} 2
|
||||
:gutter: 5
|
||||
|
||||
```{grid-item-card}
|
||||
:link: developer.introduction
|
||||
:link-type: ref
|
||||
:img-top: /assets/rocket_launch_48dp.svg
|
||||
:text-align: center
|
||||
:class-item: index-card
|
||||
|
||||
## Introduction
|
||||
|
||||
An introduction into the single-responsibility principle and the modular design of BEC Widgets.
|
||||
```
|
||||
|
||||
```{grid-item-card}
|
||||
:link: developer.widget_development
|
||||
:link-type: ref
|
||||
:img-top: /assets/apps_48dp.svg
|
||||
:text-align: center
|
||||
:class-item: index-card
|
||||
|
||||
## Widget Development
|
||||
|
||||
Learn how to develop a new modular widget for BEC Widgets.
|
||||
```
|
||||
|
||||
````{grid} 2
|
||||
|
||||
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
(developer.concepts)=
|
||||
# Concepts
|
||||
This section provides an overview of the core concepts of BEC Widgets, which are based on the single-responsibility principle and modular design.
|
||||
|
||||
## Moduler Design
|
||||
We develop widgets with the single-responsibility principle in mind, meaning each widget is designed for a specific task. Our goal is to keep widgets simple, using them primarily for visualization or to initiate actions within BEC. Following these ideas, widgets should be designed to be reusable in various applications, making them versatile building blocks for larger GUIs.
|
||||
|
||||
We offer up to three different options for composing larger GUIs from these modular widgets: BEC Designer, DockArea widget, or scripting from the command line interface. More information about these options can be found in the user sections on [applications](user.applications).
|
||||
|
||||
## Client-Server Architecture
|
||||
|
||||
BEC Widgets is built on top of the [BEC](https://bec.readthedocs.io/en/latest/) package, which provides the backend for beamline experiment control. BEC Widgets is a client of BEC, meaning it can interact with the backend through a client-server architecture. To make full usage of the available features of BEC, we recommend to check the documentation about [data access](https://bec.readthedocs.io/en/latest/developer/data_access/data_access.html) in which the messaging and event system of BEC is described.
|
||||
In the context of BEC Widgets, the {py:class}`~bec_widgets.utils.bec_dispatcher.BECDispatcher` connects to this messaging and event system, allowing you to link your Qt [`Slots`](https://www.pythonguis.com/tutorials/pyside6-signals-slots-events/) to messages and event received from BEC.
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
(developer.contributing)=
|
||||
# Contributing
|
||||
|
||||
If you like to contribute to the development of BEC Widgets, you can follow the steps below to set up your development environment.
|
||||
BEC Widgets works in conjunction with [BEC](https://bec.readthedocs.io/en/latest/).
|
||||
Therefore, we recommend that you install BEC first following the [developer instructions](https://bec.readthedocs.io/en/latest/developer/getting_started/install_developer_env.html) and include BEC Widgets.
|
||||
|
||||
If you already have a BEC environment set up, you can install BEC Widgets in editable mode into your BEC Python environment.
|
||||
|
||||
**Prerequisites**
|
||||
1. **Python Version:** BEC Widgets requires Python version 3.11 or higher. Verify your Python version to ensure compatibility.
|
||||
2. **BEC Installation:** BEC Widgets works in conjunction with BEC. While BEC is a dependency and will be installed automatically, you can find more information about BEC and its installation process in the [BEC documentation](https://beamline-experiment-control.readthedocs.io/en/latest/).
|
||||
3. **Qt Distributions:** BEC Widgets supports [PySide6](https://doc.qt.io/qtforpython-6/quickstart.html) and [PyQt6](https://www.riverbankcomputing.com/static/Docs/PyQt6/introduction.html). We use [qtpy](https://pypi.org/project/QtPy/) to abstract the underlying QT distribution.
|
||||
|
||||
**Clone the Repository**:
|
||||
```bash
|
||||
git clone https://gitlab.psi.ch/bec/bec_widgets
|
||||
cd bec_widgets
|
||||
```
|
||||
**Install in Editable Mode**:
|
||||
|
||||
Please install the package in editable mode into your BEC Python environment.
|
||||
```bash
|
||||
pip install -e '.[dev,pyside6]'
|
||||
```
|
||||
This installs the package together with [PySide6](https://doc.qt.io/qtforpython-6/quickstart.html).
|
||||
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
(developer.introduction)=
|
||||
# Introduction
|
||||
BEC Widgets is a framework providing modular components that can be integrated into various larger GUI applications. Each widget serves a specific purpose adhering to the single-responsibility principle as detailed in our [concepts section](developer.concepts), and offers a straightforward, user-friendly interface.
|
||||
These widgets provide data visualisation tools and experimental control interfaces by triggering actions within BEC.
|
||||
If you're interested in contributing to BEC Widgets, please refer to our [contributing guide](developer.contributing), which provides instructions for setting up your development environment and creating your own widgets.
|
||||
|
||||
```{toctree}
|
||||
---
|
||||
maxdepth: 2
|
||||
hidden: false
|
||||
---
|
||||
|
||||
concepts/
|
||||
contributing/
|
||||
useful_links/
|
||||
```
|
||||
@@ -1,23 +0,0 @@
|
||||
(developer.useful_links)=
|
||||
|
||||
# Useful Links
|
||||
|
||||
If you're new to the Qt framework, here are some helpful resources to get you started. In BEC Widgets, we use Qt
|
||||
distributions based on Qt6, specifically PyQt6 and PySide6. However, all code should be written using
|
||||
the [`qtpy`](https://pypi.org/project/QtPy/) abstraction layer, which allows compatibility with both. While both PyQt6
|
||||
and PySide6 are supported, we prefer PySide6 as it is the official Python binding from the Qt Company. It offers
|
||||
advantages like bundling all necessary libraries in a single package with pip installation and staying more up-to-date
|
||||
compared to PyQt6.
|
||||
|
||||
Below is a list of useful links to help you start developing with Qt and Qt Designer:
|
||||
|
||||
- [Python GUIs](https://www.pythonguis.com): A great resource with tutorials and examples for creating GUIs in Python
|
||||
using various frameworks.
|
||||
- [PySide6 Quick Start Guide](https://doc.qt.io/qtforpython-6/index.html): The official documentation for PySide6,
|
||||
including quick start guides and tutorials.
|
||||
- [Qt Designer Official Documentation](https://doc.qt.io/qt-6/qtdesigner-manual.html): Comprehensive documentation for
|
||||
Qt Designer, the underlying tool for BEC Designer.
|
||||
- [Simple PyQt Tutorial from RealPython](https://realpython.com/python-pyqt-gui-calculator/): A beginner-friendly
|
||||
tutorial on creating your first GUI application with PyQt.
|
||||
- [PyQtGraph Documentation](https://pyqtgraph.readthedocs.io/en/latest/): BEC Widgets relies on PyQtGraph for plotting;
|
||||
this is the official documentation.
|
||||
@@ -1,139 +0,0 @@
|
||||
(developer.widget_development.bec_dispatcher)=
|
||||
|
||||
# BECDispatcher
|
||||
|
||||
## Overview
|
||||
|
||||
The [`BECDispatcher`](https://bec.readthedocs.io/projects/bec-widgets/en/latest/api_reference/_autosummary/bec_widgets.utils.bec_dispatcher.BECDispatcher.html#bec_widgets.utils.bec_dispatcher.BECDispatcher)
|
||||
is a powerful tool that simplifies the process of connecting [Qt slots](https://doc.qt.io/qt-6/signalsandslots.html) to message updates from the BEC server. It enables real-time communication between your widget and the BEC server by listening to specific message channels and triggering callbacks when new data is received.
|
||||
|
||||
This tool is especially useful for creating widgets that need to respond to dynamic data, such as device readbacks or
|
||||
scan updates. By
|
||||
using [`BECDispatcher`](https://bec.readthedocs.io/projects/bec-widgets/en/latest/api_reference/_autosummary/bec_widgets.utils.bec_dispatcher.BECDispatcher.html#bec_widgets.utils.bec_dispatcher.BECDispatcher),
|
||||
you
|
||||
can create callback functions that react to incoming messages and update your widget's state or perform other tasks
|
||||
based on the data received.
|
||||
|
||||
## How It Works
|
||||
|
||||
When you create a widget that needs to respond to updates from the BEC server, you can use
|
||||
the [`BECDispatcher`](https://bec.readthedocs.io/projects/bec-widgets/en/latest/api_reference/_autosummary/bec_widgets.utils.bec_dispatcher.BECDispatcher.html#bec_widgets.utils.bec_dispatcher.BECDispatcher)
|
||||
to
|
||||
connect specific Qt slots (callback functions) to message endpoints. These endpoints are defined within the BEC system
|
||||
and represent specific channels of information (
|
||||
e.g., [`device readback`](https://beamline-experiment-control.readthedocs.io/en/latest/api_reference/_autosummary/bec_lib.endpoints.MessageEndpoints.html#bec_lib.endpoints.MessageEndpoints.device_readback),
|
||||
[`scan_segment`](https://beamline-experiment-control.readthedocs.io/en/latest/api_reference/_autosummary/bec_lib.endpoints.MessageEndpoints.html#bec_lib.endpoints.MessageEndpoints.scan_segment),
|
||||
etc.).
|
||||
|
||||
### Step-by-Step Guide
|
||||
|
||||
1. **Create a Callback Function**: Define a function within your widget that will handle the data received from the BEC
|
||||
server. This function must accept two parameters: `msg_content` (the message content) and `metadata` (
|
||||
additional
|
||||
information about the message).
|
||||
|
||||
```python
|
||||
# Example for a callback function that updates a widget display based on motor readback data
|
||||
from qtpy.QtCore import Slot
|
||||
|
||||
@Slot(dict, dict)
|
||||
def on_device_readback(self, msg_content:dict, metadata:dict):
|
||||
# Process the incoming data
|
||||
new_value = msg_content["signals"]['motor_x']["value"]
|
||||
# Update the widget's display or perform another action
|
||||
self.update_display(new_value)
|
||||
```
|
||||
|
||||
2. **Connect the Slot to an Endpoint**: Use
|
||||
the [`BECDispatcher`](https://bec.readthedocs.io/projects/bec-widgets/en/latest/api_reference/_autosummary/bec_widgets.utils.bec_dispatcher.BECDispatcher.html#bec_widgets.utils.bec_dispatcher.BECDispatcher)
|
||||
to connect your callback function to a specific
|
||||
endpoint. The endpoint represents the type of data or message you're interested in.
|
||||
|
||||
```python
|
||||
from bec_lib.endpoints import MessageEndpoints
|
||||
|
||||
self.bec_dispatcher.connect_slot(self.on_device_readback, MessageEndpoints.device_readback("motor_x"))
|
||||
```
|
||||
|
||||
3. **Handle Incoming Data**: Your callback function will be triggered automatically whenever a new message is received
|
||||
on the connected endpoint. Use the data in `msg_content` to update your widget or perform other actions.
|
||||
|
||||
4. **Clean Up Connections**: If your widget is being destroyed or you no longer need to listen for updates, make sure to
|
||||
disconnect your slots from
|
||||
the [`BECDispatcher`](https://bec.readthedocs.io/projects/bec-widgets/en/latest/api_reference/_autosummary/bec_widgets.utils.bec_dispatcher.BECDispatcher.html#bec_widgets.utils.bec_dispatcher.BECDispatcher)
|
||||
to avoid memory or thread leaks.
|
||||
|
||||
```python
|
||||
self.bec_dispatcher.disconnect_slot(self.on_device_readback, MessageEndpoints.device_readback("motor_x"))
|
||||
```
|
||||
|
||||
### Example: Motor Map Widget
|
||||
|
||||
The [`BECMotorMap`](https://bec.readthedocs.io/projects/bec-widgets/en/latest/api_reference/_autosummary/bec_widgets.widgets.figure.plots.motor_map.motor_map.BECMotorMap.html#bec-widgets-widgets-figure-plots-motor-map-motor-map-becmotormap)
|
||||
widget is a great example of
|
||||
how [`BECDispatcher`](https://bec.readthedocs.io/projects/bec-widgets/en/latest/api_reference/_autosummary/bec_widgets.utils.bec_dispatcher.BECDispatcher.html#bec_widgets.utils.bec_dispatcher.BECDispatcher)
|
||||
can be used to handle real-time data updates. This
|
||||
widget listens for updates on specific motor positions and dynamically updates the motor map display.
|
||||
|
||||
Here's a breakdown of
|
||||
how [`BECDispatcher`](https://bec.readthedocs.io/projects/bec-widgets/en/latest/api_reference/_autosummary/bec_widgets.utils.bec_dispatcher.BECDispatcher.html#bec_widgets.utils.bec_dispatcher.BECDispatcher)
|
||||
is used in
|
||||
the [`BECMotorMap`](https://bec.readthedocs.io/projects/bec-widgets/en/latest/api_reference/_autosummary/bec_widgets.widgets.figure.plots.motor_map.motor_map.BECMotorMap.html#bec-widgets-widgets-figure-plots-motor-map-motor-map-becmotormap)
|
||||
widget:
|
||||
|
||||
1. **Connecting to Motor Readbacks**:
|
||||
The widget connects to
|
||||
the [`device readback`](https://beamline-experiment-control.readthedocs.io/en/latest/api_reference/_autosummary/bec_lib.endpoints.MessageEndpoints.html#bec_lib.endpoints.MessageEndpoints.device_readback)
|
||||
endpoints using
|
||||
the [`connect_slot`](https://bec.readthedocs.io/projects/bec-widgets/en/latest/api_reference/_autosummary/bec_widgets.utils.bec_dispatcher.BECDispatcher.html#bec_widgets.utils.bec_dispatcher.BECDispatcher.connect_slot)
|
||||
method
|
||||
of [`BECDispatcher`](https://bec.readthedocs.io/projects/bec-widgets/en/latest/api_reference/_autosummary/bec_widgets.utils.bec_dispatcher.BECDispatcher.html#bec_widgets.utils.bec_dispatcher.BECDispatcher).
|
||||
This allows
|
||||
the widget to receive real-time updates about the motor positions.
|
||||
|
||||
```{literalinclude} ../../../bec_widgets/widgets/figure/plots/motor_map/motor_map.py
|
||||
:language: python
|
||||
:pyobject: BECMotorMap._connect_motor_to_slots
|
||||
:dedent: 4
|
||||
```
|
||||
|
||||
2. **Handling Readback Data**:
|
||||
The `on_device_readback` slot is called whenever new data is received from the motor readback. This slot processes
|
||||
the data and updates the motor map plot accordingly.
|
||||
|
||||
```{literalinclude} ../../../bec_widgets/widgets/figure/plots/motor_map/motor_map.py
|
||||
:language: python
|
||||
:pyobject: BECMotorMap.on_device_readback
|
||||
:dedent: 4
|
||||
```
|
||||
|
||||
3. **Updating the Plot**:
|
||||
The motor map plot is updated in response to the new data, providing a real-time visualization of the motor's
|
||||
position.
|
||||
|
||||
```{literalinclude} ../../../bec_widgets/widgets/figure/plots/motor_map/motor_map.py
|
||||
:language: python
|
||||
:pyobject: BECMotorMap._update_plot
|
||||
:dedent: 4
|
||||
```
|
||||
|
||||
4. **Disconnecting When No Longer Needed**:
|
||||
The widget ensures that connections are properly cleaned up when no longer needed.
|
||||
|
||||
```{literalinclude} ../../../bec_widgets/widgets/figure/plots/motor_map/motor_map.py
|
||||
:language: python
|
||||
:pyobject: BECMotorMap._update_plot
|
||||
:dedent: 4
|
||||
```
|
||||
|
||||
## Conclusion
|
||||
|
||||
The [`BECDispatcher`](https://bec.readthedocs.io/projects/bec-widgets/en/latest/api_reference/_autosummary/bec_widgets.utils.bec_dispatcher.BECDispatcher.html#bec_widgets.utils.bec_dispatcher.BECDispatcher)
|
||||
is a key tool for developing interactive and responsive widgets within the BEC framework. By leveraging this tool, you can create widgets that automatically respond to real-time data updates from the BEC server,
|
||||
enhancing the interactivity and functionality of your user interface.
|
||||
|
||||
In next tutorials we will cover how to create a custom widget using the BECDispatcher and BECWidget base class.
|
||||
|
||||
```{note}
|
||||
For more details on specific messages and endpoints, please refer to the [Message Endpoints Documentation](https://beamline-experiment-control.readthedocs.io/en/latest/api_reference/_autosummary/bec_lib.endpoints.MessageEndpoints.html#bec-lib-endpoints-messageendpoints).
|
||||
```
|
||||
@@ -1,81 +0,0 @@
|
||||
(developer.widget_development.tutorial_tests)=
|
||||
|
||||
# Testing BEC Widgets
|
||||
|
||||
## Importance of Writing Tests for Widgets
|
||||
|
||||
Writing tests for widgets, even for simple ones, is crucial in maintaining the reliability and stability of a software
|
||||
project. Tests help ensure that new contributions don't unintentionally break existing functionality, and they provide a
|
||||
safety net for developers making changes in the future. In the context of the BEC Widgets, testing is particularly
|
||||
important due to the complexity of interactions with external systems like the BEC server.
|
||||
|
||||
## Testing with Pytest and QtBot
|
||||
|
||||
For testing Qt-based applications, we use [`pytest`](https://docs.pytest.org/en/stable/) along with
|
||||
the [`pytest-qt`](https://pytest-qt.readthedocs.io/en/latest/) plugin, which provides the `qtbot` fixture. `qtbot` is
|
||||
specifically designed to simplify interactions with Qt applications during testing. It handles the creation, management,
|
||||
and cleanup of widgets, ensuring that your tests are robust and do not leave behind any lingering resources or open
|
||||
windows.
|
||||
|
||||
## Fixtures for Testing BEC Widgets
|
||||
|
||||
Let's break down the key fixtures used in testing BEC Widgets:
|
||||
|
||||
1. **`qapplication` Fixture**: This fixture ensures that all Qt applications and widgets are properly closed after each
|
||||
test. It uses `qtbot` to wait until all top-level widgets are closed, raising an error if any remain open.
|
||||
|
||||
2. **`rpc_register` Fixture**: This fixture manages the `RPCRegister` singleton, ensuring that it is reset after each
|
||||
test. This prevents state from leaking between tests, which could cause unexpected behavior.
|
||||
|
||||
3. **`bec_dispatcher` Fixture**: This fixture initializes the `BECDispatcher` and ensures that all connections are
|
||||
properly disconnected and the BEC client is shut down after each test. Like `rpc_register`, it resets the singleton
|
||||
after each test.
|
||||
|
||||
4. **`clean_singleton` Fixture**: This fixture cleans up any singleton instances used in error popups, preventing
|
||||
interference between tests.
|
||||
|
||||
5. **`create_widget` Helper Function**: This function is a helper that should be used in all tests requiring widget
|
||||
creation. It ensures that widgets are properly added to `qtbot`, which manages their lifecycle during tests. We
|
||||
highly recommend using this function to create widgets in your tests to ensure proper cleanup and compatibility with
|
||||
other `autouse` fixtures.
|
||||
|
||||
```{note}
|
||||
These fixtures are automatically applied to all tests within the `tests/unit_tests` directory, ensuring consistency and proper cleanup between tests. You can find all unit test fixtures in the `conftest.py` file located in the `tests/unit_tests` directory of the BEC Widgets repository.
|
||||
|
||||
```
|
||||
|
||||
````{dropdown} View code: Conftest with Fixtures
|
||||
:icon: code-square
|
||||
:animate: fade-in-slide-down
|
||||
```{literalinclude} ../../../tests/unit_tests/conftest.py
|
||||
:language: python
|
||||
```
|
||||
````
|
||||
|
||||
## Example Test for `PositionerBox`
|
||||
|
||||
Below is an example of how to write a simple test for the [`PositionerBox`](user.widgets.positioner_box) widget,
|
||||
utilizing the fixtures mentioned above:
|
||||
|
||||
````{dropdown} View code: PositionerBox Widget Unit Tests
|
||||
:icon: code-square
|
||||
:animate: fade-in-slide-down
|
||||
```{literalinclude} ../../../tests/unit_tests/test_positioner_box.py
|
||||
:language: python
|
||||
```
|
||||
````
|
||||
|
||||
## Key Points in the Test:
|
||||
|
||||
- **Fixture Use**: The `positioner_box` fixture handles widget creation and mocking of external dependencies. This
|
||||
ensures the test runs in isolation and doesn't rely on actual hardware or network connections.
|
||||
|
||||
- **Assertion Checks**: The test includes several assertions to verify that the widget initializes correctly, including
|
||||
checking the setpoint, precision, and step size.
|
||||
|
||||
## Conclusion
|
||||
|
||||
By writing tests like the one shown above, you help ensure that your widget behaves as expected. Tests also provide a
|
||||
way to automatically verify that new changes do not introduce regressions. This is particularly important in a
|
||||
collaborative environment where multiple developers are contributing to the same codebase. Your tests not only safeguard
|
||||
your code but also provide confidence to others that their contributions won't break existing functionality.
|
||||
@@ -1,192 +0,0 @@
|
||||
(developer.widget_development.widget_base_class)=
|
||||
|
||||
# BECWidget Base Class
|
||||
|
||||
When developing new widgets, it is crucial to ensure seamless integration with the BEC system. This is achieved by using
|
||||
the [`BECWidget`](https://bec.readthedocs.io/projects/bec-widgets/en/latest/api_reference/_autosummary/bec_widgets.utils.bec_widget.BECWidget.html#bec_widgets.utils.bec_widget.BECWidget)
|
||||
base class, which provides essential functionalities and shortcuts to interact with various BEC services. In this
|
||||
tutorial, we will explore the importance of this base class, the role of
|
||||
the [`BECConnector`](https://bec.readthedocs.io/projects/bec-widgets/en/latest/api_reference/_autosummary/bec_widgets.utils.bec_connector.BECConnector.html#bec_widgets.utils.bec_connector.BECConnector)
|
||||
mixin, and how these components work together to facilitate the development of powerful and responsive widgets.
|
||||
|
||||
## Understanding the `BECWidget` Base Class
|
||||
|
||||
The [`BECWidget`](https://bec.readthedocs.io/projects/bec-widgets/en/latest/api_reference/_autosummary/bec_widgets.utils.bec_widget.BECWidget.html#bec_widgets.utils.bec_widget.BECWidget)
|
||||
base class is designed to serve as the foundation for all BEC-connected widgets. It ensures that your widget is properly
|
||||
integrated with the BEC system by providing:
|
||||
|
||||
1. **Connection to BEC Services**:
|
||||
[`BECWidget`](https://bec.readthedocs.io/projects/bec-widgets/en/latest/api_reference/_autosummary/bec_widgets.utils.bec_widget.BECWidget.html#bec_widgets.utils.bec_widget.BECWidget) includes the [`BECConnector`](https://bec.readthedocs.io/projects/bec-widgets/en/latest/api_reference/_autosummary/bec_widgets.utils.bec_connector.BECConnector.html#bec_widgets.utils.bec_connector.BECConnector)
|
||||
mixin, which handles all the necessary connections to BEC services such as the BEC server, device manager, scan
|
||||
control, and more.
|
||||
|
||||
2. **Qt Integration**:
|
||||
The [`BECWidget`](https://bec.readthedocs.io/projects/bec-widgets/en/latest/api_reference/_autosummary/bec_widgets.utils.bec_widget.BECWidget.html#bec_widgets.utils.bec_widget.BECWidget)
|
||||
base class also ensures that your widget is correctly integrated with Qt by requiring that it inherits from
|
||||
both [`BECWidget`](https://bec.readthedocs.io/projects/bec-widgets/en/latest/api_reference/_autosummary/bec_widgets.utils.bec_widget.BECWidget.html#bec_widgets.utils.bec_widget.BECWidget)
|
||||
and [`QWidget`](https://doc.qt.io/qtforpython-6/PySide6/QtWidgets/QWidget.html). This combination allows your widget
|
||||
to leverage the full power of Qt for creating rich user interfaces while staying connected to the BEC ecosystem.
|
||||
|
||||
3. **Configuration Management**: The base class provides a `ConnectionConfig` model (based on Pydantic) that helps
|
||||
manage and validate the configuration of your widget. This configuration can be easily serialized to and from Python
|
||||
dictionaries, JSON, or YAML formats, allowing for persistent storage and retrieval of widget states.
|
||||
|
||||
4. **RPC Registration**: Widgets derived
|
||||
from [`BECConnector`](https://bec.readthedocs.io/projects/bec-widgets/en/latest/api_reference/_autosummary/bec_widgets.utils.bec_connector.BECConnector.html#bec_widgets.utils.bec_connector.BECConnector)
|
||||
are automatically registered with
|
||||
the [`RPCRegister`](https://bec.readthedocs.io/projects/bec-widgets/en/latest/api_reference/_autosummary/bec_widgets.cli.rpc_register.RPCRegister.html#bec_widgets.cli.rpc_register.RPCRegister),
|
||||
enabling them to handle remote procedure calls (RPCs) efficiently. This allows the widget to be controlled remotely
|
||||
from the `BECIPythonClient` via CLI, providing powerful control and automation capabilities. For example, you can
|
||||
remotely adjust widget settings, start/stop operations, or query the widget’s status directly from the command line.
|
||||
|
||||
5. **Reacting to Theme Changes**: The base class provides a dedicated input flag to subscribe to theme changes, allowing
|
||||
your widget to adapt its appearance based on the current theme (e.g., light or dark mode) and can even synchronize with the user's OS settings. The widget-specific logic can then
|
||||
be implemented in the `apply_theme` method, which is called whenever the theme changes. This ensures a consistent user experience across different themes and environments.
|
||||
|
||||
Here’s a basic example of a widget inheriting
|
||||
from [`BECWidget`](https://bec.readthedocs.io/projects/bec-widgets/en/latest/api_reference/_autosummary/bec_widgets.utils.bec_widget.BECWidget.html#bec_widgets.utils.bec_widget.BECWidget):
|
||||
|
||||
```python
|
||||
from bec_widgets.utils.bec_widget import BECWidget
|
||||
from qtpy.QtWidgets import QWidget, QVBoxLayout
|
||||
|
||||
class MyWidget(BECWidget, QWidget):
|
||||
def __init__(self, parent=None, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs) # disable theme updates
|
||||
QWidget.__init__(self, parent=parent)
|
||||
self.get_bec_shortcuts() # Initialize BEC shortcuts
|
||||
self.init_ui()
|
||||
|
||||
def init_ui(self):
|
||||
layout = QVBoxLayout(self)
|
||||
# Add more UI components here
|
||||
self.setLayout(layout)
|
||||
|
||||
|
||||
# To enable theme updates, set theme_update=True, e.g.:
|
||||
|
||||
class MyDynamicWidget(BECWidget, QWidget):
|
||||
def __init__(self, parent=None, *args, **kwargs):
|
||||
super().__init__(*args, theme_update=True, **kwargs) # enable theme updates
|
||||
QWidget.__init__(self, parent=parent)
|
||||
self.get_bec_shortcuts() # Initialize BEC shortcuts
|
||||
self.init_ui()
|
||||
|
||||
def init_ui(self):
|
||||
layout = QVBoxLayout(self)
|
||||
# Add more UI components here
|
||||
self.setLayout(layout)
|
||||
|
||||
def apply_theme(self, theme):
|
||||
# Implement theme-specific logic here
|
||||
pass
|
||||
|
||||
```
|
||||
|
||||
### The Role of `BECConnector`
|
||||
|
||||
At the heart
|
||||
of [`BECWidget`](https://bec.readthedocs.io/projects/bec-widgets/en/latest/api_reference/_autosummary/bec_widgets.utils.bec_widget.BECWidget.html#bec_widgets.utils.bec_widget.BECWidget)
|
||||
is
|
||||
the [`BECConnector`](https://bec.readthedocs.io/projects/bec-widgets/en/latest/api_reference/_autosummary/bec_widgets.utils.bec_connector.BECConnector.html#bec_widgets.utils.bec_connector.BECConnector)
|
||||
mixin, which plays a crucial role in managing the connection between your widget and the BEC system.
|
||||
The [`BECConnector`](https://bec.readthedocs.io/projects/bec-widgets/en/latest/api_reference/_autosummary/bec_widgets.utils.bec_connector.BECConnector.html#bec_widgets.utils.bec_connector.BECConnector)
|
||||
provides several key functionalities:
|
||||
|
||||
1. **Client Initialization**: It initializes a `BECClient` instance if one isn't provided, ensuring your widget is
|
||||
connected to the BEC server. This client is central to all interactions with the BEC system.
|
||||
|
||||
2. **Task Management**:
|
||||
The [`submit_task`](https://bec.readthedocs.io/projects/bec-widgets/en/latest/api_reference/_autosummary/bec_widgets.utils.bec_connector.BECConnector.html#bec_widgets.utils.bec_connector.BECConnector.submit_task)
|
||||
method allows for running tasks in separate threads, preventing long-running operations from blocking the main UI
|
||||
thread.
|
||||
|
||||
3. **Configuration Handling
|
||||
**: [`BECConnector`](https://bec.readthedocs.io/projects/bec-widgets/en/latest/api_reference/_autosummary/bec_widgets.utils.bec_connector.BECConnector.html#bec_widgets.utils.bec_connector.BECConnector)
|
||||
uses the `ConnectionConfig` model to manage the widget’s configuration, ensuring all parameters are validated and
|
||||
properly set up.
|
||||
|
||||
4. **RPC Registration**: Widgets are registered with
|
||||
the [`RPCRegister`](https://bec.readthedocs.io/projects/bec-widgets/en/latest/api_reference/_autosummary/bec_widgets.cli.rpc_register.RPCRegister.html#bec-widgets-cli-rpc-register-rpcregister),
|
||||
allowing them to handle remote procedure calls effectively.
|
||||
|
||||
5. **Error Handling**: It includes utilities for handling errors gracefully within the Qt environment, ensuring that
|
||||
issues are reported to the user without crashing the application.
|
||||
|
||||
### Utilizing `get_bec_shortcuts`
|
||||
|
||||
One of the most powerful features of
|
||||
the [`BECConnector`](https://bec.readthedocs.io/projects/bec-widgets/en/latest/api_reference/_autosummary/bec_widgets.utils.bec_connector.BECConnector.html#bec_widgets.utils.bec_connector.BECConnector)
|
||||
is the `get_bec_shortcuts` method. This method provides your widget with direct access to essential components of the
|
||||
BEC system through convenient shortcuts:
|
||||
|
||||
1. **Device Manager (`self.dev`)**:
|
||||
- Access all devices registered with the BEC system. You can interact with devices, retrieve their status, and send
|
||||
commands directly through this shortcut.
|
||||
```python
|
||||
# Moves 'motor1' to position 10
|
||||
self.dev["motor1"].move(10)
|
||||
```
|
||||
|
||||
2. **Scan Control (`self.scans`)**:
|
||||
- Control scans, initiate new ones, monitor progress, and manage their execution.
|
||||
```python
|
||||
# Starts Line Scan from -10 to 10 in samx and -5 to 5 in samy
|
||||
self.scans.line_scan(self.dev.samx,-10,10,self.dev.samy,-5,5, steps=100, exp_time=0.001,relative=False)
|
||||
```
|
||||
|
||||
3. **Queue Management (`self.queue`)**:
|
||||
- Manage the BEC scan queue, such as adding scans, checking status, or removing scans.
|
||||
```python
|
||||
# Request abortion of the current scan queue
|
||||
self.queue.request_scan_abortion()
|
||||
```
|
||||
|
||||
4. **Scan Storage (`self.scan_storage`)**:
|
||||
- Access stored scan data for retrieval and analysis.
|
||||
```python
|
||||
# Retrieve scan item for a specific scan ID
|
||||
self.scan_item = self.queue.scan_storage.find_scan_by_ID(self.scan_id)
|
||||
```
|
||||
|
||||
5. **Full BECClient Access (`self.client`)**:
|
||||
- Direct access to the BECClient instance, allowing for additional functionalities not covered by the shortcuts.
|
||||
```python
|
||||
# Shutdown the BECClient
|
||||
self.client.shutdown()
|
||||
```
|
||||
|
||||
### Example: [`PositionerBox`](user.widgets.positioner_box) Widget
|
||||
|
||||
Let’s look at an example of a widget that leverages
|
||||
the [`BECWidget`](https://bec.readthedocs.io/projects/bec-widgets/en/latest/api_reference/_autosummary/bec_widgets.utils.bec_widget.BECWidget.html#bec_widgets.utils.bec_widget.BECWidget)
|
||||
base class and `get_bec_shortcuts`:
|
||||
|
||||
````{dropdown} View code: PositionerBox Widget
|
||||
:icon: code-square
|
||||
:animate: fade-in-slide-down
|
||||
```{literalinclude} ../../../bec_widgets/widgets/positioner_box/positioner_box.py
|
||||
:language: python
|
||||
:pyobject: PositionerBox
|
||||
```
|
||||
````
|
||||
|
||||
In this widget:
|
||||
|
||||
- **Device Interaction**: The widget uses `self.dev` to interact with a positioner device, reading its state and
|
||||
updating the UI accordingly.
|
||||
|
||||
- **Scan and Queue Control**: Although not shown in this example, the widget could easily use `self.scans`
|
||||
and `self.queue` to manage scans related to the positioner or queue up new operations.
|
||||
|
||||
### Conclusion
|
||||
|
||||
The `BECWidget` base class and the `BECConnector` mixin are foundational components for creating widgets that seamlessly
|
||||
integrate with the BEC system. By inheriting from `BECWidget`, you gain access to powerful connection management, task
|
||||
handling, and configuration capabilities, as well as shortcuts that make interacting with BEC services straightforward
|
||||
and efficient.
|
||||
|
||||
By leveraging these tools, you can focus on building the core functionality of your widget, confident that the
|
||||
complexities of BEC integration are handled robustly and efficiently. In the next tutorial we will demonstrate
|
||||
step-by-step how to create a custom widget using the `BECWidget` base class and explore advanced features for creating
|
||||
responsive and interactive user interfaces.
|
||||
@@ -1,56 +0,0 @@
|
||||
(developer.widget_development)=
|
||||
|
||||
# Widget Development
|
||||
This section provides an introduction to the building blocks of BEC Widgets: widgets. Widgets are the basic components of the graphical user interface (GUI) and are used to create larger applications. We will cover key topics such as how to develop new widgets or how to customise existing widgets. For details on the already available widgets and their usage, please refer to user section about [widgets](#user.widgets).
|
||||
|
||||
To facilitate the development of new widgets, integrated into the BEC framework, we provide two main base classes: `BECWidget` and its parent class `BECDispatcher`. The `BECDispatcher` class is responsible for managing the communication between widgets and the BEC framework. The `BECWidget` class is the base class for all widgets and provides the basic functionality for creating and managing widgets. Leveraging these classes, you can rapidly develop new widgets that are responsive and interactive.
|
||||
|
||||
A very simple "Hello World" example of a widget can be seen below:
|
||||
|
||||
````{dropdown} View code: Hello World Widget
|
||||
:icon: code-square
|
||||
:animate: fade-in-slide-down
|
||||
|
||||
```python
|
||||
from qtpy.QtWidgets import QLabel, QWidget
|
||||
|
||||
from bec_widgets.utils.bec_widget import BECWidget
|
||||
|
||||
|
||||
class HelloWorldWidget(BECWidget, QWidget):
|
||||
def __init__(
|
||||
self, parent: QWidget | None = None, client=None, gui_id: str | None = None, **kwargs
|
||||
) -> None:
|
||||
# Initialize base classes
|
||||
super().__init__(parent=parent, client=client, gui_id=gui_id, **kwargs)
|
||||
|
||||
self.label = QLabel(self)
|
||||
self.label.setText("Hello World")
|
||||
|
||||
|
||||
# Run the widget as a standalone application
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
|
||||
from qtpy.QtWidgets import QApplication
|
||||
|
||||
app = QApplication(sys.argv)
|
||||
w = HelloWorldWidget()
|
||||
w.show()
|
||||
sys.exit(app.exec_())
|
||||
```
|
||||
````
|
||||
|
||||
The following sections will provide more details on how to develop new widgets and how to leverage the `BECDispatcher` and `BECWidget` classes to create interactive and responsive widgets.
|
||||
|
||||
```{toctree}
|
||||
---
|
||||
maxdepth: 2
|
||||
hidden: false
|
||||
---
|
||||
|
||||
bec_dispatcher
|
||||
widget_base_class
|
||||
widget_tutorial
|
||||
tutorial_tests
|
||||
```
|
||||
@@ -1,243 +0,0 @@
|
||||
(developer.widget_development.widget_tutorial)=
|
||||
|
||||
# Tutorial: Creating a New BEC-Connected Widget
|
||||
|
||||
In this tutorial, we'll create a BEC-connected widget that allows you to control a motor by setting its position. The
|
||||
widget will demonstrate how to retrieve data from BEC, prompt an action in BEC (like moving a motor), and expose an RPC
|
||||
interface for remote control. By the end of this tutorial, you'll have a functional widget that can interact with the
|
||||
BEC system both through a graphical interface and via command-line control.
|
||||
|
||||
We'll break the tutorial into the following steps:
|
||||
|
||||
1. **Creating the Basic Widget Layout**: We’ll design a simple UI with a `QLabel`, `QDoubleSpinBox`, and
|
||||
a `QPushButton`.
|
||||
2. **Connecting to BEC**: We’ll integrate our widget with the BEC system using
|
||||
the [`BECWidget`](https://bec.readthedocs.io/projects/bec-widgets/en/latest/api_reference/_autosummary/bec_widgets.utils.bec_widget.BECWidget.html#bec_widgets.utils.bec_widget.BECWidget)
|
||||
base class
|
||||
and [`BECDispatcher`](https://bec.readthedocs.io/projects/bec-widgets/en/latest/api_reference/_autosummary/bec_widgets.utils.bec_dispatcher.BECDispatcher.html#bec_widgets.utils.bec_dispatcher.BECDispatcher).
|
||||
3. **Implementing RPC for Remote Control**: We’ll set up an RPC interface to allow remote control of the widget via CLI.
|
||||
4. **Running the Widget**: We’ll create a small script to run the widget in a `QApplication`.
|
||||
|
||||
## Step 1: Creating the Basic Widget Layout
|
||||
|
||||
First, let's start by creating the basic layout of our widget. We’ll add a `QLabel` to display the current coordinates
|
||||
of the motor, a `QDoubleSpinBox` to input the desired coordinates, and a `QPushButton` to initiate the motor movement.
|
||||
|
||||
```python
|
||||
from qtpy.QtWidgets import QWidget, QLabel, QDoubleSpinBox, QPushButton, QVBoxLayout
|
||||
|
||||
|
||||
class MotorControlWidget(QWidget):
|
||||
def __init__(self, parent=None, motor_name: str = ""):
|
||||
super().__init__(parent)
|
||||
|
||||
self.motor_name = motor_name
|
||||
|
||||
# Initialize UI elements
|
||||
self.label_top = QLabel("Current Position:", self)
|
||||
self.label = QLabel(f"{self.motor_name} - N/A", self)
|
||||
self.spin_box = QDoubleSpinBox(self)
|
||||
self.spin_box.setRange(-10000, 10000)
|
||||
self.spin_box.setDecimals(3)
|
||||
self.spin_box.setSingleStep(0.1)
|
||||
|
||||
self.move_button = QPushButton("Move Motor", self)
|
||||
|
||||
# Set up the layout
|
||||
layout = QVBoxLayout(self)
|
||||
layout.addWidget(self.label_top)
|
||||
layout.addWidget(self.label)
|
||||
layout.addWidget(self.spin_box)
|
||||
layout.addWidget(self.move_button)
|
||||
self.setLayout(layout)
|
||||
|
||||
# Connect button click to move motor
|
||||
self.move_button.clicked.connect(self.move_motor)
|
||||
|
||||
def move_motor(self):
|
||||
# Placeholder method for motor movement
|
||||
print(f"Moving motor {self.motor_name} to {self.spin_box.value()}")
|
||||
```
|
||||
|
||||
## Step 2: Connecting to BEC
|
||||
|
||||
Now that we have the basic layout, let's connect our widget to the BEC system using
|
||||
the [`BECWidget`](https://bec.readthedocs.io/projects/bec-widgets/en/latest/api_reference/_autosummary/bec_widgets.utils.bec_widget.BECWidget.html#bec_widgets.utils.bec_widget.BECWidget)
|
||||
base class
|
||||
and [`BECDispatcher`](https://bec.readthedocs.io/projects/bec-widgets/en/latest/api_reference/_autosummary/bec_widgets.utils.bec_dispatcher.BECDispatcher.html#bec_widgets.utils.bec_dispatcher.BECDispatcher).
|
||||
We’ll modify the widget to inherit
|
||||
from [`BECWidget`](https://bec.readthedocs.io/projects/bec-widgets/en/latest/api_reference/_autosummary/bec_widgets.utils.bec_widget.BECWidget.html#bec_widgets.utils.bec_widget.BECWidget),
|
||||
pass the motor name to the widget, and use `get_bec_shortcuts` to access BEC services.
|
||||
|
||||
```python
|
||||
from bec_lib.endpoints import MessageEndpoints
|
||||
from qtpy.QtWidgets import QDoubleSpinBox, QLabel, QPushButton, QVBoxLayout, QWidget
|
||||
|
||||
from bec_widgets.utils.bec_widget import BECWidget
|
||||
from bec_widgets.utils.error_popups import SafeSlot
|
||||
|
||||
|
||||
class MotorControlWidget(BECWidget, QWidget):
|
||||
|
||||
def __init__(self, parent=None, motor_name: str = "", **kwargs):
|
||||
super().__init__(parent=parent, **kwargs)
|
||||
|
||||
self.motor_name = motor_name
|
||||
|
||||
# Initialize BEC shortcuts
|
||||
self.get_bec_shortcuts()
|
||||
|
||||
# Initialize UI elements
|
||||
self.label_top = QLabel(f"Current Position:", self)
|
||||
self.label = QLabel(f"{self.motor_name} - N/A", self)
|
||||
self.spin_box = QDoubleSpinBox(self)
|
||||
self.spin_box.setRange(-10000, 10000)
|
||||
self.spin_box.setDecimals(3)
|
||||
self.spin_box.setSingleStep(0.1)
|
||||
|
||||
self.move_button = QPushButton("Move Motor", self)
|
||||
|
||||
# Set up the layout
|
||||
layout = QVBoxLayout(self)
|
||||
layout.addWidget(self.label_top)
|
||||
layout.addWidget(self.label)
|
||||
layout.addWidget(self.spin_box)
|
||||
layout.addWidget(self.move_button)
|
||||
self.setLayout(layout)
|
||||
|
||||
# Connect button click to move motor
|
||||
self.move_button.clicked.connect(self.move_motor)
|
||||
|
||||
# Register BECDispatcher to listen for motor position updates
|
||||
self.bec_dispatcher.connect_slot(
|
||||
self.on_motor_update, MessageEndpoints.device_readback(self.motor_name)
|
||||
)
|
||||
|
||||
@SafeSlot()
|
||||
def move_motor(self):
|
||||
target_position = self.spin_box.value()
|
||||
self.dev[self.motor_name].move(target_position)
|
||||
print(f"Commanding motor {self.motor_name} to move to {target_position}")
|
||||
|
||||
@SafeSlot(dict, dict)
|
||||
def on_motor_update(self, msg_content, metadata):
|
||||
position = msg_content.get("signals", {}).get(self.motor_name, {}).get("value", "N/A")
|
||||
self.label.setText(f"{self.motor_name} : {round(position, 2)}")
|
||||
```
|
||||
|
||||
## Step 3: Implementing RPC for Remote Control
|
||||
|
||||
Next, we’ll set up an RPC interface to allow remote control of the widget from the command line via
|
||||
the `BECIPythonClient`. We’ll expose a method that allows changing the motor name through CLI commands.
|
||||
|
||||
```python
|
||||
from bec_lib.endpoints import MessageEndpoints
|
||||
from qtpy.QtWidgets import QDoubleSpinBox, QLabel, QPushButton, QVBoxLayout, QWidget
|
||||
|
||||
from bec_widgets.utils.bec_widget import BECWidget
|
||||
from bec_widgets.utils.error_popups import SafeSlot
|
||||
|
||||
|
||||
class MotorControlWidget(BECWidget, QWidget):
|
||||
USER_ACCESS = ["change_motor"]
|
||||
|
||||
def __init__(self, parent=None, motor_name: str = "", **kwargs):
|
||||
super().__init__(parent=parent, **kwargs)
|
||||
|
||||
self.motor_name = motor_name
|
||||
|
||||
# Initialize BEC shortcuts
|
||||
self.get_bec_shortcuts()
|
||||
|
||||
# Initialize UI elements
|
||||
self.label_top = QLabel(f"Current Position:", self)
|
||||
self.label = QLabel(f"{self.motor_name} - N/A", self)
|
||||
self.spin_box = QDoubleSpinBox(self)
|
||||
self.spin_box.setRange(-10000, 10000)
|
||||
self.spin_box.setDecimals(3)
|
||||
self.spin_box.setSingleStep(0.1)
|
||||
|
||||
self.move_button = QPushButton("Move Motor", self)
|
||||
|
||||
# Set up the layout
|
||||
layout = QVBoxLayout(self)
|
||||
layout.addWidget(self.label_top)
|
||||
layout.addWidget(self.label)
|
||||
layout.addWidget(self.spin_box)
|
||||
layout.addWidget(self.move_button)
|
||||
self.setLayout(layout)
|
||||
|
||||
# Connect button click to move motor
|
||||
self.move_button.clicked.connect(self.move_motor)
|
||||
|
||||
# Register BECDispatcher to listen for motor position updates
|
||||
self.bec_dispatcher.connect_slot(
|
||||
self.on_motor_update, MessageEndpoints.device_readback(self.motor_name)
|
||||
)
|
||||
|
||||
@SafeSlot()
|
||||
def move_motor(self):
|
||||
target_position = self.spin_box.value()
|
||||
self.dev[self.motor_name].move(target_position)
|
||||
print(f"Commanding motor {self.motor_name} to move to {target_position}")
|
||||
|
||||
@SafeSlot(dict, dict)
|
||||
def on_motor_update(self, msg_content, metadata):
|
||||
position = msg_content.get("signals", {}).get(self.motor_name, {}).get("value", "N/A")
|
||||
self.label.setText(f"{self.motor_name} : {round(position, 2)}")
|
||||
|
||||
def change_motor(self, motor_name):
|
||||
"""RPC method to change the motor being controlled."""
|
||||
# Disconnect from previous motor
|
||||
self.bec_dispatcher.disconnect_slot(
|
||||
self.on_motor_update, MessageEndpoints.device_readback(self.motor_name)
|
||||
)
|
||||
# Update motor name and reconnect to new motor
|
||||
self.motor_name = motor_name
|
||||
self.label.setText(f"{self.motor_name} - N/A")
|
||||
self.bec_dispatcher.connect_slot(
|
||||
self.on_motor_update, MessageEndpoints.device_readback(self.motor_name)
|
||||
)
|
||||
```
|
||||
|
||||
```{warning}
|
||||
After implementing an RPC method, you must run the `bw-generate-cli --target <your plugin repo name>` script to update the CLI commands for `BECIPythonClient`, e.g. `bw-generate-cli --target csaxs_bec`. This script generates the necessary command-line interface bindings, ensuring that your RPC method can be accessed and controlled remotely.
|
||||
```
|
||||
|
||||
```{note}
|
||||
In this tutorial, we used the @SafeSlot decorator from BEC Widgets to mark methods as slots for signals. This decorator ensures that the connected methods are treated as slots by the Qt framework, which can be connected to signals. It’s a best practice to use the @SafeSlot decorator to clearly indicate which methods are intended to handle signal events with correct argument signatures. @SafeSlot also provides error handling and logging capabilities, making it more robust and easier to debug.
|
||||
```
|
||||
|
||||
## Step 4: Running the Widget
|
||||
|
||||
Finally, let’s create a script to run our widget within a `QApplication`. This script can be used to test the widget
|
||||
independently. You can pass different motor names to control different motors using the same widget class.
|
||||
|
||||
```python
|
||||
import sys
|
||||
from qtpy.QtWidgets import QApplication
|
||||
|
||||
if __name__ == "__main__":
|
||||
app = QApplication(sys.argv)
|
||||
widget = MotorControlWidget(motor_name='samx')
|
||||
widget.show()
|
||||
sys.exit(app.exec_())
|
||||
```
|
||||
|
||||
## Conclusion
|
||||
|
||||
In this tutorial, we've created a BEC-connected widget that allows you to control a motor. We started by designing the
|
||||
UI, then connected it to the BEC system using
|
||||
the [`BECWidget`](https://bec.readthedocs.io/projects/bec-widgets/en/latest/api_reference/_autosummary/bec_widgets.utils.bec_widget.BECWidget.html#bec_widgets.utils.bec_widget.BECWidget)
|
||||
base class
|
||||
and [`BECDispatcher`](https://bec.readthedocs.io/projects/bec-widgets/en/latest/api_reference/_autosummary/bec_widgets.utils.bec_dispatcher.BECDispatcher.html#bec_widgets.utils.bec_dispatcher.BECDispatcher).
|
||||
We also implemented an RPC interface, allowing remote control of the widget through the CLI. Finally, we tested our
|
||||
widget by running it in a `QApplication`.
|
||||
|
||||
This widget demonstrates a simplified version of the [`PositionerBox`](user.widgets.positioner_box), showcasing the
|
||||
power and flexibility of
|
||||
the [`BECWidget`](https://bec.readthedocs.io/projects/bec-widgets/en/latest/api_reference/_autosummary/bec_widgets.utils.bec_widget.BECWidget.html#bec_widgets.utils.bec_widget.BECWidget)
|
||||
base class
|
||||
and [`BECDispatcher`](https://bec.readthedocs.io/projects/bec-widgets/en/latest/api_reference/_autosummary/bec_widgets.utils.bec_dispatcher.BECDispatcher.html#bec_widgets.utils.bec_dispatcher.BECDispatcher),
|
||||
making it easy to integrate with the BEC system and enabling robust, interactive control of devices directly from the
|
||||
GUI or the command line.
|
||||
@@ -1,74 +0,0 @@
|
||||
:html_theme.sidebar_secondary.remove:
|
||||
|
||||
# BEC Widgets documentation
|
||||
|
||||
A flexible and extensible framework for building graphical user interfaces in Python, optimized for use in the BEC environment.
|
||||
|
||||
<br><br>
|
||||
|
||||
````{grid} 2
|
||||
:gutter: 5
|
||||
|
||||
```{grid-item-card}
|
||||
:link: introduction
|
||||
:link-type: ref
|
||||
:img-top: /assets/index_getting_started.svg
|
||||
:text-align: center
|
||||
:class-item: index-card
|
||||
|
||||
## Introduction
|
||||
|
||||
General information about BEC Widgets.
|
||||
```
|
||||
|
||||
```{grid-item-card}
|
||||
:link: user
|
||||
:link-type: ref
|
||||
:img-top: /assets/index_user_guide.svg
|
||||
:text-align: center
|
||||
:class-item: index-card
|
||||
|
||||
## User guide
|
||||
|
||||
Information for users of BEC Widgets.
|
||||
```
|
||||
|
||||
```{grid-item-card}
|
||||
:link: developer
|
||||
:link-type: ref
|
||||
:img-top: /assets/index_contribute.svg
|
||||
:text-align: center
|
||||
:class-item: index-card
|
||||
|
||||
## Developer guide
|
||||
|
||||
Information for developers of BEC Widgets.
|
||||
```
|
||||
|
||||
```{grid-item-card}
|
||||
:link: api_reference
|
||||
:link-type: ref
|
||||
:img-top: /assets/index_api.svg
|
||||
:text-align: center
|
||||
:class-item: index-card
|
||||
|
||||
## API reference
|
||||
|
||||
Comprehensive reference of all BEC Widget classes, functions, and methods.
|
||||
```
|
||||
|
||||
````
|
||||
|
||||
|
||||
```{toctree}
|
||||
---
|
||||
numbered: true
|
||||
maxdepth: 2
|
||||
hidden: true
|
||||
---
|
||||
|
||||
introduction/introduction
|
||||
user/user
|
||||
developer/developer
|
||||
api_reference/api_reference
|
||||
```
|
||||
@@ -1,18 +0,0 @@
|
||||
(introduction)=
|
||||
# Introduction
|
||||
|
||||
## Overview
|
||||
|
||||
BEC Widgets is a GUI framework developed with beamline scientists in mind, aiming to provide a modern and modular environment for interacting with experiments. This package offers a suite of widgets specifically designed to enhance the workflow of beamline experiments, including features for running scans and data visualization.
|
||||
|
||||
Targeting the unique needs of beamline scientists, BEC Widgets stands out with its modular approach to widget design and high customizability. This flexibility allows for tailored solutions that meet the specific requirements of each beamline.
|
||||
|
||||
**Key Features**:
|
||||
|
||||
- **Integration:** Seamlessly integrates with [BEC (Beamline Experiment Control)](https://gitlab.psi.ch/bec/bec), ensuring a cohesive and efficient experiment control experience.
|
||||
- **Support for Pyside6 and PyQt6:** Provides compatibility with both Pyside6 and PyQt6, offering versatility in your development environment.
|
||||
- **Widget Modularity:** Features modular widgets that can be easily combined to create customized applications, perfectly aligning with the diverse needs of beamline experiments.
|
||||
|
||||
## Getting Started
|
||||
|
||||
For detailed usage instructions and examples showcasing the practical applications of BEC Widgets, please refer to the [User](#user) section. Developers interested in contributing or customizing BEC Widgets can find more information in the [Developer](#developer) section.
|
||||
@@ -1,35 +0,0 @@
|
||||
@ECHO OFF
|
||||
|
||||
pushd %~dp0
|
||||
|
||||
REM Command file for Sphinx documentation
|
||||
|
||||
if "%SPHINXBUILD%" == "" (
|
||||
set SPHINXBUILD=sphinx-build
|
||||
)
|
||||
set SOURCEDIR=.
|
||||
set BUILDDIR=_build
|
||||
|
||||
%SPHINXBUILD% >NUL 2>NUL
|
||||
if errorlevel 9009 (
|
||||
echo.
|
||||
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
|
||||
echo.installed, then set the SPHINXBUILD environment variable to point
|
||||
echo.to the full path of the 'sphinx-build' executable. Alternatively you
|
||||
echo.may add the Sphinx directory to PATH.
|
||||
echo.
|
||||
echo.If you don't have Sphinx installed, grab it from
|
||||
echo.https://www.sphinx-doc.org/
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
if "%1" == "" goto help
|
||||
|
||||
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
|
||||
goto end
|
||||
|
||||
:help
|
||||
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
|
||||
|
||||
:end
|
||||
popd
|
||||
@@ -1,11 +0,0 @@
|
||||
sphinx
|
||||
sphinx_copybutton
|
||||
recommonmark
|
||||
sphinx-toolbox
|
||||
pydata-sphinx-theme
|
||||
sphinx-copybutton
|
||||
sphinx-inline-tabs
|
||||
myst-parser
|
||||
sphinx-design
|
||||
sphinx-autoapi
|
||||
tomli
|
||||
@@ -1,10 +0,0 @@
|
||||
(user.api_reference)=
|
||||
# User API Reference
|
||||
|
||||
This section contains the API documentation for the main user-facing modules and classes.
|
||||
|
||||
```{toctree}
|
||||
:maxdepth: 2
|
||||
|
||||
../../autoapi/bec_widgets/cli/index
|
||||
```
|
||||
@@ -1,10 +0,0 @@
|
||||
(user.applications)=
|
||||
# Applications
|
||||
|
||||
**Coming soon**
|
||||
|
||||
```{toctree}
|
||||
---
|
||||
maxdepth: 1
|
||||
hidden: true
|
||||
---
|
||||
@@ -1,123 +0,0 @@
|
||||
(user.customisation)=
|
||||
# Customisation
|
||||
|
||||
## Leveraging BEC Widgets in custom GUI applications
|
||||
|
||||
BEC Widgets can be used to compose a complete Qt graphical application, along with
|
||||
other QWidgets. The only requirement is to connect to BEC servers in order to get
|
||||
data, or to interact with BEC components. This role is devoted to the BECDispatcher,
|
||||
a singleton object which has to be instantiated **after the QApplication is created**.
|
||||
|
||||
A typical BEC Widgets custom application "main" entry point should follow the template
|
||||
below:
|
||||
|
||||
```
|
||||
import argparse
|
||||
import sys
|
||||
|
||||
from bec_widgets.utils.bec_dispatcher import BECDispatcher
|
||||
from qtpy.QtWidgets import QApplication
|
||||
|
||||
# optional command line arguments processing
|
||||
parser = argparse.ArgumentParser(description="...")
|
||||
parser.add_argument( ...)
|
||||
...
|
||||
args = parser.parse_args()
|
||||
|
||||
# creation of the Qt application
|
||||
app = QApplication([])
|
||||
|
||||
# creation of BEC Dispatcher
|
||||
# /!\ important: after the QApplication has been instantiated
|
||||
bec_dispatcher = BECDispatcher()
|
||||
client = bec_dispatcher.client
|
||||
client.start()
|
||||
|
||||
# (optional) processing of command line args,
|
||||
# creation of a main window depending on the command line arguments (or not)
|
||||
if args.xxx == "...":
|
||||
window = ...
|
||||
|
||||
# display of the main window and start of Qt event loop
|
||||
window.show()
|
||||
sys.exit(app.exec())
|
||||
```
|
||||
|
||||
The main "window" object presents the layout of widgets to the user and allows
|
||||
users to interact. BEC Widgets must be placed in the window:
|
||||
|
||||
```
|
||||
from qtpy.QWidgets import QMainWindow
|
||||
from bec_widgets.widgets.figure import BECFigure
|
||||
|
||||
window = QMainWindow()
|
||||
bec_figure = BECFigure(gui_id="my_gui_app_id")
|
||||
window.setCentralWidget(bec_figure)
|
||||
|
||||
# prepare to plot samx motor vs bpm4i value
|
||||
bec_figure.plot(device_x="samx", device_y="bpm4i")
|
||||
```
|
||||
|
||||
In the example just above, the resulting application will show a plot of samx
|
||||
positions on the horizontal axis, and beam intensity on the vertical axis
|
||||
(when the next scan will be started).
|
||||
|
||||
It is important to ensure proper cleanup of the resources is done when application
|
||||
quits:
|
||||
|
||||
```
|
||||
def final_cleanup():
|
||||
bec_figure.clear_all()
|
||||
bec_figure.client.shutdown()
|
||||
|
||||
window.aboutToQuit.connect(final_cleanup)
|
||||
```
|
||||
|
||||
Final example:
|
||||
|
||||
```
|
||||
import sys
|
||||
from qtpy.QtWidgets import QMainWindow, QApplication
|
||||
from bec_widgets.widgets.figure import BECFigure
|
||||
from bec_widgets.utils.bec_dispatcher import BECDispatcher
|
||||
|
||||
# creation of the Qt application
|
||||
app = QApplication([])
|
||||
|
||||
# creation of BEC Dispatcher
|
||||
bec_dispatcher = BECDispatcher()
|
||||
client = bec_dispatcher.client
|
||||
client.start()
|
||||
|
||||
# creation of main window
|
||||
window = QMainWindow()
|
||||
|
||||
# inserting BEC Widgets
|
||||
bec_figure = BECFigure(parent=window, gui_id="my_gui_app_id")
|
||||
window.setCentralWidget(bec_figure)
|
||||
|
||||
bec_figure.plot(device_x="samx", device_y="bpm4i")
|
||||
|
||||
# ensuring proper cleanup
|
||||
def final_cleanup():
|
||||
bec_figure.clear_all()
|
||||
bec_figure.client.shutdown()
|
||||
|
||||
app.aboutToQuit.connect(final_cleanup)
|
||||
|
||||
# execution
|
||||
window.show()
|
||||
sys.exit(app.exec())
|
||||
```
|
||||
|
||||
## Writing applications using BEC Designer
|
||||
|
||||
BEC Widgets are designed to be used with BEC Designer to quickly design GUI.
|
||||
|
||||
## Example of promoting widgets in BEC Designer
|
||||
|
||||
_Work in progress_
|
||||
|
||||
## Implementation of plugins into BEC Designer
|
||||
|
||||
_Work in progress_
|
||||
|
Before Width: | Height: | Size: 2.0 MiB |
@@ -1,129 +0,0 @@
|
||||
(user.auto_updates)=
|
||||
# Auto updates
|
||||
BEC Widgets provides a simple way to update the entire GUI configuration based on events. These events can be of different types, such as a new scan being started or completed, a button being pressed, a device reporting an error or the existence of a specific metadata key. This allows the users to streamline the experience of the GUI and to focus on the data and the analysis, rather than on the GUI itself.
|
||||
|
||||
The auto update widget can be launched through the BEC launcher:
|
||||
|
||||

|
||||
|
||||
The auto update's launch tile also provides a combo box to select the specific auto update to be launched. These options are automatically populated with all available auto updates from a plugin repository and the default auto update.
|
||||
|
||||
Once the proper auto update is selected and launched, the CLI will automatically add a new entry to the `gui` object.
|
||||
|
||||
The default auto update only provides a simple handler that switches between `line_scan`, `grid_scan` and `best_effort`. More details can be found in the following snippet.
|
||||
|
||||
````{dropdown} Auto Updates Handler
|
||||
:icon: code-square
|
||||
:animate: fade-in-slide-down
|
||||
:open:
|
||||
```{literalinclude} ../../../bec_widgets/widgets/containers/auto_update/auto_updates.py
|
||||
:pyobject: AutoUpdates.on_scan_open
|
||||
```
|
||||
````
|
||||
|
||||
As shown, the default auto updates switches between different visualizations whenever a new scan is started. If the scan is a `line_scan`, the `simple_line_scan` update method is executed.
|
||||
|
||||
````{dropdown} Auto Updates Simple Line Scan
|
||||
:icon: code-square
|
||||
:animate: fade-in-slide-down
|
||||
:open:
|
||||
```{literalinclude} ../../../bec_widgets/widgets/containers/auto_update/auto_updates.py
|
||||
:pyobject: AutoUpdates.simple_line_scan
|
||||
```
|
||||
````
|
||||
|
||||
As can be seen from the above snippet, the update method changes the dock to a specific widget, in this case to a waveform widget. After selecting the device for the x axis, the y axis is retrieved from the list of monitored devices or from a user-specified `selected_device`.
|
||||
|
||||
The y axis can also be set by the user using the `selected_device` attribute:
|
||||
|
||||
```python
|
||||
gui.AutoUpdates.selected_device = 'bpm4i'
|
||||
```
|
||||
|
||||
|
||||
````{dropdown} Auto Updates Code
|
||||
:icon: code-square
|
||||
:animate: fade-in-slide-down
|
||||
```{literalinclude} ../../../bec_widgets/widgets/containers/auto_update/auto_updates.py
|
||||
```
|
||||
````
|
||||
|
||||
## Custom Auto Updates
|
||||
The beamline can customize their default behaviour through customized auto update classes. This can be achieved by adding an auto update class to the plugin repository: `<beamline_plugin>/bec_widgets/auto_updates/auto_updates.py`. The class must inherit from the `AutoUpdates` class.
|
||||
|
||||
An example of a custom auto update class `PXIIIUpdate` is shown below.
|
||||
|
||||
```{note}
|
||||
The code below is simply a copy of the default auto update class's 'GUI Callbacks' section. The user can modify any of the methods to suit their needs but we suggest to have a look at the 'GUI Callbacks' section and the 'Update Functions' section of the default auto update class to understand how to implement the custom auto update class.
|
||||
```
|
||||
|
||||
```python
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from bec_widgets.widgets.containers.auto_update.auto_updates import AutoUpdates
|
||||
|
||||
if TYPE_CHECKING: # pragma: no cover
|
||||
from bec_lib.messages import ScanStatusMessage
|
||||
|
||||
|
||||
class PXIIIUpdate(AutoUpdates):
|
||||
|
||||
#######################################################################
|
||||
################# GUI Callbacks #######################################
|
||||
#######################################################################
|
||||
|
||||
def on_start(self) -> None:
|
||||
"""
|
||||
Procedure to run when the auto updates are enabled.
|
||||
"""
|
||||
self.start_default_dock()
|
||||
|
||||
def on_stop(self) -> None:
|
||||
"""
|
||||
Procedure to run when the auto updates are disabled.
|
||||
"""
|
||||
|
||||
def on_scan_open(self, msg: ScanStatusMessage) -> None:
|
||||
"""
|
||||
Procedure to run when a scan starts.
|
||||
|
||||
Args:
|
||||
msg (ScanStatusMessage): The scan status message.
|
||||
"""
|
||||
if msg.scan_name == "line_scan" and msg.scan_report_devices:
|
||||
return self.simple_line_scan(msg)
|
||||
if msg.scan_name == "grid_scan" and msg.scan_report_devices:
|
||||
return self.simple_grid_scan(msg)
|
||||
if msg.scan_report_devices:
|
||||
return self.best_effort(msg)
|
||||
return None
|
||||
|
||||
def on_scan_closed(self, msg: ScanStatusMessage) -> None:
|
||||
"""
|
||||
Procedure to run when a scan ends.
|
||||
|
||||
Args:
|
||||
msg (ScanStatusMessage): The scan status message.
|
||||
"""
|
||||
|
||||
def on_scan_abort(self, msg: ScanStatusMessage) -> None:
|
||||
"""
|
||||
Procedure to run when a scan is aborted.
|
||||
|
||||
Args:
|
||||
msg (ScanStatusMessage): The scan status message.
|
||||
"""
|
||||
|
||||
```
|
||||
|
||||
|
||||
````{important}
|
||||
In order for the custom auto update method to be found, the class must be added to the `__init__.py` file of the `auto_updates` folder. This should be done already when the plugin repository is created but it is worth mentioning here. If not, the user can add the following line to the `__init__.py` file:
|
||||
```python
|
||||
from .auto_updates import *
|
||||
```
|
||||
````
|
||||
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
(user.getting_started)=
|
||||
# Getting Started
|
||||
This section provides a comprehensive guide to getting started with BEC Widgets. Whether you are new to BEC Widgets or looking to refresh your knowledge, this guide will help you set up and navigate the framework with ease.
|
||||
|
||||
```{toctree}
|
||||
---
|
||||
maxdepth: 2
|
||||
hidden: true
|
||||
---
|
||||
|
||||
installation/
|
||||
quick_start/
|
||||
auto_updates/
|
||||
video_tutorials/
|
||||
```
|
||||
|
Before Width: | Height: | Size: 6.2 MiB |
@@ -1,32 +0,0 @@
|
||||
(user.installation)=
|
||||
# Installation
|
||||
**Prerequisites**
|
||||
|
||||
Before installing BEC Widgets, please ensure the following requirements are met:
|
||||
|
||||
1. **Python Version:** BEC Widgets requires Python version 3.11 or higher. Verify your Python version to ensure compatibility.
|
||||
2. **BEC Installation:** BEC Widgets works in conjunction with BEC. While BEC is a dependency and will be installed automatically, you can find more information about BEC and its installation process in the [BEC documentation](https://beamline-experiment-control.readthedocs.io/en/latest/).
|
||||
|
||||
**Standard Installation**
|
||||
|
||||
To install BEC Widgets using the pip package manager, execute the following command in your terminal for getting the
|
||||
default PySide6 version into your python environment for BEC:
|
||||
|
||||
|
||||
```bash
|
||||
pip install 'bec_widgets[pyside6]'
|
||||
```
|
||||
|
||||
**Troubleshooting**
|
||||
|
||||
If you encounter issues during installation, particularly with Qt, try purging the pip cache:
|
||||
|
||||
```bash
|
||||
pip cache purge
|
||||
```
|
||||
|
||||
This can resolve conflicts or issues with package installations.
|
||||
|
||||
```{warning}
|
||||
At the moment PyQt6 is no longer officially supported by BEC Widgets due to incompatibilities with BEC Designer. Please use PySide6 instead.
|
||||
```
|
||||
|
Before Width: | Height: | Size: 399 KiB |
@@ -1,144 +0,0 @@
|
||||
(user.command_line_introduction)=
|
||||
# Quick start
|
||||
In order to use BEC Widgets as a plotting tool for BEC, it needs to be [installed](#user.installation) in the same Python environment as the BEC IPython client (please refer to the [BEC documentation](https://bec.readthedocs.io/en/latest/user/command_line_interface.html#start-up) for more details). Upon startup, the client will automatically launch a GUI and store it as a `gui` object in the client. The GUI backend will also be automatically connect to the BEC server, giving access to all information on the server and allowing the user to visualize the data in real-time.
|
||||
|
||||
## BECGuiClient
|
||||
The `gui` object is the main entry point for interacting with the BEC Widgets framework. It is an instance of the {py:class}`~bec_widgets.cli.client_utils.BECGuiClient` class, which provides methods to create and manage GUI components. Upon BEC startup, a default {py:class}`~bec_widgets.cli.client.BECDockArea` instance named *bec* is automatically launched.
|
||||
|
||||
A launcher interface is available via the top menu bar under New → Open Launcher. This opens a window where users can launch a new {py:class}`~bec_widgets.cli.client.BECDockArea` instance, an [AutoUpdate](#user.auto_updates) instance, individual widgets or a custom *ui file* created with *BEC Designer*. Alternatively, users can launch a new {py:class}`~bec_widgets.cli.client.BECDockArea` from the command line:
|
||||
|
||||
```python
|
||||
dock_area = gui.new() # launches a new BECDockArea instance
|
||||
gui.new('my_dock_area') # launches a new BECDockArea instance with the name 'my_dock_area'
|
||||
dock_area2 = gui.my_dock_area # Dynamic attribute access to created dock_area
|
||||
```
|
||||
|
||||
``` {note}
|
||||
If a name is provided, the new dock area will use that name. If the name already exists, an error is raised. If no name is specified, a name will be auto-generated following the pattern *dock_area_ii* where *ii* is the next available number. Named dock areas can be accessed dynamically as attributes of the gui object.
|
||||
```
|
||||
|
||||
|
||||
## BECDockArea
|
||||
The {py:class}`~bec_widgets.cli.client.BECDockArea` is a versatile container for quickly building customized GUIs. It supports adding new widgets either through the CLI or directly via toolbar actions. Widgets must be added into {py:class}`~bec_widgets.cli.client.BECDockArea` instances, which serve as the individual containers. These docks can be arranged freely, detached from the main window, and used as floating panels.
|
||||
|
||||
From the CLI, you can create new docks like this:
|
||||
|
||||
```python
|
||||
dock_area = gui.new()
|
||||
dock = dock_area.new(name='my_dock_area')
|
||||
dock = gui.new().new()
|
||||
```
|
||||
|
||||
<!-- **Schema of the BECDockArea**
|
||||
|
||||
 -->
|
||||
|
||||
## Widgets
|
||||
Widgets are the building blocks of the BEC Widgets framework. They are the visual components that allow users to interact with the data and control the behavior of the application. Each dock can contain multiple widgets, albeit we recommend for most use cases a single widget per dock. BEC Widgets provides a set of core widgets (cf. {ref}`user.widgets`). More widgets can be added by the users, and we invite you to explore the {ref}`developer.widgets` to learn how to create custom widgets.
|
||||
For the introduction given here, we will focus on the plotting widgets of BECWidgets.
|
||||
|
||||
<!-- We also provide two methods [`plot()`](/api_reference/_autosummary/bec_widgets.cli.client.BECFigure.rst#bec_widgets.cli.client.BECFigure.plot), [`image()`](/api_reference/_autosummary/bec_widgets.cli.client.BECFigure.rst#bec_widgets.cli.client.BECFigure.image) and [`motor_map()`](/api_reference/_autosummary/bec_widgets.cli.client.BECFigure.rst#bec_widgets.cli.client.BECFigure.motor_map) as shortcuts to add a plot, image or motor map to the BECFigure. -->
|
||||
|
||||
**Waveform Plot**
|
||||
|
||||
The {py:class}`~bec_widgets.cli.client.Waveform` is a widget that can be used to visualize 1D waveform data, i.e. to plot data of a monitor against a motor position. The method {py:meth}`~bec_widgets.cli.client.Waveform.plot` returns the plot object.
|
||||
|
||||
```python
|
||||
plt = gui.new().new().new(gui.available_widgets.Waveform)
|
||||
plt.plot(device_x='samx', device_y='bpm4i')
|
||||
```
|
||||
Here, we create a new plot with a subscription to the devices `samx` and `bpm4i` and assign the plot to the object `plt`. We can now use this object to further customize the plot, e.g. changing the title (`title`), axis labels (`x_label`)
|
||||
<!-- or limits (`x_lim`). -->
|
||||
|
||||
We invite you to explore the API of the WaveForm in the {ref}`user.widgets.waveform_1d` or directly in the command line.
|
||||
|
||||
To plot custom data, i.e. data that is not directly available through a scan in BEC, we can use the same method, but provide the data directly to the plot.
|
||||
|
||||
```python
|
||||
plt = gui.new().new().new(gui.available_widgets.Waveform)
|
||||
#
|
||||
plt.plot([1,2,3,4], [1,4,9,16])
|
||||
# or
|
||||
plt.plot(x=np.array([1,2,3,4]), y=np.array([1,4,9,16]))
|
||||
# or
|
||||
plt.plot(np.random.rand(10,2))
|
||||
# or if you like to receive the custom curve item
|
||||
curve = plt.plot(x=[1,2,3,4], y=[1,4,9,16])
|
||||
```
|
||||
|
||||
**Scatter Plot**
|
||||
|
||||
The {py:class}`~bec_widgets.cli.client.Waveform` widget can also be used to visualize 2D scatter plots. More details on setting up the scatter plot are available in the widget documentation of the {ref}`user.widgets.scatter_2d`.
|
||||
|
||||
**Motor Map**
|
||||
|
||||
The {py:class}`~bec_widgets.cli.client.MotorMap` widget can be used to visualize the position of motors. It's focused on tracking and visualizing the position of motors, crucial for precise alignment and movement tracking during scans. More details on setting up the motor map are available in the widget documentation of the {ref}`user.widgets.motor_map`.
|
||||
|
||||
**Image Plot**
|
||||
|
||||
The {py:class}`~bec_widgets.cli.client.Image` widget can be used to visualize 2D image data for example a camera. More details on setting up the image plot are available in the widget documentation of the {ref}`user.widgets.image`.
|
||||
|
||||
### Useful Commands
|
||||
We recommend users to explore the API of the widgets by themselves since we assume that the user interface is supposed to be intuitive and self-explanatory. We appreciate feedback from user in order to constantly improve the experience and allow easy access to the gui, widgets and their functionality. We recommend checking the {ref}`user.api_reference`, but also by using BEC Widgets, exploring the available functions and check their dockstrings.
|
||||
```python
|
||||
gui.new? # shows the dockstring of the new method
|
||||
```
|
||||
|
||||
In addition, we list below a few useful commands that can be used to interface with the widgets:
|
||||
|
||||
```python
|
||||
gui.windows # Returns a dictionary of all dock areas in the GUI
|
||||
gui.new() # Adds a new BECDockArea to the GUI
|
||||
|
||||
dock_area = gui.windows['bec']
|
||||
dock = dock_area.new('my_dock') # Adds a new dock named 'my_dock' to the dock area
|
||||
plt = dock.new(gui.available_widgets.Waveform) # Adds a Waveform widget to the dock
|
||||
|
||||
# Alternative syntax:
|
||||
# dock_area.my_dock.new(gui.available_widgets.Waveform)
|
||||
|
||||
dock.element_list # Returns a list of all widgets in the dock
|
||||
dock.elements # Equivalent to dock.element_list
|
||||
|
||||
plt.curves # Returns a list of all curves in the plot
|
||||
```
|
||||
|
||||
We note that commands can also be chained. For example, `gui.new().new().new(gui.available_widgets.Waveform)` will add a new dock_area to the gui and add a new dock with a `Waveform` widget to the dock.
|
||||
|
||||
## Composing a larger GUI
|
||||
The example given above introduces BEC Widgets with its different components, and provides an overview of how to interact with the widgets. Nevertheless, another power aspect of BEC Widgets lies in the ability to compose a larger GUI with multiple docks and widgets. This section aims to provide a tutorial like guide on how to compose a more complex GUI that (A) live-plots a 1D waveform, (B) plots data from a camera, and (C) tracks the positions of two motors.
|
||||
Let's assume BEC was just started and the `gui` object is available in the client. A single dock is already attached together with a BEC Figure. Let's add the 1D waveform to this dock, change the color of the line to white and add the title *1D Waveform* to the plot.
|
||||
|
||||
```python
|
||||
dock_area = gui.new()
|
||||
plt = dock_area.new().new(gui.available_widgets.Waveform)
|
||||
plt.plot(device_x='samx', device_y='bpm4i')
|
||||
plt.curves[0].set_color(color="white")
|
||||
plt.title = '1D Waveform'
|
||||
```
|
||||
|
||||
Next, we add 2 new docks to the gui, one to plot the data of a camera and one to track the positions of two motors.
|
||||
```ipython
|
||||
cam_widget= dock_area.new().new(gui.available_widgets.Image)
|
||||
cam_widget.image("eiger")
|
||||
motor_widget = dock_area.new().new(gui.available_widgets.MotorMap)
|
||||
motor_widget.map("samx", "samy")
|
||||
```
|
||||
|
||||
Note, we chain commands here which is possible since the `new()` and `new()` methods return the dock and the widget respectively. We can now further customize the widgets by changing the title, axis labels, etc.
|
||||
|
||||
```python
|
||||
cam_widget.title = "Camera Image Eiger"
|
||||
cam_widget.vrange = [0, 100]
|
||||
```
|
||||
As a final step, we can now add also a RingProgressBar to a new dock, and perform a grid_scan with the motors *samx* and *samy*.
|
||||
As you see in the example below, all docks are arranged below each other. This is the default behavior of the `new()` method. However, the docks can be freely arranged by drag and drop as desired by the user. We invite you to explore this by yourself following the example in the video, and build your custom GUI with BEC Widgets.
|
||||
|
||||
```python
|
||||
prog_bar = dock_area.new().new(gui.available_widgets.RingProgressBar)
|
||||
prog_bar.set_line_widths(15)
|
||||
scans.grid_scan(dev.samy, -2, 2, 10, dev.samx, -5, 5, 10, exp_time=0.1, relative=False)
|
||||
```
|
||||
|
||||

|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
(user.video_tutorials)=
|
||||
|
||||
# Video Tutorials
|
||||
|
||||
This section includes video tutorials that demonstrate various use cases of `bec-widgets`, including video tutorials,
|
||||
presentations, and conference talks.
|
||||
|
||||
## BSEG Meeting 24th July 2024
|
||||
|
||||
This video is a presentation of the BEC Widgets project at the BSEG meeting on the 24th July 2024. The presentation
|
||||
covers the basic interactions, including visualization of live data acquisition and how to steer experiments using
|
||||
user-friendly tools. Learn how BEC Widgets can enhance your experimental control projects with its intuitive interface
|
||||
and powerful features.
|
||||
|
||||
Used version of BEC Widgets: 0.91.0
|
||||
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/qZ8fWXRAdHE" frameborder="0" allowfullscreen></iframe>
|
||||
@@ -1,58 +0,0 @@
|
||||
(user.plugin_widgets)=
|
||||
# Plugin repository widgets
|
||||
|
||||
## Adding widgets to the plugin repository
|
||||
|
||||
Widgets can be created by users and added to a beamline plugin repository, then they can be used in
|
||||
all the same ways as built-in widgets. To make this work, the widget author should follow a few
|
||||
simple guidelines.
|
||||
|
||||
Widgets should be added in `plugin_repo.bec_widgets.widgets`. They may be added in submodules. If
|
||||
so, please make sure that these are properly defined python submodules with `__init__.py` files, so
|
||||
that the widgets are discoverable.
|
||||
|
||||
### Preparing a widget to be a plugin
|
||||
|
||||
- make sure that the widget class inherits from both `BECWidget` as well as `QWidget` or a subclass
|
||||
of it, such as `QComboBox` or `QLineEdit`.
|
||||
- make sure it initialises each of these superclasses in its `__init__()` method, and passes the
|
||||
`parent` keyword argument on to `QWidget.__init__()`.
|
||||
- add `PLUGIN = True` as a class variable to the widget class
|
||||
- add `USER_ACCESS = [...]`, including any methods and properties which should be accessible in the
|
||||
client to the list, as strings.
|
||||
|
||||
(Search the `bec_widgets` code for one of the above names for examples of these magic variables)
|
||||
|
||||
### Example / template
|
||||
|
||||
```Python
|
||||
class TestWidget(BECWidget, QWidget):
|
||||
USER_ACCESS = ["set_text"]
|
||||
PLUGIN = True
|
||||
|
||||
def __init__(self, parent=None, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
QWidget.__init__(self, parent=parent)
|
||||
self.setLayout(QHBoxLayout())
|
||||
self._text_widget = QLabel("Test widget text")
|
||||
self.layout().addWidget(self._text_widget)
|
||||
|
||||
def set_text(self, value: str):
|
||||
self._text_widget.setText(value)
|
||||
```
|
||||
|
||||
### Generating the plugin files and RPC client template
|
||||
|
||||
To allow the BEC client to communicate with the GUI server and to know which widgets are available,
|
||||
as well as to allow the BEC Designer to find the available widgets, a code generation tool should be
|
||||
run to prepare a client file which lists all the available widget classes and functions. Make sure
|
||||
you are in the BEC python environment where your plugin repository is also installed, and run:
|
||||
|
||||
```bash
|
||||
$ bw-generate-cli --target plugin_repo
|
||||
```
|
||||
|
||||
replacing `plugin_repo` with the name of your repository. This will overwrite the file for
|
||||
`plugin_repo.bec_widgets.client`. This file should not be edited by hand, and should always be
|
||||
regenerated when changes are made to widgets in the plugin repository. BEC will need to be restarted
|
||||
for changes made here to take effect.
|
||||
@@ -1,80 +0,0 @@
|
||||
(user)=
|
||||
# User
|
||||
Welcome to the User section of the BEC Widgets documentation! BEC Widgets is a versatile GUI framework tailored for beamline scientists, enabling efficient and intuitive interaction with beamline experiments. This section is designed to guide both new and experienced users through the essential aspects of utilizing BEC Widgets.
|
||||
|
||||
```{toctree}
|
||||
---
|
||||
maxdepth: 2
|
||||
hidden: false
|
||||
---
|
||||
|
||||
customisation.md
|
||||
plugin_widgets.md
|
||||
```
|
||||
|
||||
```{toctree}
|
||||
---
|
||||
maxdepth: 2
|
||||
hidden: true
|
||||
---
|
||||
|
||||
getting_started/getting_started.md
|
||||
applications/applications.md
|
||||
widgets/widgets.md
|
||||
api_reference/api_reference.md
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
````{grid} 2
|
||||
:gutter: 5
|
||||
|
||||
```{grid-item-card}
|
||||
:link: user.getting_started
|
||||
:link-type: ref
|
||||
:img-top: /assets/rocket_launch_48dp.svg
|
||||
:text-align: center
|
||||
:class-item: index-card
|
||||
|
||||
## Getting Started
|
||||
|
||||
Learn how to install BEC Widgets and get started with the framework.
|
||||
```
|
||||
|
||||
```{grid-item-card}
|
||||
:link: user.applications
|
||||
:link-type: ref
|
||||
:img-top: /assets/display_settings_48dp.svg
|
||||
:text-align: center
|
||||
:class-item: index-card
|
||||
|
||||
## Applications
|
||||
|
||||
Learn how to use BEC Widgets Applications, to modify and create new applications.
|
||||
|
||||
```
|
||||
|
||||
```{grid-item-card}
|
||||
:link: user.widgets
|
||||
:link-type: ref
|
||||
:img-top: /assets/apps_48dp.svg
|
||||
:text-align: center
|
||||
:class-item: index-card
|
||||
|
||||
## Widgets
|
||||
|
||||
Learn about the building blocks of larger applications: widgets.
|
||||
```
|
||||
|
||||
```{grid-item-card}
|
||||
:link: user.api_reference
|
||||
:link-type: ref
|
||||
:img-top: /assets/index_api.svg
|
||||
:text-align: center
|
||||
:class-item: index-card
|
||||
|
||||
## API reference
|
||||
|
||||
Comprehensive reference of all user-facing classes, functions, and methods.
|
||||
```
|
||||
````
|
||||
@@ -1,42 +0,0 @@
|
||||
(user.widgets.bec_progressbar)=
|
||||
# BEC Progressbar
|
||||
|
||||
```{tab} Overview
|
||||
|
||||
The {py:class}`~bec_widgets.cli.client.BECProgressBar` widget is a general purpose progress bar that follows the BEC theme and style. It can be embedded in any application to display the progress of a task or operation.
|
||||
|
||||
## Key Features:
|
||||
- **Modern Design**: The BEC Progressbar widget is designed with a modern and sleek appearance, following the BEC theme.
|
||||
- **Customizable**: Users can customize the appearance and behavior of the progress bar to suit their application.
|
||||
- **Responsive**: The progress bar updates in real-time to reflect the progress of the task or operation.
|
||||
|
||||
## Screenshot
|
||||

|
||||

|
||||
|
||||
```
|
||||
|
||||
````{tab} Examples
|
||||
|
||||
The `BECProgressBar` widget can be integrated within a [`BECDockArea`](user.widgets.bec_dock_area) or used as an individual component in your application through `BEC Designer`. Below are examples demonstrating how to create and use the `BECProgressBar` widget.
|
||||
|
||||
## Example 1 - Adding BEC Status Box to BECDockArea
|
||||
|
||||
In this example, we demonstrate how to add a `BECProgressBar` widget to a `BECDockArea`, allowing users to manually set and update the progress states.
|
||||
|
||||
```python
|
||||
# Add a new dock with a BEC Progressbar widget
|
||||
dock_area = gui.new()
|
||||
pb = dock_area.new().new(gui.available_widgets.BECProgressBar)
|
||||
pb.set_value(50)
|
||||
```
|
||||
|
||||
````
|
||||
|
||||
````{tab} API
|
||||
```{eval-rst}
|
||||
.. autoclass:: bec_widgets.cli.client.BECProgressBar
|
||||
:members:
|
||||
:show-inheritance:
|
||||
```
|
||||
````
|
||||
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 1.2 MiB |
@@ -1,40 +0,0 @@
|
||||
(user.widgets.bec_status_box)=
|
||||
# BEC Status Box
|
||||
|
||||
````{tab} Overview
|
||||
|
||||
The {py:class}`~bec_widgets.cli.client.BECStatusBox` widget is designed to monitor the status and health of all running BEC processes. This widget provides a real-time overview of the BEC core services, including DeviceServer, ScanServer, SciHub, ScanBundler, and FileWriter. The top-level display indicates the overall state of the BEC services, while the collapsed view allows users to delve into the status of each individual process. By double-clicking on a specific process, users can access a detailed popup window with live updates of the metrics for that process.
|
||||
|
||||
## Key Features:
|
||||
- **Comprehensive Service Monitoring**: Track the state of individual BEC services, including real-time updates on their health and status.
|
||||
- **Automatic Service Tracking**: Automatically detects and monitors additional clients connecting to the BEC services.
|
||||
- **Detailed Metrics**: Provides live updates of the metrics for each process, accessible through an interactive popup window.
|
||||
|
||||

|
||||
````
|
||||
|
||||
````{tab} Examples
|
||||
|
||||
The `BECStatusBox` widget can be integrated within a [`BECDockArea`](user.widgets.bec_dock_area) or used as an individual component in your application through `BEC Designer`. Below are examples demonstrating how to create and use the `BECStatusBox` widget.
|
||||
|
||||
## Example 1 - Adding BEC Status Box to BECDockArea
|
||||
|
||||
In this example, we demonstrate how to add a `BECStatusBox` widget to a `BECDockArea`, allowing users to monitor the status of BEC processes directly from the GUI.
|
||||
|
||||
```python
|
||||
# Add a new dock with a BECStatusBox widget
|
||||
sb = gui.bec.new().new(widget=gui.available_widgets.BECStatusBox)
|
||||
```
|
||||
|
||||
```{hint}
|
||||
Once the `BECStatusBox` is added, users can interact with it to view the status of individual processes. By expanding the view, you can see the status of each BEC service in detail.
|
||||
```
|
||||
````
|
||||
|
||||
````{tab} API
|
||||
```{eval-rst}
|
||||
.. autoclass:: bec_widgets.cli.client.BECStatusBox
|
||||
:members:
|
||||
:show-inheritance:
|
||||
```
|
||||
````
|
||||
@@ -1,159 +0,0 @@
|
||||
(user.widgets.buttons_appearance)=
|
||||
|
||||
# Appearance Buttons
|
||||
|
||||
`````{tab} Overview
|
||||
This section consolidates various buttons designed to manage the appearance of the BEC GUI, allowing users to easily switch themes, select colors, and choose colormaps.
|
||||
|
||||
## Dark Mode Button
|
||||
|
||||
The `Dark Mode Button` is a toggle control that allows users to switch between light and dark themes in the BEC GUI. It provides a convenient way to adjust the interface's appearance based on user preferences or environmental conditions.
|
||||
|
||||
````{grid} 2
|
||||
:gutter: 2
|
||||
|
||||
```{grid-item-card} Dark Mode
|
||||
:img-top: ./dark_mode_enabled.png
|
||||
```
|
||||
|
||||
```{grid-item-card} Light Mode
|
||||
:img-top: ./dark_mode_disabled.png
|
||||
```
|
||||
````
|
||||
|
||||
**Key Features:**
|
||||
- **Theme Switching**: Enables users to switch between light and dark themes with a single click.
|
||||
- **Configurable from BEC Designer**: The defaults for the dark mode can be set in the BEC Designer, allowing users to customize the startup appearance of the GUI.
|
||||
|
||||
## Color Button
|
||||
|
||||
The `Color Button` is a user interface element that provides a dialog to select colors. This button, adapted from `pyqtgraph`, is a simple yet powerful tool to integrate color selection functionality into the BEC GUIs.
|
||||
|
||||
**Key Features:**
|
||||
- **Color Selection**: Opens a dialog for selecting colors, returning the selected color in both RGBA and HEX formats.
|
||||
|
||||
## Colormap Selector
|
||||
|
||||
The `Colormap Selector` is a specialized combobox that allows users to select a colormap. It includes a preview of the colormap, making it easier for users to choose the appropriate one for their needs.
|
||||
|
||||
**Key Features:**
|
||||
- **Colormap Selection**: Provides a dropdown to select from all available colormaps in `pyqtgraph`.
|
||||
- **Visual Preview**: Displays a small preview of the colormap next to its name, enhancing usability.
|
||||
|
||||
## Colormap Button
|
||||
|
||||
The `Colormap Button` is a custom widget that displays the current colormap and, upon clicking, shows a nested menu for selecting a different colormap. It integrates the `ColorMapMenu` from `pyqtgraph`, providing an intuitive and interactive way for users to choose colormaps within the GUI.
|
||||
|
||||
**Key Features:**
|
||||
- **Current Colormap Display**: Shows the name and a gradient icon of the current colormap directly on the button.
|
||||
- **Nested Menu Selection**: Offers a nested menu with categorized colormaps, making it easy to find and select the desired colormap.
|
||||
- **Signal Emission**: Emits a signal when the colormap changes, providing the new colormap name as a string.
|
||||
- **BEC Designer Integration**: Exposes properties and signals to be used within BEC Designer, allowing for customization within the designer interface.
|
||||
- **Resizable and Styled**: Features adjustable size policies and styles to match the look and feel of standard `QPushButton` widgets, including rounded edges.
|
||||
`````
|
||||
|
||||
````{tab} Examples
|
||||
|
||||
Integrating these buttons into a BEC GUI layout is straightforward. The following examples demonstrate how to embed these buttons within a custom GUI layout using `QtWidgets`.
|
||||
|
||||
## Example 1 - Adding a Dark Mode Button
|
||||
|
||||
```python
|
||||
from qtpy.QtWidgets import QWidget, QVBoxLayout
|
||||
from bec_widgets.widgets.buttons import DarkModeButton
|
||||
|
||||
class MyGui(QWidget):
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent=parent)
|
||||
self.setLayout(QVBoxLayout(self))
|
||||
|
||||
# Create and add the DarkModeButton to the layout
|
||||
self.dark_mode_button = DarkModeButton(parent=self)
|
||||
self.layout().addWidget(self.dark_mode_button)
|
||||
|
||||
# Example of how this custom GUI might be used:
|
||||
my_gui = MyGui()
|
||||
my_gui.show()
|
||||
```
|
||||
|
||||
## Example 2 - Adding a Color Button
|
||||
|
||||
```python
|
||||
from qtpy.QtWidgets import QWidget, QVBoxLayout
|
||||
from bec_widgets.widgets.buttons import ColorButton
|
||||
|
||||
class MyGui(QWidget):
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent=parent)
|
||||
self.setLayout(QVBoxLayout(self))
|
||||
|
||||
# Create and add the ColorButton to the layout
|
||||
self.color_button = ColorButton(self)
|
||||
self.layout().addWidget(self.color_button)
|
||||
|
||||
# Example of how this custom GUI might be used:
|
||||
my_gui = MyGui()
|
||||
my_gui.show()
|
||||
```
|
||||
|
||||
## Example 3 - Adding a Colormap Selector
|
||||
|
||||
```python
|
||||
from qtpy.QtWidgets import QWidget, QVBoxLayout
|
||||
from bec_widgets.widgets.buttons import ColormapSelector
|
||||
|
||||
class MyGui(QWidget):
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent=parent)
|
||||
self.setLayout(QVBoxLayout(self))
|
||||
|
||||
# Create and add the ColormapSelector to the layout
|
||||
self.colormap_selector = ColormapSelector(self)
|
||||
self.layout().addWidget(self.colormap_selector)
|
||||
|
||||
# Example of how this custom GUI might be used:
|
||||
my_gui = MyGui()
|
||||
my_gui.show()
|
||||
```
|
||||
|
||||
## Example 4 - Adding a Colormap Button
|
||||
|
||||
```python
|
||||
from qtpy.QtWidgets import QWidget, QVBoxLayout
|
||||
from bec_widgets.widgets.buttons import ColormapButton
|
||||
|
||||
class MyGui(QWidget):
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent=parent)
|
||||
self.setLayout(QVBoxLayout(self))
|
||||
|
||||
# Create and add the ColormapButton to the layout
|
||||
self.colormap_button = ColormapButton(self)
|
||||
self.layout().addWidget(self.colormap_button)
|
||||
|
||||
# Connect the signal to handle colormap changes
|
||||
self.colormap_button.colormap_changed_signal.connect(self.on_colormap_changed)
|
||||
|
||||
def on_colormap_changed(self, colormap_name):
|
||||
print(f"Selected colormap: {colormap_name}")
|
||||
|
||||
# Example of how this custom GUI might be used:
|
||||
my_gui = MyGui()
|
||||
my_gui.show()
|
||||
```
|
||||
|
||||
````
|
||||
|
||||
````{tab} API
|
||||
```{eval-rst}
|
||||
.. autoclass:: bec_widgets.cli.client.DarkModeButton
|
||||
:members:
|
||||
:show-inheritance:
|
||||
.. autoclass:: bec_widgets.cli.client.ColorButton
|
||||
:members:
|
||||
:show-inheritance:
|
||||
.. autoclass:: bec_widgets.cli.client.ColormapSelector
|
||||
:members:
|
||||
:show-inheritance:
|
||||
```
|
||||
````
|
||||
|
Before Width: | Height: | Size: 5.0 KiB |
|
Before Width: | Height: | Size: 4.0 KiB |
@@ -1,86 +0,0 @@
|
||||
(user.widgets.buttons_queue)=
|
||||
|
||||
# Queue Control Buttons
|
||||
|
||||
```{tab} Overview
|
||||
This section consolidates various buttons designed to manage the BEC scan queue, providing essential controls for operations like stopping, resuming, aborting, and resetting the scan queue.
|
||||
|
||||
## Stop Button
|
||||
|
||||
The `Stop Button` is a specialized control that provides an immediate interface to halt ongoing operations in the BEC Client. It is essential for scenarios where operations need to be terminated quickly, such as in the case of an error or when an operation needs to be interrupted by the user.
|
||||
|
||||
**Key Features:**
|
||||
- **Immediate Termination**: Instantly halts the execution of the current script or process.
|
||||
- **Queue Management**: Stops the current scan or the entire scan queue.
|
||||
|
||||
## Resume Button
|
||||
|
||||
The `Resume Button` allows users to continue the paused scan queue. It’s useful in scenarios where the scan queue has been halted and needs to be resumed.
|
||||
|
||||
**Key Features:**
|
||||
- **Queue Continuation**: Resumes the scan queue after a pause.
|
||||
- **Toolbar and Button Options**: Can be configured as a toolbar button or a standard push button.
|
||||
|
||||
## Abort Button
|
||||
|
||||
The `Abort Button` provides an interface to abort a specific scan or the entire queue. This is useful for scenarios where an operation needs to be terminated but in a controlled manner.
|
||||
|
||||
**Key Features:**
|
||||
- **Scan Abortion**: Aborts the current scan or a specific scan in the queue.
|
||||
- **Toolbar and Button Options**: Can be configured as a toolbar button or a standard push button.
|
||||
|
||||
## Reset Queue Button
|
||||
|
||||
The `Reset Button` is used to reset the scan queue. It prompts the user for confirmation before resetting, ensuring that the action is intentional.
|
||||
|
||||
**Key Features:**
|
||||
- **Queue Reset**: Resets the entire scan queue.
|
||||
- **Confirmation Dialog**: Prompts the user to confirm the reset action to prevent accidental resets.
|
||||
- **Toolbar and Button Options**: Can be configured as a toolbar button or a standard push button.
|
||||
```
|
||||
|
||||
````{tab} Examples
|
||||
|
||||
Integrating these buttons into a BEC GUI layout is straightforward. The following examples demonstrate how to embed these buttons within a custom GUI layout using `QtWidgets`.
|
||||
|
||||
### Example 1 - Embedding a Stop Button in a Custom GUI Layout
|
||||
|
||||
```python
|
||||
import sys
|
||||
from qtpy.QtWidgets import QApplication, QVBoxLayout, QWidget
|
||||
from bec_widgets.widgets.control.buttons.stop_button.stop_button import StopButton
|
||||
|
||||
class MyGui(QWidget):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.setLayout(QVBoxLayout())
|
||||
# Create and add the StopButton to the layout
|
||||
self.stop_button = StopButton()
|
||||
self.layout().addWidget(self.stop_button)
|
||||
|
||||
# Example of how this custom GUI might be used:
|
||||
app = QApplication([])
|
||||
my_gui = MyGui()
|
||||
my_gui.show()
|
||||
app.exec_()
|
||||
```
|
||||
|
||||
`ResumeButton`, `ResetButton`, and `AbortButton` may be used in an exactly analogous way.
|
||||
````
|
||||
|
||||
````{tab} API
|
||||
```{eval-rst}
|
||||
.. autoclass:: bec_widgets.cli.client.StopButton
|
||||
:members:
|
||||
:show-inheritance:
|
||||
.. autoclass:: bec_widgets.cli.client.ResumeButton
|
||||
:members:
|
||||
:show-inheritance:
|
||||
.. autoclass:: bec_widgets.cli.client.AbortButton
|
||||
:members:
|
||||
:show-inheritance:
|
||||
.. autoclass:: bec_widgets.cli.client.ResetButton
|
||||
:members:
|
||||
:show-inheritance:
|
||||
```
|
||||
````
|
||||
@@ -1,41 +0,0 @@
|
||||
(user.widgets.dap_combo_box)=
|
||||
|
||||
# DAP Combobox
|
||||
|
||||
````{tab} Overview
|
||||
|
||||
The {py:class}`~bec_widgets.widgets.dap_combo_box.dap_combo_box.DAPComboBox` is a widget that extends the functionality of a standard `QComboBox` to allow the user to select a DAP process from all available DAP models.
|
||||
One of its signals `new_dap_config` is designed to be connected to the {py:class}`~bec_widgets.widgets.plots.waveform.waveform.Waveform.add_dap_curve` slot from the Waveform widget to add a DAP process.
|
||||
|
||||
## Key Features:
|
||||
- **Select DAP model**: Select one of the available DAP models.
|
||||
- **Signal/Slot Interaction**: Signal and slots to configure the fit_model, x_axis, and y_axis, and to add a DAP model to the BECWaveformWidget.
|
||||
```{figure} /assets/widget_screenshots/dap_combo_box.png
|
||||
---
|
||||
name: lmfit_dialog
|
||||
---
|
||||
LMFit Dialog
|
||||
```
|
||||
````
|
||||
````{tab} Summary of Signals
|
||||
The following signals are emitted by the `DAP ComboBox` widget:
|
||||
- `new_dap_config(str, str, str)` : Signal to add a DAP model to the BECWaveformWidget
|
||||
- `x_axis_updated(str)` : Signal to emit the current x axis
|
||||
- `y_axis_updated(str)` : Signal to emit the current y axis
|
||||
- `fit_model_updated(str)` : Signal to emit the current fit model
|
||||
````
|
||||
````{tab} Summary of Slots
|
||||
The following slots are available for the `DAP ComboBox` widget:
|
||||
- `select_x_axis(str)` : Slot to select the current x axis, emits the `x_axis_updated` signal
|
||||
- `select_y_axis(str)` : Slot to select the current y axis, emits the `x_axis_updated` signal
|
||||
- `select_fit_model(str)` : Slot to select the current fit model, emits the `fit_model_updated` signal. If x and y axis are set, it will also emit the `new_dap_config` signal.
|
||||
````
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
(user.widgets.device_browser)=
|
||||
|
||||
# Device Browser
|
||||
|
||||
````{tab} Overview
|
||||
|
||||
The {py:class}`~bec_widgets.cli.client.DeviceBrowser` widget provides a user-friendly interface for browsing through all available devices in the current BEC session. As it supports drag functionality, users can easily drag and drop device into other widgets or applications.
|
||||
|
||||
```{note}
|
||||
The `Device Browser` widget is currently under development. Other widgets may not support drag and drop functionality yet.
|
||||
```
|
||||
|
||||
## Key Features:
|
||||
- **Device Search**: Allows users to search for devices using regular expressions.
|
||||
- **Drag and Drop**: Supports drag and drop functionality for easy transfer of devices to other widgets or applications.
|
||||
|
||||
```{figure} ./device_browser.png
|
||||
```
|
||||
````
|
||||
|
||||
````{tab} Examples
|
||||
|
||||
In this example, we demonstrate how to add a `DeviceBrowser` widget to a `BECDockArea` to visualize the progress of a task.
|
||||
|
||||
```python
|
||||
# Add a new dock with a DeviceBrowser widget
|
||||
dock_area = gui.new()
|
||||
browser = dock_area.new("device_browser").new(gui.available_widgets.DeviceBrowser)
|
||||
# You can also access the DeviceBrowser widget directly from the dock_area
|
||||
dock_area.device_browser.DeviceBrowser
|
||||
```
|
||||
|
||||
````
|
||||
|
||||
````{tab} API
|
||||
```{eval-rst}
|
||||
.. autoclass:: bec_widgets.cli.client.DeviceBrowser
|
||||
:members:
|
||||
:show-inheritance:
|
||||
```
|
||||
````
|
||||
|
Before Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 63 KiB |
@@ -1,129 +0,0 @@
|
||||
(user.widgets.device_input)=
|
||||
|
||||
# Device Input Widgets
|
||||
|
||||
````{tab} Overview
|
||||
|
||||
The `Device Input Widgets` consist of two primary widgets: `DeviceLineEdit` and `DeviceComboBox`. Both widgets are designed to facilitate the selection of devices within the BEC environment, allowing users to filter, search, and select devices dynamically. These widgets are highly customizable and can be integrated into a GUI either through direct code instantiation or by using `BEC Designer`.
|
||||
|
||||
## DeviceLineEdit
|
||||
The `DeviceLineEdit` widget provides a line edit interface with autocomplete functionality for device names, making it easier for users to quickly search and select devices.
|
||||
|
||||
## DeviceComboBox
|
||||
The `DeviceComboBox` widget offers a dropdown interface for device selection, providing a more visual way to browse through available devices.
|
||||
|
||||
## Key Features:
|
||||
- **Device Filtering**: Both widgets allow users to filter devices by device type and readout priority, ensuring that only relevant devices are shown.
|
||||
- **Default Device Setting**: Users can set a default device to be pre-selected when the widget is initialized.
|
||||
- **Set Device Selection**: Both widgets allow users to set the available devices to be displayed independent of the applied filters.
|
||||
- **Real-Time Autocomplete (LineEdit)**: The `DeviceLineEdit` widget supports real-time autocomplete, helping users find devices faster.
|
||||
- **Real-Time Input Validation (LineEdit)**: User input is validated in real-time with a red border around the `DeviceLineEdit` indicating an invalid input.
|
||||
- **Dropdown Selection (ComboBox)**: The `DeviceComboBox` widget displays devices in a dropdown list, making selection straightforward.
|
||||
- **BEC Designer Integration**: Both widgets can be added as custom widgets in `BEC Designer` or instantiated directly in code.
|
||||
|
||||
## Screenshot
|
||||
```{figure} /assets/widget_screenshots/device_inputs.png
|
||||
```
|
||||
|
||||
````
|
||||
|
||||
````{tab} Examples
|
||||
|
||||
Both `DeviceLineEdit` and `DeviceComboBox` can be integrated within a GUI application through direct code instantiation or by using `BEC Designer`. Below are examples demonstrating how to create and use these widgets.
|
||||
|
||||
|
||||
## Example 1 - Creating a DeviceLineEdit in Code
|
||||
|
||||
In this example, we demonstrate how to create a `DeviceLineEdit` widget in code and customize its behavior.
|
||||
We filter down to Positioners with readout_priority Baseline.
|
||||
Note, if we do not specify a device_filter or readout_filter, all enabled devices will be included.
|
||||
|
||||
```python
|
||||
from qtpy.QtWidgets import QApplication, QVBoxLayout, QWidget
|
||||
from bec_widgets.widgets.device_line_edit.device_line_edit import DeviceLineEdit
|
||||
from bec_lib.device import ReadoutPriority
|
||||
from bec_widgets.widgets.base_classes.device_input_base import BECDeviceFilter
|
||||
|
||||
class MyGui(QWidget):
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent=parent)
|
||||
self.setLayout(QVBoxLayout(self)) # Initialize the layout for the widget
|
||||
|
||||
# Create and add the DeviceLineEdit to the layout
|
||||
self.device_line_edit = DeviceLineEdit(parent=self, device_filter=BECDeviceFilter.POSITIONER, readout_priority_filter=ReadoutPriority.BASELINE)
|
||||
self.layout().addWidget(self.device_line_edit)
|
||||
|
||||
# Example of how this custom GUI might be used:
|
||||
app = QApplication([])
|
||||
my_gui = MyGui()
|
||||
my_gui.show()
|
||||
app.exec_()
|
||||
```
|
||||
|
||||
## Example 2 - Creating a DeviceComboBox in Code
|
||||
|
||||
Similarly, here is an example of creating a `DeviceComboBox` widget in code and customizing its behavior.
|
||||
|
||||
```python
|
||||
from qtpy.QtWidgets import QApplication, QVBoxLayout, QWidget
|
||||
from bec_widgets.widgets.device_combobox.device_combobox import DeviceComboBox
|
||||
from bec_lib.device import ReadoutPriority
|
||||
from bec_widgets.widgets.base_classes.device_input_base import BECDeviceFilter
|
||||
|
||||
class MyGui(QWidget):
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent=parent)
|
||||
self.setLayout(QVBoxLayout(self)) # Initialize the layout for the widget
|
||||
|
||||
# Create and add the DeviceComboBox to the layout
|
||||
self.device_combobox = DeviceComboBox(parent=self, device_filter=BECDeviceFilter.POSITIONER, readout_priority_filter=ReadoutPriority.BASELINE)
|
||||
self.layout().addWidget(self.device_combobox)
|
||||
|
||||
# Example of how this custom GUI might be used:
|
||||
app = QApplication([])
|
||||
my_gui = MyGui()
|
||||
my_gui.show()
|
||||
app.exec_()
|
||||
```
|
||||
|
||||
## Example 3 - Setting Default Device
|
||||
|
||||
Both `DeviceLineEdit` and `DeviceComboBox` allow you to set a default device that will be selected when the widget is initialized.
|
||||
|
||||
```python
|
||||
# Set default device for DeviceLineEdit
|
||||
self.device_line_edit.set_device("motor1")
|
||||
|
||||
# Set default device for DeviceComboBox
|
||||
self.device_combo_box.set_device("motor2")
|
||||
|
||||
# Set the available devices to be displayed independent of the applied filters
|
||||
self.device_combo_box.set_available_devices(["motor1", "motor2", "motor3"])
|
||||
```
|
||||
````
|
||||
````{tab} BEC Designer
|
||||
Both widgets are also available as plugins for the BEC Designer. We have included Qt properties for both widgets, allowing customization of filtering and default device settings directly from the designer. In addition to the common signals and slots for `DeviceLineEdit` and `DeviceComboBox`, the following slots are available:
|
||||
- `set_device(str)` to set the default device
|
||||
- `update_devices()` to refresh the devices list
|
||||
|
||||
The following Qt properties are also included:
|
||||
```{figure} ./QProperties_DeviceInput.png
|
||||
```
|
||||
|
||||
````
|
||||
|
||||
````{tab} API - ComboBox
|
||||
```{eval-rst}
|
||||
.. autoclass:: bec_widgets.cli.client.DeviceComboBox
|
||||
:members:
|
||||
:show-inheritance:
|
||||
```
|
||||
````
|
||||
|
||||
````{tab} API - LineEdit
|
||||
```{eval-rst}
|
||||
.. autoclass:: bec_widgets.cli.client.DeviceLineEdit
|
||||
:members:
|
||||
:show-inheritance:
|
||||
```
|
||||
````
|
||||
|
Before Width: | Height: | Size: 322 KiB |
@@ -1,122 +0,0 @@
|
||||
(user.widgets.bec_dock_area)=
|
||||
|
||||
# BECDockArea
|
||||
|
||||
````{tab} Overview
|
||||
|
||||
`BECDockArea` is a powerful and flexible container designed to host various widgets and docks within a grid layout. It provides an environment for organizing and managing complex user interfaces, making it ideal for applications that require multiple tools and data visualizations to be displayed simultaneously. BECDockArea is particularly useful for embedding not only visualization tools but also other interactive components, allowing users to tailor their workspace to their specific needs.
|
||||
|
||||
- **Flexible Dock Management**: Easily add, remove, and rearrange docks within `BECDockArea`, providing a customized layout for different tasks.
|
||||
- **State Persistence**: Save and restore the state of the dock area, enabling consistent user experiences across sessions.
|
||||
- **Dock Customization**: Add docks with customizable positions, names, and behaviors, such as floating or closable docks.
|
||||
- **Integration with Widgets**: Integrate various widgets like [`WaveformWidget`](user.widgets.waveform_widget), [`ImageWidget`](user.widgets.image_widget), and [`MotorMapWidget`](user.widgets.motor_map) into `BECDockArea`, either as standalone tools or as part of a more complex interface.
|
||||
|
||||
**BEC Dock Area Components Schema**
|
||||
|
||||

|
||||
````
|
||||
|
||||
````{tab} Examples - CLI
|
||||
In the following examples, we will use `BECIPythonClient` as the main object to interact with the `BECDockArea`. These tutorials focus on how to work with the `BECDockArea` framework, such as adding and removing docks, saving and restoring layouts, and managing the docked widgets. By default the `BECDockArea` is referred to as `gui` in `BECIPythonClient`. For more detailed examples of each individual component, please refer to the example sections of each individual [`widget`](user.widgets).
|
||||
|
||||
## Example 1 - Adding Docks to BECDockArea
|
||||
|
||||
In this example, we will demonstrate how to add different docks to a single `BECDockArea` widget. New docks are always added to the bottom of the dock area by default; however, you can specify the position of the dock by using the `position` and `relative_to` arguments.
|
||||
|
||||
```python
|
||||
# Create a new dock_area from GUI object
|
||||
dock_area = gui.new()
|
||||
|
||||
# Add a new dock with a Waveform to the BECDockArea
|
||||
dock_area.new(name="waveform_dock", widget="Waveform")
|
||||
dock1 = dock_area.waveform_dock # dynamic namespace was created
|
||||
|
||||
# Add a second dock with a MotorMapWidget to the BECDockArea to the right of the first dock
|
||||
dock2 = dock_area.new(name="motor_dock", widget="MotorMap",relative_to="Waveform Dock", position="right")
|
||||
|
||||
# Add a third dock with an ImageWidget to the BECDockArea, placing it on bottom of the dock area
|
||||
dock3 = dock_area.new(name="image_dock", widget="Image")
|
||||
```
|
||||
|
||||
```{hint}
|
||||
You can move docks around by dragging them with the mouse using the dock's title bar. The dock will snap to the grid layout of the dock area.
|
||||
```
|
||||
|
||||
## Example 2 - Access of Docks in BECDockArea
|
||||
|
||||
Docks can be accessed by their name or by the dock object. The dock object can be used to modify the dock properties or to add widgets to the dock.
|
||||
|
||||
```python
|
||||
# All docks can be accessed by their name from the panels dictionary
|
||||
dock_area.panels
|
||||
|
||||
# Output
|
||||
{'waveform_dock': <BECDock with name: waveform_dock>,
|
||||
'motor_dock': <BECDock with name: motor_dock>,
|
||||
'image_dock': <BECDock with name: image_dock>}
|
||||
# Access all docks from the dock area via list
|
||||
dock_area.panel_list
|
||||
|
||||
# Access through dynamic namespace mapping
|
||||
dock_area.waveform_dock
|
||||
dock_area.motor_dock
|
||||
dock_area.image_dock
|
||||
|
||||
# If objects were closed, we will keep a reference that will indicate that the dock was deleted
|
||||
# Try closing the window with the dock_area via mouse click on x
|
||||
|
||||
dock_area
|
||||
# Output
|
||||
<Deleted widget with gui_id BECDockArea_2025_04_24_14_28_11_742887>
|
||||
```
|
||||
|
||||
## Example 3 - Detaching and Attaching Docks in BECDockArea
|
||||
|
||||
Docks in `BECDockArea` can be detached (floated) or reattached to the main dock area. This is useful when you want to temporarily undock a widget for better visibility or organization.
|
||||
|
||||
```python
|
||||
# Detach the dock named "Waveform Dock"
|
||||
dock_area.detach_dock("waveform_dock")
|
||||
# Alternatively, you can use the dock object to detach the dock
|
||||
dock1 = dock_area.waveform_dock
|
||||
dock1.detach()
|
||||
|
||||
# Docks can be individually reattached to the main dock area
|
||||
dock2.attach()
|
||||
|
||||
# Reattach all floating docks to the main dock area
|
||||
gui.attach_all()
|
||||
```
|
||||
|
||||
```{note}
|
||||
Floating docks are always returned to the original dock area if they are closed manually. Docks can also be detached by double-clicking on the dock title.
|
||||
```
|
||||
|
||||
## Example 4 - Removing Docks from BECDockArea
|
||||
|
||||
Docks can be removed from the dock area by their name or by the dock object. The dock object can be used to remove the dock from the dock area.
|
||||
|
||||
```python
|
||||
# Removing docks by their name
|
||||
dock_area.delete("waveform_dock")
|
||||
# Alternatively, you can use the dock object to remove the dock
|
||||
dock1 = dock_area.motor_dock
|
||||
dock1.remove()
|
||||
|
||||
# Removing all docks from the dock area
|
||||
gui.delete_all()
|
||||
```
|
||||
|
||||
```{warning}
|
||||
When removing a dock, all widgets within the dock will be removed as well. This action cannot be undone, and all references to the dock and its widgets will be lost.
|
||||
```
|
||||
````
|
||||
|
||||
````{tab} API
|
||||
```{eval-rst}
|
||||
.. autoclass:: bec_widgets.cli.client.BECDockArea
|
||||
:members:
|
||||
:show-inheritance:
|
||||
```
|
||||
````
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
(user.widgets.games)=
|
||||
|
||||
# Game widgets
|
||||
|
||||
To provide some entertainment during long nights at the beamline, there are game widgets available. Well, only one, so far.
|
||||
|
||||
## Minesweeper
|
||||
|
||||

|
||||
|
||||
The classic game Minesweeper. You may select from three different levels. The game can be ended or reset by clicking on the icon in the top-centre (the robot in the screenshot).
|
||||
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 10 MiB |
|
Before Width: | Height: | Size: 825 KiB |
@@ -1,108 +0,0 @@
|
||||
(user.widgets.heatmap_widget)=
|
||||
|
||||
# Heatmap widget
|
||||
|
||||
````{tab} Overview
|
||||
|
||||
The Heatmap widget is a specialized plotting tool designed for visualizing 2D grid data with color mapping for the z-axis. It excels at displaying data from grid scans or arbitrary step scans, automatically interpolating scattered data points into a coherent 2D image. Directly integrated with the `BEC` framework, it can display live data streams from scanning experiments within the current `BEC` session.
|
||||
|
||||
## Key Features:
|
||||
- **Flexible Integration**: The widget can be integrated into [`BECDockArea`](user.widgets.bec_dock_area), or used as an individual component in your application through `BEC Designer`.
|
||||
- **Live Grid Scan Visualization**: Real-time plotting of grid scan data with automatic positioning and color mapping based on scan parameters.
|
||||
- **Dual Scan Support**: Handles both structured grid scans (with pre-allocated grids) and unstructured step scans (with interpolation).
|
||||
- **Intelligent Data Interpolation**: For arbitrary step scans, the widget automatically interpolates scattered (x, y, z) data points into a smooth 2D heatmap using various interpolation methods.
|
||||
- **Oversampling**: Supports oversampling to enhance the appearance of the heatmap, allowing for smoother transitions and better visual representation of data. Especially useful the for nearest-neighbor interpolation.
|
||||
- **Customizable Color Maps**: Wide variety of color maps available for data visualization, with support for both simple and full color bars.
|
||||
- **Real-time Image Processing**: Apply real-time processing techniques such as FFT and logarithmic scaling to enhance data visualization.
|
||||
- **Interactive Controls**: Comprehensive toolbar with settings for heatmap configuration, crosshair tools, mouse interaction, and data export capabilities.
|
||||
|
||||
|
||||
```{figure} ./heatmap_grid_scan.gif
|
||||
:width: 60%
|
||||
|
||||
Real-time heatmap visualization of a 2D grid scan showing motor positions and detector intensity
|
||||
```
|
||||
|
||||
```{figure} ./heatmap_fermat_scan.gif
|
||||
:width: 80%
|
||||
|
||||
Real-time heatmap visualization of an (not path-optimized) scan following Fermat's spiral pattern. On the left, the heatmap widget is shown with the oversampling option set to 10 and the interpolation method set to nearest neighbor. On the right, the scatter waveform widget is shown with the same data.
|
||||
```
|
||||
|
||||
|
||||
````
|
||||
|
||||
````{tab} Examples - CLI
|
||||
|
||||
`HeatmapWidget` can be embedded in [`BECDockArea`](user.widgets.bec_dock_area), or used as an individual component in your application through `BEC Designer`. The command-line API is the same for all cases.
|
||||
|
||||
## Example 1 - Visualizing Grid Scan Data
|
||||
|
||||
In this example, we demonstrate how to add a `HeatmapWidget` to visualize live data from a 2D grid scan with motor positions and detector readout.
|
||||
|
||||
```python
|
||||
# Add a new dock with HeatmapWidget
|
||||
dock_area = gui.new()
|
||||
heatmap_widget = dock_area.new().new(gui.available_widgets.Heatmap)
|
||||
|
||||
# Plot a heatmap with x and y motor positions and z detector signal
|
||||
heatmap_widget.plot(
|
||||
device_x='samx', # X-axis motor
|
||||
device_y='samy', # Y-axis motor
|
||||
device_z='bpm4i', # Z-axis detector signal
|
||||
color_map='plasma'
|
||||
)
|
||||
heatmap_widget.title = "Grid Scan - Sample Position vs BPM Intensity"
|
||||
```
|
||||
|
||||
## Example 2 - Step Scan with Custom Entries
|
||||
|
||||
This example shows how to visualize data from an arbitrary step scan by specifying custom data entries for each axis.
|
||||
|
||||
```python
|
||||
# Add a new dock with HeatmapWidget
|
||||
dock_area = gui.new()
|
||||
heatmap_widget = dock_area.new().new(gui.available_widgets.Heatmap)
|
||||
|
||||
# Plot heatmap with specific data entries
|
||||
heatmap_widget.plot(
|
||||
device_x='motor1',
|
||||
device_y='motor2',
|
||||
device_z='detector1',
|
||||
signal_x='RBV', # Use readback value for x
|
||||
signal_y='RBV', # Use readback value for y
|
||||
signal_z='value', # Use main value for z
|
||||
color_map='viridis',
|
||||
reload=True # Force reload of data
|
||||
)
|
||||
```
|
||||
|
||||
## Example 3 - Real-time Processing and Customization
|
||||
|
||||
The `Heatmap` widget provides real-time processing capabilities and extensive customization options for enhanced data visualization.
|
||||
|
||||
```python
|
||||
# Configure heatmap appearance and processing
|
||||
heatmap_widget.color_map = 'plasma'
|
||||
heatmap_widget.lock_aspect_ratio = True
|
||||
|
||||
# Apply real-time processing
|
||||
heatmap_widget.fft = True # Apply FFT to the data
|
||||
heatmap_widget.log = True # Use logarithmic scaling
|
||||
|
||||
# Configure color bar and range
|
||||
heatmap_widget.enable_full_colorbar = True
|
||||
heatmap_widget.v_min = 0
|
||||
heatmap_widget.v_max = 1000
|
||||
|
||||
```
|
||||
|
||||
````
|
||||
|
||||
````{tab} API
|
||||
```{eval-rst}
|
||||
.. autoclass:: bec_widgets.widgets.plots.heatmap.heatmap.Heatmap
|
||||
:members:
|
||||
:show-inheritance:
|
||||
```
|
||||
````
|
||||
|
Before Width: | Height: | Size: 24 MiB |
@@ -1,112 +0,0 @@
|
||||
(user.widgets.image_widget)=
|
||||
|
||||
# Image widget
|
||||
|
||||
````{tab} Overview
|
||||
|
||||
The Image widget is a versatile tool designed for visualizing both 1D and 2D data, such as camera images or waveform data, in real-time. Directly integrated with the `BEC` framework, it can display live data streams from connected detectors or other data sources within the current `BEC` session. The widget provides advanced customization options for color maps and scale bars, allowing users to tailor the visualization to their specific needs.
|
||||
|
||||
## Key Features:
|
||||
- **Flexible Integration**: The widget can be integrated into [`BECDockArea`](user.widgets.bec_dock_area), or used as an individual component in your application through `BEC Designer`.
|
||||
- **Live Data Visualization**: Real-time plotting of both 1D and 2D data from detectors or other data sources, provided that a data stream is available in the BEC session.
|
||||
- **Support for Multiple Monitor Types**: The Image widget supports different monitor types (`'1d'` and `'2d'`), allowing visualization of various data dimensions. It can automatically determine the best way to visualise the data based on the shape of the data source.
|
||||
- **Customizable Color Maps and Scale Bars**: Users can customize the appearance of images with various color maps and adjust scale bars to better interpret the visualized data.
|
||||
- **Real-time Image Processing**: Apply real-time image processing techniques directly within the widget to enhance the quality or analyze specific aspects of the data, such as rotation, logarithmic scaling, and Fast Fourier Transform (FFT).
|
||||
- **Data Export**: Export visualized data to various formats such as PNG, TIFF, or H5 for further analysis or reporting.
|
||||
- **Interactive Controls**: Offers interactive controls for zooming, panning, and adjusting the visual properties of the images on the fly.
|
||||
|
||||

|
||||
````
|
||||
|
||||
````{tab} Examples - CLI
|
||||
|
||||
`ImageWidget` can be embedded in [`BECDockArea`](user.widgets.bec_dock_area), or used as an individual component in your application through `BEC Designer`. The command-line API is the same for all cases.
|
||||
|
||||
## Example 1 - Visualizing 2D Image Data from a Detector
|
||||
|
||||
In this example, we demonstrate how to add an `ImageWidget` to a [`BECDockArea`](user.widgets.bec_dock_area) to visualize live 2D image data from a connected camera detector.
|
||||
|
||||
```python
|
||||
# Add a new dock with BECFigure widget
|
||||
dock_area = gui.new()
|
||||
img_widget = dock_area.new().new(gui.available_widgets.Image)
|
||||
|
||||
# Add an ImageWidget to the BECFigure for a 2D detector
|
||||
img_widget.image(device='eiger', signal='preview')
|
||||
img_widget.title = "Camera Image - Eiger Detector"
|
||||
```
|
||||
|
||||
## Example 2 - Visualizing 1D Waveform Data from a Detector
|
||||
|
||||
This example demonstrates how to set up the Image widget to visualize 1D waveform data from a detector, such as a line detector or a spectrometer. The widget will stack incoming 1D data arrays to construct a 2D image.
|
||||
|
||||
```python
|
||||
# Add a new dock with BECFigure widget
|
||||
dock_area = gui.new()
|
||||
img_widget = dock_area.new().new(gui.available_widgets.Image)
|
||||
|
||||
# Add an ImageWidget to the BECFigure for a 2D detector
|
||||
img_widget.image(device='waveform', signal='data')
|
||||
img_widget.title = "Line Detector Data"
|
||||
|
||||
# Optional: Set the color map and value range
|
||||
img_widget.colormap = "plasma"
|
||||
img_widget.vrange= [0, 100]
|
||||
```
|
||||
|
||||
## Example 3 - Real-time Image Processing
|
||||
|
||||
The `Image` provides real-time image processing capabilities, such as rotating, scaling, applying logarithmic scaling, and performing FFT on the displayed images. The following example demonstrates how to apply these transformations to an image.
|
||||
|
||||
```python
|
||||
# Rotate the image by 90 degrees (1,2,3,4 are multiplied by 90 degrees)
|
||||
img_widget.num_rotation_90 = 1
|
||||
|
||||
# Transpose the image
|
||||
img_widget.transpose = True
|
||||
|
||||
# Apply FFT to the image
|
||||
img_widget.fft = True
|
||||
|
||||
# Set logarithmic scaling for the image display
|
||||
img_widget.log = True
|
||||
|
||||
# Set autorange for the image color map
|
||||
img_widget.autorange = True
|
||||
img_widget.autorange_mode = 'mean'# or 'max'
|
||||
```
|
||||
<!--
|
||||
## Example 6 - Setting Up for Different Detectors
|
||||
|
||||
The Image Widget can be configured for different detectors by specifying the correct monitor name and monitor type. Here's how to set it up for various detectors:
|
||||
|
||||
### For a 2D Camera Detector (e.g., 'eiger')
|
||||
|
||||
```python
|
||||
# For a 2D camera detector
|
||||
img_widget = fig.image(device='eiger', signal='preview')
|
||||
img_widget.set_title("Eiger Camera Image")
|
||||
```
|
||||
|
||||
### For a 1D Line Detector (e.g., 'waveform')
|
||||
|
||||
```python
|
||||
# For a 1D line detector
|
||||
img_widget = fig.image(device='waveform', signal='data')
|
||||
img_widget.set_title("Line Detector Data")
|
||||
```
|
||||
|
||||
```{note}
|
||||
Since the Image Widget does not have prior information about the shape of incoming data, it is essential to specify the correct `monitor_type` when setting up the widget. This ensures that the data is processed and displayed correctly.
|
||||
``` -->
|
||||
|
||||
|
||||
````
|
||||
|
||||
````{tab} API
|
||||
```{eval-rst}
|
||||
.. autoclass:: bec_widgets.cli.client.Image
|
||||
:members:
|
||||
:show-inheritance:
|
||||
```
|
||||
````
|
||||
@@ -1,46 +0,0 @@
|
||||
(user.widgets.lmfit_dialog)=
|
||||
|
||||
# LMFit Dialog
|
||||
|
||||
````{tab} Overview
|
||||
|
||||
The `LMFitDialog` is a widget that is developed to be used together with the `Waveform` widget. The `Waveform` widget allows user to submit a fit request to BEC's [DAP server](https://bec.readthedocs.io/en/latest/developer/getting_started/architecture.html) choosing from a selection of [LMFit models](https://lmfit.github.io/lmfit-py/builtin_models.html#) to fit monitored data sources. The `LMFit Dialog` provides an interface to monitor these fits, including statistics and fit parameters in real time.
|
||||
Within the `Waveform` widget, the dialog is accessible via the toolbar and will be automatically linked to the current waveform widget. For a more customised use, we can embed the `LMFit Dialog` in a larger GUI using the *BEC Designer*. In this case, one has to connect the `update_summary_tree` slot of the LMFit Dialog to the `dap_summary_update` signal of the Waveform widget to ensure its functionality.
|
||||
|
||||
|
||||
## Key Features:
|
||||
- **Fit Summary**: Display updates on LMFit DAP processes and fit statistics.
|
||||
- **Fit Parameter**: Display current fit parameter.
|
||||
- **`Waveform` Widget Integration**: Directly connect to `Waveform` widget to display fit statistics and parameters.
|
||||
```{figure} /assets/widget_screenshots/lmfit_dialog.png
|
||||
---
|
||||
name: lmfit_dialog
|
||||
---
|
||||
LMFit Dialog
|
||||
```
|
||||
````
|
||||
````{tab} Connect in BEC Designer
|
||||
The `LMFit Dialog` widget can be connected to a `Waveform` widget to display fit statistics and parameters from the LMFit DAP process hooked up to the waveform widget. You can use the signal/slot editor from the BEC Designer to connect the `dap_summary_update` signal of the `Waveform` widget to the `update_summary_tree` slot of the LMFit Dialog.
|
||||
|
||||
```{figure} /assets/widget_screenshots/lmfit_dialog_connect.png
|
||||
````
|
||||
````{tab} Connect in Python
|
||||
It is also possible to directly connect the `dap_summary_update` signal of the `Waveform` widget to the `update_summary_tree` slot of the LMFit Dialog in Python.
|
||||
|
||||
```python
|
||||
waveform = Waveform(...)
|
||||
lmfit_dialog = LMFitDialog(...)
|
||||
waveform.dap_summary_update.connect(lmfit_dialog.update_summary_tree)
|
||||
|
||||
```
|
||||
````
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
(user.widgets.log_panel)=
|
||||
|
||||
# LogPanel widget
|
||||
|
||||
The LogPanel widget can be used to view logs:
|
||||
|
||||

|
||||
|
||||
It automatically subscribes to log updates. You can fetch the log history with the "Fetch history" button.
|
||||
|
||||
## Filtering based on log level
|
||||
|
||||
If you select a dropdown box, only logs of that priority level or higher will be displayed:
|
||||
|
||||

|
||||
|
||||
|
||||
## Filtering based on a search string
|
||||
|
||||
If you type in a search string into the box in the toolbar, and hit enter or press the update button, that filter will be applied:
|
||||
|
||||

|
||||
|
||||
This search uses the [Python regular expression syntax](https://docs.python.org/3/library/re.html) if the checkbox for this option is selected:
|
||||
|
||||

|
||||
|
||||
|
||||
## Filtering based on time range
|
||||
|
||||
You may filter the logs to those occurring within a given time range.
|
||||
|
||||

|
||||
|
||||
## Filtering based on service
|
||||
|
||||
You can select which services to show logs from.
|
||||
|
||||

|
||||
|
Before Width: | Height: | Size: 213 KiB |
|
Before Width: | Height: | Size: 159 KiB |
|
Before Width: | Height: | Size: 396 KiB |
|
Before Width: | Height: | Size: 303 KiB |