Skip to content

Commit a740e31

Browse files
authored
Merge pull request #96 from ISISComputingGroup/scripting_python_edit
Copyedit scripting & python sections
2 parents 5f6b44a + bbe37e4 commit a740e31

File tree

10 files changed

+87
-42
lines changed

10 files changed

+87
-42
lines changed

doc/Scripting.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Scripting (Python)
22

33
```{note}
4-
These pages document user-facing scripting workflows. Looking for developer information about python? See [Python](system_components/Python).
4+
These pages document python libraries or workflows which users may use directly from their scripts. Looking for information about how Python is used in the IBEX backend? See [Python](system_components/Python).
55
```
66

77
```{toctree}

doc/conf.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@
100100
"client/coding/Migrating-or-adding-a-button-to-the-E4-perspective-switcher": "Perspectives.html", # noqa E501
101101
"client/coding/Adding-a-Button-to-the-Perspective-Switcher": "Perspectives.html",
102102
"client/testing/Using-Mockito-for-Testing-in-the-GUI": "Mockito.html",
103+
"scripting/uv": "../system_components/python/Python-venvs.html",
103104
}
104105

105106
intersphinx_mapping = {
@@ -108,4 +109,7 @@
108109
# If it does, then fall back to local inventory. This local inventory should be
109110
# updated periodically.
110111
"EPICS": ("https://docs.epics-controls.org/en/latest/", (None, "epics-controls.inv")),
112+
"genie_python": ("https://isiscomputinggroup.github.io/genie/", None),
113+
"ibex_bluesky_core": ("https://isiscomputinggroup.github.io/ibex_bluesky_core/", None),
114+
"matplotlib": ("https://matplotlib.org/stable/", None),
111115
}

doc/scripting/Bluesky-scanning.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
# Bluesky
22

33
For information about scanning using bluesky, including information about:
4-
- The bluesky run engine, `RE`
5-
- Bluesky ophyd-async devices (for example `BlockR`, `BlockRw`, `BlockRwRbv`, `ReflParameter`, or `SimpleDae`)
4+
- The bluesky run engine, {external+ibex_bluesky_core:py:obj}`RE <ibex_bluesky_core.run_engine.get_run_engine>`
5+
- Bluesky ophyd-async devices (for example {external+ibex_bluesky_core:py:obj}`BlockR <ibex_bluesky_core.devices.block.BlockR>`, {external+ibex_bluesky_core:py:obj}`BlockRw <ibex_bluesky_core.devices.block.BlockRw>`, {external+ibex_bluesky_core:py:obj}`BlockRwRbv <ibex_bluesky_core.devices.block.BlockRwRbv>`, {external+ibex_bluesky_core:py:obj}`ReflParameter <ibex_bluesky_core.devices.reflectometry.ReflParameter>`, or {external+ibex_bluesky_core:py:obj}`SimpleDae <ibex_bluesky_core.devices.simpledae.SimpleDae>`)
66
* If you are looking at bluesky code which uses `async def` and `await`, and imports `ophyd_async`, you're probably looking at a device.
77
- Bluesky plans, (for example `scan`, `adaptive_scan`)
88
* If you are looking at bluesky code with lots of `yield from` statements, you're probably looking at a plan.
9-
- Bluesky callbacks (for example `LivePlot`, `LiveFit`, `ISISCallbacks`, file-writing)
9+
- Bluesky callbacks (for example {external+ibex_bluesky_core:doc}`LivePlot <callbacks/plotting>`, {external+ibex_bluesky_core:doc}`LiveFit <callbacks/fitting/fitting>`, {external+ibex_bluesky_core:doc}`ISISCallbacks <callbacks/isiscallbacks>`, {external+ibex_bluesky_core:doc}`file-writing <callbacks/file_writing>`)
1010

11-
**See [ibex_bluesky_core docs](https://isiscomputinggroup.github.io/ibex_bluesky_core).**
11+
**See {external+ibex_bluesky_core:doc}`index`.**
1212

1313
---
1414

15-
For troubleshooting, see [ibex_bluesky_core troubleshooting guide](https://isiscomputinggroup.github.io/ibex_bluesky_core/dev/troubleshooting.html#).
15+
For troubleshooting, see {external+ibex_bluesky_core:doc}`ibex_bluesky_core troubleshooting guide <dev/troubleshooting>`.
1616

17-
Please add troubleshooting information to that guide (via a pull-request on `ibex_bluesky_core`) rather than this page.
17+
Please add troubleshooting information to that guide via a pull-request onto the [ibex_bluesky_core repository](https://github.com/ISISComputingGroup/ibex_bluesky_core/), rather than this page.

doc/scripting/Genie-Python.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,4 @@ genie_python/*
1414
### User documentation
1515

1616
- {external+ibex_user_manual:doc}`Scripting in the user manual <Scripting>`
17-
- [genie_python reference](http://shadow.nd.rl.ac.uk/genie_python/sphinx/genie_python.html)
17+
- {external+genie_python:doc}`genie_python reference manual <genie_python>`

doc/scripting/Matplotlib.md

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,38 @@
11
# Matplotlib
22

33
```{seealso}
4-
{external+ibex_user_manual:doc}`scripting/Matplotlib` on the user manual.
4+
- {external+ibex_user_manual:doc}`scripting/Matplotlib` on the user manual
5+
- {external+matplotlib:doc}`index` (reference documentation)
56
```
67

7-
We allow plotting in IBEX via `matplotlib`. These plots will appear in the IBEX client.
8+
We allow plotting in IBEX via {external+matplotlib:doc}`matplotlib <index>`. These plots will appear in the IBEX client.
89

9-
As of [ticket 6719](https://github.com/ISISComputingGroup/IBEX/issues/6719), we are using a custom matplotlib backend. This backend comprises two main components:
10-
- The websocket backend in `genie_python\matplotlib_backend\ibex_websocket_backend.py`, which is based on matplotlib's `WebAgg` backend. This serves plots over a websocket connection.
11-
- The front-end code in `/uk.ac.stfc.isis.ibex.ui.graphing` in the GUI. This reads data from the websockets published by the backend. It is effectively a Java reimplementation of `WebAgg`'s front-end code, which is in `python\Lib\site-packages\matplotlib\backends\web_backend`.
10+
As of [ticket 6719](https://github.com/ISISComputingGroup/IBEX/issues/6719), we are using a custom {external+matplotlib:doc}`matplotlib backend <users/explain/figure/backends>`. This backend comprises two main components:
11+
- The websocket backend in `genie_python\matplotlib_backend\ibex_websocket_backend.py`, which is based on matplotlib's {external+matplotlib:py:obj}`WebAgg <matplotlib.backends.backend_webagg>` backend. This serves plots over a websocket connection.
12+
- The front-end code in the `uk.ac.stfc.isis.ibex.ui.graphing` plugin in the GUI. This reads data from the websockets published by the backend. It is effectively a Java reimplementation of {external+matplotlib:py:obj}`WebAgg <matplotlib.backends.backend_webagg>`'s front-end code.
1213

1314
## Python (backend) component
1415

15-
Our custom backend is defined in `genie_python\matplotlib_backend\ibex_websocket_backend.py`. It uses/builds on `WebAggCore` under the hood.
16+
Our custom backend is defined in `genie_python\matplotlib_backend\ibex_websocket_backend.py`. It uses/builds on {external+matplotlib:py:obj}`WebAggCore <matplotlib.backends.backend_webagg_core>` under the hood.
1617

1718
Fundamentally, it is a relatively simple backend which publishes a websocket. This websocket can send or receive:
1819
- Binary messages, send only. These are PNG-encoded frames which should be published by the frontend.
1920
- String messages, send & receive. These are encoded using JSON. They can be used, for example:
2021
* To notify the front-end that a new frame is available
2122
* To allow the front-end to request a new frame
2223
* To allow the front-end to resize a plot
23-
* To allow the front-end to pan/zoom the plot, via mouse handlers. Note the front end simply sends mouse events to the backend, `WebAgg` then interprets these and redraws an appropriate plot.
24+
* To allow the front-end to pan/zoom the plot, via mouse handlers. Note the front end simply sends mouse events to the backend, {external+matplotlib:py:obj}`WebAgg <matplotlib.backends.backend_webagg>` then interprets these and redraws an appropriate plot.
2425

2526
We have modified the backend to:
2627
- Be non-blocking, so that scientists can update their plot and still continue running scripts in the background
27-
- To notify the IBEX client on calling `plt.show()`, so that IBEX can show the plot windows.
28+
- To notify the IBEX client on calling {external+matplotlib:py:obj}`matplotlib.pyplot.show`, so that IBEX can show the plot windows.
2829

2930

3031
## GUI (java) component
3132

32-
`WebAgg` is published by matplotlib as a browser-based backend. IBEX previously rendered plots in an embedded web browser view within an OPI, but this had significant reliability problems.
33+
{external+matplotlib:py:obj}`WebAgg <matplotlib.backends.backend_webagg>` is published by matplotlib as a browser-based backend. IBEX previously rendered plots in an embedded web browser view within an OPI, but this had significant reliability problems.
3334

34-
We have since moved to reimplementing the javascript based frontend code in java, as it is very simple. When matplotlib is updated, we should verify that plots still work and update the protocol in the GUI if the underlying protocol in `WebAgg` has changed or been extended. However this should be relatively rare as WebAgg is designed to be embedded in other applications (per [mpl docs](https://matplotlib.org/stable/gallery/user_interfaces/embedding_webagg_sgskip.html)).
35+
We have since moved to reimplementing the javascript based frontend code in java, as it is very simple. When matplotlib is updated, we should verify that plots still work and update the protocol in the GUI if the underlying protocol in {external+matplotlib:py:obj}`WebAgg <matplotlib.backends.backend_webagg>` has changed or been extended. However this should be relatively rare as WebAgg is designed to be embedded in other applications (per {external+matplotlib:doc}`gallery/user_interfaces/embedding_webagg_sgskip`).
3536

3637
The front-end receives binary messages from the backend, and displays the binary message content as a PNG in the user interface. The user interface also occasionally forces plots to be redrawn, so that any missed updates will not cause a plot to completely freeze/fail to update.
3738

doc/scripting/genie_python/genie_python-Troubleshooting.md

Lines changed: 38 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
### Where are the logs?
66

7-
Genie_python writes its logs to `C:\Instrument\var\logs\genie_python`.
7+
`genie_python` writes its logs to `C:\Instrument\var\logs\genie_python`.
88

99
### What does `ERROR: CAException` mean when it is in the log?
1010

@@ -15,35 +15,54 @@ The following is written to the log when a virtual circuit disconnects from the
1515
2018-05-21T15:21:31 (CA) (15712) ERROR: CAException: type=6 state=192 op=0 file=..\getCopy.cpp lineNo=92
1616
```
1717

