diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml index 2413f979..3dad078f 100644 --- a/.github/workflows/publish-pypi.yml +++ b/.github/workflows/publish-pypi.yml @@ -1,6 +1,7 @@ -# This workflow will upload a Python Package using flit when a release is -# created. For more information see: -# https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries +# This workflows will upload a Python Package when a release is created. +# For more information see: +# - https://docs.pypi.org/trusted-publishers/adding-a-publisher/ +# - https://github.com/pypa/gh-action-pypi-publish name: PyPI upload @@ -12,28 +13,27 @@ jobs: publish_pypi: name: Publish package to PyPI runs-on: ubuntu-latest + permissions: + id-token: write steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 + - uses: actions/checkout@v3 + with: + fetch-depth: 0 - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: '3.x' + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.x' - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install wheel twine setuptools + - name: Build package + run: | + set -vxeuo pipefail + python -m pip install --upgrade pip + pip install wheel setuptools + python setup.py sdist bdist_wheel - - name: Build and publish - env: - TWINE_USERNAME: __token__ - # The PYPI_PASSWORD must be a pypi token with the "pypi-" prefix with sufficient permissions to upload this package - # https://pypi.org/help/#apitoken - TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }} - run: | - python setup.py sdist bdist_wheel - twine upload dist/* + - name: Publish wheels to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 + with: + packages-dir: ./dist/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 660c5c84..c54fb967 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -8,7 +8,7 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/ambv/black - rev: 23.1.0 + rev: 23.3.0 hooks: - id: black - repo: https://github.com/pycqa/flake8 diff --git a/docs/source/notebooks-new-api.rst b/docs/source/examples.rst similarity index 67% rename from docs/source/notebooks-new-api.rst rename to docs/source/examples.rst index 70aa7165..b69d3afd 100644 --- a/docs/source/notebooks-new-api.rst +++ b/docs/source/examples.rst @@ -1,5 +1,5 @@ -Notebooks (new API) -=================== +Examples +======== .. toctree:: :maxdepth: 2 diff --git a/docs/source/index.rst b/docs/source/index.rst index fdaf9d48..fd6bf1a3 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -10,7 +10,6 @@ sirepo-bluesky Documentation :maxdepth: 2 installation - notebooks-old-api - notebooks-new-api + examples simulations release-history diff --git a/docs/source/notebooks-old-api.rst b/docs/source/notebooks-old-api.rst deleted file mode 100644 index db4a0bbe..00000000 --- a/docs/source/notebooks-old-api.rst +++ /dev/null @@ -1,8 +0,0 @@ -Notebooks (old API) -=================== - -.. toctree:: - :maxdepth: 2 - - notebooks/srw.ipynb - notebooks/shadow.ipynb diff --git a/docs/source/notebooks/shadow.ipynb b/docs/source/notebooks/shadow.ipynb deleted file mode 100644 index c7ef5761..00000000 --- a/docs/source/notebooks/shadow.ipynb +++ /dev/null @@ -1,113 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "# Run Sirepo/Shadow simulations with Bluesky\n", - "\n", - "This section is based on the **basic** example.\n", - "\n", - "**Hint**: See the [List of predefined simulations in Sirepo](../simulations.rst) for examples of identifiers for different beamlines." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Run \"Beamline\" Shadow simulations\n", - "\n", - "In this example, we run a single Shadow simulation and collect the resulting averaged intensity and corresponding 2D intensity distribution from the \"Watchpoint\" report on the \"Beamline\" page of Sirepo/Shadow app." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Start ``ipython`` and run the following where ``sim_id`` is the UID for the simulation we are working with:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "%run -i ../../../examples/prepare_det_env.py\n", - "\n", - "from sirepo_bluesky.shadow_detector import SirepoShadowDetector\n", - "\n", - "shadow_det = SirepoShadowDetector(\n", - " name=\"shadow_det\",\n", - " sim_id=\"00000001\",\n", - " sim_report_type=\"default_report\",\n", - " sirepo_server=\"http://localhost:8000\",\n", - " root_dir=\"/tmp/sirepo-bluesky-data\",\n", - ")\n", - "\n", - "shadow_det.select_optic(\"Aperture\")\n", - "shadow_det.create_parameter(\"horizontalSize\")\n", - "shadow_det.create_parameter(\"verticalSize\")\n", - "shadow_det.read_attrs = [\"image\", \"mean\"]\n", - "shadow_det.configuration_attrs = [\"horizontal_extent\", \"vertical_extent\", \"shape\"]\n", - "\n", - "shadow_det.active_parameters[\"Aperture_horizontalSize\"].set(1.0)\n", - "shadow_det.active_parameters[\"Aperture_verticalSize\"].set(1.0)\n", - "shadow_det.duration.kind = \"hinted\"\n", - "\n", - "uid, = RE(bp.count([shadow_det]))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We can access the data as the last item in the database (`db[-1]`) or directly via the returned `uid`, which when plotted as an image will look like:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "hdr = db[uid]\n", - "imgs = np.array(list(hdr.data(f'{shadow_det.name}_image')))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "cfg = hdr.config_data(shadow_det.name)[\"primary\"][0]\n", - "hor_ext = cfg[f\"{shadow_det.name}_horizontal_extent\"]\n", - "vert_ext = cfg[f\"{shadow_det.name}_vertical_extent\"]\n", - "plt.imshow(imgs[0], aspect=\"equal\", extent=(*hor_ext, *vert_ext))" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/docs/source/notebooks/srw.ipynb b/docs/source/notebooks/srw.ipynb deleted file mode 100644 index d7ccdb8d..00000000 --- a/docs/source/notebooks/srw.ipynb +++ /dev/null @@ -1,245 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Run Sirepo/SRW simulations with Bluesky\n", - "\n", - "This section is based on the **Young's Double Slit Experiment** Sirepo example\n", - "that can be found in the wavefront propagation folder on the SRW simulations\n", - "section.\n", - "\n", - "**Hint**: See the [List of predefined simulations in Sirepo](../simulations.rst) for examples of identifiers for different beamlines." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Run \"Source\" SRW simulations\n", - "\n", - "In this example, we run a simulation using the \"Single-Electron Spectrum\" report on the \"Source\" page of Sirepo/SRW app." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "%run -i ../../../examples/prepare_det_env.py\n", - "\n", - "import sirepo_bluesky.srw_detector as sd\n", - "import bluesky.plans as bp\n", - "\n", - "srw_det = sd.SirepoSRWDetector(sim_id=\"00000000\", sim_type=\"srw\",\n", - " source_simulation=True,\n", - " sirepo_server=\"http://localhost:8000\",\n", - " root_dir=\"/tmp/sirepo-bluesky-data\")\n", - "\n", - "srw_det.configuration_attrs = [\"photon_energy\", \"shape\"]\n", - "srw_det.duration.kind = 'hinted'\n", - "\n", - "uid, = RE(bp.count([srw_det]))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We can observe the produced spectrum as:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "hdr = db[uid]\n", - "cfg = hdr.config_data(srw_det.name)[\"primary\"][0]\n", - "energies = cfg[f\"{srw_det.name}_photon_energy\"]\n", - "spectrum, = hdr.data(f\"{srw_det.name}_image\")\n", - "plt.plot(energies, spectrum)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Run \"Beamline\" SRW simulations sequentially\n", - "\n", - "In this example, we scan the horizontal size of the aperture and collect the resulting averaged intensities and corresponding 2D intensity distributions from the \"Watchpoint\" report on the \"Beamline\" page of Sirepo/SRW app." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Start ``ipython`` and run the code in the following cell. Note that ``sim_id`` may be replaced by the identifier for any supported Sirepo simulation." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "%run -i ../../../examples/prepare_det_env.py\n", - "\n", - "import sirepo_bluesky.srw_detector as sd\n", - "import bluesky.plans as bp\n", - "\n", - "srw_det = sd.SirepoSRWDetector(sim_id=\"00000000\", sim_type=\"srw\",\n", - " sirepo_server=\"http://localhost:8000\",\n", - " root_dir=\"/tmp/sirepo-bluesky-data\")\n", - "\n", - "srw_det.select_optic(\"Aperture\")\n", - "param1 = srw_det.create_parameter(\"horizontalSize\")\n", - "param2 = srw_det.create_parameter(\"verticalSize\")\n", - "srw_det.configuration_attrs = [\"horizontal_extent\", \"vertical_extent\", \"shape\"]\n", - "srw_det.duration.kind = 'hinted'\n", - "\n", - "uid, = RE(bp.scan([srw_det], param1, 0.0, 0.25, 11))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We can access the data as the last item in the database (`db[-1]`) or directly via the returned `uid`, which when plotted as an image will look like:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "hdr = db[uid]\n", - "hdr.table()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "imgs = list(hdr.data(f\"{srw_det.name}_image\"))\n", - "cfg = hdr.config_data(srw_det.name)[\"primary\"][0]\n", - "hor_ext = cfg[f\"{srw_det.name}_horizontal_extent\"]\n", - "vert_ext = cfg[f\"{srw_det.name}_vertical_extent\"]\n", - "plt.imshow(imgs[-2], aspect=\"equal\", extent=(*hor_ext, *vert_ext))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Run \"Beamline\" SRW simulations in parallel\n", - "\n", - "In this example, we are using [Bluesky's fly scans](https://blueskyproject.io/bluesky/async.html#flying)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "%run -i ../../../examples/prepare_flyer_env.py\n", - "\n", - "import bluesky.plans as bp\n", - "import sirepo_bluesky.sirepo_flyer as sf" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We can create 3 different simulations that change 4 parameters at a time:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "params_to_change = []\n", - "key1 = \"Aperture\"\n", - "key2 = \"Lens\"\n", - "key3 = \"Obstacle\"\n", - "for i in range(1, 3 + 1):\n", - " parameters_update1 = {\"horizontalSize\": i * 0.1, \"verticalSize\": (16 - i) * 0.1}\n", - " parameters_update2 = {\"horizontalFocalLength\": i + 7}\n", - " parameters_update3 = {\"horizontalSize\": 6 - i}\n", - " params_to_change.append({key1: parameters_update1,\n", - " key2: parameters_update2,\n", - " key3: parameters_update3})" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To create the flyer and run a fly scan, where ``sim_id`` is the UID of this simulation, we run:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "sirepo_flyer = sf.SirepoFlyer(sim_id=\"00000000\",\n", - " server_name=\"http://localhost:8000\",\n", - " root_dir=\"/tmp/sirepo-bluesky-data\",\n", - " params_to_change=params_to_change,\n", - " watch_name=\"W60\")\n", - "\n", - "uid, = RE(bp.fly([sirepo_flyer]))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We access the data in the same manner as before:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "hdr = db[uid]\n", - "hdr.table(stream_name=\"sirepo_flyer\")" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/docs/source/release-history.rst b/docs/source/release-history.rst index 4768baee..d7f06b49 100644 --- a/docs/source/release-history.rst +++ b/docs/source/release-history.rst @@ -2,6 +2,36 @@ Release History =============== +v0.6.2 (2023-06-09) +------------------- +This is a maintenance release with small API, tests, packaging, and documentation updates. + +API +... +- Fixed the ``BeamStatisticsReport``'s default values which cannot be a + dictionary (discovered when using `bluesky v1.11.0 + `_). + +Packaging +......... +- Added ``xraylib`` to the list of requirements as ``shadow3`` does not + automatically install it, and imports of ``xraylib`` will print the + information about that missing library, even for irrelevant code (like + MAD-X). Adding the package as a dependency explicitly silences the messages. + +- Remove pinning of the ``urllib3`` package as the issue is resolved on the + ``vcrpy`` side. + +Documentation +............. +- Updated databroker configuration instructions for Windows. +- Removed old API examples. + +Tests +..... +- Removed a test for ``BeamStatisticsReport`` for the old API. + + v0.6.1 (2023-05-26) ------------------- This is a maintenance release primarily addressing the packaging, continuous @@ -14,8 +44,8 @@ API Tests ..... -- Recreated `vcrpy `_ cassettes for the - tests using old API (to be deprecated in the future). +- Recreated `vcrpy `_ cassettes for + the tests using old API (to be deprecated in the future). - Fixed beam statistics report test. CI improvements diff --git a/sirepo_bluesky/sirepo_ophyd.py b/sirepo_bluesky/sirepo_ophyd.py index 49b4b640..1df3874f 100644 --- a/sirepo_bluesky/sirepo_ophyd.py +++ b/sirepo_bluesky/sirepo_ophyd.py @@ -257,7 +257,7 @@ class BeamStatisticsReport(DeviceWithJSONData): # NOTE: TES aperture changes don't seem to change the beam statistics # report graph on the website? - report = Cpt(Signal, value={}, kind="normal") + report = Cpt(Signal, value="", kind="normal") # values are always strings, not dictionaries def __init__(self, connection, *args, **kwargs): super().__init__(*args, **kwargs) @@ -284,11 +284,11 @@ def trigger(self, *args, **kwargs): def stage(self): super().stage() - self.report.put({}) + self.report.put("") def unstage(self): super().unstage() - self.report.put({}) + self.report.put("") class SirepoSignalGrazingAngle(SirepoSignal): diff --git a/sirepo_bluesky/tests/test_shadow_det.py b/sirepo_bluesky/tests/test_shadow_det.py index a5a50e9d..6b2c6f99 100644 --- a/sirepo_bluesky/tests/test_shadow_det.py +++ b/sirepo_bluesky/tests/test_shadow_det.py @@ -1,5 +1,3 @@ -import json - import bluesky.plans as bp import numpy as np import pytest @@ -57,72 +55,3 @@ def test_shadow_detector_docker_default_report(RE, db, tmpdir): mean = t.iloc[0]["shadow_det_mean"] assert mean == 9.7523, "incorrect mean value from bp.count" - - -@pytest.mark.docker -def test_shadow_detector_docker_beam_stats_report(RE, db, tmpdir): - _test_shadow_detector( - RE, - db, - tmpdir, - sim_id="00000002", - sim_report_type="beam_stats_report", - server_name="http://localhost:8000", - ) - - hdr = db[-1] - t = hdr.table() - assert list(t.columns) == [ - "time", - "shadow_det_image", - "shadow_det_mean", - "shadow_det_duration", - "shadow_det_photon_energy", - "shadow_det_beam_statistics_report", - ] - beam_statistics_report_str = t["shadow_det_beam_statistics_report"][1] - assert type(beam_statistics_report_str) is str - beam_statistics_report = json.loads(beam_statistics_report_str) - - available_fields = [ - "angxpzp", - "angxz", - "s", - "sigdix", - "sigdiz", - "sigmax", - "sigmaxpzp", - "sigmaxz", - "sigmaz", - "x", - "xi_x", - "xi_z", - "xp", - "z", - "zp", - "emit_x", - "emit_z", - "sigxdix", - "sigzdiz", - ] - - assert set(beam_statistics_report.keys()) == set(available_fields) - - length = 803 - - for field in available_fields: - assert np.array(beam_statistics_report[field]).shape == (length,) - - assert np.allclose(np.mean(beam_statistics_report["angxpzp"]), -6.709432215885232e-08) - assert np.allclose(np.mean(beam_statistics_report["angxz"]), 5.799778383039559e-07) - assert np.allclose(np.mean(beam_statistics_report["s"]), 33.527130759651484) - assert np.allclose(np.mean(beam_statistics_report["sigdix"]), 0.00010306010813853688) - assert np.allclose(np.mean(beam_statistics_report["sigdiz"]), 5.194134141905759e-05) - assert np.allclose(np.mean(beam_statistics_report["sigmax"]), 0.0003968859146781542) - assert np.allclose(np.mean(beam_statistics_report["sigmaxpzp"]), -2.317882293458049e-12) - assert np.allclose(np.mean(beam_statistics_report["sigmaxz"]), 6.3950298662456295e-09) - assert np.allclose(np.mean(beam_statistics_report["sigmaz"]), 0.00017662967956586314) - assert np.allclose(np.mean(beam_statistics_report["x"]), -1.742303638933747e-17) - assert np.allclose(np.mean(beam_statistics_report["xp"]), -9.277770695212126e-27) - assert np.allclose(np.mean(beam_statistics_report["z"]), -4.3043179437100645e-09) - assert np.allclose(np.mean(beam_statistics_report["zp"]), 2.5086128695294103e-13)