diff --git a/.github/workflows/compile_madng.yml b/.github/workflows/compile_madng.yml index dc8ca4e..d5f92c3 100644 --- a/.github/workflows/compile_madng.yml +++ b/.github/workflows/compile_madng.yml @@ -74,8 +74,8 @@ jobs: name: mad-Linux path: MAD/src/mad - build-macos-x86_64: - runs-on: macos-15-intel + build-macos-arm64: + runs-on: macos-15 defaults: run: shell: bash @@ -93,203 +93,121 @@ jobs: - name: Install build tools run: | - brew update - brew install gcc@12 make cmake automake autoconf libtool pkg-config curl + brew install gcc cmake automake autoconf libtool pkg-config curl - - name: Prepare compiler shims + - name: Select native compiler toolchain run: | set -euo pipefail - gcc_prefix="$(brew --prefix gcc@12)" - toolshim="${RUNNER_TEMP}/gcc-shim" - mkdir -p "${toolshim}" - - ln -sf "${gcc_prefix}/bin/gcc-12" "${toolshim}/gcc" - ln -sf "${gcc_prefix}/bin/g++-12" "${toolshim}/g++" - ln -sf "${gcc_prefix}/bin/gfortran-12" "${toolshim}/gfortran" - ln -sf "/usr/local/bin/make" "${toolshim}/make" - ln -sf "/usr/local/bin/cmake" "${toolshim}/cmake" - ln -sf "/usr/local/bin/pkg-config" "${toolshim}/pkg-config" - ln -sf "/usr/local/bin/libtool" "${toolshim}/libtool" - ln -sf "/usr/local/bin/ar" "${toolshim}/ar" - ln -sf "/usr/local/bin/ranlib" "${toolshim}/ranlib" + gcc_bin="$(ls /opt/homebrew/bin/gcc-[0-9]* | sort -V | tail -n1)" + ver="${gcc_bin##*-}" { - echo "${toolshim}" - echo "/usr/local/bin" - echo "$(brew --prefix)/bin" - } >> "${GITHUB_PATH}" - - - name: Select MAD-NG macOS Makefile - run: | - cp MAD/src/Makefile.macosx MAD/src/Makefile - python3 - <<'PY' - from pathlib import Path - - path = Path("MAD/src/Makefile") - text = path.read_text() - replacements = [ - ("CC := gcc-11", "CC := gcc"), - ("CXX := g++-11", "CXX := g++"), - ("FC := gfortran-11", "FC := gfortran"), - ("-fdiagnostics-all-candidates", ""), - ("-flto", ""), - ("-march=native", ""), - ("-mtune=native", ""), - ("-mfma", ""), - ] - for old, new in replacements: - text = text.replace(old, new) - path.write_text(text) - PY - - - name: Build MAD-NG dependencies (README order) + echo "CC=gcc-${ver}" + echo "CXX=g++-${ver}" + echo "FC=gfortran-${ver}" + echo "MACOSX_DEPLOYMENT_TARGET=14" + } >> "${GITHUB_ENV}" + + - name: Build native MAD-NG dependencies (lib/README.md) + env: + MAD_ROOT: ${{ github.workspace }}/MAD run: | set -euo pipefail echo "== Toolchain ==" - which gcc - gcc --version - which g++ - g++ --version - which gfortran - gfortran --version - - export OS=macosx - export MACOSX_DEPLOYMENT_TARGET=11 - export JOBS="$(sysctl -n hw.ncpu)" - export CC=gcc - export CXX=g++ - export FC=gfortran - export AR=ar - export RANLIB=ranlib - - mkdir -p MAD/bin/macosx - - cd MAD/lib - echo "== MAD/lib contents (before download) ==" - ls -la - - echo "== LuaJIT (README.luajit) ==" - rm -rf luajit - git clone https://github.com/MethodicalAcceleratorDesign/LuaJIT.git luajit - cd luajit - git checkout mad-patch - git pull + which "${CC}"; "${CC}" --version + which "${CXX}"; "${CXX}" --version + which "${FC}"; "${FC}" --version + + export MAD_BIN="${MAD_ROOT}/bin/macosx" + export MAD_DEPS="${RUNNER_TEMP}/mad-deps" + mkdir -p "${MAD_BIN}" "${MAD_DEPS}" + JOBS="$(sysctl -n hw.ncpu)" + + cd "${MAD_DEPS}" + git clone --depth 1 --branch mad-patch https://github.com/MethodicalAcceleratorDesign/LuaJIT.git luajit + git clone --depth 1 https://github.com/MethodicalAcceleratorDesign/luafilesystem.git lfs + git clone --depth 1 --branch v3.12.1 https://github.com/Reference-LAPACK/lapack.git lapack + git clone --depth 1 --branch v2.7.1 https://github.com/stevengj/nlopt.git nlopt + curl -fsSL -o fftw-3.3.10.tar.gz https://www.fftw.org/fftw-3.3.10.tar.gz + curl -fsSL -o nfft-3.5.3.tar.gz https://www-user.tu-chemnitz.de/~potts/nfft/download/nfft-3.5.3.tar.gz + curl -fsSL -o lpeg-1.1.0.tar.gz http://www.inf.puc-rio.br/~roberto/lpeg/lpeg-1.1.0.tar.gz + tar xzf fftw-3.3.10.tar.gz + tar xzf nfft-3.5.3.tar.gz + tar xzf lpeg-1.1.0.tar.gz + + echo "== LuaJIT ==" + cd "${MAD_DEPS}/luajit" make clean - make -j"${JOBS}" amalg PREFIX="$(pwd)" + make -j"${JOBS}" amalg PREFIX="$(pwd)" CC="${CC}" make install PREFIX="$(pwd)" - cp -f src/libluajit.a ../../bin/macosx/ - cd .. + cp -f src/libluajit.a "${MAD_BIN}/" - echo "== LFS (README.lfs) ==" - rm -rf lfs - git clone https://github.com/MethodicalAcceleratorDesign/luafilesystem.git lfs - cd lfs - make clean || true - make lfs.a - cp -f liblfs.a ../../bin/macosx/ - cd .. + echo "== FFTW3 ==" + cd "${MAD_DEPS}/fftw-3.3.10" + CC="${CC}" CFLAGS='-O3 -fPIC' ./configure --disable-shared --enable-static + make -j"${JOBS}" + cp -f .libs/libfftw3.a "${MAD_BIN}/" - echo "== LPEG (README.lpeg) ==" - rm -rf lpeg lpeg-1.1.0 lpeg-1.1.0.tar.gz - curl -fsSL -o lpeg-1.1.0.tar.gz http://www.inf.puc-rio.br/~roberto/lpeg/lpeg-1.1.0.tar.gz - tar xvzf lpeg-1.1.0.tar.gz - ln -s lpeg-1.1.0 lpeg - cd lpeg - python3 - <<'PY' - from pathlib import Path - import re - - path = Path("makefile") - text = path.read_text() - text = re.sub(r"^LUADIR[ \t]*=.*$", "LUADIR = ../luajit/include/luajit-2.1", text, flags=re.MULTILINE) - text = re.sub(r"^LUALIB[ \t]*=.*$", "LUALIB = ../luajit/lib/libluajit-5.1.a", text, flags=re.MULTILINE) - text = re.sub(r"^COPT[ \t]*=.*$", "COPT = -O3 -DNDEBUG", text, flags=re.MULTILINE) - path.write_text(text) - PY - make clean || true - make -j"${JOBS}" CC="${CC:-gcc}" LUADIR="../luajit/include/luajit-2.1" lpvm.o lpcap.o lptree.o lpcode.o lpprint.o lpcset.o - ar -r liblpeg.a lpvm.o lpcap.o lptree.o lpcode.o lpprint.o lpcset.o - ranlib liblpeg.a - cp -f liblpeg.a ../../bin/macosx/ - cd .. - - echo "== LAPACK (README.lapack) ==" - rm -rf lapack - git clone https://github.com/Reference-LAPACK/lapack lapack - cd lapack - cp -f make.inc.example make.inc - python3 - <<'PY' - from pathlib import Path - import re - - path = Path("make.inc") - text = path.read_text() - for key in ("CFLAGS", "FFLAGS", "FFLAGS_NOOPT"): - text = re.sub(rf"^({key}[ \t]*=[ \t]*)(?!-fPIC\b)", r"\1-fPIC ", text, flags=re.MULTILINE) - path.write_text(text) - PY + echo "== LuaFileSystem ==" + cd "${MAD_DEPS}/lfs" make clean || true - make -j"${JOBS}" blaslib - make -j"${JOBS}" lapacklib - cp -f librefblas.a ../../bin/macosx/ - cp -f liblapack.a ../../bin/macosx/ - cd .. - - echo "== FFTW3 (README.fftw3) ==" - rm -rf fftw3 fftw-3.3.10 fftw-3.3.10.tar.gz - curl -fsSL -o fftw-3.3.10.tar.gz ftp://ftp.fftw.org/pub/fftw/fftw-3.3.10.tar.gz - tar xvzf fftw-3.3.10.tar.gz - ln -s fftw-3.3.10 fftw3 - cd fftw3 - make clean || true - ./configure --disable-shared - make -j"${JOBS}" - cp -f .libs/libfftw3.a ../../bin/macosx/ - cd .. + make lfs.a CC="${CC}" AR=ar CFLAGS="-O3 -fPIC -I${MAD_DEPS}/luajit/src" + cp -f liblfs.a "${MAD_BIN}/" - echo "== NFFT3 (README.nfft3) ==" - rm -rf nfft3 nfft-3.5.3 nfft-3.5.3.tar.gz - curl -fsSL -o nfft-3.5.3.tar.gz https://www-user.tu-chemnitz.de/~potts/nfft/download/nfft-3.5.3.tar.gz - tar xvzf nfft-3.5.3.tar.gz - ln -s nfft-3.5.3 nfft3 - cd nfft3 + echo "== LPeg ==" + cd "${MAD_DEPS}/lpeg-1.1.0" make clean || true - ./configure --enable-all --disable-shared \ - --with-fftw3="$(pwd)"/../fftw3 \ - --with-fftw3-libdir="$(pwd)"/../fftw3/.libs \ - --with-fftw3-includedir="$(pwd)"/../fftw3/api - make -j"${JOBS}" - cp -f .libs/libnfft3.a ../../bin/macosx/ - cd .. - - echo "== NLOPT (README.nlopt) ==" - rm -rf nlopt - git clone https://github.com/stevengj/nlopt nlopt - cd nlopt - rm -rf build - mkdir -p build - cd build - cmake -DBUILD_SHARED_LIBS=OFF -DNLOPT_CXX=OFF .. + make -j"${JOBS}" CC="${CC}" LUADIR="${MAD_DEPS}/luajit/src" COPT='-O3 -DNDEBUG' \ + lpvm.o lpcap.o lptree.o lpcode.o lpprint.o lpcset.o + ar -rcs liblpeg.a lpvm.o lpcap.o lptree.o lpcode.o lpprint.o lpcset.o + cp -f liblpeg.a "${MAD_BIN}/" + + echo "== NLopt ==" + cd "${MAD_DEPS}/nlopt" + cmake -S . -B build-arm64 -DBUILD_SHARED_LIBS=OFF -DNLOPT_CXX=OFF -DNLOPT_FORTRAN=OFF \ + -DCMAKE_C_COMPILER="${CC}" -DCMAKE_OSX_ARCHITECTURES=arm64 -DCMAKE_POLICY_VERSION_MINIMUM=3.5 + CMAKE_POLICY_VERSION_MINIMUM=3.5 cmake --build build-arm64 -j"${JOBS}" + cp -f build-arm64/libnlopt.a "${MAD_BIN}/" + + echo "== LAPACK and reference BLAS ==" + cd "${MAD_DEPS}/lapack" + cmake -S . -B build-arm64 -DBUILD_SHARED_LIBS=OFF -DBUILD_TESTING=OFF \ + -DCMAKE_C_COMPILER="${CC}" -DCMAKE_Fortran_COMPILER="${FC}" -DCMAKE_OSX_ARCHITECTURES=arm64 + cmake --build build-arm64 -j"${JOBS}" --target blas lapack + cp -f build-arm64/lib/libblas.a "${MAD_BIN}/librefblas.a" + cp -f build-arm64/lib/liblapack.a "${MAD_BIN}/" + + echo "== NFFT3 ==" + cd "${MAD_DEPS}/nfft-3.5.3" + CC="${CC}" CFLAGS='-O3 -fPIC' ./configure --enable-all --disable-shared \ + --with-fftw3="${MAD_DEPS}/fftw-3.3.10" \ + --with-fftw3-libdir="${MAD_DEPS}/fftw-3.3.10/.libs" \ + --with-fftw3-includedir="${MAD_DEPS}/fftw-3.3.10/api" make -j"${JOBS}" - cp -f libnlopt.a ../../../bin/macosx/ + cp -f .libs/libnfft3.a "${MAD_BIN}/" + + echo "== Verify native archives ==" + lipo -info "${MAD_BIN}"/*.a - name: Compile MAD-NG working-directory: MAD/src + env: + MAD_DEPS: ${{ runner.temp }}/mad-deps run: | echo "== Toolchain ==" - which gcc - gcc --version - which g++ - g++ --version - which gfortran - gfortran --version + which "${CC}"; "${CC}" --version + which "${CXX}"; "${CXX}" --version + which "${FC}"; "${FC}" --version - make SHELL=/bin/bash CC=gcc CXX=g++ FC=gfortran + make -f Makefile.macosx clean + make -f Makefile.macosx SHELL=/bin/bash CC="${CC}" CXX="${CXX}" FC="${FC}" LIB="${MAD_DEPS}" + lipo -info mad + chmod 755 mad - name: Upload binary uses: actions/upload-artifact@v4 with: - name: mad-macOS-x86_64 + name: mad-macOS-arm64 path: MAD/src/mad diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml index 0940240..40bd958 100644 --- a/.github/workflows/python-publish.yml +++ b/.github/workflows/python-publish.yml @@ -52,7 +52,7 @@ jobs: if: ${{ vars.PYMADNG_BUILD_MADNG_FROM_SOURCE != 'false' }} uses: actions/download-artifact@v5 with: - name: mad-macOS-x86_64 + name: mad-macOS-arm64 path: build/mad-Darwin - name: Add compiled MAD-NG binaries to the package if: ${{ vars.PYMADNG_BUILD_MADNG_FROM_SOURCE != 'false' }} @@ -64,8 +64,8 @@ jobs: if: ${{ vars.PYMADNG_BUILD_MADNG_FROM_SOURCE == 'false' }} run: | mkdir -p src/pymadng/bin - curl --fail --location https://madx.web.cern.ch/releases/madng/1.1/mad-linux-1.1.14 -o src/pymadng/bin/mad_Linux - curl --fail --location https://madx.web.cern.ch/releases/madng/1.1/mad-macos-1.1.14 -o src/pymadng/bin/mad_Darwin + curl --fail --location https://madx.web.cern.ch/releases/madng/1.1/mad-linux-1.1.15 -o src/pymadng/bin/mad_Linux + curl --fail --location https://madx.web.cern.ch/releases/madng/1.1/mad-macos-1.1.15 -o src/pymadng/bin/mad_Darwin chmod +x src/pymadng/bin/mad_Linux src/pymadng/bin/mad_Darwin - name: Build package run: python -m build diff --git a/.github/workflows/test-pymadng.yml b/.github/workflows/test-pymadng.yml index 0ba9c39..6be932c 100644 --- a/.github/workflows/test-pymadng.yml +++ b/.github/workflows/test-pymadng.yml @@ -33,13 +33,13 @@ jobs: - name: Get MAD Binaries run: | mkdir ./src/pymadng/bin - curl https://madx.web.cern.ch/releases/madng/1.1/mad-linux-1.1.14 -o ./src/pymadng/bin/mad_Linux - curl https://madx.web.cern.ch/releases/madng/1.1/mad-macos-1.1.14 -o ./src/pymadng/bin/mad_Darwin + curl https://madx.web.cern.ch/releases/madng/1.1/mad-linux-1.1.15 -o ./src/pymadng/bin/mad_Linux + curl https://madx.web.cern.ch/releases/madng/1.1/mad-macos-1.1.15 -o ./src/pymadng/bin/mad_Darwin chmod +x ./src/pymadng/bin/mad_Linux ./src/pymadng/bin/mad_Darwin - name: Install dependencies run: | python -m pip install --upgrade pip - python -m pip install -e .[tfs] + python -m pip install -e .[tfs,jupyter] - name: Test with python run: | python -m unittest tests/*.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ee3e6f..03a26bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ +0.10.0 (2026/09/06) \ +Major behaviour change: MAD-NG's stdout/stderr are now always piped back through Python. +This means the output has to be captured and manually handled on each send and receive +command. Due to the deliberate asynchronous design of the PyMAD-NG interface, this +means that the output may be delayed and not appear immediately after MAD-NG sends it. +The reason for this change was to support environments where stdout/stderr are not real +OS file descriptors, such as Jupyter notebooks. \ +Bump MAD-NG to 1.1.15. \ +Fixed a stack overflow in the `ex-recv-lhc` deferred-expressions example (hit a +recursive call). \ +Fixed an incorrect range-construction snippet in the `ex-LowLevel` example. \ +Added `examples/ex-jupyter` and automated notebook execution tests. + 0.9.6 (2026/07/11) \ -Added way to compile on pull request and new release. +Added way to compile on pull request and new release. 0.9.5 (2026/07/11) \ Update pymadng version diff --git a/examples/ex-LowLevel/ex-send-multypes.py b/examples/ex-LowLevel/ex-send-multypes.py index 0ae002a..17271ba 100644 --- a/examples/ex-LowLevel/ex-send-multypes.py +++ b/examples/ex-LowLevel/ex-send-multypes.py @@ -103,7 +103,7 @@ # Receive ranges from MAD mad.send(""" -py:send(3..11..2) +py:send(MAD.range(3, 11, 2)) py:send(MAD.nrange(3.5, 21.4, 12)) py:send(MAD.nlogrange(1, 20, 20)) """) diff --git a/examples/ex-jupyter/ex-jupyter.ipynb b/examples/ex-jupyter/ex-jupyter.ipynb new file mode 100644 index 0000000..2a71e96 --- /dev/null +++ b/examples/ex-jupyter/ex-jupyter.ipynb @@ -0,0 +1,158 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Using pymadng in a Jupyter notebook\n", + "\n", + "`pymadng` runs MAD-NG as a subprocess and talks to it over a pair of pipes, but MAD-NG's own `print`/`io.write` output is a separate stream that is forwarded straight to Python's `stdout`/`stderr`. This notebook works as a simple check to see if this is working correctly. If you see the output of MAD-NG's `print` statements in the notebook, then everything is working as expected." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "from pathlib import Path\n", + "\n", + "import matplotlib.pyplot as plt\n", + "\n", + "from pymadng import MAD\n", + "\n", + "os.chdir(Path.cwd()) # run from this notebook's directory so fodo.seq is found\n", + "\n", + "mad = MAD() # no stdout= argument needed: the notebook's stdout is detected automatically" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "MAD-NG's own `print` calls stream directly into the cell output below, live, as the sequence is loaded and twiss is computed:" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "mad.send(\"\"\"\n", + "print(\"loading the fodo sequence...\")\n", + "MADX:load(\"fodo.seq\", \"fodo.mad\")\n", + "local seq in MADX\n", + "seq.beam = beam -- use default beam\n", + "print(\"running twiss...\")\n", + "mtbl, mflw = twiss {sequence=seq, implicit=true, nslice=10, save=\"atbody\"}\n", + "print(\"done\")\n", + "\"\"\")" + ] + }, + { + "cell_type": "markdown", + "id": "f1932487", + "metadata": {}, + "source": [ + "The output does not come out immediately. The python interface works asynchronously, so the MAD-NG process is running in the background while the notebook kernel is free to do other things. We only see the ouputs once we interact and MAD-NG has had a chance to flush its output buffers. Since the recv call is blocking, typically at this point you will receive this output. " + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "loading the fodo sequence...\n", + "running twiss...\n", + "done\n" + ] + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.plot(mad.mtbl.s, mad.mtbl.beta11, label=r\"$\\beta_{11}$\")\n", + "plt.plot(mad.mtbl.s, mad.mtbl.beta22, label=r\"$\\beta_{22}$\")\n", + "plt.xlabel(\"s [m]\")\n", + "plt.ylabel(r\"$\\beta$ [m]\")\n", + "plt.legend()\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['beam', 'beta0', 'element', 'match', 'mflw', 'mtable', 'mtbl', 'object', 'py', 'sequence', 'survey', 'track', 'twiss']\n", + "['MAD', 'MADX', 'arg', 'assert', 'beam', 'beta0', 'bit', 'close', 'collectgarbage', 'coroutine', 'create_deferred_expression', 'debug', 'dofile', 'element', 'error', 'eval', 'evaluate_in_madx_environment', 'ffi', 'gcinfo', 'getfenv', 'getmetatable', 'globals', 'help', 'history', 'io', 'ipairs', 'jit', 'load', 'load', 'loadfile', 'loadfile', 'loadstring', 'match', 'math', 'mflw', 'module', 'mtable', 'mtbl', 'newproxy', 'next', 'object', 'os', 'package', 'pairs', 'pcall', 'print', 'protected_send', 'psend', 'py', 'py_name', 'quote_strings', 'rawequal', 'rawget', 'rawlen', 'rawset', 'receive', 'recv', 'recv_and_exec', 'recv_vars', 'require', 'select', 'send', 'send_cpx_tpsa', 'send_logrange', 'send_range', 'send_tpsa', 'send_vars', 'sequence', 'setfenv', 'setmetatable', 'show', 'string', 'survey', 'table', 'tonumber', 'tostring', 'track', 'twiss', 'type', 'unpack', 'xpcall']\n" + ] + } + ], + "source": [ + "all_in_mad = dir(mad)\n", + "print(mad.globals())\n", + "print(all_in_mad)\n", + "mad.close()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bbbc4189", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "accpy (3.11.4.final.0)", + "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.11.4" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/examples/ex-jupyter/fodo.seq b/examples/ex-jupyter/fodo.seq new file mode 100644 index 0000000..3f96b5d --- /dev/null +++ b/examples/ex-jupyter/fodo.seq @@ -0,0 +1,15 @@ +circum = 60; +lcell = 20; +f := lcell/sin(pi/4)/4; +k := 1/f; +qf: multipole, knl := {0, k}; +qd: multipole, knl := {0, -k}; + +seq: sequence, refer=centre, l=circum; +qf: qf, at = 0; +qd: qd, at = 0.5 * lcell; +qf: qf, at = 1.0 * lcell; +qd: qd, at = 1.5 * lcell; +qf: qf, at = 2.0 * lcell; +qd: qd, at = 2.5 * lcell; +endsequence; diff --git a/examples/ex-ps-twiss/ex-ps-twiss.mad b/examples/ex-ps-twiss/ex-ps-twiss.mad new file mode 100644 index 0000000..703654c --- /dev/null +++ b/examples/ex-ps-twiss/ex-ps-twiss.mad @@ -0,0 +1,29 @@ +! Equivalent MAD-NG script for examples/ex-ps-twiss/ex-ps-twiss.py +local beam, survey, twiss in MAD +local melmcol in MAD.gphys + +local psbeam = beam { particle = 'proton', pc = 2.794987 } +MADX.BEAM = psbeam +MADX.BRHO = psbeam.brho +MADX:load('ps_unset_vars.mad') +MADX:load('ps_mu.seq') +MADX:load('ps_ss.seq') +MADX:load('ps_fb_lhc.str') + +local ps in MADX +ps.beam = psbeam +local srv, mflw = survey { sequence = ps } + +srv:write('PS_survey_py.tfs', + {"name", "kind", "s", "l", "angle", "x", "y", "z", "theta"}) + +local mtbl = twiss { sequence = ps, method = 6, nslice = 3, cmap = false } + +-- Add element properties as columns +melmcol(mtbl, + {"angle", "tilt", "k0l", "k1l", "k2l", "k3l", "k4l", "k5l", "k6l", "k0sl", + "k1sl", "k2sl", "k3sl", "k4sl", "k5sl", "k6sl", "ksl", "hkick", "vkick"}) + +mtbl:write('PS_twiss_py.tfs', + {"name", "kind", "s", "x", "px", "beta11", "alfa11", "beta22", "alfa22", "dx", + "dpx", "mu1", "mu2", "l", "angle", "k0l", "k1l", "k2l", "k3l", "hkick", "vkick"}) \ No newline at end of file diff --git a/examples/ex-recv-lhc/ex-defexpr.py b/examples/ex-recv-lhc/ex-defexpr.py index d4a7a6d..d5784f4 100644 --- a/examples/ex-recv-lhc/ex-defexpr.py +++ b/examples/ex-recv-lhc/ex-defexpr.py @@ -30,6 +30,7 @@ local is_number, is_string, is_function, is_table in MAD.typeid expr = {} -- list of deferred expressions +seen = {} -- tables already visited, to avoid infinite recursion on cycles (e.g. parent backrefs) function reg_expr(k,v) -- collect deferred expressions if is_number(v) or is_string(v) then @@ -37,6 +38,8 @@ elseif is_function(v) then -- deferred expressions are functions expr[#expr+1] = v elseif is_table(v) then + if seen[v] then return end + seen[v] = true for kk, vv in pairs(v) do reg_expr(kk,vv) end -- recursive call else print(k, v, type(v)) -- unexpected for MAD-X, just for debug diff --git a/pyproject.toml b/pyproject.toml index d15aefe..55d58ae 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -39,6 +39,7 @@ version = {attr = "pymadng.__version__"} [project.optional-dependencies] tfs = ["tfs-pandas>3.0.0"] +jupyter = ["ipykernel", "nbclient", "nbformat", "matplotlib"] # (examples/ex-jupyter) # ----- Dev Tools Configuration ----- # diff --git a/src/pymadng/__init__.py b/src/pymadng/__init__.py index 8b5c39f..949a982 100644 --- a/src/pymadng/__init__.py +++ b/src/pymadng/__init__.py @@ -1,7 +1,7 @@ from .madp_object import MAD __title__ = "pymadng" -__version__ = "0.9.6" +__version__ = "0.10.0" __summary__ = "Python interface to MAD-NG running as subprocess" __uri__ = "https://github.com/MethodicalAcceleratorDesign/MAD-NG.py" diff --git a/src/pymadng/madp_object.py b/src/pymadng/madp_object.py index 0432ea3..60c84d4 100644 --- a/src/pymadng/madp_object.py +++ b/src/pymadng/madp_object.py @@ -109,7 +109,10 @@ def __init__( if not ipython_use_jedi: # Stop jedi running getattr on my classes... try: ipython = get_ipython() # type: ignore - if ipython.__class__.__name__ == "TerminalInteractiveShell": + # Applies to both the terminal shell (TerminalInteractiveShell) and + # Jupyter notebooks/lab/qtconsole (ZMQInteractiveShell), which both + # expose a jedi-backed Completer; other shells are left untouched. + if hasattr(ipython, "Completer"): ipython.Completer.use_jedi = False except NameError: pass @@ -307,6 +310,7 @@ def load(self, module: str, *varnames: str): Import classes or functions from a specific MAD-NG module. If no specific names are provided, imports all available members from the module. + This is not recommended for large modules due to potential namespace pollution. Args: module (str): The module name in MAD-NG. @@ -314,7 +318,7 @@ def load(self, module: str, *varnames: str): """ script = "" if varnames == (): - varnames = [x.strip("()") for x in dir(self.__get_MadRef(module))] + varnames = tuple([x.strip("()") for x in dir(self.__get_MadRef(module))]) for classname in varnames: script += f"""{classname} = {module}.{classname}\n""" self.__process.send(script) @@ -331,9 +335,7 @@ def loadfile(self, path: str | Path, *varnames: str): """ path: Path = Path(path).resolve() if varnames == (): - self.__process.send( - f"assert(loadfile('{path}', nil, {self.py_name}._env))()" - ) + self.__process.send(f"assert(loadfile('{path}', nil, {self.py_name}._env))()") else: # The parent/stem is necessary, otherwise the file will not be found # This is thanks to the way the require function works in MAD-NG (how it searches for files) @@ -466,7 +468,7 @@ def create_deferred_expression(self, **kwargs) -> MadLastRef: def __dir__(self) -> Iterable[str]: py_objs = [x for x in super().__dir__() if x[0] != "_"] py_objs.extend(self.globals()) - py_objs.extend(dir(self.recv_vars("_G", shallow_copy=True))) + py_objs.extend(dir(self.__process.protected_variable_retrieval("_G", shallow_copy=True))) return py_objs def globals(self) -> list[str]: diff --git a/src/pymadng/madp_pymad.py b/src/pymadng/madp_pymad.py index ca5df4c..19c1f94 100644 --- a/src/pymadng/madp_pymad.py +++ b/src/pymadng/madp_pymad.py @@ -69,16 +69,13 @@ def __init__( self.stdout_file = self.stdout_file_path.open("w") stdout = self.stdout_file - # Convert stdout to a file descriptor - try: - stdout_fileno: int = stdout.fileno() - except AttributeError as e: + if not callable(getattr(stdout, "write", None)): raise TypeError( - "Stdout must be a file name, file descriptor, or an object with the fileno method" - ) from e + "Stdout must be a file name, file descriptor, or an object with a write method" + ) # Redirect stderr to stdout, if specified - stderr = stdout if redirect_stderr else sys.stderr.fileno() + stderr_target = stdout if redirect_stderr else sys.stderr # Create a chunk of code to start the process lua_debug_flag = "true" if debug else "false" @@ -89,24 +86,28 @@ def __init__( if threading.current_thread() is threading.main_thread(): self._setup_signal_handler() - # Start the process + # Start the process. stdout/stderr are always piped back through Python + # rather than handed to the subprocess as raw file descriptors - essential + # for jupyter notebooks self.process = subprocess.Popen( [str(mad_path), "-q", "-e", startup_chunk], bufsize=0, stdin=mad_read, # Set the stdin of MAD to the read end of the pipe - stdout=stdout_fileno, # Forward stdout - stderr=stderr, # Forward stderr - pass_fds=[ - mad_write, - stdout_fileno, - sys.stderr.fileno(), - ], # Don't close these (python closes all fds by default) + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT if redirect_stderr else subprocess.PIPE, + pass_fds=[mad_write], # Don't close this (python closes all fds by default) ) # Close the ends of the pipes that are not used by the process os.close(mad_write) os.close(mad_read) + # Forward synchronously from the blocked send/recv thread. + # ipykernel uses thread-local state to attribute output to the current cell. + self._piped_outputs: list[tuple[Any, TextIO]] = [(self.process.stdout, stdout)] + if not redirect_stderr: + self._piped_outputs.append((self.process.stderr, stderr_target)) + # Create a global variable dictionary for the exec function (could be extended to include more variables) self.python_exec_context = {"np": np} @@ -150,6 +151,32 @@ def delete_process(sig, frame): signal.signal(signal.SIGINT, delete_process) + def _drain_piped_outputs(self, timeout: float = 0.0) -> None: + """Forward MAD-NG's piped stdout/stderr to the specified output streams. + + A pipe at EOF (the subprocess closed its end) reads as b"" forever and + `select` keeps reporting it ready, so it is dropped from + `_piped_outputs` once that happens, to avoid spinning on it. + """ + wait = timeout + while self._piped_outputs: + piped_fds = [pipe.fileno() for pipe, _ in self._piped_outputs] + ready, _, _ = select.select(piped_fds, [], [], wait) + if not ready: + return + for pipe, dest in list(self._piped_outputs): + if pipe.fileno() not in ready: + continue + chunk = os.read(pipe.fileno(), 65536) + if not chunk: + self._piped_outputs.remove((pipe, dest)) + pipe.close() + continue + with suppress(Exception): + dest.write(chunk.decode(errors="replace")) + dest.flush() + wait = 0.0 + def send_range(self, start: float, stop: float, size: int) -> None: """Send a linear range (numpy array) to MAD-NG. @@ -188,6 +215,7 @@ def send(self, data: Any) -> MadProcess: Accepts several types (str, int, float, ndarray, bool, list, dict, NoneType) and sends them using the appropriate serialization. Returns self to allow method chaining. """ + self._drain_piped_outputs() try: typ = type_str[get_typestr(data)] self.mad_input_stream.write(typ.encode("utf-8")) @@ -254,6 +282,7 @@ def recv(self, varname: str | None = None) -> Any: Any: The value received from MAD-NG, which can be of various types (str, int, float, ndarray, bool, list, dict). """ typ = self.mad_read_stream.read(4).decode("utf-8") + self._drain_piped_outputs() # Read out any output from MAD-NG before returning the value self.varname = varname # For mad reference return type_fun[typ]["recv"](self) # type: ignore @@ -340,6 +369,10 @@ def close(self) -> None: self.process.kill() self.process.wait() + self._drain_piped_outputs(timeout=1.0) + for pipe, _ in self._piped_outputs: + pipe.close() + # Close the debug file if it exists with suppress(AttributeError): self.stdout_file.close() diff --git a/tests/inputs/example.log b/tests/inputs/example.log index 8855532..0e8514f 100644 --- a/tests/inputs/example.log +++ b/tests/inputs/example.log @@ -27,7 +27,7 @@ match = MAD.match ***pymad.recv: [py:__err(true):send(MAD['env']['version'], false):__err(false)] 62 bytes ***pymad.send: [str_] 4 bytes ***pymad.send: binary data 4 bytes -***pymad.send: [1.1.14] 6 bytes +***pymad.send: [1.1.15] 6 bytes ***pymad.recv: binary data 4 bytes ***pymad.recv: [ function __mklast__ (a, b, ...) diff --git a/tests/test_examples.py b/tests/test_examples.py new file mode 100644 index 0000000..5d6e1c6 --- /dev/null +++ b/tests/test_examples.py @@ -0,0 +1,74 @@ +import importlib.util +import os +import subprocess +import sys +import unittest +from pathlib import Path + +EXAMPLES_DIR = Path(__file__).parent.parent / "examples" + +# Mirrors examples/runall.py's list, run one process per example so a single +# failure doesn't stop the rest, and each gets its own cwd/env. +EXAMPLE_SCRIPTS = [ + "ex-benchmark-and-fork/ex-benchmark-and-fork.py", + "ex-fodo/ex-fodos.py", + "ex-lhc-couplingLocal/ex-lhc-couplingLocal.py", + "ex-managing-refs/ex-managing-refs.py", + "ex-LowLevel/ex-send-multypes.py", + "ex-LowLevel/ex-send-recv.py", + "ex-ps-twiss/ex-ps-twiss.py", + "ex-recv-lhc/ex-defexpr.py", +] + +NEEDS_MATPLOTLIB = { + "ex-benchmark-and-fork/ex-benchmark-and-fork.py", + "ex-fodo/ex-fodos.py", + "ex-lhc-couplingLocal/ex-lhc-couplingLocal.py", +} + +HAS_MATPLOTLIB = importlib.util.find_spec("matplotlib") is not None + + +def _make_test(name): + def test(self): + if name in NEEDS_MATPLOTLIB and not HAS_MATPLOTLIB: + self.skipTest("install the 'jupyter' extra (pip install .[jupyter]) for matplotlib") + + script = EXAMPLES_DIR / name + env = dict(os.environ) + # Non-interactive backend: plt.show()/plt.ion()/canvas.draw() become + # no-ops instead of opening a GUI window and blocking the test. + env["MPLBACKEND"] = "Agg" + + result = subprocess.run( + [sys.executable, str(script)], + cwd=str(script.parent), + env=env, + capture_output=True, + text=True, + timeout=300, + ) + + if result.returncode != 0: + self.fail( + f"{name} exited with code {result.returncode}\n" + f"--- stdout ---\n{result.stdout}\n" + f"--- stderr ---\n{result.stderr}" + ) + return test + + +class TestExamplesRun(unittest.TestCase): + """Runs every example script end-to-end as a subprocess, to catch + regressions that break the examples (import errors, API drift, etc.) + without needing plotting windows to open. + """ + + +for _name in EXAMPLE_SCRIPTS: + _test_name = "test_" + _name.replace("/", "_").replace("-", "_").replace(".py", "") + setattr(TestExamplesRun, _test_name, _make_test(_name)) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_jupyter_notebook.py b/tests/test_jupyter_notebook.py new file mode 100644 index 0000000..8526648 --- /dev/null +++ b/tests/test_jupyter_notebook.py @@ -0,0 +1,81 @@ +import unittest +from pathlib import Path + +try: + import nbformat + from nbclient import NotebookClient + from nbclient.exceptions import CellExecutionError + + HAS_NBCLIENT = True +except ImportError: + HAS_NBCLIENT = False + +NOTEBOOK = Path(__file__).parent.parent / "examples" / "ex-jupyter" / "ex-jupyter.ipynb" + + +@unittest.skipUnless( + HAS_NBCLIENT, "install the 'jupyter' extra (pip install .[jupyter]) to run this test" +) +class TestJupyterExample(unittest.TestCase): + """Runs examples/ex-jupyter/ex-jupyter.ipynb in a Jupyter + kernel, to prove that pymadng works from inside a notebook. + + mad.send() does not block until MAD-NG finishes running the sent code, so + (as the notebook itself explains) the output of a `send()`-only cell is + only drained and displayed once Python next talks to the MAD-NG process - + here, that is the following cell, which pulls mtbl.s/mtbl.beta11 back. + """ + + def test_notebook_runs_and_streams_output(self): + nb = nbformat.read(NOTEBOOK, as_version=4) + client = NotebookClient( + nb, + timeout=120, + kernel_name="python3", + resources={"metadata": {"path": str(NOTEBOOK.parent)}}, + ) + try: + client.execute() + except CellExecutionError as e: + self.fail(f"Example notebook failed to execute: {e}") + + def cell_stream_text(cell) -> str: + return "".join( + output.get("text", "") + for output in cell.get("outputs", []) + if output.get("output_type") == "stream" + ) + + creation_cell = next( + cell + for cell in nb.cells + if cell.cell_type == "code" and "mad = MAD()" in cell.source + ) + twiss_cell = next( + cell for cell in nb.cells if cell.cell_type == "code" and "twiss" in cell.source + ) + plot_cell = next( + cell for cell in nb.cells if cell.cell_type == "code" and "plt.plot" in cell.source + ) + + # Check not there in the first cell + self.assertNotIn("loading the fodo sequence", cell_stream_text(creation_cell)) + + # Check not in the twiss cell, but in the next cell (plot_cell) that actually interacts with MAD-NG + self.assertNotIn("loading the fodo sequence", cell_stream_text(twiss_cell)) + self.assertNotIn("running twiss", cell_stream_text(twiss_cell)) + + # The print output is not attributed to twiss_cell itself (send() does not + # block), but to the next cell that actually interacts with MAD-NG (plot_cell). + self.assertEqual(cell_stream_text(twiss_cell), "") + self.assertIn("loading the fodo sequence", cell_stream_text(plot_cell)) + self.assertIn("running twiss", cell_stream_text(plot_cell)) + self.assertIn("done", cell_stream_text(plot_cell)) + + cached_translation = NOTEBOOK.parent / "fodo.mad" + if cached_translation.exists(): + cached_translation.unlink() + + +if __name__ == "__main__": + unittest.main()