18-
The time stamp on these are for the first `get_pv` call or equivalent after a disconnect.
18+
The time stamp on these are for the first {external+genie_python:py:obj}`get_pv <genie.get_pv>` call or equivalent after a disconnect.
1919

2020
## Command problems
2121

22-
### Can not set or get a block reports disconnected
22+
### Can not set or get a block; reports disconnected
2323

2424
There can be multiple problems, check:
2525

2626
1. Block exists
2727
1. Block is spelt correctly, use `b.` and autocomplete
28-
1. Try getting the underlying PV `g.get_pv("IN:<instrument>:CS:SB:<Block name?")`
29-
1. Restart the GUI genie_python console
28+
1. Try getting the underlying PV `g.get_pv("IN:<instrument>:CS:SB:<Block name>")`
29+
1. Restart the GUI Python console
3030

31-
## Import problems
31+
## Problems finding a python interpreter
3232

33-
### Can't find Python 3
33+
### Can't find the Uktena Python distribution
3434

3535
If you get an error message similar to
3636

3737
```
3838
*** Cannot find GENIE-PYTHON 3 - some things are not likely to work ***
3939
```
40-
on running `config_env.bat`, you need to ensure you have Python 3 available on your system.
40+
on running `config_env.bat`, you need to ensure you have the {doc}`/system_components/Python` installed on your system.
41+
You may need to follow the {doc}`/system_components/python/Building-and-installing-uktena` instructions.
4142

42-
## Other Issues
43+
```{note}
44+
As of October 2025, many processes in the IBEX backend depend on the Uktena python distribution. However, we are
45+
gradually migrating these to use {doc}`python virtual environments </system_components/python/Python-venvs>`; the eventual goal is that Uktena will not be required
46+
for the IBEX server backend.
47+
```
48+
49+
### No appropriate `venv` has been created for a backend process
4350

44-
### Can not set change users
51+
We are gradually migrating our server-side processes to use {doc}`uv python environments </system_components/python/Python-venvs>`.
4552

46-
Users seems not to get set properly using g.change_users, see ticket [5812](https://github.com/ISISComputingGroup/IBEX/issues/5812). Look into this it is more than a one off.
53+
These virtual environments are created on instruments [by the IBEX deployment script](https://github.com/ISISComputingGroup/ibex_utils/blob/b5998462ddd4d5aa4123e30104166043151cefea/installation_and_upgrade/ibex_install_utils/tasks/system_tasks.py#L146). If that step has previously been missed or failed during a deployment, it will need to be re-run.
54+
55+
If you need to do this manually for one specific module, you may run:
56+
```
57+
rmdir /s /q .venv
58+
uv venv .venv
59+
uv pip sync requirements-frozen.txt
60+
```
61+
at the top-level of the relevant module. Modules using this approach will have a `requirements-frozen.txt`.
62+
63+
On a developer machine, the virtual environments are created by the [developer update script](https://github.com/ISISComputingGroup/ibex_utils/blob/master/installation_and_upgrade/developer_update.bat); if you are missing virtual environments on your developer machine, you will need to re-run that script.
64+
65+
## Other Issues
4766

4867
### Repeated error messages in console while waiting
4968

@@ -55,9 +74,13 @@ If you get repeated errors of the form:
5574
```
5675
You may need to restart the genie_python session. The root cause of this issue is currently unknown. See ticket [5893](https://github.com/ISISComputingGroup/IBEX/issues/5893) for details, including a script which can scan all instruments for occurrences of this issue. If this issue is seen again, please create a new ticket to investigate further and also link it here.
5776

58-
### can read local PVs from instrument but not e.g. `CS:INSTLIST` or accelerator ones like beam current
77+
### Can read local PVs but not central PVs
5978

60-
In one case this was due to the firewall rule for `A:\python3\python.exe` had been disabled - a process firewall exception is needed to allow it to receive the UDP name query reply
79+
Central PVs could include:
80+
- `CS:INSTLIST` (the instrument list)
81+
- Accelerator PVs, for example beam current
82+
83+
In one case, this was due to the firewall rule for `A:\python3\python.exe` which had been disabled - a process firewall exception is needed to allow it to receive the UDP name query reply.
6184

6285
### Can't import channel-access modules
6386

@@ -89,7 +112,7 @@ When trying to import channel access libraries (`CaChannel`, `pcaspy`, `aioca`,
89112

90113
It's also technically possible to replace `import pip` with:
91114

92-
```
115+
```python
93116
import _distutils_hack
94117
_distutils_hack.remove_shim()
95118
import pip
@@ -101,4 +124,4 @@ But this is not recommended for obvious reasons.
101124

102125
Pyright keeps a cache directory in `c:\Users\<user>\.cache\pyright-python`, this can get corrupted, if it does get corrupted pyright will entirely fail to execute. This cache directory can be deleted (at the cost of the next script-check operation being much slower).
103126

104-
Error from `g.load_script` will be a `json.decoder.JSONDecodeError` as pyright does not return JSON in this case (but rather, returns some non-JSON error message).
127+
Error from {external+genie_python:py:obj}`g.load_script <genie.load_script>` will be a `json.decoder.JSONDecodeError` as pyright does not return JSON in this case (but rather, returns some non-JSON error message).
Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,28 @@
11
# `genie_python` script checking (linting)
22

3-
On `g.load_script` genie_python now runs pylint on the scripts. This help the user see errors before the script is run. However sometimes this causes its own issues. There is a {external+ibex_user_manual:doc}`page in the user manual <scripting/Error-Checking-Troubleshooting>` describing what the user should do.
3+
On {external+genie_python:py:obj}`g.load_script <genie.load_script>` genie_python now runs pylint on the scripts. This help the user see errors before the script is run. However sometimes this causes its own issues. There is a {external+ibex_user_manual:doc}`page in the user manual <scripting/Error-Checking-Troubleshooting>` describing what the user should do.
44

5-
Here are some more tips that we don't necessarily want to encourage.
5+
If a warning cannot be fixed, and you are sure the code is otherwise correct, warnings can be ignored from a line by adding a comment:
66

7-
Warnings can be removed from a line by adding a comment
7+
```python
8+
some_code() # pylint disable=<warning name>
9+
```
810

9-
`<line> # pylint disable=<warning name>`
11+
For example:
12+
```python
13+
from IMAT_library import * # pylint: disable=wildcard-import, unused-wildcard-import
14+
```
1015

11-
e.g. `from IMAT_library import * # pylint: disable=wildcard-import, unused-wildcard-import`
16+
If the error is a pyright (typing) error, as opposed to a pylint error, then the comment syntax is:
1217

18+
```python
19+
some_code() # pyright: ignore
20+
```
1321

1422
### Linting dynamically defined variables
23+
1524
Python allows programmers to set attributes dynamically using expressions like `locals()['foo'] = 1`, which creates a local variable called `foo` with value `1`. Pylint doesn't support dynamic assignment, so if `foo` was subsequently referenced in the code it would be counted as an undefined variable.
1625

17-
In cases where we need to lint scripts containing dynamic assignments, we can write a Pylint [transform plugin](http://pylint.pycqa.org/en/latest/how_tos/transform_plugins.html) to let Pylint know that the dynamically assigned variables are OK and should not be counted as undefined. This has been done [here](https://github.com/ISISComputingGroup/genie_python/blob/0a5f5093486e85e550b8168810e3d5cd762e34ff/Lib/site-packages/genie_python/scanning_instrument_pylint_plugin.py) to support dynamic assignments in the [SCANS library](https://github.com/ISISComputingGroup/IBEX/issues/5214), where some scripts were dynamically adding all methods of classes derived from `ScanningInstrument` to the local module.
26+
In cases where we need to lint scripts containing dynamic assignments, we can write a Pylint [transform plugin](http://pylint.pycqa.org/en/latest/how_tos/transform_plugins.html) to let Pylint know that the dynamically assigned variables are OK and should not be counted as undefined. This has been done [here](https://github.com/ISISComputingGroup/genie/blob/19cdfeedaf5ec9107f0328a69204b621858c859a/src/genie_python/scanning_instrument_pylint_plugin.py#L14) to support dynamic assignments in the [SCANS library](https://github.com/ISISComputingGroup/IBEX/issues/5214), where some scripts were dynamically adding all methods of classes derived from `ScanningInstrument` to the local module.
1827

1928

doc/scripting/instrument-scripts.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
# Shared Instrument Scripts
22

3-
The general instrument scripts are in this [repository](https://github.com/ISISNeutronMuon/InstrumentScripts) and include scripts like `do_sans` and `do_trans`, as well as the (old) scans library.
3+
The general instrument scripts are in this [repository](https://github.com/ISISNeutronMuon/InstrumentScripts). These scripts include:
4+
- The ['old' scans library](https://pygenie-scans.readthedocs.io/en/latest/index.html); as of October 2025, this is used by SANS instruments and reflectometers, but is being gradually replaced by {doc}`Bluesky-based scans <Bluesky-scanning>`
5+
- A shared SANS scripting framework. Contains definitions of `do_sans` and `do_trans`
6+
- Shared utilities for Muon beamlines, for example including:
7+
* Background plot configuration (using {doc}`/specific_iocs/other/Background-Script-IOC` and {doc}`Matplotlib`)
8+
* {doc}`Zero-field system </specific_iocs/magnets/Zero-field-controller>` calibration routines
9+
* {doc}`DAE pre & post commands </specific_iocs/dae/DAE-Pre-and-Post-commands>`
10+
11+
## Deployment
412

513
During IBEX deployment, an optional step has been added to the deploy script (see [ticket](https://github.com/ISISComputingGroup/IBEX/issues/7914)
614
for details) to pull the latest master branch of the scripts repository and attempt an automatic merge with the local branch.

doc/system_components/Python.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Python (Uktena)
1+
# Python (including Uktena, `uv`)
22

33
```{toctree}
44
:glob:

doc/scripting/uv.md renamed to doc/system_components/python/Python-venvs.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{#uv}
2-
# `uv` and python environments
2+
# Virtual environments (`uv`)
33

44
[`uv`](https://github.com/astral-sh/uv) is a Python package and project manager. See [`uv`'s docs](https://docs.astral.sh/uv/) for more information.
55

0 commit comments

Comments
 (0)