diff --git a/.epicsdb2bob.yml b/.epicsdb2bob.yml new file mode 100644 index 0000000..38577be --- /dev/null +++ b/.epicsdb2bob.yml @@ -0,0 +1,6 @@ +--- +debug: false +label_alignment: right +rtype_to_widget_map: + bo: ComboBox + bi: TextUpdate diff --git a/.github/workflows/CI.yaml b/.github/workflows/ci.yaml similarity index 81% rename from .github/workflows/CI.yaml rename to .github/workflows/ci.yaml index 7c3b2c6..e401189 100644 --- a/.github/workflows/CI.yaml +++ b/.github/workflows/ci.yaml @@ -30,7 +30,7 @@ jobs: run: pixi run lint build-and-test: - name: Build and Test + name: Build and Test ADXSPD on EL${{ matrix.rhel_version }} needs: lint runs-on: ubuntu-latest @@ -46,6 +46,14 @@ jobs: uses: actions/checkout@v4 with: persist-credentials: false + + - name: Setup pixi + uses: prefix-dev/setup-pixi@8ca4608ef7f4daeb54f5205b20d0b7cb42f11143 # v0.8.14 + with: + pixi-version: v0.56.0 + cache: false + frozen: true + - name: Create CONFIG_SITE.local run: | cat > configure/CONFIG_SITE.local << EOF @@ -76,6 +84,11 @@ jobs: XML2_EXTERNAL=YES WITH_ZLIB=YES ZLIB_EXTERNAL=YES + + # Enable coverage flags for unit tests + USR_CXX_FLAGS_Linux += --coverage + USR_LD_FLAGS_Linux += --coverage + EOF echo "CONFIG_SITE.local created:" @@ -96,7 +109,6 @@ jobs: STREAM=/usr/lib64/epics SNCSEQ=/usr/lib64/epics RECCASTER=/usr/lib64/epics - MOTOR=/usr/lib64/epics # EPICS_BASE should always be last EPICS_BASE=/usr/lib64/epics @@ -118,4 +130,13 @@ jobs: - name: Run unit tests run: | - ./bin/linux-x86_64/TestADXSPD + pixi run tests + + # TODO: add coverage reporting to CI once it is working & codecov enabled + # - name: Get coverage info + # run: | + # pixi run get-coverage-info + + # - name: Show coverage summary + # run: | + # pixi run lcov -l coverage.info diff --git a/.gitignore b/.gitignore index 54d3d0e..0387486 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,5 @@ test.py notes.txt checkVar.sh setVar.sh +coverage.info +coverage-report/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 9f6cfaf..075cfc0 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -18,13 +18,16 @@ repos: - id: mixed-line-ending args: ['--fix=lf'] - - repo: https://github.com/pre-commit/mirrors-clang-format - rev: v14.0.6 - hooks: - - id: clang-format - - repo: local hooks: + - id: clang-format + name: clang-format + entry: clang-format -i + language: python + types_or: [c++, c] + args: ["-style=file"] + require_serial: false + - id: ruff name: lint with ruff language: system diff --git a/Makefile b/Makefile index 4c4ddb8..c34d3ea 100644 --- a/Makefile +++ b/Makefile @@ -27,10 +27,15 @@ realuninstall_iocs: bobfiles: pixi run make-bobfiles +# Generate parameter definitions and then immediately format with clang-format paramdefs: pixi run make-paramdefs + pixi run clang-format -i -style=file $(shell find xspdApp -name '*.h' -o -name '*.cpp') lint: pixi run lint -runtests: - cd xspdApp/tests && make -sj && cd ../.. && ./bin/linux-x86_64/ADXSPDTests + +coverage-report: + pixi run tests + pixi run get-coverage-info + pixi run make-coverage-report diff --git a/configure/CONFIG_SITE b/configure/CONFIG_SITE index 6c2cef6..67e2c77 100644 --- a/configure/CONFIG_SITE +++ b/configure/CONFIG_SITE @@ -35,7 +35,6 @@ CHECK_RELEASE = YES #IOCS_APPL_TOP = BUILD_TESTS=NO - CURL_EXTERNAL=YES # Get settings from AREA_DETECTOR, so we only have to configure once for all detectors if we want to diff --git a/iocs/xspdIOC/iocBoot/iocXSPD/st_base.cmd b/iocs/xspdIOC/iocBoot/iocXSPD/st_base.cmd index 07579ed..78f638f 100644 --- a/iocs/xspdIOC/iocBoot/iocXSPD/st_base.cmd +++ b/iocs/xspdIOC/iocBoot/iocXSPD/st_base.cmd @@ -33,9 +33,22 @@ dbLoadRecords("$(ADXSPD)/db/ADXSPDModule.template", "P=$(PREFIX), R=mod1:,PORT=$ # Load all other plugins using commonPlugins.cmd < $(ADCORE)/iocBoot/commonPlugins.cmd +# Load Apache Arrow file plugin +NDFileArrowConfigure("ARR1", $(QSIZE), 0, "$(PORT)", 0) +dbLoadRecords("$(ADPLUGINARROW)/db/NDFileArrow.template", "P=$(PREFIX),R=arrow1:,PORT=ARR1,ADDR=0,TIMEOUT=1,NDARRAY_PORT=PROC1") + # set_requestfile_path("$(ADXSPD)/xspdApp/Db") iocInit() # save things every thirty seconds create_monitor_set("auto_settings.req", 30, "P=$(PREFIX)") + +# Set initial plugin arrow params + +dbpf $(PREFIX)arrow1:FilePath "/tmp" +dbpf $(PREFIX)arrow1:FileTemplate "%s%s_%3.3d.csv" +dbpf $(PREFIX)arrow1:AutoIncrement 1 +dbpf $(PREFIX)arrow1:OutputFileFormat 1 +dbpf $(PREFIX)arrow1:EnableCallbacks 1 +dbpf $(PREFIX)arrow1:FileName "Test" diff --git a/pixi.lock b/pixi.lock index 9d399f2..fc9ddac 100644 --- a/pixi.lock +++ b/pixi.lock @@ -7,93 +7,108 @@ environments: - https://pypi.org/simple packages: linux-64: - - conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/backports.zstd-1.3.0-py312h90b7ffd_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/blinker-1.9.0-pyhff2d567_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_8.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2025.10.5-hbd8a1cb_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-2.0.0-py312h35888ee_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/cfgv-3.3.1-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.3.0-pyh707e725_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.12.12-py312hd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.2.0-py312hdb49522_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_9.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.2.25-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-2.0.0-py312h460c074_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cfgv-3.5.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.5-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/clang-format-21-21.1.8-default_h99862b1_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/clang-format-21.1.8-default_h99862b1_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.3.1-pyh8f84b5b_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.12.13-py312hd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.4.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.20.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/flask-3.1.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/identify-2.6.15-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.25.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/flask-3.1.3-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.2-h33c6efd_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/identify-2.6.17-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/itsdangerous-2.2.0-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.21.3-h659f571_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.44-ha97dd6f_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.22.2-ha1258a1_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/lcov-1.16-ha770c72_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_101.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libclang-cpp21.1-21.1.8-default_h99862b1_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.1-hecca717_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.4.6-h2dba641_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-h767d61c_7.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_7.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-h767d61c_7.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.1-hb9d3cd8_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.4-hecca717_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.18-h3b78370_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libllvm21-21.1.8-hf7376ad_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.2-hb03c661_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hb9d3cd8_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libsodium-1.0.20-h4ab18f5_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.50.4-h0c1763c_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h8f9b012_7.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-15.2.0-h4852527_7.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.41.2-he9a06e4_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsodium-1.0.21-h280c20c_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.52.0-hf4e2dac_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_18.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.41.3-h5347b49_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-16-2.15.2-hca6bf5a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.15.2-he237659_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.3-py312h8a5da7c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.3-py312h8a5da7c_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/nodeenv-1.9.1-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.5.4-h26f9b46_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pip-25.2-pyh8b19718_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.5.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nodeenv-1.10.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.1-h35e630c_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/perl-5.32.1-7_hd590300_perl5.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-25.3-pyh8b19718_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.2-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pre-commit-4.5.1-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyh29332c3_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.12-hfe2f287_0_cpython.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.12.12-hd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.13-hd63d673_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-discovery-1.1.1-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.12.13-hd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-8_cp312.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py312h8a5da7c_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/pyzmq-27.1.0-py312hfb55c3c_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8c095d6_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/ruff-0.14.0-ha3a3aed_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-80.9.0-pyhff2d567_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_hd72426e_102.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py312h8a5da7c_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pyzmq-27.1.0-py312hda471dd_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.32.5-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ruff-0.14.14-h40fa522_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.0-pyh332efcf_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025b-h78e105d_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/ukkonen-1.0.1-py312h68727a3_5.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-20.35.3-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/werkzeug-3.1.3-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.45.1-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ukkonen-1.1.0-py312hd9148b4_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-21.1.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/werkzeug-3.1.6-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.46.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/zeromq-4.3.5-h387f397_9.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhd8ed1ab_0.conda - - pypi: git+https://github.com/NSLS2/epicsdb2bob.git#56d3d8059022637ce19011a9e1394fc96c4ba1c2 - - pypi: git+https://github.com/jwlodek/epicsdbtools.git#27f2f545b44ce9e9139980f6736d2fa7431d3d27 - - pypi: https://files.pythonhosted.org/packages/24/07/47b797ef5dd22d1b293936aee48d04a1f3901d9b87f01fe719fe34de9100/phoebusgen-3.1.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/88/5b/6f4b0772d6b648c03420bad32cbdd354799816e84d0961c6f5435036e594/rectangle_packer-2.0.5-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl + - conda: https://conda.anaconda.org/conda-forge/linux-64/zeromq-4.3.5-h41580af_10.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda + - pypi: git+https://github.com/NSLS2/epicsdb2bob.git#13ecb7eeb67857f8b32a44cf664ae74244ac3319 + - pypi: git+https://github.com/jwlodek/epicsdbtools.git#9c1913b694cea222a7296662a9431400d9435e91 + - pypi: https://files.pythonhosted.org/packages/c6/f3/ccadde3be7063fd2630908fe533ad8d9812d86c20996ba572196235ba78f/phoebusgen-3.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8a/7f/8989eeda506badc28ee9b0ea9b95620cd12437358e1339293b55a6647e2f/rectangle_packer-2.0.6-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl packages: -- conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 - sha256: fe51de6107f9edc7aa4f786a70f4a883943bc9d39b3bb7307c04c41410990726 - md5: d7c89558ba9fa0495403155b64376d81 - license: None - purls: [] - size: 2562 - timestamp: 1578324546067 -- conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 - build_number: 16 - sha256: fbe2c5e56a653bebb982eda4876a9178aedfc2b545f25d0ce9c4c0b508253d22 - md5: 73aaf86a425cc6e73fcf236a5a46396d - depends: - - _libgcc_mutex 0.1 conda_forge +- conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda + build_number: 20 + sha256: 1dd3fffd892081df9726d7eb7e0dea6198962ba775bd88842135a4ddb4deb3c9 + md5: a9f577daf3de00bca7c3c76c0ecbd1de + depends: + - __glibc >=2.17,<3.0.a0 - libgomp >=7.5.0 constrains: - - openmp_impl 9999 + - openmp_impl <0.0a0 license: BSD-3-Clause license_family: BSD purls: [] - size: 23621 - timestamp: 1650670423406 + size: 28948 + timestamp: 1770939786096 - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda sha256: a3967b937b9abf0f2a99f3173fa4630293979bd1644709d89580e7c62a544661 md5: aaa2a381ccc56eac91d63b6c1240312f @@ -105,6 +120,20 @@ packages: purls: [] size: 8191 timestamp: 1744137672556 +- conda: https://conda.anaconda.org/conda-forge/linux-64/backports.zstd-1.3.0-py312h90b7ffd_0.conda + sha256: d77a24be15e283d83214121428290dbe55632a6e458378205b39c550afa008cf + md5: 5b8c55fed2e576dde4b0b33693a4fdb1 + depends: + - python + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + - python_abi 3.12.* *_cp312 + - zstd >=1.5.7,<1.6.0a0 + license: BSD-3-Clause AND MIT AND EPL-2.0 + purls: + - pkg:pypi/backports-zstd?source=hash-mapping + size: 237970 + timestamp: 1767045004512 - conda: https://conda.anaconda.org/conda-forge/noarch/blinker-1.9.0-pyhff2d567_0.conda sha256: f7efd22b5c15b400ed84a996d777b6327e5c402e79e3c534a7e086236f1eb2dc md5: 42834439227a4551b939beeeb8a4b085 @@ -116,32 +145,59 @@ packages: - pkg:pypi/blinker?source=hash-mapping size: 13934 timestamp: 1731096548765 -- conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_8.conda - sha256: c30daba32ddebbb7ded490f0e371eae90f51e72db620554089103b4a6934b0d5 - md5: 51a19bba1b8ebfb60df25cde030b7ebc +- conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.2.0-py312hdb49522_1.conda + sha256: 49df13a1bb5e388ca0e4e87022260f9501ed4192656d23dc9d9a1b4bf3787918 + md5: 64088dffd7413a2dd557ce837b4cbbdb + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libstdcxx >=14 + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + constrains: + - libbrotlicommon 1.2.0 hb03c661_1 + license: MIT + license_family: MIT + purls: + - pkg:pypi/brotli?source=compressed-mapping + size: 368300 + timestamp: 1764017300621 +- conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_9.conda + sha256: 0b75d45f0bba3e95dc693336fa51f40ea28c980131fec438afb7ce6118ed05f6 + md5: d2ffd7602c02f2b316fd921d39876885 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 license: bzip2-1.0.6 license_family: BSD purls: [] - size: 260341 - timestamp: 1757437258798 -- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2025.10.5-hbd8a1cb_0.conda - sha256: 3b5ad78b8bb61b6cdc0978a6a99f8dfb2cc789a451378d054698441005ecbdb6 - md5: f9e5fbc24009179e8b0409624691758a + size: 260182 + timestamp: 1771350215188 +- conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.2.25-hbd8a1cb_0.conda + sha256: 67cc7101b36421c5913a1687ef1b99f85b5d6868da3abbf6ec1a4181e79782fc + md5: 4492fd26db29495f0ba23f146cd5638d depends: - __unix license: ISC purls: [] - size: 155907 - timestamp: 1759649036195 -- conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-2.0.0-py312h35888ee_0.conda - sha256: f9e906b2cb9ae800b5818259472c3f781b14eb1952e867ac5c1f548e92bf02d9 - md5: 60b9cd087d22272885a6b8366b1d3d43 + size: 147413 + timestamp: 1772006283803 +- conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2026.2.25-pyhd8ed1ab_0.conda + sha256: a6b118fd1ed6099dc4fc03f9c492b88882a780fadaef4ed4f93dc70757713656 + md5: 765c4d97e877cdbbb88ff33152b86125 + depends: + - python >=3.10 + license: ISC + purls: + - pkg:pypi/certifi?source=compressed-mapping + size: 151445 + timestamp: 1772001170301 +- conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-2.0.0-py312h460c074_1.conda + sha256: 7dafe8173d5f94e46cf9cd597cc8ff476a8357fbbd4433a8b5697b2864845d9c + md5: 648ee28dcd4e07a1940a17da62eccd40 depends: - __glibc >=2.17,<3.0.a0 - - libffi >=3.4.6,<3.5.0a0 + - libffi >=3.5.2,<3.6.0a0 - libgcc >=14 - pycparser - python >=3.12,<3.13.0a0 @@ -149,43 +205,84 @@ packages: license: MIT license_family: MIT purls: - - pkg:pypi/cffi?source=compressed-mapping - size: 296986 - timestamp: 1758716192805 -- conda: https://conda.anaconda.org/conda-forge/noarch/cfgv-3.3.1-pyhd8ed1ab_1.conda - sha256: d5696636733b3c301054b948cdd793f118efacce361d9bd4afb57d5980a9064f - md5: 57df494053e17dce2ac3a0b33e1b2a2e + - pkg:pypi/cffi?source=hash-mapping + size: 295716 + timestamp: 1761202958833 +- conda: https://conda.anaconda.org/conda-forge/noarch/cfgv-3.5.0-pyhd8ed1ab_0.conda + sha256: aa589352e61bb221351a79e5946d56916e3c595783994884accdb3b97fe9d449 + md5: 381bd45fb7aa032691f3063aff47e3a1 depends: - - python >=3.9 + - python >=3.10 license: MIT license_family: MIT purls: - pkg:pypi/cfgv?source=hash-mapping - size: 12973 - timestamp: 1734267180483 -- conda: https://conda.anaconda.org/conda-forge/noarch/click-8.3.0-pyh707e725_0.conda - sha256: c6567ebc27c4c071a353acaf93eb82bb6d9a6961e40692a359045a89a61d02c0 - md5: e76c4ba9e1837847679421b8d549b784 + size: 13589 + timestamp: 1763607964133 +- conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.4.5-pyhd8ed1ab_0.conda + sha256: 05ea76a016c77839b64f9f8ec581775f6c8a259044bd5b45a177e46ab4e7feac + md5: beb628209b2b354b98203066f90b3287 depends: - - __unix - python >=3.10 + license: MIT + license_family: MIT + purls: + - pkg:pypi/charset-normalizer?source=compressed-mapping + size: 53210 + timestamp: 1772816516728 +- conda: https://conda.anaconda.org/conda-forge/linux-64/clang-format-21.1.8-default_h99862b1_3.conda + sha256: 1b3deb505af39c18e6ed74c2f80a81e93ccfe856dba53cb1dc6abc4a43928186 + md5: 60c5a8962694a08e5a6c053a34ecf133 + depends: + - __glibc >=2.17,<3.0.a0 + - clang-format-21 21.1.8 default_h99862b1_3 + - libclang-cpp21.1 >=21.1.8,<21.2.0a0 + - libgcc >=14 + - libllvm21 >=21.1.8,<21.2.0a0 + - libstdcxx >=14 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + purls: [] + size: 28574 + timestamp: 1770190879400 +- conda: https://conda.anaconda.org/conda-forge/linux-64/clang-format-21-21.1.8-default_h99862b1_3.conda + sha256: 10d5448a9fd8c9413d28ed328df4765646c122d24ba28fea70a25671a123d09b + md5: a6fcbe2c5df28f02d03a05faf532d908 + depends: + - __glibc >=2.17,<3.0.a0 + - libclang-cpp21.1 >=21.1.8,<21.2.0a0 + - libgcc >=14 + - libllvm21 >=21.1.8,<21.2.0a0 + - libstdcxx >=14 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + purls: [] + size: 71340 + timestamp: 1770190821742 +- conda: https://conda.anaconda.org/conda-forge/noarch/click-8.3.1-pyh8f84b5b_1.conda + sha256: 38cfe1ee75b21a8361c8824f5544c3866f303af1762693a178266d7f198e8715 + md5: ea8a6c3256897cc31263de9f455e25d9 + depends: + - python >=3.10 + - __unix + - python license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/click?source=compressed-mapping - size: 91622 - timestamp: 1758270534287 -- conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.12.12-py312hd8ed1ab_1.conda + - pkg:pypi/click?source=hash-mapping + size: 97676 + timestamp: 1764518652276 +- conda: https://conda.anaconda.org/conda-forge/noarch/cpython-3.12.13-py312hd8ed1ab_0.conda noarch: generic - sha256: b88c76a6d6b45378552ccfd9e88b2a073161fe83fd1294c8fa103ffd32f7934a - md5: 99d689ccc1a360639eec979fd7805be9 + sha256: d3e9bbd7340199527f28bbacf947702368f31de60c433a16446767d3c6aaf6fe + md5: f54c1ffb8ecedb85a8b7fcde3a187212 depends: - python >=3.12,<3.13.0a0 - python_abi * *_cp312 license: Python-2.0 purls: [] - size: 45767 - timestamp: 1761175217281 + size: 46463 + timestamp: 1772728929620 - conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.4.0-pyhd8ed1ab_0.conda sha256: 6d977f0b2fc24fee21a9554389ab83070db341af6d6f09285360b2e09ef8b26e md5: 003b8ba0a94e2f1e117d0bd46aebc901 @@ -197,9 +294,9 @@ packages: - pkg:pypi/distlib?source=hash-mapping size: 275642 timestamp: 1752823081585 -- pypi: git+https://github.com/NSLS2/epicsdb2bob.git#56d3d8059022637ce19011a9e1394fc96c4ba1c2 +- pypi: git+https://github.com/NSLS2/epicsdb2bob.git#13ecb7eeb67857f8b32a44cf664ae74244ac3319 name: epicsdb2bob - version: 0.1.dev53+g56d3d8059 + version: 0.1.dev54+g13ecb7eeb requires_dist: - phoebusgen - rectangle-packer @@ -215,9 +312,9 @@ packages: - types-mock ; extra == 'dev' - import-linter ; extra == 'dev' requires_python: '>=3.11' -- pypi: git+https://github.com/jwlodek/epicsdbtools.git#27f2f545b44ce9e9139980f6736d2fa7431d3d27 +- pypi: git+https://github.com/jwlodek/epicsdbtools.git#9c1913b694cea222a7296662a9431400d9435e91 name: epicsdbtools - version: 0.1.dev44+g27f2f545b + version: 0.1.dev73+g9c1913b69 requires_dist: - copier ; extra == 'dev' - pipdeptree ; extra == 'dev' @@ -230,37 +327,85 @@ packages: - types-mock ; extra == 'dev' - import-linter ; extra == 'dev' requires_python: '>=3.11' -- conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.20.0-pyhd8ed1ab_0.conda - sha256: 19025a4078ff3940d97eb0da29983d5e0deac9c3e09b0eabf897daeaf9d1114e - md5: 66b8b26023b8efdf8fcb23bac4b6325d +- conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.25.0-pyhd8ed1ab_0.conda + sha256: 55162ec0ff4e22d8f762b3e774f08f79f234ba37ab5e64d7a1421ed9216a222c + md5: 49a92015e912176999ae81bea11ea778 depends: - python >=3.10 license: Unlicense purls: - - pkg:pypi/filelock?source=hash-mapping - size: 17976 - timestamp: 1759948208140 -- conda: https://conda.anaconda.org/conda-forge/noarch/flask-3.1.2-pyhd8ed1ab_0.conda - sha256: 8a97eba37e0723720706d4636cc89c6b07eea1b7cc66fd8994fa8983a81ed988 - md5: ba67a9febeda36948fee26a3dec3d914 + - pkg:pypi/filelock?source=compressed-mapping + size: 25656 + timestamp: 1772380968183 +- conda: https://conda.anaconda.org/conda-forge/noarch/flask-3.1.3-pyhcf101f3_1.conda + sha256: 3980dfba1e3900106cc3e6210294e73f50d02a67fdfe7b3bb36b2721ba9379cb + md5: 156398929bf849da6df8f89a2c390185 depends: + - python >=3.10 - blinker >=1.9.0 - click >=8.1.3 - - importlib-metadata >=3.6.0 - itsdangerous >=2.2.0 - jinja2 >=3.1.2 - markupsafe >=2.1.1 - - python >=3.9 - werkzeug >=3.1.0 + - python license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/flask?source=hash-mapping - size: 82438 - timestamp: 1755674743256 -- conda: https://conda.anaconda.org/conda-forge/noarch/identify-2.6.15-pyhd8ed1ab_0.conda - sha256: 32d5007d12e5731867908cbf5345f5cd44a6c8755a2e8e63e15a184826a51f82 - md5: 25f954b7dae6dd7b0dc004dab74f1ce9 + - pkg:pypi/flask?source=compressed-mapping + size: 87428 + timestamp: 1771489274528 +- conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.3.0-pyhcf101f3_0.conda + sha256: 84c64443368f84b600bfecc529a1194a3b14c3656ee2e832d15a20e0329b6da3 + md5: 164fc43f0b53b6e3a7bc7dce5e4f1dc9 + depends: + - python >=3.10 + - hyperframe >=6.1,<7 + - hpack >=4.1,<5 + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/h2?source=compressed-mapping + size: 95967 + timestamp: 1756364871835 +- conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda + sha256: 6ad78a180576c706aabeb5b4c8ceb97c0cb25f1e112d76495bff23e3779948ba + md5: 0a802cb9888dd14eeefc611f05c40b6e + depends: + - python >=3.9 + license: MIT + license_family: MIT + purls: + - pkg:pypi/hpack?source=hash-mapping + size: 30731 + timestamp: 1737618390337 +- conda: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda + sha256: 77af6f5fe8b62ca07d09ac60127a30d9069fdc3c68d6b256754d0ffb1f7779f8 + md5: 8e6923fc12f1fe8f8c4e5c9f343256ac + depends: + - python >=3.9 + license: MIT + license_family: MIT + purls: + - pkg:pypi/hyperframe?source=hash-mapping + size: 17397 + timestamp: 1737618427549 +- conda: https://conda.anaconda.org/conda-forge/linux-64/icu-78.2-h33c6efd_0.conda + sha256: 142a722072fa96cf16ff98eaaf641f54ab84744af81754c292cb81e0881c0329 + md5: 186a18e3ba246eccfc7cff00cd19a870 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libstdcxx >=14 + license: MIT + license_family: MIT + purls: [] + size: 12728445 + timestamp: 1767969922681 +- conda: https://conda.anaconda.org/conda-forge/noarch/identify-2.6.17-pyhd8ed1ab_0.conda + sha256: 7cd5eccdb171a0adbf83a1ad8fc4e17822f4fc3f5518da9040de64e88bc07343 + md5: 5b7ae2ec4e0750e094f804a6cf1b2a37 depends: - python >=3.10 - ukkonen @@ -268,8 +413,19 @@ packages: license_family: MIT purls: - pkg:pypi/identify?source=hash-mapping - size: 79151 - timestamp: 1759437561529 + size: 79520 + timestamp: 1772402363021 +- conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.11-pyhd8ed1ab_0.conda + sha256: ae89d0299ada2a3162c2614a9d26557a92aa6a77120ce142f8e0109bbf0342b0 + md5: 53abe63df7e10a6ba605dc5f9f961d36 + depends: + - python >=3.10 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/idna?source=hash-mapping + size: 50721 + timestamp: 1760286526795 - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.7.0-pyhe01879c_1.conda sha256: c18ab120a0613ada4391b15981d86ff777b5690ca461ea7e9e49531e8f374745 md5: 63ccfdc3a3ce25b027b8767eb722fca8 @@ -294,18 +450,19 @@ packages: - pkg:pypi/itsdangerous?source=hash-mapping size: 19180 timestamp: 1733308353037 -- conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhd8ed1ab_0.conda - sha256: f1ac18b11637ddadc05642e8185a851c7fab5998c6f5470d716812fae943b2af - md5: 446bd6c8cb26050d528881df495ce646 +- conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.6-pyhcf101f3_1.conda + sha256: fc9ca7348a4f25fed2079f2153ecdcf5f9cf2a0bc36c4172420ca09e1849df7b + md5: 04558c96691bed63104678757beb4f8d depends: - markupsafe >=2.0 - - python >=3.9 + - python >=3.10 + - python license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/jinja2?source=hash-mapping - size: 112714 - timestamp: 1741263433881 + - pkg:pypi/jinja2?source=compressed-mapping + size: 120685 + timestamp: 1764517220861 - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.3-hb9d3cd8_0.conda sha256: 0960d06048a7185d3542d850986d807c6e37ca2e644342dd0c72feefcf26c2a4 md5: b38117a3c920364aff79f870c984b4a3 @@ -316,33 +473,58 @@ packages: purls: [] size: 134088 timestamp: 1754905959823 -- conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.21.3-h659f571_0.conda - sha256: 99df692f7a8a5c27cd14b5fb1374ee55e756631b9c3d659ed3ee60830249b238 - md5: 3f43953b7d3fb3aaa1d0d0723d91e368 +- conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.22.2-ha1258a1_0.conda + sha256: 3e307628ca3527448dd1cb14ad7bb9d04d1d28c7d4c5f97ba196ae984571dd25 + md5: fb53fb07ce46a575c5d004bbc96032c2 depends: - - keyutils >=1.6.1,<2.0a0 - - libedit >=3.1.20191231,<3.2.0a0 - - libedit >=3.1.20191231,<4.0a0 - - libgcc-ng >=12 - - libstdcxx-ng >=12 - - openssl >=3.3.1,<4.0a0 + - __glibc >=2.17,<3.0.a0 + - keyutils >=1.6.3,<2.0a0 + - libedit >=3.1.20250104,<3.2.0a0 + - libedit >=3.1.20250104,<4.0a0 + - libgcc >=14 + - libstdcxx >=14 + - openssl >=3.5.5,<4.0a0 license: MIT license_family: MIT purls: [] - size: 1370023 - timestamp: 1719463201255 -- conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.44-ha97dd6f_2.conda - sha256: 707dfb8d55d7a5c6f95c772d778ef07a7ca85417d9971796f7d3daad0b615de8 - md5: 14bae321b8127b63cba276bd53fac237 + size: 1386730 + timestamp: 1769769569681 +- conda: https://conda.anaconda.org/conda-forge/linux-64/lcov-1.16-ha770c72_0.tar.bz2 + sha256: 538b8d96b40ed297406fedabdf642b0ed3678a74084da4e86dd22c8e5128a247 + md5: 4fcf17a55d833638446a29be185fc228 + depends: + - perl 5.* + license: GPL-2.0-or-later + license_family: GPL-2 + purls: [] + size: 98421 + timestamp: 1664797155586 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.45.1-default_hbd61a6d_101.conda + sha256: 565941ac1f8b0d2f2e8f02827cbca648f4d18cd461afc31f15604cd291b5c5f3 + md5: 12bd9a3f089ee6c9266a37dab82afabd depends: - __glibc >=2.17,<3.0.a0 + - zstd >=1.5.7,<1.6.0a0 constrains: - - binutils_impl_linux-64 2.44 + - binutils_impl_linux-64 2.45.1 license: GPL-3.0-only license_family: GPL purls: [] - size: 747158 - timestamp: 1758810907507 + size: 725507 + timestamp: 1770267139900 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libclang-cpp21.1-21.1.8-default_h99862b1_3.conda + sha256: de512ce246faec2d4f7766774769921a85b5aa053a74abd2f8c97ad50b393aac + md5: 24a2802074d26aecfdbc9b3f1d8168d1 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libllvm21 >=21.1.8,<21.2.0a0 + - libstdcxx >=14 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + purls: [] + size: 21066639 + timestamp: 1770190428756 - conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20250104-pl5321h7949ede_0.conda sha256: d789471216e7aba3c184cd054ed61ce3f6dac6f87a50ec69291b9297f8c18724 md5: c277e0a4d549b03ac1e9d6cbbe3d017b @@ -356,76 +538,102 @@ packages: purls: [] size: 134676 timestamp: 1738479519902 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.1-hecca717_0.conda - sha256: da2080da8f0288b95dd86765c801c6e166c4619b910b11f9a8446fb852438dc2 - md5: 4211416ecba1866fab0c6470986c22d6 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.4-hecca717_0.conda + sha256: d78f1d3bea8c031d2f032b760f36676d87929b18146351c4464c66b0869df3f5 + md5: e7f7ce06ec24cfcfb9e36d28cf82ba57 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 constrains: - - expat 2.7.1.* + - expat 2.7.4.* license: MIT license_family: MIT purls: [] - size: 74811 - timestamp: 1752719572741 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.4.6-h2dba641_1.conda - sha256: 764432d32db45466e87f10621db5b74363a9f847d2b8b1f9743746cd160f06ab - md5: ede4673863426c0883c0063d853bbd85 + size: 76798 + timestamp: 1771259418166 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda + sha256: 31f19b6a88ce40ebc0d5a992c131f57d919f73c0b92cd1617a5bec83f6e961e6 + md5: a360c33a5abe61c07959e449fa1453eb depends: - __glibc >=2.17,<3.0.a0 - - libgcc >=13 + - libgcc >=14 license: MIT license_family: MIT purls: [] - size: 57433 - timestamp: 1743434498161 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-h767d61c_7.conda - sha256: 08f9b87578ab981c7713e4e6a7d935e40766e10691732bba376d4964562bcb45 - md5: c0374badb3a5d4b1372db28d19462c53 + size: 58592 + timestamp: 1769456073053 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-15.2.0-he0feb66_18.conda + sha256: faf7d2017b4d718951e3a59d081eb09759152f93038479b768e3d612688f83f5 + md5: 0aa00f03f9e39fb9876085dee11a85d4 depends: - __glibc >=2.17,<3.0.a0 - _openmp_mutex >=4.5 constrains: - - libgomp 15.2.0 h767d61c_7 - - libgcc-ng ==15.2.0=*_7 + - libgcc-ng ==15.2.0=*_18 + - libgomp 15.2.0 he0feb66_18 license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] - size: 822552 - timestamp: 1759968052178 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_7.conda - sha256: 2045066dd8e6e58aaf5ae2b722fb6dfdbb57c862b5f34ac7bfb58c40ef39b6ad - md5: 280ea6eee9e2ddefde25ff799c4f0363 + size: 1041788 + timestamp: 1771378212382 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-15.2.0-h69a702a_18.conda + sha256: e318a711400f536c81123e753d4c797a821021fb38970cebfb3f454126016893 + md5: d5e96b1ed75ca01906b3d2469b4ce493 depends: - - libgcc 15.2.0 h767d61c_7 + - libgcc 15.2.0 he0feb66_18 license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] - size: 29313 - timestamp: 1759968065504 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-h767d61c_7.conda - sha256: e9fb1c258c8e66ee278397b5822692527c5f5786d372fe7a869b900853f3f5ca - md5: f7b4d76975aac7e5d9e6ad13845f92fe + size: 27526 + timestamp: 1771378224552 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-15.2.0-he0feb66_18.conda + sha256: 21337ab58e5e0649d869ab168d4e609b033509de22521de1bfed0c031bfc5110 + md5: 239c5e9546c38a1e884d69effcf4c882 depends: - __glibc >=2.17,<3.0.a0 license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] - size: 447919 - timestamp: 1759967942498 -- conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.1-hb9d3cd8_2.conda - sha256: f2591c0069447bbe28d4d696b7fcb0c5bd0b4ac582769b89addbcf26fb3430d8 - md5: 1a580f7796c7bf6393fddb8bbbde58dc + size: 603262 + timestamp: 1771378117851 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.18-h3b78370_2.conda + sha256: c467851a7312765447155e071752d7bf9bf44d610a5687e32706f480aad2833f + md5: 915f5995e94f60e9a4826e0b0920ee88 depends: - __glibc >=2.17,<3.0.a0 - - libgcc >=13 + - libgcc >=14 + license: LGPL-2.1-only + purls: [] + size: 790176 + timestamp: 1754908768807 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libllvm21-21.1.8-hf7376ad_0.conda + sha256: 91bb4f5be1601b40b4995911d785e29387970f0b3c80f33f7f9028f95335399f + md5: 1a2708a460884d6861425b7f9a7bef99 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - libstdcxx >=14 + - libxml2 + - libxml2-16 >=2.14.6 + - libzlib >=1.3.1,<2.0a0 + - zstd >=1.5.7,<1.6.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + purls: [] + size: 44333366 + timestamp: 1765959132513 +- conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.2-hb03c661_0.conda + sha256: 755c55ebab181d678c12e49cced893598f2bab22d582fbbf4d8b83c18be207eb + md5: c7c83eecbb72d88b940c249af56c8b17 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 constrains: - - xz 5.8.1.* + - xz 5.8.2.* license: 0BSD purls: [] - size: 112894 - timestamp: 1749230047870 + size: 113207 + timestamp: 1768752626120 - conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hb9d3cd8_1.conda sha256: 927fe72b054277cde6cb82597d0fcf6baf127dcbce2e0a9d8925a68f1265eef5 md5: d864d34357c3b65a4b731f78c0801dc4 @@ -437,60 +645,52 @@ packages: purls: [] size: 33731 timestamp: 1750274110928 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libsodium-1.0.20-h4ab18f5_0.conda - sha256: 0105bd108f19ea8e6a78d2d994a6d4a8db16d19a41212070d2d1d48a63c34161 - md5: a587892d3c13b6621a6091be690dbca2 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libsodium-1.0.21-h280c20c_3.conda + sha256: 64e5c80cbce4680a2d25179949739a6def695d72c40ca28f010711764e372d97 + md5: 7af961ef4aa2c1136e11dd43ded245ab depends: - - libgcc-ng >=12 + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 license: ISC purls: [] - size: 205978 - timestamp: 1716828628198 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.50.4-h0c1763c_0.conda - sha256: 6d9c32fc369af5a84875725f7ddfbfc2ace795c28f246dc70055a79f9b2003da - md5: 0b367fad34931cb79e0d6b7e5c06bb1c + size: 277661 + timestamp: 1772479381288 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.52.0-hf4e2dac_0.conda + sha256: d716847b7deca293d2e49ed1c8ab9e4b9e04b9d780aea49a97c26925b28a7993 + md5: fd893f6a3002a635b5e50ceb9dd2c0f4 depends: - __glibc >=2.17,<3.0.a0 + - icu >=78.2,<79.0a0 - libgcc >=14 - libzlib >=1.3.1,<2.0a0 license: blessing purls: [] - size: 932581 - timestamp: 1753948484112 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h8f9b012_7.conda - sha256: 1b981647d9775e1cdeb2fab0a4dd9cd75a6b0de2963f6c3953dbd712f78334b3 - md5: 5b767048b1b3ee9a954b06f4084f93dc + size: 951405 + timestamp: 1772818874251 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-15.2.0-h934c35e_18.conda + sha256: 78668020064fdaa27e9ab65cd2997e2c837b564ab26ce3bf0e58a2ce1a525c6e + md5: 1b08cd684f34175e4514474793d44bcb depends: - __glibc >=2.17,<3.0.a0 - - libgcc 15.2.0 h767d61c_7 + - libgcc 15.2.0 he0feb66_18 constrains: - - libstdcxx-ng ==15.2.0=*_7 - license: GPL-3.0-only WITH GCC-exception-3.1 - license_family: GPL - purls: [] - size: 3898269 - timestamp: 1759968103436 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-15.2.0-h4852527_7.conda - sha256: 024fd46ac3ea8032a5ec3ea7b91c4c235701a8bf0e6520fe5e6539992a6bd05f - md5: f627678cf829bd70bccf141a19c3ad3e - depends: - - libstdcxx 15.2.0 h8f9b012_7 + - libstdcxx-ng ==15.2.0=*_18 license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL purls: [] - size: 29343 - timestamp: 1759968157195 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.41.2-he9a06e4_0.conda - sha256: e5ec6d2ad7eef538ddcb9ea62ad4346fde70a4736342c4ad87bd713641eb9808 - md5: 80c07c68d2f6870250959dcc95b209d1 + size: 5852330 + timestamp: 1771378262446 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.41.3-h5347b49_0.conda + sha256: 1a7539cfa7df00714e8943e18de0b06cceef6778e420a5ee3a2a145773758aee + md5: db409b7c1720428638e7c0d509d3e1b5 depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 license: BSD-3-Clause license_family: BSD purls: [] - size: 37135 - timestamp: 1758626800002 + size: 40311 + timestamp: 1766271528534 - conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda sha256: 6ae68e0b86423ef188196fff6207ed0c8195dd84273cb5623b85aa08033a410c md5: 5aa797f8787fe7a17d1b0821485b5adc @@ -500,6 +700,39 @@ packages: purls: [] size: 100393 timestamp: 1702724383534 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.15.2-he237659_0.conda + sha256: 275c324f87bda1a3b67d2f4fcc3555eeff9e228a37655aa001284a7ceb6b0392 + md5: e49238a1609f9a4a844b09d9926f2c3d + depends: + - __glibc >=2.17,<3.0.a0 + - icu >=78.2,<79.0a0 + - libgcc >=14 + - libiconv >=1.18,<2.0a0 + - liblzma >=5.8.2,<6.0a0 + - libxml2-16 2.15.2 hca6bf5a_0 + - libzlib >=1.3.1,<2.0a0 + license: MIT + license_family: MIT + purls: [] + size: 45968 + timestamp: 1772704614539 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-16-2.15.2-hca6bf5a_0.conda + sha256: 08d2b34b49bec9613784f868209bb7c3bb8840d6cf835ff692e036b09745188c + md5: f3bc152cb4f86babe30f3a4bf0dbef69 + depends: + - __glibc >=2.17,<3.0.a0 + - icu >=78.2,<79.0a0 + - libgcc >=14 + - libiconv >=1.18,<2.0a0 + - liblzma >=5.8.2,<6.0a0 + - libzlib >=1.3.1,<2.0a0 + constrains: + - libxml2 2.15.2 + license: MIT + license_family: MIT + purls: [] + size: 557492 + timestamp: 1772704601644 - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda sha256: d4bfe88d7cb447768e31650f06257995601f89076080e76df55e3112d4e47dc4 md5: edb0dca6bc32e4f4789199455a1dbeb8 @@ -513,9 +746,9 @@ packages: purls: [] size: 60963 timestamp: 1727963148474 -- conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.3-py312h8a5da7c_0.conda - sha256: f77f9f1a4da45cbc8792d16b41b6f169f649651a68afdc10b2da9da12b9aa42b - md5: f775a43412f7f3d7ed218113ad233869 +- conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.3-py312h8a5da7c_1.conda + sha256: 5f3aad1f3a685ed0b591faad335957dbdb1b73abfd6fc731a0d42718e0653b33 + md5: 93a4752d42b12943a355b682ee43285b depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 @@ -526,9 +759,9 @@ packages: license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/markupsafe?source=hash-mapping - size: 25321 - timestamp: 1759055268795 + - pkg:pypi/markupsafe?source=compressed-mapping + size: 26057 + timestamp: 1772445297924 - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda sha256: 3fde293232fa3fca98635e1167de6b7c7fda83caf24b9d6c91ec9eefb4f4d586 md5: 47e340acb35de30501a76c7c799c41d7 @@ -539,21 +772,21 @@ packages: purls: [] size: 891641 timestamp: 1738195959188 -- conda: https://conda.anaconda.org/conda-forge/noarch/nodeenv-1.9.1-pyhd8ed1ab_1.conda - sha256: 3636eec0e60466a00069b47ce94b6d88b01419b6577d8e393da44bb5bc8d3468 - md5: 7ba3f09fceae6a120d664217e58fe686 +- conda: https://conda.anaconda.org/conda-forge/noarch/nodeenv-1.10.0-pyhd8ed1ab_0.conda + sha256: 4fa40e3e13fc6ea0a93f67dfc76c96190afd7ea4ffc1bac2612d954b42cdc3ee + md5: eb52d14a901e23c39e9e7b4a1a5c015f depends: - - python >=3.9 + - python >=3.10 - setuptools license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/nodeenv?source=hash-mapping - size: 34574 - timestamp: 1734112236147 -- conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.5.4-h26f9b46_0.conda - sha256: e807f3bad09bdf4075dbb4168619e14b0c0360bacb2e12ef18641a834c8c5549 - md5: 14edad12b59ccbfa3910d42c72adc2a0 + size: 40866 + timestamp: 1766261270149 +- conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.1-h35e630c_1.conda + sha256: 44c877f8af015332a5d12f5ff0fb20ca32f896526a7d0cdb30c769df1144fb5c + md5: f61eb8cd60ff9057122a3d338b99c00f depends: - __glibc >=2.17,<3.0.a0 - ca-certificates @@ -561,43 +794,66 @@ packages: license: Apache-2.0 license_family: Apache purls: [] - size: 3119624 - timestamp: 1759324353651 -- pypi: https://files.pythonhosted.org/packages/24/07/47b797ef5dd22d1b293936aee48d04a1f3901d9b87f01fe719fe34de9100/phoebusgen-3.1.0-py3-none-any.whl + size: 3164551 + timestamp: 1769555830639 +- conda: https://conda.anaconda.org/conda-forge/noarch/packaging-26.0-pyhcf101f3_0.conda + sha256: c1fc0f953048f743385d31c468b4a678b3ad20caffdeaa94bed85ba63049fd58 + md5: b76541e68fea4d511b1ac46a28dcd2c6 + depends: + - python >=3.8 + - python + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/packaging?source=compressed-mapping + size: 72010 + timestamp: 1769093650580 +- conda: https://conda.anaconda.org/conda-forge/linux-64/perl-5.32.1-7_hd590300_perl5.conda + build_number: 7 + sha256: 9ec32b6936b0e37bcb0ed34f22ec3116e75b3c0964f9f50ecea5f58734ed6ce9 + md5: f2cfec9406850991f4e3d960cc9e3321 + depends: + - libgcc-ng >=12 + - libxcrypt >=4.4.36 + license: GPL-1.0-or-later OR Artistic-1.0-Perl + purls: [] + size: 13344463 + timestamp: 1703310653947 +- pypi: https://files.pythonhosted.org/packages/c6/f3/ccadde3be7063fd2630908fe533ad8d9812d86c20996ba572196235ba78f/phoebusgen-3.2.0-py3-none-any.whl name: phoebusgen - version: 3.1.0 - sha256: 3f757aee231a74c99999c4a6b5c4788a0d060a780d2ec9dacd0353dc6fabd38a + version: 3.2.0 + sha256: f6318730ffc9a17706d0e39c9738305cee8b7767c01bb0c0f853c5eb20677fef requires_dist: - pre-commit ; extra == 'dev' - sphinx ; extra == 'docs' - sphinx-rtd-theme ; extra == 'docs' - sphinx-autodoc-typehints ; extra == 'docs' requires_python: '>=3.5' -- conda: https://conda.anaconda.org/conda-forge/noarch/pip-25.2-pyh8b19718_0.conda - sha256: ec9ed3cef137679f3e3a68e286c6efd52144684e1be0b05004d9699882dadcdd - md5: dfce4b2af4bfe90cdcaf56ca0b28ddf5 +- conda: https://conda.anaconda.org/conda-forge/noarch/pip-25.3-pyh8b19718_0.conda + sha256: b67692da1c0084516ac1c9ada4d55eaf3c5891b54980f30f3f444541c2706f1e + md5: c55515ca43c6444d2572e0f0d93cb6b9 depends: - - python >=3.9,<3.13.0a0 + - python >=3.10,<3.13.0a0 - setuptools - wheel license: MIT license_family: MIT purls: - pkg:pypi/pip?source=hash-mapping - size: 1177168 - timestamp: 1753924973872 -- conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.5.0-pyhcf101f3_0.conda - sha256: 7efd51b48d908de2d75cbb3c4a2e80dd9454e1c5bb8191b261af3136f7fa5888 - md5: 5c7a868f8241e64e1cf5fdf4962f23e2 + size: 1177534 + timestamp: 1762776258783 +- conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.9.2-pyhcf101f3_0.conda + sha256: 7f263219cecf0ba6d74c751efa60c4676ce823157ca90aa43ebba5ac615ca0fa + md5: 4fefefb892ce9cc1539405bec2f1a6cd depends: - python >=3.10 - python license: MIT license_family: MIT purls: - - pkg:pypi/platformdirs?source=hash-mapping - size: 23625 - timestamp: 1759953252315 + - pkg:pypi/platformdirs?source=compressed-mapping + size: 25643 + timestamp: 1771233827084 - conda: https://conda.anaconda.org/conda-forge/noarch/pre-commit-4.5.1-pyha770c72_0.conda sha256: 5b81b7516d4baf43d0c185896b245fa7384b25dc5615e7baa504b7fa4e07b706 md5: 7f3ac694319c7eaf81a0325d6405e974 @@ -626,43 +882,69 @@ packages: - pkg:pypi/pycparser?source=hash-mapping size: 110100 timestamp: 1733195786147 -- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.12-hfe2f287_0_cpython.conda - sha256: 5386d8c8230b6478ae165ff34f57d498891ac160e871629cbb4d4256e69cc542 - md5: ceada987beec823b3c702710ee073fba +- conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha55dd90_7.conda + sha256: ba3b032fa52709ce0d9fd388f63d330a026754587a2f461117cac9ab73d8d0d8 + md5: 461219d1a5bd61342293efa2c0c90eac + depends: + - __unix + - python >=3.9 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/pysocks?source=hash-mapping + size: 21085 + timestamp: 1733217331982 +- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.13-hd63d673_0_cpython.conda + sha256: a44655c1c3e1d43ed8704890a91e12afd68130414ea2c0872e154e5633a13d7e + md5: 7eccb41177e15cc672e1babe9056018e depends: - __glibc >=2.17,<3.0.a0 - bzip2 >=1.0.8,<2.0a0 - ld_impl_linux-64 >=2.36.1 - - libexpat >=2.7.1,<3.0a0 - - libffi >=3.4.6,<3.5.0a0 + - libexpat >=2.7.4,<3.0a0 + - libffi >=3.5.2,<3.6.0a0 - libgcc >=14 - - liblzma >=5.8.1,<6.0a0 + - liblzma >=5.8.2,<6.0a0 - libnsl >=2.0.1,<2.1.0a0 - - libsqlite >=3.50.4,<4.0a0 - - libuuid >=2.41.2,<3.0a0 + - libsqlite >=3.51.2,<4.0a0 + - libuuid >=2.41.3,<3.0a0 - libxcrypt >=4.4.36 - libzlib >=1.3.1,<2.0a0 - ncurses >=6.5,<7.0a0 - - openssl >=3.5.4,<4.0a0 - - readline >=8.2,<9.0a0 + - openssl >=3.5.5,<4.0a0 + - readline >=8.3,<9.0a0 - tk >=8.6.13,<8.7.0a0 - tzdata constrains: - python_abi 3.12.* *_cp312 license: Python-2.0 purls: [] - size: 31547362 - timestamp: 1760367376467 -- conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.12.12-hd8ed1ab_1.conda - sha256: 59f17182813f8b23709b7d4cfda82c33b72dd007cb729efa0033c609fbd92122 - md5: c20172b4c59fbe288fa50cdc1b693d73 + size: 31608571 + timestamp: 1772730708989 +- conda: https://conda.anaconda.org/conda-forge/noarch/python-discovery-1.1.1-pyhcf101f3_0.conda + sha256: c63b41f7e1b1484ce6b36fb3b33b9f4bfadd0f80b415c82713e9268202cc1e8b + md5: 956fd3cd4fb0c749143875b8a616c055 + depends: + - python >=3.10 + - filelock >=3.15.4 + - platformdirs <5,>=4.3.6 + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/python-discovery?source=hash-mapping + size: 33390 + timestamp: 1772879430293 +- conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.12.13-hd8ed1ab_0.conda + sha256: 97327b9509ae3aae28d27217a5d7bd31aff0ab61a02041e9c6f98c11d8a53b29 + md5: 32780d6794b8056b78602103a04e90ef depends: - - cpython 3.12.12.* + - cpython 3.12.13.* - python_abi * *_cp312 license: Python-2.0 purls: [] - size: 45888 - timestamp: 1761175248278 + size: 46449 + timestamp: 1772728979370 - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.12-8_cp312.conda build_number: 8 sha256: 80677180dd3c22deb7426ca89d6203f1c7f1f256f2d5a94dc210f6e758229809 @@ -674,9 +956,9 @@ packages: purls: [] size: 6958 timestamp: 1752805918820 -- conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py312h8a5da7c_0.conda - sha256: 1b3dc4c25c83093fff08b86a3574bc6b94ba355c8eba1f35d805c5e256455fc7 - md5: fba10c2007c8b06f77c5a23ce3a635ad +- conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.3-py312h8a5da7c_1.conda + sha256: cb142bfd92f6e55749365ddc244294fa7b64db6d08c45b018ff1c658907bfcbf + md5: 15878599a87992e44c059731771591cb depends: - __glibc >=2.17,<3.0.a0 - libgcc >=14 @@ -686,81 +968,103 @@ packages: license: MIT license_family: MIT purls: - - pkg:pypi/pyyaml?source=hash-mapping - size: 204539 - timestamp: 1758892248166 -- conda: https://conda.anaconda.org/conda-forge/linux-64/pyzmq-27.1.0-py312hfb55c3c_0.conda + - pkg:pypi/pyyaml?source=compressed-mapping + size: 198293 + timestamp: 1770223620706 +- conda: https://conda.anaconda.org/conda-forge/linux-64/pyzmq-27.1.0-py312hda471dd_2.conda noarch: python - sha256: a00a41b66c12d9c60e66b391e9a4832b7e28743348cf4b48b410b91927cd7819 - md5: 3399d43f564c905250c1aea268ebb935 + sha256: be66c1f85c3b48137200d62c12d918f4f8ad329423daef04fed292818efd3c28 + md5: 082985717303dab433c976986c674b35 depends: - python - - __glibc >=2.17,<3.0.a0 - - libstdcxx >=14 - libgcc >=14 + - libstdcxx >=14 + - __glibc >=2.17,<3.0.a0 + - zeromq >=4.3.5,<4.4.0a0 - _python_abi3_support 1.* - cpython >=3.12 - - zeromq >=4.3.5,<4.4.0a0 license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/pyzmq?source=hash-mapping - size: 212218 - timestamp: 1757387023399 -- conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8c095d6_2.conda - sha256: 2d6d0c026902561ed77cd646b5021aef2d4db22e57a5b0178dfc669231e06d2c - md5: 283b96675859b20a825f8fa30f311446 + - pkg:pypi/pyzmq?source=compressed-mapping + size: 211567 + timestamp: 1771716961404 +- conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.3-h853b02a_0.conda + sha256: 12ffde5a6f958e285aa22c191ca01bbd3d6e710aa852e00618fa6ddc59149002 + md5: d7d95fc8287ea7bf33e0e7116d2b95ec depends: - - libgcc >=13 + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 - ncurses >=6.5,<7.0a0 license: GPL-3.0-only license_family: GPL purls: [] - size: 282480 - timestamp: 1740379431762 -- pypi: https://files.pythonhosted.org/packages/88/5b/6f4b0772d6b648c03420bad32cbdd354799816e84d0961c6f5435036e594/rectangle_packer-2.0.5-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl + size: 345073 + timestamp: 1765813471974 +- pypi: https://files.pythonhosted.org/packages/8a/7f/8989eeda506badc28ee9b0ea9b95620cd12437358e1339293b55a6647e2f/rectangle_packer-2.0.6-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl name: rectangle-packer - version: 2.0.5 - sha256: 7083c4cbc90c5cac58673bfa51edf39e870eb582814c0dee9e96052a706d9a18 -- conda: https://conda.anaconda.org/conda-forge/linux-64/ruff-0.14.0-ha3a3aed_0.conda + version: 2.0.6 + sha256: 70c642063cdcbaeb82d28a9a4580ad2b6480749be7d43089f96474a04204f6cb + requires_python: '>=3.9' +- conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.32.5-pyhcf101f3_1.conda + sha256: 7813c38b79ae549504b2c57b3f33394cea4f2ad083f0994d2045c2e24cb538c5 + md5: c65df89a0b2e321045a9e01d1337b182 + depends: + - python >=3.10 + - certifi >=2017.4.17 + - charset-normalizer >=2,<4 + - idna >=2.5,<4 + - urllib3 >=1.21.1,<3 + - python + constrains: + - chardet >=3.0.2,<6 + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/requests?source=compressed-mapping + size: 63602 + timestamp: 1766926974520 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ruff-0.14.14-h40fa522_1.conda noarch: python - sha256: 3af418d75043ca682d190e7c1f86064fca1de0e7c04db63c1fbe4e78863b5767 - md5: bf901feac47041795ef6666c777f3422 + sha256: 0c6c9825ff88195fd13936d63872213d6c88c1fe795d136881c0753c3037c5ff + md5: d3e1d08b141529c7fce6a13b4d670605 depends: - python - - libgcc >=14 - __glibc >=2.17,<3.0.a0 + - libgcc >=14 constrains: - __glibc >=2.17 license: MIT license_family: MIT purls: - pkg:pypi/ruff?source=compressed-mapping - size: 11084173 - timestamp: 1759875841049 -- conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-80.9.0-pyhff2d567_0.conda - sha256: 972560fcf9657058e3e1f97186cc94389144b46dbdf58c807ce62e83f977e863 - md5: 4de79c071274a53dcaf2a8c749d1499e + size: 9131490 + timestamp: 1769520999080 +- conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-82.0.0-pyh332efcf_0.conda + sha256: fd7201e38e38bf7f25818d624ca8da97b8998957ca9ae3fb7fdc9c17e6b25fcd + md5: 1d00d46c634177fc8ede8b99d6089239 depends: - - python >=3.9 + - python >=3.10 license: MIT license_family: MIT purls: - - pkg:pypi/setuptools?source=hash-mapping - size: 748788 - timestamp: 1748804951958 -- conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_hd72426e_102.conda - sha256: a84ff687119e6d8752346d1d408d5cf360dee0badd487a472aa8ddedfdc219e1 - md5: a0116df4f4ed05c303811a837d5b39d8 + - pkg:pypi/setuptools?source=compressed-mapping + size: 637506 + timestamp: 1770634745653 +- conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h366c992_103.conda + sha256: cafeec44494f842ffeca27e9c8b0c27ed714f93ac77ddadc6aaf726b5554ebac + md5: cffd3bdd58090148f4cfcd831f4b26ab depends: - __glibc >=2.17,<3.0.a0 - - libgcc >=13 + - libgcc >=14 - libzlib >=1.3.1,<2.0a0 + constrains: + - xorg-libx11 >=1.8.12,<2.0a0 license: TCL license_family: BSD purls: [] - size: 3285204 - timestamp: 1748387766691 + size: 3301196 + timestamp: 1769460227866 - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda sha256: 032271135bca55aeb156cee361c81350c6f3fb203f57d024d7e5a1fc9ef18731 md5: 0caa1af407ecff61170c9437a808404d @@ -773,67 +1077,87 @@ packages: - pkg:pypi/typing-extensions?source=hash-mapping size: 51692 timestamp: 1756220668932 -- conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025b-h78e105d_0.conda - sha256: 5aaa366385d716557e365f0a4e9c3fca43ba196872abbbe3d56bb610d131e192 - md5: 4222072737ccff51314b5ece9c7d6f5a +- conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2025c-hc9c84f9_1.conda + sha256: 1d30098909076af33a35017eed6f2953af1c769e273a0626a04722ac4acaba3c + md5: ad659d0a2b3e47e38d829aa8cad2d610 license: LicenseRef-Public-Domain purls: [] - size: 122968 - timestamp: 1742727099393 -- conda: https://conda.anaconda.org/conda-forge/linux-64/ukkonen-1.0.1-py312h68727a3_5.conda - sha256: 9fb020083a7f4fee41f6ece0f4840f59739b3e249f157c8a407bb374ffb733b5 - md5: f9664ee31aed96c85b7319ab0a693341 + size: 119135 + timestamp: 1767016325805 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ukkonen-1.1.0-py312hd9148b4_0.conda + sha256: c975070ac28fe23a5bbb2b8aeca5976b06630eb2de2dc149782f74018bf07ae8 + md5: 55fd03988b1b1bc6faabbfb5b481ecd7 depends: - __glibc >=2.17,<3.0.a0 - cffi - - libgcc >=13 - - libstdcxx >=13 + - libgcc >=14 + - libstdcxx >=14 - python >=3.12,<3.13.0a0 - python_abi 3.12.* *_cp312 license: MIT license_family: MIT purls: - pkg:pypi/ukkonen?source=hash-mapping - size: 13904 - timestamp: 1725784191021 -- conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-20.35.3-pyhd8ed1ab_0.conda - sha256: af9662662648f7f57c0a79afee98e393dacf68887c40aea1eec68b48afebb724 - md5: bf0dc4c8a32e91290e3fae5403798c63 + size: 14882 + timestamp: 1769438717830 +- conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.6.3-pyhd8ed1ab_0.conda + sha256: af641ca7ab0c64525a96fd9ad3081b0f5bcf5d1cbb091afb3f6ed5a9eee6111a + md5: 9272daa869e03efe68833e3dc7a02130 depends: + - backports.zstd >=1.0.0 + - brotli-python >=1.2.0 + - h2 >=4,<5 + - pysocks >=1.5.6,<2.0,!=1.5.7 + - python >=3.10 + license: MIT + license_family: MIT + purls: + - pkg:pypi/urllib3?source=hash-mapping + size: 103172 + timestamp: 1767817860341 +- conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-21.1.0-pyhcf101f3_0.conda + sha256: 84b4127637b15f4650fd6546eef3f3b3d1587e74488926696ec75153ded7a6f4 + md5: 047d1cc5b89b7b15e2a368976e70fb1d + depends: + - python >=3.10 - distlib >=0.3.7,<1 - - filelock >=3.12.2,<4 + - filelock <4,>=3.24.2 + - importlib-metadata >=6.6 - platformdirs >=3.9.1,<5 - - python >=3.10 + - python-discovery >=1 - typing_extensions >=4.13.2 + - python license: MIT license_family: MIT purls: - pkg:pypi/virtualenv?source=compressed-mapping - size: 4380205 - timestamp: 1760134237380 -- conda: https://conda.anaconda.org/conda-forge/noarch/werkzeug-3.1.3-pyhd8ed1ab_1.conda - sha256: cd9a603beae0b237be7d9dfae8ae0b36ad62666ac4bb073969bce7da6f55157c - md5: 0a9b57c159d56b508613cc39022c1b9e + size: 4647744 + timestamp: 1772626120915 +- conda: https://conda.anaconda.org/conda-forge/noarch/werkzeug-3.1.6-pyhcf101f3_0.conda + sha256: 06e3d5bec9d2730a23ecf023b7cba329c0772c51f2704714c17b3080b0385113 + md5: 2d9bfc6055e55ff58b2c359323a753d2 depends: - markupsafe >=2.1.1 - - python >=3.9 + - python >=3.10 + - python license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/werkzeug?source=hash-mapping - size: 243546 - timestamp: 1733160561258 -- conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.45.1-pyhd8ed1ab_1.conda - sha256: 1b34021e815ff89a4d902d879c3bd2040bc1bd6169b32e9427497fa05c55f1ce - md5: 75cb7132eb58d97896e173ef12ac9986 + - pkg:pypi/werkzeug?source=compressed-mapping + size: 257130 + timestamp: 1771530143814 +- conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.46.3-pyhd8ed1ab_0.conda + sha256: d6cf2f0ebd5e09120c28ecba450556ce553752652d91795442f0e70f837126ae + md5: bdbd7385b4a67025ac2dba4ef8cb6a8f depends: - - python >=3.9 + - packaging >=24.0 + - python >=3.10 license: MIT license_family: MIT purls: - pkg:pypi/wheel?source=hash-mapping - size: 62931 - timestamp: 1733130309598 + size: 31858 + timestamp: 1769139207397 - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h280c20c_3.conda sha256: 6d9ea2f731e284e9316d95fa61869fe7bbba33df7929f82693c121022810f4ad md5: a77f85f77be52ff59391544bfe73390a @@ -845,29 +1169,40 @@ packages: purls: [] size: 85189 timestamp: 1753484064210 -- conda: https://conda.anaconda.org/conda-forge/linux-64/zeromq-4.3.5-h387f397_9.conda - sha256: 47cfe31255b91b4a6fa0e9dbaf26baa60ac97e033402dbc8b90ba5fee5ffe184 - md5: 8035e5b54c08429354d5d64027041cad +- conda: https://conda.anaconda.org/conda-forge/linux-64/zeromq-4.3.5-h41580af_10.conda + sha256: 325d370b28e2b9cc1f765c5b4cdb394c91a5d958fbd15da1a14607a28fee09f6 + md5: 755b096086851e1193f3b10347415d7c depends: - - libstdcxx >=14 - libgcc >=14 - __glibc >=2.17,<3.0.a0 - - libgcc >=14 - - libsodium >=1.0.20,<1.0.21.0a0 - - krb5 >=1.21.3,<1.22.0a0 + - libstdcxx >=14 + - krb5 >=1.22.2,<1.23.0a0 + - libsodium >=1.0.21,<1.0.22.0a0 license: MPL-2.0 license_family: MOZILLA purls: [] - size: 310648 - timestamp: 1757370847287 -- conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhd8ed1ab_0.conda - sha256: 7560d21e1b021fd40b65bfb72f67945a3fcb83d78ad7ccf37b8b3165ec3b68ad - md5: df5e78d904988eb55042c0c97446079f + size: 311150 + timestamp: 1772476812121 +- conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.23.0-pyhcf101f3_1.conda + sha256: b4533f7d9efc976511a73ef7d4a2473406d7f4c750884be8e8620b0ce70f4dae + md5: 30cd29cb87d819caead4d55184c1d115 depends: - - python >=3.9 + - python >=3.10 + - python license: MIT license_family: MIT purls: - - pkg:pypi/zipp?source=hash-mapping - size: 22963 - timestamp: 1749421737203 + - pkg:pypi/zipp?source=compressed-mapping + size: 24194 + timestamp: 1764460141901 +- conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda + sha256: 68f0206ca6e98fea941e5717cec780ed2873ffabc0e1ed34428c061e2c6268c7 + md5: 4a13eeac0b5c8e5b8ab496e6c4ddd829 + depends: + - __glibc >=2.17,<3.0.a0 + - libzlib >=1.3.1,<2.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 601375 + timestamp: 1764777111296 diff --git a/pixi.toml b/pixi.toml index e2ed881..d9668ee 100644 --- a/pixi.toml +++ b/pixi.toml @@ -8,9 +8,12 @@ version = "0.1.0" [tasks] lint = "pre-commit run --all-files" build = "make -sj" -make-paramdefs = "dbtools-gen-paramdefs xspdApp/Db xspdApp/src && pre-commit run --all-files" -make-bobfiles = "epicsdb2bob xspdApp/Db xspdApp/op/bob -d -r _RBV -t none" -simulator = "sim/xspdSimulator.py" +make-paramdefs = "epicsdbtools paramdefs xspdApp/Db xspdApp/src -p XSPD" +make-bobfiles = "epicsdb2bob xspdApp/Db xspdApp/op/bob/autogenerated -d -r _RBV -t none" +make-sample-responses = "./xspdApp/tests/scripts/generate_sample_response_json.py" +tests = "./xspdApp/tests/O.linux-x86_64/TestADXSPD" +get-coverage-info = "lcov --no-external --capture --directory xspdApp/src --output-file coverage.info" +make-coverage-report = "genhtml coverage.info --output-directory coverage-report" [dependencies] pre-commit = ">=4.5.1,<5" @@ -19,6 +22,9 @@ pip = ">=25.2,<26" python = ">=3.12.12,<3.13" flask = ">=3.1.2,<4" pyzmq = ">=27.1.0,<28" +requests = ">=2.32.5,<3" +clang-format = ">=21.1.8,<22" +lcov = ">=1.16,<2" [pypi-dependencies] epicsdbtools = { git = "https://github.com/jwlodek/epicsdbtools.git" } diff --git a/xspdApp/Db/ADXSPD.template b/xspdApp/Db/ADXSPD.template index fb5256a..b12c4c0 100644 --- a/xspdApp/Db/ADXSPD.template +++ b/xspdApp/Db/ADXSPD.template @@ -34,9 +34,6 @@ record(mbbi, "$(P)$(R)ImageMode_RBV") { } record(mbbo, "$(P)$(R)TriggerMode") { - field(DESC, "Trigger mode") - field(DTYP, "asynInt32") - field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))TRIGGER_MODE") field(ZRVL, "0") field(ZRST, "Software") field(ONVL, "1") @@ -48,16 +45,12 @@ record(mbbo, "$(P)$(R)TriggerMode") { } record(mbbi, "$(P)$(R)TriggerMode_RBV") { - field(DESC, "Trigger mode readback") - field(DTYP, "asynInt32") - field(INP, "@asyn($(PORT),$(ADDR),$(TIMEOUT))TRIGGER_MODE") field(ZRVL, "0") field(ZRST, "Software") field(ONVL, "1") field(ONST, "External Frames") field(TWVL, "2") field(TWST, "External Sequence") - field(SCAN, "I/O Intr") } # XSPD specific records @@ -339,18 +332,98 @@ record(ai, "$(P)$(R)SummedFrames_RBV"){ field(SCAN, "I/O Intr") } -record(ao, "$(P)$(R)ROIRows"){ +record(ai, "$(P)$(R)AvgBoardTemp_RBV"){ + field(DESC, "Average board temp") + field(DTYP, "asynFloat64") + field(INP, "@asyn($(PORT),$(ADDR),$(TIMEOUT))XSPD_AVG_BOARD_TEMP") + field(EGU, "C") + field(VAL, "0.0") + field(SCAN, "I/O Intr") +} + +record(ai, "$(P)$(R)AvgFPGATemp_RBV"){ + field(DESC, "Average FPGA temp") + field(DTYP, "asynFloat64") + field(INP, "@asyn($(PORT),$(ADDR),$(TIMEOUT))XSPD_AVG_FPGA_TEMP") + field(EGU, "C") + field(VAL, "0.0") + field(SCAN, "I/O Intr") +} + +record(ai, "$(P)$(R)AvgSensorTemp_RBV"){ + field(DESC, "Average sensor temp") + field(DTYP, "asynFloat64") + field(INP, "@asyn($(PORT),$(ADDR),$(TIMEOUT))XSPD_AVG_SENSOR_TEMP") + field(EGU, "C") + field(VAL, "0.0") + field(SCAN, "I/O Intr") +} + +record(stringin, "$(P)$(R)SensorMaterial_RBV"){ + field(DESC, "Sensor material") + field(DTYP, "asynOctetRead") + field(VAL, "Unknown") + field(INP, "@asyn($(PORT),$(ADDR),$(TIMEOUT))XSPD_SENSOR_MATERIAL") + field(SCAN, "I/O Intr") +} + +record(ai, "$(P)$(R)SensorThickness_RBV"){ + field(DESC, "Sensor thickness") + field(DTYP, "asynFloat64") + field(INP, "@asyn($(PORT),$(ADDR),$(TIMEOUT))XSPD_SENSOR_THICKNESS") + field(EGU, "um") + field(VAL, "0.0") + field(SCAN, "I/O Intr") +} + +record(mbbo, "$(P)$(R)ROIRows"){ field(DESC, "ROI rows") field(DTYP, "asynInt32") field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))XSPD_ROI_ROWS") - field(VAL, "0") + field(VAL, "256") + field(ZRVL, "256") + field(ZRST, "256") + field(ONVL, "128") + field(ONST, "128") + field(TWVL, "64") + field(TWST, "64") + field(THVL, "32") + field(THST, "32") + field(FRVL, "16") + field(FRST, "16") + field(FVVL, "8") + field(FVST, "8") + field(SXVL, "4") + field(SXST, "4") + field(SVVL, "2") + field(SVST, "2") + field(EIVL, "1") + field(EIST, "1") field(PINI, "NO") } -record(ai, "$(P)$(R)ROIRows_RBV"){ +record(mbbi, "$(P)$(R)ROIRows_RBV"){ field(DESC, "ROI rows readback") field(DTYP, "asynInt32") field(INP, "@asyn($(PORT),$(ADDR),$(TIMEOUT))XSPD_ROI_ROWS") + field(ZRVL, "0") + field(ZRST, "256") + field(ONVL, "1") + field(ONST, "128") + field(TWVL, "2") + field(TWST, "64") + field(THVL, "3") + field(THST, "32") + field(FRVL, "4") + field(FRST, "16") + field(FVVL, "5") + field(FVST, "8") + field(SXVL, "6") + field(SXST, "4") + field(SVVL, "7") + field(SVST, "2") + field(EIVL, "8") + field(EIST, "1") field(SCAN, "I/O Intr") } @@ -445,63 +518,122 @@ record(bi, "$(P)$(R)CountrateCorrection_RBV"){ field(SCAN, "I/O Intr") } -record(ao, "$(P)$(R)StatusInterval"){ - field(DESC, "Status update interval in s") +record(bo, "$(P)$(R)MonitorMode"){ + field(DESC, "Monitor mode") + field(DTYP, "asynInt32") + field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))XSPD_MONITOR_MODE") + field(ZNAM, "Disabled") + field(ONAM, "Enabled") + field(VAL, "1") + field(PINI, "NO") +} + +record(bi, "$(P)$(R)MonitorMode_RBV"){ + field(DESC, "Monitor mode readback") + field(DTYP, "asynInt32") + field(INP, "@asyn($(PORT),$(ADDR),$(TIMEOUT))XSPD_MONITOR_MODE") + field(ZNAM, "Disabled") + field(ONAM, "Enabled") + field(SCAN, "I/O Intr") +} + +record(ao, "$(P)$(R)MonitorInterval"){ + field(DESC, "Monitor interval in s") field(DTYP, "asynFloat64") - field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))XSPD_STATUS_INTERVAL") + field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))XSPD_MONITOR_INTERVAL") field(VAL, "5") field(LOLO, "0.5") + field(PREC, "3") field(EGU, "s") field(PINI, "YES") } -record(ai, "$(P)$(R)StatusInterval_RBV"){ - field(DESC, "Status update interval readback in s") +record(ai, "$(P)$(R)MonitorInterval_RBV"){ + field(DESC, "Monitor interval readback in s") field(DTYP, "asynFloat64") - field(INP, "@asyn($(PORT),$(ADDR),$(TIMEOUT))XSPD_STATUS_INTERVAL") + field(INP, "@asyn($(PORT),$(ADDR),$(TIMEOUT))XSPD_MONITOR_INTERVAL") field(EGU, "s") field(VAL, "5") + field(PREC, "3") field(SCAN, "I/O Intr") } # Disable any ADBase records we don't want to use -# On-chip ROI size set by ROIRows PV -record(ao, "$(P)$(R)SizeX") { - field(DISA, 1) +record(mbbo, "$(P)$(R)DataType") +{ + field(DISA, "1") } - -record(ao, "$(P)$(R)SizeY") { - field(DISA, 1) +record(mbbo, "$(P)$(R)ColorMode") +{ + field(DISA, "1") } - -# Only mono supported, and data type set by bit depth parameter -record(mbbo, "$(P)$(R)DataType") { - field(DISA, 1) +record(mbbi, "$(P)$(R)ColorMode_RBV") +{ + field(DISA, "1") } - -record(mbbo, "$(P)$(R)ColorMode") { - field(DISA, 1) +record(longout, "$(P)$(R)BinX") +{ + field(DISA, "1") } - -# Binning not supported on-chip -record(ao, "$(P)$(R)BinX") { - field(DISA, 1) +record(longin, "$(P)$(R)BinX_RBV") +{ + field(DISA, "1") } - -record(ao, "$(P)$(R)BinY") { - field(DISA, 1) +record(longout, "$(P)$(R)BinY") +{ + field(DISA, "1") } - -record(ao, "$(P)$(R)AcquirePeriod") { - field(DISA, 1) +record(longin, "$(P)$(R)BinY_RBV") +{ + field(DISA, "1") } - -record(ao, "$(P)$(R)Gain") { - field(DISA, 1) +record(longout, "$(P)$(R)MinX") +{ + field(DISA, "1") } - -record(ao, "$(P)$(R)NumExposures") { - field(DISA, 1) +record(longin, "$(P)$(R)MinX_RBV") +{ + field(DISA, "1") +} +record(longout, "$(P)$(R)MinY") +{ + field(DISA, "1") +} +record(longin, "$(P)$(R)MinY_RBV") +{ + field(DISA, "1") +} +record(longout, "$(P)$(R)SizeX") +{ + field(DISA, "1") +} +record(longin, "$(P)$(R)SizeX_RBV") +{ + field(DISA, "1") +} +record(longout, "$(P)$(R)SizeY") +{ + field(DISA, "1") +} +record(longin, "$(P)$(R)SizeY_RBV") +{ + field(DISA, "1") +} +record(bo, "$(P)$(R)ReverseX") +{ + field(DISA, "1") +} +record(bi, "$(P)$(R)ReverseX_RBV") +{ + field(DISA, "1") +} +record(bo, "$(P)$(R)ReverseY") +{ + field(DISA, "1") +} +record(bi, "$(P)$(R)ReverseY_RBV") +{ + field(DISA, "1") } diff --git a/xspdApp/Db/ADXSPDModule.template b/xspdApp/Db/ADXSPDModule.template index 09df9d8..cf3c0c3 100644 --- a/xspdApp/Db/ADXSPDModule.template +++ b/xspdApp/Db/ADXSPDModule.template @@ -293,21 +293,21 @@ record(ai, "$(P)$(R)FramesQueued_RBV"){ field(SCAN, "I/O Intr") } -record(bo, "$(P)$(R)UsePixelMask"){ +record(bo, "$(P)$(R)PixelMask"){ field(DESC, "Use pixel mask") field(DTYP, "asynInt32") - field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))XSPD_USE_PIXEL_MASK") - field(ZNAM, "Disable") - field(ONAM, "Enable") + field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))XSPD_PIXEL_MASK") + field(ZNAM, "Disabled") + field(ONAM, "Enabled") field(VAL, "0") field(PINI, "NO") } -record(bi, "$(P)$(R)UsePixelMask_RBV"){ +record(bi, "$(P)$(R)PixelMask_RBV"){ field(DESC, "Use pixel mask rb") field(DTYP, "asynInt32") - field(INP, "@asyn($(PORT),$(ADDR),$(TIMEOUT))XSPD_USE_PIXEL_MASK") - field(ZNAM, "Disable") + field(INP, "@asyn($(PORT),$(ADDR),$(TIMEOUT))XSPD_PIXEL_MASK") + field(ZNAM, "Disabled") field(ONAM, "Enable") field(SCAN, "I/O Intr") } diff --git a/xspdApp/op/bob/ADXSPD.bob b/xspdApp/op/bob/ADXSPD.bob index 57d64a8..230b0dd 100644 --- a/xspdApp/op/bob/ADXSPD.bob +++ b/xspdApp/op/bob/ADXSPD.bob @@ -1,999 +1,3756 @@ - - ADXSPD + + + ADXSPD Top + +

DEV:XSPD1:

+ cam1: +
+ 1125 + 900 + + + + + 4 + 4 + + Monitor + 750 + 582 + 375 + 144 + + + + + + + + + + + + + true - 10 - 10 - 150 - 20 - API Version - - - - - - + Label_22 + Timeout (s) + 34 + 49 + 110 - + + - 0 - Label_1 + + + + + 2 - 170 - 10 - 150 - 20 - $(P)$(R)APIVersion_RBV + TextUpdate_14 + $(P)$(R)MonitorInterval_RBV + 229 + 49 + 80 + + + + - + + - + + + + + TextEntry_6 + $(P)$(R)MonitorInterval + 161 + 49 + 60 - + + - TextUpdate_1 - - - 10 - 40 - 150 - 20 - XSPD Version - - - - + + + + + Label_45 + Monitor mode + 6 + 24 - + + - 0 - Label_2 + + + + + 2 - - 170 - 40 - 150 + + ComboBox_15 + $(P)$(R)MonitorMode + 118 + 24 20 - $(P)$(R)XSPDVersion_RBV - - - + + + + - + + + + + TextUpdate_33 + $(P)$(R)MonitorMode_RBV + 234 + 24 - + + - TextUpdate_2 - - - 10 - 70 - 150 - 20 - Num modules - + + - + + + + + + Acquisition Status + 375 + 333 + 375 + 310 + + + + + + + + + + + + + true + + text #111 + Image counter + 29 + 229 + 130 - + + - 0 - Label_3 + 2 - - 170 - 70 - 150 - 20 - $(P)$(R)NumModules_RBV - - - + + text entry #107 + $(P)$(R)ArrayCounter + 164 + 229 + 60 + + + + - + + + 1 + false + false + + + text update #114 + $(P)$(R)ArrayCounter_RBV + 229 + 230 + 80 + 18 - + + - TextUpdate_3 - - - 10 - 100 - 150 - 20 - Compress level readback - + + - + + - - - - 0 - Label_4 + 1 + false + false - 170 - 100 - 150 - 20 - $(P)$(R)CompressLevel_RBV + text update #121_1 + $(P)$(R)ArrayRate_RBV + 164 + 255 + 18 + + + + - + + - + + + 1 + false + false + + + text #118 + Image rate + 59 + 254 - + + - TextUpdate_4 + 2 - 10 - 130 - 150 - 20 - Compressor readback - - - - - - + text #89 + Image size (bytes) + 9 + 184 + 180 - + + - 0 - Label_5 + 2 - 170 - 130 - 150 - 20 - $(P)$(R)Compressor_RBV + text update #92 + $(P)$(R)ArraySize_RBV + 216 + 185 + 61 + 18 + + + + - + + - + + + 1 + false + 1 + false + + + text #144 + Image size + 12 + 159 - + + - TextUpdate_5 + 2 - - 10 + + text update #147 + $(P)$(R)ArraySizeX_RBV + 123 160 - 150 - 20 - Beam energy + 61 + 18 + + + + - + + - + + - - - - 0 - Label_6 + 1 + false + 1 + false - - 170 + + text update #151 + $(P)$(R)ArraySizeY_RBV + 216 160 - 150 - 20 - $(P)$(R)BeamEnergy + 61 + 18 + + + + - + + - + + + 1 + false + 1 + false + + + text #46 + # Images complete + 209 + 170 - + + - TextEntry_1 + 2 - 330 - 160 - 150 - 20 - $(P)$(R)BeamEnergy_RBV + text update #42 + $(P)$(R)NumImagesCounter_RBV + 219 + 210 + 80 + 18 + + + + - + + - + + + 1 + false + false + + + text #60_1 + Done + 197 + 11 + 40 - + + - TextUpdate_6 + + + + + 1 + + + + false + + $(P)$(R)Acquire + + - 10 - 190 - 150 - 20 - Saturation flag + text #64 + Collecting + 168 + 11 + + + + - + + + 1 + + + + false + + $(P)$(R)Acquire + + + + + message button #68 + + + $(P)$(R)Acquire + 1 + Write + + + $(P)$(R)Acquire + Start + 154 + 31 + 59 + 20 - + + - - - - 0 - Label_7 - - 170 - 190 - 150 + + message button #71 + + + $(P)$(R)Acquire + 0 + Write + + + $(P)$(R)Acquire + Stop + 221 + 31 + 59 20 - $(P)$(R)SaturationFlag - - - - + + - - - - ChoiceButton_1 - - 330 - 190 - 20 - 20 - $(P)$(R)SaturationFlag_RBV - - - + + text #74 + Acquire + 79 + 31 + 70 - + + - LED_1 + 2 - 10 - 220 + text #142 + # Queued arrays + -1 + 56 150 - 20 - Charge summing + + + + + 2 + + + text update #145 + $(P)$(R)NumQueuedArrays + 154 + 57 + 60 + 18 + + + + - + + - + + + 1 + false + 2 + false + + + text #159 + Wait for plugins + -11 + 81 + 160 - + + - 0 - Label_8 + 2 - - 170 - 220 - 150 + + menu #162 + $(P)$(R)WaitForPlugins + 184 + 81 + 80 20 - $(P)$(R)ChargeSumming - - - - + + + false + + + text #165 + Acquire busy + 29 + 106 + 120 - + + - ChoiceButton_2 + 2 - - 330 - 220 - 20 - 20 - $(P)$(R)ChargeSumming_RBV - - - + + text update #168 + $(P)$(R)AcquireBusy + 154 + 107 + 160 + 18 - + + - LED_2 - - - 10 - 250 - 150 - 20 - Flatfield correction - + + - + + + 6 + false + + + + Acquisition Setup + 375 + 35 + 375 + 298 + + + + + + + + + + + + + true + + Label_17 + Low threshold + 28 + 115 - + + - 0 - Label_9 - - - 170 - 250 - 150 - 20 - $(P)$(R)FlatFieldCorrection - - - - + + + 2 + + + Label_18 + High threshold + 53 + 115 - + + - ChoiceButton_3 + + + + + 2 - - 330 - 250 - 20 - 20 - $(P)$(R)FlatFieldCorrection_RBV - - - + + text #9 + Exposure time + 78 + 115 - + + - LED_3 + 2 - 10 - 280 - 150 - 20 - Gating mode - - - + Label_28 + Beam energy + 103 + 115 + + + + - + + + 2 + + + text #31_1 + # Images + 128 + 115 - + + - 0 - Label_10 + 2 - - 170 - 280 - 150 - 20 - $(P)$(R)GatingMode - - - + + Label_15 + Frames to sum + 153 + 115 + + + + - + + + 2 + + + text #83 + Image mode + 178 + 115 - + + - ChoiceButton_4 + 2 - - 330 - 280 - 20 - 20 - $(P)$(R)GatingMode_RBV - - - + + text #149 + Trigger mode + 203 + 115 - + + - LED_4 + 2 - 10 - 310 - 150 - 20 + Label_33 Counter mode - - - + 228 + 115 + + + + - + + + 2 + + + TextEntry_4 + $(P)$(R)LowThreshold + 123 + 28 - + + - 0 - Label_11 - - - 170 - 310 - 150 - 20 - $(P)$(R)CounterMode - - - - + + + + + TextUpdate_10 + $(P)$(R)LowThreshold_RBV + 227 + 28 - + + - ChoiceButton_5 - - - 330 - 310 - 20 - 20 - $(P)$(R)CounterMode_RBV - + + + + + + + + + TextEntry_5 + $(P)$(R)HighThreshold + 123 + 53 - + + - LED_5 - + + + + + + + TextUpdate_11 + $(P)$(R)HighThreshold_RBV + 227 + 53 + + + + + + + + + + + + + + + text entry #12 + $(P)$(R)AcquireTime + 123 + 78 + + + + + + + + + 1 + false + false + + + text update #16 + $(P)$(R)AcquireTime_RBV + 227 + 79 + 18 + + + + + + + + + + + + + 1 + false + false + + + TextEntry_7 + $(P)$(R)BeamEnergy + 123 + 103 + + + + + + + + + + + TextUpdate_20 + $(P)$(R)BeamEnergy_RBV + 227 + 103 + + + + + + + + + + + + + + + text entry #34 + $(P)$(R)NumImages + 123 + 128 + + + + + + + + + 1 + false + false + + + text update #38 + $(P)$(R)NumImages_RBV + 227 + 128 + 18 + + + + + + + + + + + + + 1 + false + false + + + TextEntry_2 + $(P)$(R)SummedFrames + 123 + 153 + + + + + + + + + + + TextUpdate_8 + $(P)$(R)SummedFrames_RBV + 227 + 153 + + + + + + + + + + + + + + + menu #86 + $(P)$(R)ImageMode + 123 + 178 + 20 + + + + + false + + + text update #89_1 + $(P)$(R)ImageMode_RBV + 227 + 180 + 18 + + + + + + + + + + + + + 6 + false + false + + + menu #152 + $(P)$(R)TriggerMode + 123 + 203 + 20 + + + + + false + + + text update #155 + $(P)$(R)TriggerMode_RBV + 227 + 204 + 18 + + + + + + + + + + + + + 6 + false + false + + + menu #86_1 + $(P)$(R)CounterMode + 123 + 228 + 20 + + + + + false + + + text update #89_2 + $(P)$(R)CounterMode_RBV + 227 + 228 + 18 + + + + + + + + + + + + + 6 + false + false + + + + text #25_2 + XSPD Detector Control - $(P)$(R) + 1125 + 25 + + + + + + + + + + + + + false + 1 + 1 + + + File + 375 + 820 + 375 + 71 + + + + + + + + + + + + + true + + text #21_1 + Driver file I/O + 18 + 10 + 150 + + + + + 2 + + + related display #24_1 + + + NDFile.opi + tab + Open Display + + + + 175 + 10 + 94 + 20 + + + + + $(actions) + + + + Shutter + 675 + 375 + 166 + + + + + + + + + + + + + true + + text #15_4 + Shutter mode + 46 + 5 + 120 + + + + + 2 + + + menu #18 + $(P)$(R)ShutterMode + 173 + 5 + 120 + 20 + + + + + false + + + text #21_2 + Open/Close + 66 + 54 + + + + + 2 + + + message button #24 + + + $(P)$(R)ShutterControl + 1 + Write + + + $(P)$(R)ShutterControl + Open + 173 + 54 + 60 + 20 + + + + + + + message button #27 + + + $(P)$(R)ShutterControl + 0 + Write + + + $(P)$(R)ShutterControl + Close + 240 + 54 + 60 + 20 + + + + + + + text #30 + Status: Det. + 6 + 29 + 120 + + + + + 2 + + + text update #33_1 + $(P)$(R)ShutterStatus_RBV + 132 + 30 + 60 + 18 + + + + + + + + + + + + + 6 + false + 1 + + + text entry #37 + $(P)$(R)ShutterOpenDelay + 132 + 79 + 60 + + + + + + + + + 1 + false + false + + + text #41 + Delay: Open + 15 + 79 + 110 + + + + + 2 + + + text #44 + Close + 215 + 79 + 50 + + + + + 2 + + + text entry #47 + $(P)$(R)ShutterCloseDelay + 272 + 79 + 60 + + + + + + + + + 1 + false + false + + + related display #51 + + + ADEpicsShutter.opi + tab + EPICS shutter setup + + + + 205 + 107 + 70 + 20 + + + + + $(actions) + + + text #54_1 + EPICS shutter setup + 6 + 107 + 190 + + + + + 2 + + + text #57_1 + EPICS + 215 + 29 + 50 + + + + + 2 + + + text update #60 + $(P)$(R)ShutterStatusEPICS_RBV + 272 + 30 + 60 + 18 + + + + + + + + + + + + + 6 + false + 1 + + + + Detector Status + 475 + 375 + + + + + + + + + + + + + true + + message button #68_1 + + + $(P)$(R)Acquire + 1 + Write + + + $(P)$(R)GenerateFlatfield + Generate + 178 + 74 + 20 + + + + + true + + + message button #68_2 + + + $(P)$(R)Acquire + 1 + Write + + + $(P)$(R)Reset + Reset + 178 + 44 + 20 + + + + + true + + + Label_13 + Generate flatfield + 18 + 74 + 150 + + + + + + + + + 2 + + + Label_34 + Reset detector + 18 + 44 + 150 + + + + + + + + + 2 + + + text update #138 + $(P)$(R)StatusMessage_RBV + 4 + 138 + 318 + 18 + + + + + + + + + + + + + 6 + false + false + + + text #135 + Status Message + 4 + 112 + 151 + + + + + + + text #93 + Detector state + 18 + 17 + 140 + + + + + 2 + + + text update #96_1 + $(P)$(R)DetectorState_RBV + 163 + 17 + 160 + 18 + + + + + + + + + + + + + 6 + false + + + + Setup + 35 + 375 + 350 + + + + + + + + + + + + + true + + text update #77 + $(P)$(R)Model_RBV + 155 + 85 + 165 + 18 + + + + + + + + + + + + + 6 + false + false + + + text update #81 + $(P)$(R)SerialNumber_RBV + 155 + 110 + 165 + 18 + + + + + + + + + + + + + 6 + false + false + + + text update #85 + $(P)$(R)FirmwareVersion_RBV + 155 + 135 + 165 + 18 + + + + + + + + + + + + + 6 + false + false + + + text update #89 + $(P)$(R)SDKVersion_RBV + 155 + 160 + 165 + 18 + + + + + + + + + + + + + 6 + false + false + + + text update #93 + $(P)$(R)DriverVersion_RBV + 155 + 184 + 165 + 18 + + + + + + + + + + + + + 6 + false + false + + + text update #97 + $(P)$(R)ADCoreVersion_RBV + 155 + 209 + 165 + 18 + + + + + + + + + + + + + 6 + false + false + + + text #15 + Debugging + 48 + 286 + 90 + + + + + 2 + + + related display #18 + + + asynRecord.opi + + $(R)AsynIO + + tab + asyn record + + + save_restoreStatus_more.opi + tab + Save restore status + + + + 147 + 286 + 70 + 20 + + + + + $(actions) + + + text #22 + Connection + 38 + 257 + + + + + 2 + + + message button #25 + + + $(P)$(R)AsynIO.CNCT + 1 + Write + + + $(P)$(R)AsynIO.CNCT + Connect + 146 + 257 + 80 + 20 + + + + + + + message button #28 + + + $(P)$(R)AsynIO.CNCT + 0 + Write + + + $(P)$(R)AsynIO.CNCT + Disconnect + 231 + 257 + 80 + 20 + + + + + + + text #31 + Connected + 177 + 230 + 90 + + + + + + + + + 1 + + + + false + + $(P)$(R)AsynIO.CNCT + + + + + text #35 + Disconnected + 162 + 230 + 120 + + + + + + + + + 1 + + + + false + + $(P)$(R)AsynIO.CNCT + + + + + text #39 + EPICS name + 50 + 34 + + + + + 2 + + + text #42 + Manufacturer + 30 + 59 + 120 + + + + + 2 + + + text #45 + asyn port + 60 + 9 + 90 + + + + + 2 + + + text #48 + Model + 100 + 84 + 50 + + + + + 2 + + + text #51 + Serial number + 20 + 109 + 130 + + + + + 2 + + + text #54 + Firmware version + 134 + 160 + + + + + 2 + + + text #57 + SDK version + 40 + 159 + 110 + + + + + 2 + + text #60 + Driver version 10 - 340 - 150 - 20 - Reset + 183 + 140 + + + + + 2 + + + text #63 + ADCore version + 10 + 208 + 140 + + + + + 2 + + + text #66 + $(P)$(R) + 155 + 35 + 138 + 19 + + + + + + + + + true + + + text update #69 + $(P)$(R)Manufacturer_RBV + 155 + 60 + 165 + 18 + + + + - + + - + + + 6 + false + false + + + text update #73 + $(P)$(R)PortName_RBV + 155 + 10 + 165 + 18 - + + - 0 - Label_12 + + + + + + + + + 6 + false + false - - 170 - 340 - 150 + + + Plugins + 375 + 375 + 100 + + + + + + + + + + + + + true + + text #18 + File + 78 + 11 + 26 + 19 + + + + + true + + + text #21 + ROI + 218 + 11 + 29 + 19 + + + + + true + + + related display #24 + + + NDFileNetCDF.opi + + nc + netCDF1: + + tab + netCDF file #1 + + + NDFileTIFF.opi + + tif + TIFF1: + + tab + TIFF file #1 + + + NDFileJPEG.opi + + jpg + JPEG1: + + tab + JPEG file #1 + + + NDFileNexus.opi + + h5 + Nexus1: + + tab + NeXus file #1 + + + NDFileMagick.opi + + tif + Magick1: + + tab + Magick file #1 + + + NDFileHDF5.opi + + h5 + HDF1: + + tab + HDF5 file #1 + + + NDFileNull.opi + + null + Null1: + + tab + Null file #1 + + + + 123 + 11 + 64 20 - $(P)$(R)Reset + + + + + $(actions) + + + related display #33 + + + NDROI.opi + + ROI1: + + tab + ROI #1 + + + NDROI.opi + + ROI2: + + tab + ROI #2 + + + NDROI.opi + + ROI3: + + tab + ROI #3 + + + NDROI.opi + + ROI4: + + tab + ROI #4 + + + NDROI4.opi + + ROI1: + ROI2: + ROI3: + ROI4: + + tab + ROI 1-4 combined + + + + 253 + 11 + 64 + 20 + + + + + $(actions) + + + related display #40 + + + commonPlugins.opi + tab + Common plugins + + + All + 4 + 11 + 64 + 20 + + + + + $(actions) + + + text #43 + Stats + 4 + 37 + 37 + 19 + + + + + true + + + related display #46 + + + NDStats.opi + + Stats1: + + tab + Statistics #1 + + + NDStats.opi + + Stats2: + + tab + Statistics #2 + + + NDStats.opi + + Stats3: + + tab + Statistics #3 + + + NDStats.opi + + Stats4: + + tab + Statistics #4 + + + NDStats.opi + + Stats5: + + tab + Statistics #5 + + + NDStats5.opi + + Stats1: + Stats2: + Stats3: + Stats4: + Stats5: + + tab + Statistics 1-5 + + + + 53 + 37 + 64 + 20 + + + + + $(actions) + + + related display #54 + + + NDStdArrays.opi + + image1: + + tab + Image #1 + + + NDPva.opi + + Pva1: + + tab + Pva #1 + + + NDProcess.opi + + Proc1: + + tab + Process #1 + + + NDTransform.opi + + Trans1: + + tab + Transform #1 + + + NDColorConvert.opi + + CC1: + + tab + Color convert #1 + + + NDColorConvert.opi + + CC2: + + tab + Color convert #2 + + + NDOverlay.opi + + Over1: + + tab + Overlay #1 + + + NDOverlay8.opi + + Over1:1: + Over1:2: + Over1:3: + Over1:4: + Over1:5: + Over1:6: + Over1:7: + Over1:8: + Over1: + + tab + Overlays 1-8 + + + NDCircularBuff.opi + + CB1: + + tab + Circular buffer #1 + + + NDROIStat.opi + + ROIStat1: + + tab + ROI Statistics #1 + + + NDPluginAttribute.opi + + Attr1: + + tab + Attribute #1 + + + NDFFT.opi + + FFT1: + + tab + FFT #1 + + + NDScatter.opi + + Scatter1: + + tab + Scatter #1 + + + NDGather8.opi + + Gather1: + + tab + Gather #1 + + + NDCodec.opi + + Codec1: + + tab + Codec #1 + + + NDCodec.opi + + Codec2: + + tab + Codec #2 + + + Other #1 + 165 + 37 + 80 + 20 + + + + + $(actions) + + + related display #72 + + + NDStdArrays.opi + + image2: + + tab + Image #2 + + + scan_more.opi + + 1 + scan1 + + tab + Scan #1 + + + yySseq.opi + + AcquireSequence + + tab + Acquire Sequence + + + ioc_stats_soft.opi + + $(P) + + tab + devIocStats + + + ADCompVision.opi + + CV1: + + tab + Open CV #1 + + + NDPluginEdge.opi + + Edge1: + + tab + Edge #1 + + + NDBadPixel.opi + + BadPix1: + + tab + Bad Pixel #1 + + + configMenu.opi + + ADAutoSave + + tab + AS configMenu + + + Other #2 + 252 + 37 + 80 + 20 + + + + + $(actions) + + + + Detector Info + 750 + 35 + 375 + 235 + + + + + + + + + + + + + true + + Label_35 + Sensor material + 22 + 30 + 125 + + + + + + + + + 2 + + + Label_36 + Sensor thickness + 22 + 55 + 125 + + + + + + + + + 2 + + + TextUpdate_21 + $(P)$(R)SensorMaterial_RBV + 163 + 30 + 150 + + + + - + + - + + + + + TextUpdate_22 + $(P)$(R)SensorThickness_RBV + 163 + 55 + 150 - + + - ChoiceButton_6 + + + + + + + + - 10 - 370 + text #78 + Sensor size + 22 + 5 + 125 + + + + + 2 + + + text update #81_1 + $(P)$(R)MaxSizeX_RBV + 163 + 5 + 61 + 18 + + + + + + + + + + + + + 1 + false + 1 + false + + + text update #85_1 + $(P)$(R)MaxSizeY_RBV + 245 + 5 + 61 + 18 + + + + + + + + + + + + + 1 + false + 1 + false + + + Label_37 + Num modules + 6 + 80 + 150 + + + + + + + + + 2 + + + TextUpdate_23 + $(P)$(R)NumModules_RBV + 166 + 80 150 + + + + + + + + + + + + + + + Label_23 + API Version + 34 + 110 + 125 + + + + + + + + + 2 + + + TextUpdate_15 + $(P)$(R)APIVersion_RBV + 161 + 110 + 165 + + + + + + + + + + + + + + + Label_24 + XSPD Version + 34 + 135 + 125 + + + + + + + + + 2 + + + TextUpdate_16 + $(P)$(R)XSPDVersion_RBV + 161 + 135 + 165 + + + + + + + + + + + + + + + Label_38 + Modules + 22 + 163 + 125 + + + + + + + + + 2 + + + related display #24_3 + + + ADXSPDModule.bob + + mod1: + + tab + Module #1 + + + ADXSPDModule.bob + + mod2: + + tab + Module #2 + + + ADXSPDModule.bob + + mod3: + + tab + Module #3 + + + ADXSPDModule.bob + + mod4: + + tab + Module #4 + + + ADXSPDModule.bob + + mod5: + + tab + Module #5 + + + ADXSPDModule.bob + + mod6: + + tab + Module #6 + + + ADXSPDModule.bob + + mod7: + + tab + Module #7 + + + ADXSPDModule.bob + + mod8: + + tab + Module #8 + + + ADXSPDModule.bob + + mod9: + + tab + Module #9 + + + ADXSPDModule.bob + + mod10: + + tab + Module #10 + + + + 166 + 163 + 140 20 - Generate flatfield + + + + + $(actions) + + + + Readout + 750 + 264 + 375 + 318 + + + + + + + + + + + + + true + + menu #110_1 + $(P)$(R)ROIRows + 140 + 10 + 20 + + + + + false + + + Label_16 + ROI rows + 6 + 10 + 125 + + + + + + + + + 2 + + + TextUpdate_9 + $(P)$(R)ROIRows_RBV + 251 + 10 + 79 + + + + - + + - + + + + + Label_20 + Bit depth + 6 + 35 + 125 - + + - 0 - Label_13 + + + + + 2 - - 170 - 370 - 150 + + ComboBox_2 + $(P)$(R)BitDepth + 140 + 35 20 - $(P)$(R)GenerateFlatfield + + + + + + + + + + + TextUpdate_13 + $(P)$(R)BitDepth_RBV + 251 + 35 + 79 + + + + - + + - + + + + + + text #125_1 + Array callbacks + 6 + 185 + 125 + + + + + 2 + + + menu #128_1 + $(P)$(R)ArrayCallbacks + 140 + 185 + 20 + + + + false + + + text update #131 + $(P)$(R)ArrayCallbacks_RBV + 251 + 185 + 80 + 18 - + + - ChoiceButton_7 + + + + + + + + + 6 + false + false - 10 - 400 - 150 + Label_10 + Saturation flag + 6 + 60 + 125 + + + + + + + + + 2 + + + ComboBox_3 + $(P)$(R)SaturationFlag + 140 + 60 20 - Shuffle mode + + + + + + + + + + + TextUpdate_24 + $(P)$(R)SaturationFlag_RBV + 251 + 60 + 80 + + + + - + + - + + + + + Label_11 + Charge summing + 6 + 85 + 125 - + + - 0 - Label_14 + + + + + 2 - 170 - 400 - 150 + ComboBox_4 + $(P)$(R)ChargeSumming + 140 + 85 20 - $(P)$(R)ShuffleMode - - - - - - - + + - ComboBox_1 - - - 330 - 400 - 150 - 20 - $(P)$(R)ShuffleMode_RBV - - - - + + + + + TextUpdate_25 + $(P)$(R)ChargeSumming_RBV + 251 + 85 + 80 - + + - TextUpdate_7 - - - 10 - 430 - 150 - 20 - Number of frames to sum - + + - + + + + + Label_12 + Flatfield corr. + 6 + 110 + 125 - + + - 0 - Label_15 - - - 170 - 430 - 150 - 20 - $(P)$(R)SummedFrames - - - - + + + 2 + + + ComboBox_5 + $(P)$(R)FlatFieldCorrection + 140 + 110 + 20 - + + - TextEntry_2 + + + + - 330 - 430 - 150 - 20 - $(P)$(R)SummedFrames_RBV + TextUpdate_26 + $(P)$(R)FlatFieldCorrection_RBV + 251 + 110 + 80 + + + + - + + - + + + + + Label_39 + Gating mode + 6 + 135 + 125 - + + - TextUpdate_8 + + + + + 2 - - 10 - 460 - 150 + + ComboBox_6 + $(P)$(R)GatingMode + 140 + 135 20 - ROI rows - - - + + + + - + + + + + TextUpdate_27 + $(P)$(R)GatingMode_RBV + 251 + 135 + 80 - + + - 0 - Label_16 - - - 170 - 460 - 150 - 20 - $(P)$(R)ROIRows - + + - + + + + + Label_40 + Count rate corr. + 6 + 160 + 125 - + + - TextEntry_3 + + + + + 2 - - 330 - 460 - 150 + + ComboBox_13 + $(P)$(R)CountrateCorrection + 140 + 160 20 - $(P)$(R)ROIRows_RBV - - - + + + + - + + + + + TextUpdate_28 + $(P)$(R)CountrateCorrection_RBV + 251 + 160 + 80 - + + - TextUpdate_9 - - - 10 - 490 - 150 - 20 - Low threshold - + + - + + + + + Label_41 + Compress level readback + 6 + 235 + 125 - + + - 0 - Label_17 + + + + + 2 - - 170 - 490 + + TextUpdate_29 + $(P)$(R)CompressLevel_RBV + 140 + 235 150 - 20 - $(P)$(R)LowThreshold + + + + - + + - + + + + + Label_42 + Compressor readback + 6 + 260 + 125 - + + - TextEntry_4 + + + + + 2 - 330 - 490 + TextUpdate_30 + $(P)$(R)Compressor_RBV + 140 + 260 150 - 20 - $(P)$(R)LowThreshold_RBV + + + + - + + - + + + + + Label_43 + Shuffle mode + 6 + 210 + 125 - + + - TextUpdate_10 + + + + + 2 - - 10 - 520 - 150 + + ComboBox_14 + $(P)$(R)ShuffleMode + 140 + 210 20 - High threshold - - - + + + + - + + + + + TextUpdate_31 + $(P)$(R)ShuffleMode_RBV + 251 + 210 + 80 - + + - 0 - Label_18 - - - 170 - 520 - 150 - 20 - $(P)$(R)HighThreshold - + + - + + + + + + Buffers + 375 + 643 + 375 + 177 + + + + + + + + + + + + + true + + text #15_16 + Pre-allocate + 1 + 12 + 120 - + + - TextEntry_5 + 2 - 330 - 520 - 150 - 20 - $(P)$(R)HighThreshold_RBV + text update #18_1 + $(P)$(R)PoolUsedBuffers + 156 + 38 + 50 + 18 + + + + - + + - + + - - - - TextUpdate_11 + 1 + false + 2 + false - 10 - 550 + text #22_3 + Used/Alloc/Free + 1 + 37 150 - 20 - Number of frames queued - - - - - - - + + - 0 - Label_19 + 2 - 170 - 550 - 150 - 20 - $(P)$(R)FramesQueued_RBV + text update #25_1 + $(P)$(R)PoolAllocBuffers + 211 + 38 + 50 + 18 + + + + - + + - + + + 1 + false + 2 + false + + + text update #29_2 + $(P)$(R)PoolFreeBuffers + 266 + 38 + 50 + 18 - + + - TextUpdate_12 - - - 10 - 580 - 150 - 20 - Bit depth - + + - + + - - - - 0 - Label_20 + 1 + false + 2 + false - 170 - 580 - 150 + menu #36_1 + $(P)$(R)PoolPollStats.SCAN + 236 + 87 + 90 20 - $(P)$(R)BitDepth - - - - + + + false + + + text #39_2 + Buffer & memory polling + 1 + 87 + 230 - + + - ComboBox_2 + 2 - 330 - 580 - 150 - 20 - $(P)$(R)BitDepth_RBV + text update #42_2 + $(P)$(R)PoolMaxMem + 206 + 63 + 60 + 18 + + + + - + + - + + + 1 + false + 2 + false + + + text update #46_1 + $(P)$(R)PoolUsedMem + 271 + 63 + 60 + 18 - + + - TextUpdate_13 - - - 10 - 610 - 150 - 20 - Count rate correction enable - + + - + + + 1 + false + 2 + false + + + text #50_1 + Memory max/used (MB) + 1 + 62 + 200 - + + - 0 - Label_21 + 2 - - 170 - 610 + + text #53_1 + Empty free list + 51 + 112 150 + + + + + 2 + + + message button #56_1 + + + $(P)$(R)EmptyFreeList + 1 + Write + + + $(P)$(R)EmptyFreeList + Empty + 206 + 112 + 83 20 - $(P)$(R)CountrateCorrection - - - - + + + + + text entry #59_1 + $(P)$(R)NumPreAllocBuffers + 126 + 12 - + + - ChoiceButton_8 + + + + + 1 + false + false - - 330 - 610 - 20 + + message button #63_1 + + + $(P)$(R)PreAllocBuffers + 1 + Write + + + $(P)$(R)PreAllocBuffers + Allocate + 231 + 12 + 81 20 - $(P)$(R)CountrateCorrection_RBV - - - + + + + + + + + Attributes + 750 + 726 + 375 + 120 + + + + + + + + + + + + + true + + text #15_6 + File + 14 + 6 + 40 - + + - LED_6 + 2 - - 10 - 640 - 150 - 20 - Status update interval in s - - - + + text entry #18 + $(P)$(R)NDAttributesFile + 60 + 7 + 275 + + + + - + + + 6 + false + false + + + text #22_2 + Macros + -6 + 31 + 60 - + + - 0 - Label_22 + 2 - - 170 - 640 - 150 - 20 - $(P)$(R)StatusInterval - - - + + text entry #25_1 + $(P)$(R)NDAttributesMacros + 59 + 32 + 275 + + + + - + + + 6 + false + false + + + text #29 + Status + -6 + 56 + 60 - + + - TextEntry_6 + 2 - 330 - 640 - 150 - 20 - $(P)$(R)StatusInterval_RBV - - - - - - + text update #32 + $(P)$(R)NDAttributesStatus + 59 + 57 + 275 + 18 - + + - TextUpdate_14 + + + + + 6 + false - - - - 680 - 490 -
+ +
diff --git a/xspdApp/op/bob/autogenerated/ADXSPD.bob b/xspdApp/op/bob/autogenerated/ADXSPD.bob new file mode 100644 index 0000000..7183510 --- /dev/null +++ b/xspdApp/op/bob/autogenerated/ADXSPD.bob @@ -0,0 +1,1861 @@ + + + ADXSPD + + 10 + 10 + 150 + 20 + ImageMode + + + + + + + + + + 0 + Label_1 + + + 170 + 10 + 150 + 20 + $(P)$(R)ImageMode + + + + + + + + + + ComboBox_1 + + + 330 + 10 + 150 + 20 + $(P)$(R)ImageMode_RBV + + + + + + + + + + TextUpdate_1 + + + 10 + 40 + 150 + 20 + TriggerMode + + + + + + + + + + 0 + Label_2 + + + 170 + 40 + 150 + 20 + $(P)$(R)TriggerMode + + + + + + + + + + ComboBox_2 + + + 330 + 40 + 150 + 20 + $(P)$(R)TriggerMode_RBV + + + + + + + + + + TextUpdate_2 + + + 10 + 70 + 150 + 20 + API Version + + + + + + + + + + 0 + Label_3 + + + 170 + 70 + 150 + 20 + $(P)$(R)APIVersion_RBV + + + + + + + + + + TextUpdate_3 + + + 10 + 100 + 150 + 20 + XSPD Version + + + + + + + + + + 0 + Label_4 + + + 170 + 100 + 150 + 20 + $(P)$(R)XSPDVersion_RBV + + + + + + + + + + TextUpdate_4 + + + 10 + 130 + 150 + 20 + Num modules + + + + + + + + + + 0 + Label_5 + + + 170 + 130 + 150 + 20 + $(P)$(R)NumModules_RBV + + + + + + + + + + TextUpdate_5 + + + 10 + 160 + 150 + 20 + Compress level readback + + + + + + + + + + 0 + Label_6 + + + 170 + 160 + 150 + 20 + $(P)$(R)CompressLevel_RBV + + + + + + + + + + TextUpdate_6 + + + 10 + 190 + 150 + 20 + Compressor readback + + + + + + + + + + 0 + Label_7 + + + 170 + 190 + 150 + 20 + $(P)$(R)Compressor_RBV + + + + + + + + + + TextUpdate_7 + + + 10 + 220 + 150 + 20 + Beam energy + + + + + + + + + + 0 + Label_8 + + + 170 + 220 + 150 + 20 + $(P)$(R)BeamEnergy + + + + + + + + + + TextEntry_1 + + + 330 + 220 + 150 + 20 + $(P)$(R)BeamEnergy_RBV + + + + + + + + + + TextUpdate_8 + + + 10 + 250 + 150 + 20 + Saturation flag + + + + + + + + + + 0 + Label_9 + + + 170 + 250 + 150 + 20 + $(P)$(R)SaturationFlag + + + + + + + + + + ComboBox_3 + + + 330 + 250 + 150 + 20 + $(P)$(R)SaturationFlag_RBV + + + + + + + + + + TextUpdate_9 + + + 10 + 280 + 150 + 20 + Charge summing + + + + + + + + + + 0 + Label_10 + + + 170 + 280 + 150 + 20 + $(P)$(R)ChargeSumming + + + + + + + + + + ComboBox_4 + + + 330 + 280 + 150 + 20 + $(P)$(R)ChargeSumming_RBV + + + + + + + + + + TextUpdate_10 + + + 10 + 310 + 150 + 20 + Flatfield correction + + + + + + + + + + 0 + Label_11 + + + 170 + 310 + 150 + 20 + $(P)$(R)FlatFieldCorrection + + + + + + + + + + ComboBox_5 + + + 330 + 310 + 150 + 20 + $(P)$(R)FlatFieldCorrection_RBV + + + + + + + + + + TextUpdate_11 + + + 10 + 340 + 150 + 20 + Gating mode + + + + + + + + + + 0 + Label_12 + + + 170 + 340 + 150 + 20 + $(P)$(R)GatingMode + + + + + + + + + + ComboBox_6 + + + 330 + 340 + 150 + 20 + $(P)$(R)GatingMode_RBV + + + + + + + + + + TextUpdate_12 + + + 10 + 370 + 150 + 20 + Counter mode + + + + + + + + + + 0 + Label_13 + + + 170 + 370 + 150 + 20 + $(P)$(R)CounterMode + + + + + + + + + + ComboBox_7 + + + 330 + 370 + 150 + 20 + $(P)$(R)CounterMode_RBV + + + + + + + + + + TextUpdate_13 + + + 10 + 400 + 150 + 20 + Reset + + + + + + + + + + 0 + Label_14 + + + 170 + 400 + 150 + 20 + $(P)$(R)Reset + + + + + + + + + + ComboBox_8 + + + 10 + 430 + 150 + 20 + Generate flatfield + + + + + + + + + + 0 + Label_15 + + + 170 + 430 + 150 + 20 + $(P)$(R)GenerateFlatfield + + + + + + + + + + ComboBox_9 + + + 10 + 460 + 150 + 20 + Shuffle mode + + + + + + + + + + 0 + Label_16 + + + 170 + 460 + 150 + 20 + $(P)$(R)ShuffleMode + + + + + + + + + + ComboBox_10 + + + 330 + 460 + 150 + 20 + $(P)$(R)ShuffleMode_RBV + + + + + + + + + + TextUpdate_14 + + + 10 + 490 + 150 + 20 + Number of frames to sum + + + + + + + + + + 0 + Label_17 + + + 170 + 490 + 150 + 20 + $(P)$(R)SummedFrames + + + + + + + + + + TextEntry_2 + + + 330 + 490 + 150 + 20 + $(P)$(R)SummedFrames_RBV + + + + + + + + + + TextUpdate_15 + + + 10 + 520 + 150 + 20 + Average board temp + + + + + + + + + + 0 + Label_18 + + + 170 + 520 + 150 + 20 + $(P)$(R)AvgBoardTemp_RBV + + + + + + + + + + TextUpdate_16 + + + 10 + 550 + 150 + 20 + Average FPGA temp + + + + + + + + + + 0 + Label_19 + + + 170 + 550 + 150 + 20 + $(P)$(R)AvgFPGATemp_RBV + + + + + + + + + + TextUpdate_17 + + + 10 + 580 + 150 + 20 + Average sensor temp + + + + + + + + + + 0 + Label_20 + + + 170 + 580 + 150 + 20 + $(P)$(R)AvgSensorTemp_RBV + + + + + + + + + + TextUpdate_18 + + + 10 + 610 + 150 + 20 + Sensor material + + + + + + + + + + 0 + Label_21 + + + 170 + 610 + 150 + 20 + $(P)$(R)SensorMaterial_RBV + + + + + + + + + + TextUpdate_19 + + + 10 + 640 + 150 + 20 + Sensor thickness + + + + + + + + + + 0 + Label_22 + + + 170 + 640 + 150 + 20 + $(P)$(R)SensorThickness_RBV + + + + + + + + + + TextUpdate_20 + + + 10 + 670 + 150 + 20 + ROI rows + + + + + + + + + + 0 + Label_23 + + + 170 + 670 + 150 + 20 + $(P)$(R)ROIRows + + + + + + + + + + ComboBox_11 + + + 330 + 670 + 150 + 20 + $(P)$(R)ROIRows_RBV + + + + + + + + + + TextUpdate_21 + + + 10 + 700 + 150 + 20 + Low threshold + + + + + + + + + + 0 + Label_24 + + + 170 + 700 + 150 + 20 + $(P)$(R)LowThreshold + + + + + + + + + + TextEntry_3 + + + 330 + 700 + 150 + 20 + $(P)$(R)LowThreshold_RBV + + + + + + + + + + TextUpdate_22 + + + 10 + 730 + 150 + 20 + High threshold + + + + + + + + + + 0 + Label_25 + + + 170 + 730 + 150 + 20 + $(P)$(R)HighThreshold + + + + + + + + + + TextEntry_4 + + + 330 + 730 + 150 + 20 + $(P)$(R)HighThreshold_RBV + + + + + + + + + + TextUpdate_23 + + + 10 + 760 + 150 + 20 + Number of frames queued + + + + + + + + + + 0 + Label_26 + + + 170 + 760 + 150 + 20 + $(P)$(R)FramesQueued_RBV + + + + + + + + + + TextUpdate_24 + + + 10 + 790 + 150 + 20 + Bit depth + + + + + + + + + + 0 + Label_27 + + + 170 + 790 + 150 + 20 + $(P)$(R)BitDepth + + + + + + + + + + ComboBox_12 + + + 330 + 790 + 150 + 20 + $(P)$(R)BitDepth_RBV + + + + + + + + + + TextUpdate_25 + + + 10 + 820 + 150 + 20 + Count rate correction enable + + + + + + + + + + 0 + Label_28 + + + 170 + 820 + 150 + 20 + $(P)$(R)CountrateCorrection + + + + + + + + + + ComboBox_13 + + + 330 + 820 + 150 + 20 + $(P)$(R)CountrateCorrection_RBV + + + + + + + + + + TextUpdate_26 + + + 10 + 850 + 150 + 20 + Monitor mode + + + + + + + + + + 0 + Label_29 + + + 170 + 850 + 150 + 20 + $(P)$(R)MonitorMode + + + + + + + + + + ComboBox_14 + + + 330 + 850 + 150 + 20 + $(P)$(R)MonitorMode_RBV + + + + + + + + + + TextUpdate_27 + + + 10 + 880 + 150 + 20 + Monitor interval in s + + + + + + + + + + 0 + Label_30 + + + 170 + 880 + 150 + 20 + $(P)$(R)MonitorInterval + + + + + + + + + + TextEntry_5 + + + 330 + 880 + 150 + 20 + $(P)$(R)MonitorInterval_RBV + + + + + + + + + + TextUpdate_28 + + + 10 + 910 + 150 + 20 + DataType + + + + + + + + + + 0 + Label_31 + + + 170 + 910 + 150 + 20 + $(P)$(R)DataType + + + + + + + + + + ComboBox_15 + + + 10 + 940 + 150 + 20 + ColorMode + + + + + + + + + + 0 + Label_32 + + + 170 + 940 + 150 + 20 + $(P)$(R)ColorMode + + + + + + + + + + ComboBox_16 + + + 330 + 940 + 150 + 20 + $(P)$(R)ColorMode_RBV + + + + + + + + + + TextUpdate_29 + + + 10 + 970 + 150 + 20 + BinX + + + + + + + + + + 0 + Label_33 + + + 170 + 970 + 150 + 20 + $(P)$(R)BinX + + + + + + + + + + TextEntry_6 + + + 330 + 970 + 150 + 20 + $(P)$(R)BinX_RBV + + + + + + + + + + TextUpdate_30 + + + 10 + 1000 + 150 + 20 + BinY + + + + + + + + + + 0 + Label_34 + + + 170 + 1000 + 150 + 20 + $(P)$(R)BinY + + + + + + + + + + TextEntry_7 + + + 330 + 1000 + 150 + 20 + $(P)$(R)BinY_RBV + + + + + + + + + + TextUpdate_31 + + + 10 + 1030 + 150 + 20 + MinX + + + + + + + + + + 0 + Label_35 + + + 170 + 1030 + 150 + 20 + $(P)$(R)MinX + + + + + + + + + + TextEntry_8 + + + 330 + 1030 + 150 + 20 + $(P)$(R)MinX_RBV + + + + + + + + + + TextUpdate_32 + + + 10 + 1060 + 150 + 20 + MinY + + + + + + + + + + 0 + Label_36 + + + 170 + 1060 + 150 + 20 + $(P)$(R)MinY + + + + + + + + + + TextEntry_9 + + + 330 + 1060 + 150 + 20 + $(P)$(R)MinY_RBV + + + + + + + + + + TextUpdate_33 + + + 10 + 1090 + 150 + 20 + SizeX + + + + + + + + + + 0 + Label_37 + + + 170 + 1090 + 150 + 20 + $(P)$(R)SizeX + + + + + + + + + + TextEntry_10 + + + 330 + 1090 + 150 + 20 + $(P)$(R)SizeX_RBV + + + + + + + + + + TextUpdate_34 + + + 10 + 1120 + 150 + 20 + SizeY + + + + + + + + + + 0 + Label_38 + + + 170 + 1120 + 150 + 20 + $(P)$(R)SizeY + + + + + + + + + + TextEntry_11 + + + 330 + 1120 + 150 + 20 + $(P)$(R)SizeY_RBV + + + + + + + + + + TextUpdate_35 + + + 10 + 1150 + 150 + 20 + ReverseX + + + + + + + + + + 0 + Label_39 + + + 170 + 1150 + 150 + 20 + $(P)$(R)ReverseX + + + + + + + + + + ComboBox_17 + + + 330 + 1150 + 150 + 20 + $(P)$(R)ReverseX_RBV + + + + + + + + + + TextUpdate_36 + + + 10 + 1180 + 150 + 20 + ReverseY + + + + + + + + + + 0 + Label_40 + + + 170 + 1180 + 150 + 20 + $(P)$(R)ReverseY + + + + + + + + + + ComboBox_18 + + + 330 + 1180 + 150 + 20 + $(P)$(R)ReverseY_RBV + + + + + + + + + + TextUpdate_37 + + + 480 + 10 + 2 + 1190 + + + + Rectangle_1 + + + + + 1210 + 810 + diff --git a/xspdApp/op/bob/ADXSPDModule.bob b/xspdApp/op/bob/autogenerated/ADXSPDModule.bob similarity index 96% rename from xspdApp/op/bob/ADXSPDModule.bob rename to xspdApp/op/bob/autogenerated/ADXSPDModule.bob index dc1dbc5..a24ee38 100644 --- a/xspdApp/op/bob/ADXSPDModule.bob +++ b/xspdApp/op/bob/autogenerated/ADXSPDModule.bob @@ -596,19 +596,22 @@ 0 Label_17 - + 170 490 - 20 + 150 20 $(P)$(R)InterpolationMode_RBV - + + + + - LED_1 + TextUpdate_17 10 @@ -643,7 +646,7 @@ - TextUpdate_17 + TextUpdate_18 10 @@ -678,7 +681,7 @@ - TextUpdate_18 + TextUpdate_19 10 @@ -713,7 +716,7 @@ - TextUpdate_19 + TextUpdate_20 10 @@ -733,19 +736,22 @@ 0 Label_21 - + 170 610 - 20 + 150 20 $(P)$(R)RamAllocated_RBV - + + + + - LED_2 + TextUpdate_21 10 @@ -765,19 +771,22 @@ 0 Label_22 - + 170 640 - 20 + 150 20 $(P)$(R)FlatfieldEnabled_RBV - + + + + - LED_3 + TextUpdate_22 10 @@ -812,7 +821,7 @@ - TextUpdate_20 + TextUpdate_23 10 @@ -847,7 +856,7 @@ - TextUpdate_21 + TextUpdate_24 10 @@ -882,7 +891,7 @@ - TextUpdate_22 + TextUpdate_25 10 @@ -917,7 +926,7 @@ - TextUpdate_23 + TextUpdate_26 10 @@ -952,7 +961,7 @@ - TextUpdate_24 + TextUpdate_27 10 @@ -972,12 +981,12 @@ 0 Label_28 - + 170 820 150 20 - $(P)$(R)UsePixelMask + $(P)$(R)PixelMask @@ -987,21 +996,24 @@ - ChoiceButton_1 + ComboBox_1 - + 330 820 - 20 + 150 20 - $(P)$(R)UsePixelMask_RBV + $(P)$(R)PixelMask_RBV - + + + + - LED_4 + TextUpdate_28 10 @@ -1036,7 +1048,7 @@ - ComboBox_1 + ComboBox_2 330 @@ -1053,7 +1065,7 @@ - TextUpdate_25 + TextUpdate_29 diff --git a/xspdApp/op/bob/ADXSPD_Top.bob b/xspdApp/op/bob/autogenerated/ADXSPD_Top.bob similarity index 93% rename from xspdApp/op/bob/ADXSPD_Top.bob rename to xspdApp/op/bob/autogenerated/ADXSPD_Top.bob index ee7920c..b95a5ed 100644 --- a/xspdApp/op/bob/ADXSPD_Top.bob +++ b/xspdApp/op/bob/autogenerated/ADXSPD_Top.bob @@ -22,7 +22,7 @@ Embedded Display_1 - ../../../../ADCore/ADApp/op/bob/autoconvert/ADBase.bob + ../../../../../ADCore/ADApp/op/bob/autoconvert/ADBase.bob 10 20 715 diff --git a/xspdApp/src/ADXSPD.cpp b/xspdApp/src/ADXSPD.cpp index 429edc8..3962743 100644 --- a/xspdApp/src/ADXSPD.cpp +++ b/xspdApp/src/ADXSPD.cpp @@ -65,6 +65,41 @@ static void monitorThreadC(void* drvPvt) { // ADXSPD Acquisition Functions // ----------------------------------------------------------------------- +/** + * @brief Helper function that will read a parameter from the XSPD API and set the corresponding + * asyn parameter + * + * @param paramIndex The index of the asyn parameter to set + * @param component The XSPD API component to read the variable from (e.g. detector, data port, + * module) + * @param varName The name of the variable to read from the XSPD API + * @return asynStatus asynSuccess on success, asynError on failure + */ +template +asynStatus ADXSPD::getAPIVar(int paramIndex, XSPD::APIComponent& component, string varName) { + try { + T value = component.GetVar(varName); + if constexpr (is_same_v || is_same_v) { + setIntegerParam(paramIndex, value); + } else if constexpr (is_enum_v) { + setIntegerParam(paramIndex, static_cast(value)); + } else if constexpr (is_same_v) { + setDoubleParam(paramIndex, value); + } else if constexpr (is_same_v) { + setStringParam(paramIndex, value.c_str()); + } else { + ERR_ARGS("Unsupported parameter type for variable %s/%s", component.GetId().c_str(), + varName.c_str()); + return asynError; + } + } catch (std::exception& e) { + ERR_ARGS("Failed to read API parameter %s/%s: %s", component.GetId().c_str(), + varName.c_str(), e.what()); + return asynError; + } + return asynSuccess; +} + /** * @brief Starts acquisition * @@ -143,7 +178,6 @@ void ADXSPD::acquisitionThread() { NDArray* pArray = nullptr; ADImageMode_t acquisitionMode; NDArrayInfo arrayInfo; - // TODO: Support other data types NDDataType_t dataType; NDColorMode_t colorMode = NDColorModeMono; // Only monochrome is supported. XSPD::CounterMode counterMode; @@ -225,7 +259,7 @@ void ADXSPD::acquisitionThread() { // TODO: This assumes no compression; handle compressed data later size_t frameSizeBytes = zmq_msg_size(&frameMessages[2]); - DEBUG_ARGS( + INFO_ARGS( "Received frame number %d, trigger number %d, status code %d, size %d, %ld bytes", frameNumber, triggerNumber, statusCode, size, frameSizeBytes); @@ -389,13 +423,23 @@ void ADXSPD::acquisitionThread() { */ void ADXSPD::monitorThread() { double pollInterval; + int monitorEnabled; while (true) { - getDoubleParam(ADXSPD_StatusInterval, &pollInterval); + getDoubleParam(ADXSPD_MonitorInterval, &pollInterval); + getIntegerParam(ADXSPD_MonitorMode, &monitorEnabled); // Don't allow polling faster than minimum interval if (pollInterval <= ADXSPD_MIN_STATUS_POLL_INTERVAL) pollInterval = ADXSPD_MIN_STATUS_POLL_INTERVAL; + if (epicsEventWaitWithTimeout(this->shutdownEventId, pollInterval) == epicsEventWaitOK) { + INFO("Shutdown event received, exiting monitor thread..."); + break; + } + + // If monitoring is disabled, skip the rest of the loop and wait for the next interval + if (monitorEnabled == 0) continue; + this->lock(); try { @@ -416,9 +460,6 @@ void ADXSPD::monitorThread() { } setIntegerParam(ADStatus, adStatus); - setIntegerParam(ADXSPD_FramesQueued, - this->pDetector->GetActiveDataPort()->GetVar("frames_queued")); - // Reading out module status takes too long. Probably should become a "GetModuleStatus" // PV that can have its Scan rate updated from I/O Intr to some rate. // for (auto& module : this->modules) { @@ -429,12 +470,9 @@ void ADXSPD::monitorThread() { setIntegerParam(ADStatus, ADStatusError); } - this->unlock(); + this->getDataPortVar(ADXSPD_FramesQueued, "frames_queued"); - if (epicsEventWaitWithTimeout(this->shutdownEventId, pollInterval) == epicsEventWaitOK) { - INFO("Shutdown event received, exiting monitor thread..."); - break; - } + this->unlock(); callParamCallbacks(); } @@ -454,12 +492,25 @@ NDDataType_t ADXSPD::getDataTypeForBitDepth(int bitDepth) { } } -void ADXSPD::getInitialDetState() { +/** + * @brief Reads initial state of the detector from the XSPD API and sets asyn parameters accordingly + * + * @return asynStatus asynSuccess if all parameters were read successfully, asynError if any + * parameter failed to be read + */ +asynStatus ADXSPD::getInitialDetState() { + int status = asynSuccess; + try { - setDoubleParam(ADAcquireTime, this->pDetector->GetVar("shutter_time") / - 1000.0); // XSPD API uses milliseconds - setIntegerParam(ADXSPD_SummedFrames, this->pDetector->GetVar("summed_frames")); + // Get initial exposure time setting; XSPD API uses milliseconds, but ADAcquireTime is in + // seconds + setDoubleParam(ADAcquireTime, this->pDetector->GetVar("shutter_time") / 1000.0); + } catch (std::exception& e) { + ERR_ARGS("Failed to read initial acquire time: %s", e.what()); + status |= asynError; + } + try { // Set ADNumImages and ADImageMode based on n_frames int numImages = this->pDetector->GetVar("n_frames"); setIntegerParam(ADNumImages, numImages); @@ -467,68 +518,60 @@ void ADXSPD::getInitialDetState() { setIntegerParam(ADImageMode, ADImageSingle); else setIntegerParam(ADImageMode, ADImageMultiple); + } catch (std::exception& e) { + ERR_ARGS("Failed to read initial number of images: %s", e.what()); + status |= asynError; + } - setIntegerParam(ADXSPD_CompressLevel, this->pDetector->GetVar("compression_level")); - setIntegerParam(ADXSPD_Compressor, - static_cast(this->pDetector->GetVar("compressor"))); - setDoubleParam(ADXSPD_BeamEnergy, this->pDetector->GetVar("beam_energy")); - setIntegerParam(ADXSPD_GatingMode, - static_cast(this->pDetector->GetVar("gating_mode"))); - setIntegerParam( - ADXSPD_FFCorrection, - static_cast(this->pDetector->GetVar("flatfield_correction"))); - setIntegerParam(ADXSPD_ChargeSumming, - static_cast(this->pDetector->GetVar("charge_summing"))); - setIntegerParam( - ADTriggerMode, - static_cast(this->pDetector->GetVar("trigger_mode"))); - + try { + // Get initial bit depth and set data type accordingly int bitDepth = this->pDetector->GetVar("bit_depth"); setIntegerParam(ADXSPD_BitDepth, bitDepth); setIntegerParam(NDDataType, static_cast(getDataTypeForBitDepth(bitDepth))); + } catch (std::exception& e) { + ERR_ARGS("Failed to read initial bit depth: %s", e.what()); + status |= asynError; + } - setIntegerParam( - ADXSPD_CrCorr, - static_cast(this->pDetector->GetVar("countrate_correction"))); - setIntegerParam( - ADXSPD_CounterMode, - static_cast(this->pDetector->GetVar("counter_mode"))); - setIntegerParam(ADXSPD_SaturationFlag, - static_cast(this->pDetector->GetVar("saturation_flag"))); - setIntegerParam( - ADXSPD_ShuffleMode, - static_cast(this->pDetector->GetVar("shuffle_mode"))); - - setStringParam(ADModel, this->pDetector->GetVar("type").c_str()); - + try { + // Get initial threshold settings. vector thresholds = this->pDetector->GetVar>("thresholds"); if (thresholds.size() > 0) setDoubleParam(ADXSPD_LowThreshold, thresholds[0]); if (thresholds.size() > 1) setDoubleParam(ADXSPD_HighThreshold, thresholds[1]); - - int maxSizeX = this->pDetector->GetActiveDataPort()->GetVar("frame_width"); - int maxSizeY = this->pDetector->GetActiveDataPort()->GetVar("frame_height"); - setIntegerParam(ADMaxSizeX, maxSizeX); - setIntegerParam(ADMaxSizeY, maxSizeY); - setIntegerParam(ADSizeX, maxSizeX); - setIntegerParam(ADSizeY, maxSizeY); - - setIntegerParam(ADXSPD_FramesQueued, - this->pDetector->GetActiveDataPort()->GetVar("frames_queued")); - - setIntegerParam(ADXSPD_RoiRows, this->pDetector->GetVar("roi_rows")); - - // TODO: BinY should reflect roi rows and vice versa. - setIntegerParam(ADBinX, 1); - setIntegerParam(ADBinY, 1); - setIntegerParam(ADMinX, 0); - setIntegerParam(ADMinY, 0); - setIntegerParam(NDColorMode, NDColorModeMono); - } catch (std::exception& e) { - ERR_ARGS("Failed to get initial detector state: %s", e.what()); + ERR_ARGS("Failed to read initial threshold settings: %s", e.what()); + status |= asynError; } + // Retrieve all remaining initial parameters. + status |= this->getDataPortVar(ADMaxSizeX, "frame_width"); + status |= this->getDataPortVar(ADMaxSizeY, "frame_height"); + status |= this->getDetVar(ADXSPD_SummedFrames, "summed_frames"); + status |= this->getDetVar(ADXSPD_CompressLevel, "compression_level"); + status |= this->getDetVar(ADXSPD_Compressor, "compressor"); + status |= this->getDetVar(ADXSPD_BeamEnergy, "beam_energy"); + status |= this->getDetVar(ADXSPD_GatingMode, "gating_mode"); + status |= this->getDetVar(ADXSPD_FFCorrection, "flatfield_enabled"); + status |= this->getDetVar(ADXSPD_ChargeSumming, "charge_summing"); + status |= this->getDetVar(ADTriggerMode, "trigger_mode"); + status |= this->getDetVar(ADXSPD_CrCorr, "countrate_correction_enabled"); + status |= this->getDetVar(ADXSPD_CounterMode, "counter_mode"); + status |= this->getDetVar(ADXSPD_SaturationFlag, "saturation_flag_enabled"); + status |= this->getDetVar(ADXSPD_ShuffleMode, "shuffle_mode"); + status |= this->getDetVar(ADModel, "type"); + status |= this->getDataPortVar(ADXSPD_FramesQueued, "frames_queued"); + status |= this->getDetVar(ADXSPD_RoiRows, "roi_rows"); + + // Sensor information is stored as user-data, so we can't guarantee it will be available or + // correct, so treat failure to read these parameters as a warning rather than an error. + int sensorInfoStatus = asynSuccess; + sensorInfoStatus |= this->getDetVar(ADXSPD_SensorMaterial, "user_data/sensor_material"); + sensorInfoStatus |= this->getDetVar(ADXSPD_SensorThickness, "user_data/sensor_thickness"); + if (sensorInfoStatus != asynSuccess) WARN("Failed to read one or more sensor info parameters."); + callParamCallbacks(); + + return static_cast(status); } //------------------------------------------------------------------------- @@ -640,7 +683,7 @@ asynStatus ADXSPD::writeInt32(asynUser* pasynUser, epicsInt32 value) { } else if (function == ADXSPD_ShuffleMode) { actualValue = static_cast(this->pDetector->SetVar( "shuffle_mode", static_cast(value))); - } else if (function == ADXSPD_StatusInterval) { + } else if (function == ADXSPD_MonitorInterval) { if (value < ADXSPD_MIN_STATUS_POLL_INTERVAL) { actualValue = ADXSPD_MIN_STATUS_POLL_INTERVAL; } @@ -704,15 +747,13 @@ asynStatus ADXSPD::writeFloat64(asynUser* pasynUser, epicsFloat64 value) { status = ADDriver::writeFloat64(pasynUser, value); } else { double actualValue = value; - string endpoint; if (function == ADXSPD_BeamEnergy) { - endpoint = "beam_energy"; - actualValue = this->pDetector->SetVar(endpoint, value); + actualValue = this->pDetector->SetVar("beam_energy", value); } else if (function == ADXSPD_LowThreshold) { actualValue = this->pDetector->SetThreshold(XSPD::Threshold::LOW, value); } else if (function == ADXSPD_HighThreshold) { actualValue = this->pDetector->SetThreshold(XSPD::Threshold::HIGH, value); - } else if (function == ADXSPD_StatusInterval && value < ADXSPD_MIN_STATUS_POLL_INTERVAL) { + } else if (function == ADXSPD_MonitorInterval && value < ADXSPD_MIN_STATUS_POLL_INTERVAL) { actualValue = ADXSPD_MIN_STATUS_POLL_INTERVAL; } setDoubleParam(function, actualValue); @@ -773,7 +814,7 @@ ADXSPD::ADXSPD(const char* portName, const char* ip, int portNum, const char* de INFO_ARGS("Connecting to XSPD api at %s:%d...", ip, portNum); this->pApi = new XSPD::API(string(ip), portNum); if (deviceId == nullptr) { - INFO("No device ID specified, will connect to first device found."); + INFO("No device ID specified, will connect to first available device."); this->pDetector = this->pApi->Initialize(); } else { INFO_ARGS("Requested device ID: %s", deviceId); @@ -801,7 +842,8 @@ ADXSPD::ADXSPD(const char* portName, const char* ip, int portNum, const char* de this->modules.push_back(new ADXSPDModule(modulePortName.c_str(), moduleList[index], this)); } - this->getInitialDetState(); + asynStatus status = this->getInitialDetState(); + if (status != asynSuccess) ERR("Failed to read one or more initial detector parameters."); // Create a shutdown event so we can signal to other threads to exit. this->shutdownEventId = epicsEventCreate(epicsEventEmpty); diff --git a/xspdApp/src/ADXSPD.h b/xspdApp/src/ADXSPD.h index 5370e58..53522ee 100644 --- a/xspdApp/src/ADXSPD.h +++ b/xspdApp/src/ADXSPD.h @@ -147,7 +147,7 @@ class ADXSPD : ADDriver { ADXSPDLogLevel getLogLevel() { return this->logLevel; } - void getInitialDetState(); + asynStatus getInitialDetState(); asynStatus acquireStart(); asynStatus acquireStop(); NDDataType_t getDataTypeForBitDepth(int bitDepth); @@ -156,6 +156,23 @@ class ADXSPD : ADDriver { void subtractFrames(void* currentFrame, void* previousFrame, void* outputFrame, size_t numBytes); + template + asynStatus getAPIVar(int paramIndex, XSPD::APIComponent& component, string varName); + + template + asynStatus getDetVar(int paramIndex, string varName) { + return getAPIVar(paramIndex, *(this->pDetector), varName); + } + + template + asynStatus getDataPortVar(int paramIndex, string varName) { + if (this->pDetector->GetActiveDataPort() == nullptr) { + ERR_ARGS("No active data port to read parameter %s from", varName.c_str()); + return asynError; + } + return getAPIVar(paramIndex, *(this->pDetector->GetActiveDataPort()), varName); + } + protected: // Load auto-generated parameter string and index definitions #include "ADXSPDParamDefs.h" diff --git a/xspdApp/src/ADXSPDModule.cpp b/xspdApp/src/ADXSPDModule.cpp index 38c517f..6aa34c1 100644 --- a/xspdApp/src/ADXSPDModule.cpp +++ b/xspdApp/src/ADXSPDModule.cpp @@ -63,10 +63,12 @@ void ADXSPDModule::getInitialModuleState() { (int) this->module->GetVar("compressor")); setIntegerParam(ADXSPDModule_InterpMode, - (int) this->module->GetVar("interpolation")); + (int) this->module->GetVar("interpolation_enabled")); setIntegerParam(ADXSPDModule_NumCons, this->module->GetVar("n_connectors")); + setIntegerParam(ADXSPDModule_PixelMask, this->module->GetVar("pixel_mask_enabled")); + getFlatfieldState(); vector position = this->module->GetVar>("position"); @@ -74,8 +76,7 @@ void ADXSPDModule::getInitialModuleState() { setDoubleParam(ADXSPDModule_PosY, position[1]); setDoubleParam(ADXSPDModule_PosZ, position[2]); - // TODO: ram_allocated endpoint doesn't seem to work - // setIntegerParam(ADXSPDModule_RamAllocated, this->module->GetVar("ram_allocated")); + setIntegerParam(ADXSPDModule_RamAllocated, this->module->GetVar("ram_allocated")); vector rotation = this->module->GetVar>("rotation"); setDoubleParam(ADXSPDModule_RotYaw, rotation[0]); @@ -85,16 +86,9 @@ void ADXSPDModule::getInitialModuleState() { setIntegerParam(ADXSPDModule_SatThresh, this->module->GetVar("saturation_threshold")); // Module feature support is stored as a bitmask w/ 4 bits. - vector features = this->module->GetVar>("features"); int featureBitmask = 0; - for (auto& featureStr : features) { - auto feature = magic_enum::enum_cast("FEAT_" + featureStr); - if (!feature.has_value()) { - ERR_ARGS("Unknown module feature: %s", featureStr.c_str()); - continue; - } else { - featureBitmask += pow(2, static_cast(feature.value())); - } + for (auto& feature : this->module->GetFeatures()) { + featureBitmask += pow(2, static_cast(feature)); } setIntegerParam(ADXSPDModule_FeatBitmask, featureBitmask); diff --git a/xspdApp/src/ADXSPDModuleParamDefs.cpp b/xspdApp/src/ADXSPDModuleParamDefs.cpp index 62068ae..82454a6 100644 --- a/xspdApp/src/ADXSPDModuleParamDefs.cpp +++ b/xspdApp/src/ADXSPDModuleParamDefs.cpp @@ -35,6 +35,6 @@ void ADXSPDModule::createAllParams() { createParam(ADXSPDModule_HighThreshFfDateString, asynParamOctet, &ADXSPDModule_HighThreshFfDate); createParam(ADXSPDModule_FramesQueuedString, asynParamInt32, &ADXSPDModule_FramesQueued); - createParam(ADXSPDModule_UsePixelMaskString, asynParamInt32, &ADXSPDModule_UsePixelMask); + createParam(ADXSPDModule_PixelMaskString, asynParamInt32, &ADXSPDModule_PixelMask); createParam(ADXSPDModule_ShuffleModeString, asynParamInt32, &ADXSPDModule_ShuffleMode); } diff --git a/xspdApp/src/ADXSPDModuleParamDefs.h b/xspdApp/src/ADXSPDModuleParamDefs.h index 2b8817f..78602b8 100644 --- a/xspdApp/src/ADXSPDModuleParamDefs.h +++ b/xspdApp/src/ADXSPDModuleParamDefs.h @@ -33,7 +33,7 @@ #define ADXSPDModule_LowThreshFfDateString "XSPD_LOW_THRESH_FF_DATE" #define ADXSPDModule_HighThreshFfDateString "XSPD_HIGH_THRESH_FF_DATE" #define ADXSPDModule_FramesQueuedString "XSPD_FRAMES_QUEUED" -#define ADXSPDModule_UsePixelMaskString "XSPD_USE_PIXEL_MASK" +#define ADXSPDModule_PixelMaskString "XSPD_PIXEL_MASK" #define ADXSPDModule_ShuffleModeString "XSPD_SHUFFLE_MODE" // Parameter index definitions @@ -65,12 +65,12 @@ int ADXSPDModule_HighThreshFfAuthor; int ADXSPDModule_LowThreshFfDate; int ADXSPDModule_HighThreshFfDate; int ADXSPDModule_FramesQueued; -int ADXSPDModule_UsePixelMask; +int ADXSPDModule_PixelMask; int ADXSPDModule_ShuffleMode; #define ADXSPDMODULE_FIRST_PARAM ADXSPDModule_BoardTemp #define ADXSPDMODULE_LAST_PARAM ADXSPDModule_ShuffleMode -#define NUM_ADXSPDMODULE_PARAMS ((int) (&ADXSPDMODULE_LAST_PARAM - &ADXSPDMODULE_FIRST_PARAM + 1)) +#define NUM_ADXSPDMODULE_PARAMS 30 #endif diff --git a/xspdApp/src/ADXSPDParamDefs.cpp b/xspdApp/src/ADXSPDParamDefs.cpp index 6806dde..47e8794 100644 --- a/xspdApp/src/ADXSPDParamDefs.cpp +++ b/xspdApp/src/ADXSPDParamDefs.cpp @@ -20,11 +20,17 @@ void ADXSPD::createAllParams() { createParam(ADXSPD_FlatfieldStatusString, asynParamOctet, &ADXSPD_FlatfieldStatus); createParam(ADXSPD_ShuffleModeString, asynParamInt32, &ADXSPD_ShuffleMode); createParam(ADXSPD_SummedFramesString, asynParamInt32, &ADXSPD_SummedFrames); + createParam(ADXSPD_AvgBoardTempString, asynParamFloat64, &ADXSPD_AvgBoardTemp); + createParam(ADXSPD_AvgFpgaTempString, asynParamFloat64, &ADXSPD_AvgFpgaTemp); + createParam(ADXSPD_AvgSensorTempString, asynParamFloat64, &ADXSPD_AvgSensorTemp); + createParam(ADXSPD_SensorMaterialString, asynParamOctet, &ADXSPD_SensorMaterial); + createParam(ADXSPD_SensorThicknessString, asynParamFloat64, &ADXSPD_SensorThickness); createParam(ADXSPD_RoiRowsString, asynParamInt32, &ADXSPD_RoiRows); createParam(ADXSPD_LowThresholdString, asynParamFloat64, &ADXSPD_LowThreshold); createParam(ADXSPD_HighThresholdString, asynParamFloat64, &ADXSPD_HighThreshold); createParam(ADXSPD_FramesQueuedString, asynParamInt32, &ADXSPD_FramesQueued); createParam(ADXSPD_BitDepthString, asynParamInt32, &ADXSPD_BitDepth); createParam(ADXSPD_CrCorrString, asynParamInt32, &ADXSPD_CrCorr); - createParam(ADXSPD_StatusIntervalString, asynParamFloat64, &ADXSPD_StatusInterval); + createParam(ADXSPD_MonitorModeString, asynParamInt32, &ADXSPD_MonitorMode); + createParam(ADXSPD_MonitorIntervalString, asynParamFloat64, &ADXSPD_MonitorInterval); } diff --git a/xspdApp/src/ADXSPDParamDefs.h b/xspdApp/src/ADXSPDParamDefs.h index 0607a6a..dc132d2 100644 --- a/xspdApp/src/ADXSPDParamDefs.h +++ b/xspdApp/src/ADXSPDParamDefs.h @@ -21,13 +21,19 @@ #define ADXSPD_FlatfieldStatusString "XSPD_FLATFIELD_STATUS" #define ADXSPD_ShuffleModeString "XSPD_SHUFFLE_MODE" #define ADXSPD_SummedFramesString "XSPD_SUMMED_FRAMES" +#define ADXSPD_AvgBoardTempString "XSPD_AVG_BOARD_TEMP" +#define ADXSPD_AvgFpgaTempString "XSPD_AVG_FPGA_TEMP" +#define ADXSPD_AvgSensorTempString "XSPD_AVG_SENSOR_TEMP" +#define ADXSPD_SensorMaterialString "XSPD_SENSOR_MATERIAL" +#define ADXSPD_SensorThicknessString "XSPD_SENSOR_THICKNESS" #define ADXSPD_RoiRowsString "XSPD_ROI_ROWS" #define ADXSPD_LowThresholdString "XSPD_LOW_THRESHOLD" #define ADXSPD_HighThresholdString "XSPD_HIGH_THRESHOLD" #define ADXSPD_FramesQueuedString "XSPD_FRAMES_QUEUED" #define ADXSPD_BitDepthString "XSPD_BIT_DEPTH" #define ADXSPD_CrCorrString "XSPD_CR_CORR" -#define ADXSPD_StatusIntervalString "XSPD_STATUS_INTERVAL" +#define ADXSPD_MonitorModeString "XSPD_MONITOR_MODE" +#define ADXSPD_MonitorIntervalString "XSPD_MONITOR_INTERVAL" // Parameter index definitions int ADXSPD_ApiVersion; @@ -46,17 +52,23 @@ int ADXSPD_GenerateFlatfield; int ADXSPD_FlatfieldStatus; int ADXSPD_ShuffleMode; int ADXSPD_SummedFrames; +int ADXSPD_AvgBoardTemp; +int ADXSPD_AvgFpgaTemp; +int ADXSPD_AvgSensorTemp; +int ADXSPD_SensorMaterial; +int ADXSPD_SensorThickness; int ADXSPD_RoiRows; int ADXSPD_LowThreshold; int ADXSPD_HighThreshold; int ADXSPD_FramesQueued; int ADXSPD_BitDepth; int ADXSPD_CrCorr; -int ADXSPD_StatusInterval; +int ADXSPD_MonitorMode; +int ADXSPD_MonitorInterval; #define ADXSPD_FIRST_PARAM ADXSPD_ApiVersion -#define ADXSPD_LAST_PARAM ADXSPD_StatusInterval +#define ADXSPD_LAST_PARAM ADXSPD_MonitorInterval -#define NUM_ADXSPD_PARAMS ((int) (&ADXSPD_LAST_PARAM - &ADXSPD_FIRST_PARAM + 1)) +#define NUM_ADXSPD_PARAMS 29 #endif diff --git a/xspdApp/src/Makefile b/xspdApp/src/Makefile index edf5c34..625c691 100644 --- a/xspdApp/src/Makefile +++ b/xspdApp/src/Makefile @@ -1,9 +1,9 @@ -TOP=../.. +TOP =../.. include $(TOP)/configure/CONFIG #---------------------------------------- -# ADD MACRO DEFINITIONS AFTER THIS LINE +# ADD MACRO DEFINITIONS AFTER THIS LINE -ifeq (windows-x64, $(findstring windows-x64, $(T_A))) +ifeq (windows - x64, $(findstring windows - x64, $(T_A))) USR_CPPFLAGS += -D__X64 endif @@ -14,13 +14,12 @@ INC += ADXSPD.h ADXSPDParamDefs.h ADXSPDModule.h ADXSPDModuleParamDefs.h XSPDAPI LIBRARY_IOC = ADXSPD LIB_SRCS += ADXSPDParamDefs.cpp ADXSPD.cpp ADXSPDModuleParamDefs.cpp ADXSPDModule.cpp XSPDAPI.cpp - DBD += xspdSupport.dbd include $(ADCORE)/ADApp/commonLibraryMakefile -#============================= +#---------------------------------------- include $(TOP)/configure/RULES -#---------------------------------------- -# ADD RULES AFTER THIS LINE +#-------------------------------------- +# ADD RULES AFTER THIS LINE diff --git a/xspdApp/src/XSPDAPI.cpp b/xspdApp/src/XSPDAPI.cpp index 14c9b76..47a9a82 100644 --- a/xspdApp/src/XSPDAPI.cpp +++ b/xspdApp/src/XSPDAPI.cpp @@ -350,3 +350,16 @@ double XSPD::Detector::SetThreshold(XSPD::Threshold threshold, double value) { return rbThresholds[static_cast(threshold)]; } + +vector XSPD::Module::GetFeatures() { + vector featureStrings = this->GetVar>("features"); + vector features; + for (auto& featureStr : featureStrings) { + auto feature = magic_enum::enum_cast(featureStr); + // TODO: Handle error case + if (feature.has_value()) { + features.push_back(feature.value()); + } + } + return features; +} diff --git a/xspdApp/src/XSPDAPI.h b/xspdApp/src/XSPDAPI.h index d7b7d04..47ae64b 100644 --- a/xspdApp/src/XSPDAPI.h +++ b/xspdApp/src/XSPDAPI.h @@ -27,8 +27,8 @@ using std::tuple; using std::vector; #define MIN_XSPD_MAJOR_VERSION 1 -#define MIN_XSPD_MINOR_VERSION 5 -#define MIN_XSPD_PATCH_VERSION 2 +#define MIN_XSPD_MINOR_VERSION 6 +#define MIN_XSPD_PATCH_VERSION 0 namespace XSPD { @@ -210,10 +210,6 @@ class API { throw runtime_error("Failed to cast value " + valAsStr + " to enum for variable " + varName); } - } else if constexpr (is_same::value) { - // Temporarily handle booleans manually, since they are being passed as strings - // instead of bools. - return response[key].get() == "true"; } else { return response[key].get(); } @@ -234,7 +230,7 @@ class APIComponent { API* GetAPI() { return this->api; } /** - * @brief Retrieves the value of a variable from the DataPort + * @brief Retrieves the value of a variable from the API for this component * * @tparam T The expected type of the variable * @param varName The name of the variable @@ -301,6 +297,7 @@ class Module : public APIComponent { virtual ~Module() = default; string GetFirmware() { return this->moduleFirmware; } vector GetChipIds() { return this->chipIds; } + vector GetFeatures(); private: string moduleFirmware; @@ -388,5 +385,5 @@ class Detector : public APIComponent { map dataPorts; DataPort* activeDataPort = nullptr; }; -}; // namespace XSPD +}; // namespace XSPD #endif // XSPDAPI_H diff --git a/xspdApp/tests/Makefile b/xspdApp/tests/Makefile index 62f50ca..0c0794d 100644 --- a/xspdApp/tests/Makefile +++ b/xspdApp/tests/Makefile @@ -5,7 +5,7 @@ include $(TOP)/configure/CONFIG USR_CPPFLAGS += -std=c++17 -PROD_IOC = TestADXSPD +TESTPROD_IOC = TestADXSPD TestADXSPD_SRCS += TestADXSPDMain.cpp # TestADXSPD_SRCS += ADXSPDTestUtils.cpp diff --git a/xspdApp/tests/MockXSPDAPI.cpp b/xspdApp/tests/MockXSPDAPI.cpp index 2905d68..797f2d6 100644 --- a/xspdApp/tests/MockXSPDAPI.cpp +++ b/xspdApp/tests/MockXSPDAPI.cpp @@ -15,7 +15,7 @@ using ::testing::Throw; MockXSPDAPI::MockXSPDAPI() : XSPD::API("localhost", 8008) { // Load sample responses from JSON file. The sample responses were pulled from // the simulator provided by X-Spectrum - string sampleResponsesPath = "xspdApp/tests/samples/xspd_sample_resp_sim.json"; + string sampleResponsesPath = "xspdApp/tests/samples/xspd_sample_responses.json"; std::ifstream file(sampleResponsesPath); if (!file.is_open()) throw std::runtime_error("Failed to open sample responses JSON file at " + @@ -23,8 +23,7 @@ MockXSPDAPI::MockXSPDAPI() : XSPD::API("localhost", 8008) { this->sampleResponses = json::parse(file); // Add a second device - this->sampleResponses["localhost:8008/api/v1/devices"]["devices"].push_back( - {{"id", "device456"}}); + this->sampleResponses["api/v1/devices"]["devices"].push_back({{"id", "device456"}}); }; /** @@ -34,9 +33,9 @@ MockXSPDAPI::MockXSPDAPI() : XSPD::API("localhost", 8008) { */ void MockXSPDAPI::MockAPIVersionCheck(json* alternateResponse) { string uri = "localhost:8008/api"; - json response = alternateResponse ? *alternateResponse : this->sampleResponses[uri]; + json response = alternateResponse ? *alternateResponse : this->sampleResponses["api"]; EXPECT_CALL(*this, SubmitRequest(uri, XSPD::RequestType::GET)).WillOnce(Return(response)); - std::cout << "Mocked GET request to URI: " << uri << std::endl; + std::cout << "Mocked GET request to endpoint: api" << std::endl; std::cout << "Returning response: " << response.dump(4) << std::endl; } @@ -47,16 +46,17 @@ void MockXSPDAPI::MockAPIVersionCheck(json* alternateResponse) { * @param alternateResponse Optional alternate response to return */ void MockXSPDAPI::MockGetRequest(string endpoint, json* alternateResponse) { - string uri = "localhost:8008/api/v1/" + endpoint; - if (!this->sampleResponses.contains(uri)) { + string fullEndpoint = "api/v1/" + endpoint; + string uri = "localhost:8008/" + fullEndpoint; + std::cout << "Mocking GET request to URI: " << fullEndpoint << std::endl; + if (!this->sampleResponses.contains(fullEndpoint)) { EXPECT_CALL(*this, SubmitRequest(uri, XSPD::RequestType::GET)) .WillOnce(Throw(std::runtime_error("Failed to get data from " + uri))); - std::cout << "Mocked GET request to URI: " << uri << std::endl; std::cout << "Mocking non 200 response code." << std::endl; } else { - json response = alternateResponse ? *alternateResponse : this->sampleResponses[uri]; + json response = + alternateResponse ? *alternateResponse : this->sampleResponses[fullEndpoint]; EXPECT_CALL(*this, SubmitRequest(uri, XSPD::RequestType::GET)).WillOnce(Return(response)); - std::cout << "Mocked GET request to URI: " << uri << std::endl; std::cout << "Returning response: " << response.dump(4) << std::endl; } } @@ -78,8 +78,9 @@ void MockXSPDAPI::MockGetVarRequest(string variableEndpoint, json* alternateResp * @param alternateResponse Optional alternate response to return */ void MockXSPDAPI::MockRepeatedGetRequest(string endpoint, json* alternateResponse) { - string uri = "localhost:8008/api/v1/" + endpoint; - json response = alternateResponse ? *alternateResponse : this->sampleResponses[uri]; + string fullEndpoint = "api/v1/" + endpoint; + string uri = "localhost:8008/" + fullEndpoint; + json response = alternateResponse ? *alternateResponse : this->sampleResponses[fullEndpoint]; EXPECT_CALL(*this, SubmitRequest(uri, XSPD::RequestType::GET)).WillRepeatedly(Return(response)); std::cout << "Mocked GET request to URI: " << uri << std::endl; std::cout << "Returning response: " << response.dump(4) << std::endl; @@ -92,8 +93,10 @@ void MockXSPDAPI::MockRepeatedGetRequest(string endpoint, json* alternateRespons * @param alternateResponse Optional alternate response to return */ void MockXSPDAPI::MockSetRequest(string endpoint, json* alternateResponse) { - string uri = "localhost:8008/api/v1/" + endpoint; - string rbUri = "localhost:8008/api/v1/" + endpoint.substr(0, endpoint.find_last_of("&")); + string fullEndpointWithArg = "api/v1/" + endpoint; + string fullEndpoint = "api/v1/" + endpoint.substr(0, endpoint.find_last_of("&")); + string uri = "localhost:8008/" + fullEndpointWithArg; + string rbUri = "localhost:8008/" + fullEndpoint; string newValue = endpoint.substr(endpoint.find_last_of('=') + 1); @@ -105,18 +108,19 @@ void MockXSPDAPI::MockSetRequest(string endpoint, json* alternateResponse) { json newValueJson = json::parse(newValue); - if (!this->sampleResponses.contains(rbUri)) { + std::cout << "Mocked PUT request with value " << newValue << "to endpoint: " << fullEndpoint + << std::endl; + if (!this->sampleResponses.contains(fullEndpoint)) { EXPECT_CALL(*this, SubmitRequest(uri, XSPD::RequestType::PUT)) .WillOnce(Throw(std::runtime_error("Failed to put data to " + uri))); - std::cout << "Mocked PUT request to URI: " << uri << std::endl; std::cout << "Mocking non 200 response code." << std::endl; } else { // Update our sample responses json with the new value - this->sampleResponses[rbUri]["value"] = newValueJson; + this->sampleResponses[fullEndpoint]["value"] = newValueJson; - json response = alternateResponse ? *alternateResponse : this->sampleResponses[rbUri]; + json response = + alternateResponse ? *alternateResponse : this->sampleResponses[fullEndpoint]; EXPECT_CALL(*this, SubmitRequest(uri, XSPD::RequestType::PUT)).WillOnce(Return(response)); - std::cout << "Mocked PUT request to URI: " << uri << std::endl; std::cout << "Returning response: " << response.dump(4) << std::endl; } } diff --git a/xspdApp/tests/MockXSPDAPI.h b/xspdApp/tests/MockXSPDAPI.h index e00da6d..0c253c2 100644 --- a/xspdApp/tests/MockXSPDAPI.h +++ b/xspdApp/tests/MockXSPDAPI.h @@ -23,12 +23,12 @@ class MockXSPDAPI : public XSPD::API { void MockAPIVersionCheck(json* alternateResponse = nullptr); void UpdateSampleResp(string endpoint, json response) { - string uri = "localhost:8008/api/v1/" + endpoint; - this->sampleResponses[uri] = response; + string fullEndpoint = "api/v1/" + endpoint; + this->sampleResponses[fullEndpoint] = response; } json GetSampleResp(string endpoint) { - string uri = "localhost:8008/api/v1/" + endpoint; - return this->sampleResponses[uri]; + string fullEndpoint = "api/v1/" + endpoint; + return this->sampleResponses[fullEndpoint]; } private: diff --git a/xspdApp/tests/TestXSPDAPI.cpp b/xspdApp/tests/TestXSPDAPI.cpp index 6746837..7c77280 100644 --- a/xspdApp/tests/TestXSPDAPI.cpp +++ b/xspdApp/tests/TestXSPDAPI.cpp @@ -34,31 +34,31 @@ TEST_F(TestXSPDAPI, TestParseVersionStringNotNumeric) { TEST_F(TestXSPDAPI, TestGetApiVersionNotInitialized) { EXPECT_THAT( - [&]() { this->mockXSPDAPI->GetApiVersion(); }, + [&]() { this->mapi->GetApiVersion(); }, testing::ThrowsMessage(testing::HasSubstr("XSPD API not initialized"))); } TEST_F(TestXSPDAPI, TestGetXSPDVersionNotInitialized) { EXPECT_THAT( - [&]() { this->mockXSPDAPI->GetXSPDVersion(); }, + [&]() { this->mapi->GetXSPDVersion(); }, testing::ThrowsMessage(testing::HasSubstr("XSPD API not initialized"))); } TEST_F(TestXSPDAPI, TestGetLibXSPVersionNotInitialized) { EXPECT_THAT( - [&]() { this->mockXSPDAPI->GetLibXSPVersion(); }, + [&]() { this->mapi->GetLibXSPVersion(); }, testing::ThrowsMessage(testing::HasSubstr("XSPD API not initialized"))); } TEST_F(TestXSPDAPI, TestGetDeviceIdNotInitialized) { EXPECT_THAT( - [&]() { this->mockXSPDAPI->GetDeviceId(); }, + [&]() { this->mapi->GetDeviceId(); }, testing::ThrowsMessage(testing::HasSubstr("XSPD API not initialized"))); } TEST_F(TestXSPDAPI, TestGetSystemIdNotInitialized) { EXPECT_THAT( - [&]() { this->mockXSPDAPI->GetSystemId(); }, + [&]() { this->mapi->GetSystemId(); }, testing::ThrowsMessage(testing::HasSubstr("XSPD API not initialized"))); } @@ -68,61 +68,61 @@ TEST_F(TestXSPDAPI, TestInitializationFailsXSPDVersionInvalid) { {"api version", "1"}, }; - this->mockXSPDAPI->MockAPIVersionCheck(&versionResp); - ASSERT_THAT([&]() { this->mockXSPDAPI->Initialize(); }, + this->mapi->MockAPIVersionCheck(&versionResp); + ASSERT_THAT([&]() { this->mapi->Initialize(); }, testing::ThrowsMessage(testing::HasSubstr( "XSPD version 0.9.0 is not supported. Minimum required version is"))); } TEST_F(TestXSPDAPI, TestGetDeviceIdAfterInitialization) { - this->mockXSPDAPI->MockInitialization(); - ASSERT_EQ(this->mockXSPDAPI->GetDeviceId(), "lambda01"); + this->mapi->MockInitialization(); + ASSERT_EQ(this->mapi->GetDeviceId(), "lambda01"); } TEST_F(TestXSPDAPI, TestGetSystemIdAfterInitialization) { - this->mockXSPDAPI->MockInitialization(); - ASSERT_EQ(this->mockXSPDAPI->GetSystemId(), "SYSTEM"); + this->mapi->MockInitialization(); + ASSERT_EQ(this->mapi->GetSystemId(), "SYSTEM"); } TEST_F(TestXSPDAPI, TestGetVersionInfoAfterInitialization) { - this->mockXSPDAPI->MockInitialization(); - ASSERT_EQ(this->mockXSPDAPI->GetApiVersion(), "1"); - ASSERT_EQ(this->mockXSPDAPI->GetXSPDVersion(), "1.5.2"); - ASSERT_EQ(this->mockXSPDAPI->GetLibXSPVersion(), "2.7.5"); + this->mapi->MockInitialization(); + ASSERT_EQ(this->mapi->GetApiVersion(), "1"); + ASSERT_EQ(this->mapi->GetXSPDVersion(), "1.6.0"); + ASSERT_EQ(this->mapi->GetLibXSPVersion(), "2.7.6"); } TEST_F(TestXSPDAPI, TestGetDeviceAtIndex) { - this->mockXSPDAPI->MockInitialization(); - this->mockXSPDAPI->MockRepeatedGetRequest("devices"); - std::string deviceId = mockXSPDAPI->GetDeviceAtIndex(0); + this->mapi->MockInitialization(); + this->mapi->MockRepeatedGetRequest("devices"); + std::string deviceId = mapi->GetDeviceAtIndex(0); ASSERT_EQ(deviceId, "lambda01"); - deviceId = mockXSPDAPI->GetDeviceAtIndex(1); + deviceId = mapi->GetDeviceAtIndex(1); ASSERT_EQ(deviceId, "device456"); } TEST_F(TestXSPDAPI, TestDeviceExists) { - this->mockXSPDAPI->MockInitialization(); - this->mockXSPDAPI->MockRepeatedGetRequest("devices"); - ASSERT_EQ(mockXSPDAPI->DeviceExists("lambda01"), true); - ASSERT_EQ(mockXSPDAPI->DeviceExists("device456"), true); - ASSERT_EQ(mockXSPDAPI->DeviceExists("device789"), false); + this->mapi->MockInitialization(); + this->mapi->MockRepeatedGetRequest("devices"); + ASSERT_EQ(mapi->DeviceExists("lambda01"), true); + ASSERT_EQ(mapi->DeviceExists("device456"), true); + ASSERT_EQ(mapi->DeviceExists("device789"), false); } TEST_F(TestXSPDAPI, TestAPIInitInvalidDeviceId) { InSequence seq; - this->mockXSPDAPI->MockAPIVersionCheck(); - this->mockXSPDAPI->MockGetRequest("devices"); - EXPECT_THAT([&]() { this->mockXSPDAPI->Initialize("device789"); }, + this->mapi->MockAPIVersionCheck(); + this->mapi->MockGetRequest("devices"); + EXPECT_THAT([&]() { this->mapi->Initialize("device789"); }, testing::ThrowsMessage( testing::HasSubstr("Device with ID device789 does not exist."))); } TEST_F(TestXSPDAPI, TestAPIInitDeviceIndexOutOfRange) { InSequence seq; - this->mockXSPDAPI->MockAPIVersionCheck(); - this->mockXSPDAPI->MockGetRequest("devices"); - EXPECT_THAT([&]() { this->mockXSPDAPI->Initialize("5"); }, + this->mapi->MockAPIVersionCheck(); + this->mapi->MockGetRequest("devices"); + EXPECT_THAT([&]() { this->mapi->Initialize("5"); }, testing::ThrowsMessage( testing::HasSubstr("Device index 5 is out of range."))); } @@ -130,36 +130,34 @@ TEST_F(TestXSPDAPI, TestAPIInitDeviceIndexOutOfRange) { TEST_F(TestXSPDAPI, TestAPIInitNoDeviceInfo) { InSequence seq; json emptyResponse = json(); - this->mockXSPDAPI->MockAPIVersionCheck(); - this->mockXSPDAPI->MockGetRequest("devices"); - this->mockXSPDAPI->MockGetVarRequest("info", &emptyResponse); - EXPECT_THAT([&]() { this->mockXSPDAPI->Initialize("lambda01"); }, + this->mapi->MockAPIVersionCheck(); + this->mapi->MockGetRequest("devices"); + this->mapi->MockGetVarRequest("info", &emptyResponse); + EXPECT_THAT([&]() { this->mapi->Initialize("lambda01"); }, testing::ThrowsMessage( testing::HasSubstr("Failed to retrieve device info for device ID lambda01"))); } TEST_F(TestXSPDAPI, TestAPIInitNoDetectors) { InSequence seq; - json modifiedInfoResp = - this->mockXSPDAPI->GetSampleResp("devices/lambda01/variables?path=info"); + json modifiedInfoResp = this->mapi->GetSampleResp("devices/lambda01/variables?path=info"); modifiedInfoResp["value"]["detectors"] = json::array(); - this->mockXSPDAPI->MockAPIVersionCheck(); - this->mockXSPDAPI->MockGetRequest("devices"); - this->mockXSPDAPI->MockGetVarRequest("info", &modifiedInfoResp); - EXPECT_THAT([&]() { this->mockXSPDAPI->Initialize("lambda01"); }, + this->mapi->MockAPIVersionCheck(); + this->mapi->MockGetRequest("devices"); + this->mapi->MockGetVarRequest("info", &modifiedInfoResp); + EXPECT_THAT([&]() { this->mapi->Initialize("lambda01"); }, testing::ThrowsMessage( testing::HasSubstr("No detector information found for device ID lambda01"))); } TEST_F(TestXSPDAPI, TestAPIInitNoDetectorID) { InSequence seq; - json modifiedInfoResp = - this->mockXSPDAPI->GetSampleResp("devices/lambda01/variables?path=info"); + json modifiedInfoResp = this->mapi->GetSampleResp("devices/lambda01/variables?path=info"); modifiedInfoResp["value"]["detectors"][0].erase("detector-id"); - this->mockXSPDAPI->MockAPIVersionCheck(); - this->mockXSPDAPI->MockGetRequest("devices"); - this->mockXSPDAPI->MockGetVarRequest("info", &modifiedInfoResp); - EXPECT_THAT([&]() { this->mockXSPDAPI->Initialize("lambda01"); }, + this->mapi->MockAPIVersionCheck(); + this->mapi->MockGetRequest("devices"); + this->mapi->MockGetVarRequest("info", &modifiedInfoResp); + EXPECT_THAT([&]() { this->mapi->Initialize("lambda01"); }, testing::ThrowsMessage( testing::HasSubstr("Detector information is missing 'detector-id' or 'modules' " "field for device ID lambda01"))); @@ -167,13 +165,12 @@ TEST_F(TestXSPDAPI, TestAPIInitNoDetectorID) { TEST_F(TestXSPDAPI, TestAPIInitNoModules) { InSequence seq; - json modifiedInfoResp = - this->mockXSPDAPI->GetSampleResp("devices/lambda01/variables?path=info"); + json modifiedInfoResp = this->mapi->GetSampleResp("devices/lambda01/variables?path=info"); modifiedInfoResp["value"]["detectors"][0].erase("modules"); - this->mockXSPDAPI->MockAPIVersionCheck(); - this->mockXSPDAPI->MockGetRequest("devices"); - this->mockXSPDAPI->MockGetVarRequest("info", &modifiedInfoResp); - EXPECT_THAT([&]() { this->mockXSPDAPI->Initialize("lambda01"); }, + this->mapi->MockAPIVersionCheck(); + this->mapi->MockGetRequest("devices"); + this->mapi->MockGetVarRequest("info", &modifiedInfoResp); + EXPECT_THAT([&]() { this->mapi->Initialize("lambda01"); }, testing::ThrowsMessage( testing::HasSubstr("Detector information is missing 'detector-id' or 'modules' " "field for device ID lambda01"))); @@ -181,99 +178,97 @@ TEST_F(TestXSPDAPI, TestAPIInitNoModules) { TEST_F(TestXSPDAPI, TestAPIInitNoDataPorts) { InSequence seq; - json modifiedDeviceInfo = this->mockXSPDAPI->GetSampleResp("devices/lambda01"); + json modifiedDeviceInfo = this->mapi->GetSampleResp("devices/lambda01"); modifiedDeviceInfo["system"]["data-ports"] = json::array(); - this->mockXSPDAPI->MockAPIVersionCheck(); - this->mockXSPDAPI->MockGetRequest("devices"); - this->mockXSPDAPI->MockGetVarRequest("info"); - this->mockXSPDAPI->MockGetRequest("devices/lambda01", &modifiedDeviceInfo); - EXPECT_THAT([&]() { this->mockXSPDAPI->Initialize("lambda01"); }, + this->mapi->MockAPIVersionCheck(); + this->mapi->MockGetRequest("devices"); + this->mapi->MockGetVarRequest("info"); + this->mapi->MockGetRequest("devices/lambda01", &modifiedDeviceInfo); + EXPECT_THAT([&]() { this->mapi->Initialize("lambda01"); }, testing::ThrowsMessage( testing::HasSubstr("No data ports found for device ID lambda01"))); } TEST_F(TestXSPDAPI, TestAPIInitMissingDataPortInfo) { InSequence seq; - json modifiedDeviceInfo = this->mockXSPDAPI->GetSampleResp("devices/lambda01"); + json modifiedDeviceInfo = this->mapi->GetSampleResp("devices/lambda01"); modifiedDeviceInfo["system"]["data-ports"][0].erase("ip"); - this->mockXSPDAPI->MockAPIVersionCheck(); - this->mockXSPDAPI->MockGetRequest("devices"); - this->mockXSPDAPI->MockGetVarRequest("info"); - this->mockXSPDAPI->MockGetRequest("devices/lambda01", &modifiedDeviceInfo); - EXPECT_THAT([&]() { this->mockXSPDAPI->Initialize("lambda01"); }, + this->mapi->MockAPIVersionCheck(); + this->mapi->MockGetRequest("devices"); + this->mapi->MockGetVarRequest("info"); + this->mapi->MockGetRequest("devices/lambda01", &modifiedDeviceInfo); + EXPECT_THAT([&]() { this->mapi->Initialize("lambda01"); }, testing::ThrowsMessage( testing::HasSubstr("Data port information is missing 'id', 'ip', or 'port' " "field for device ID lambda01"))); } TEST_F(TestXSPDAPI, TestAPIInitNoDeviceId) { - this->mockXSPDAPI->MockInitializationSeq(); - XSPD::Detector* pdet = this->mockXSPDAPI->Initialize(); - ASSERT_EQ(this->mockXSPDAPI->GetDeviceId(), "lambda01"); + this->mapi->MockInitializationSeq(); + XSPD::Detector* pdet = this->mapi->Initialize(); + ASSERT_EQ(this->mapi->GetDeviceId(), "lambda01"); ASSERT_EQ(pdet->GetId(), "lambda"); ASSERT_EQ(pdet->GetActiveDataPort()->GetId(), "port-1"); } TEST_F(TestXSPDAPI, TestAPIInitDeviceIndex) { - this->mockXSPDAPI->MockInitializationSeq(); - XSPD::Detector* pdet = this->mockXSPDAPI->Initialize("0"); - ASSERT_EQ(this->mockXSPDAPI->GetDeviceId(), "lambda01"); + this->mapi->MockInitializationSeq(); + XSPD::Detector* pdet = this->mapi->Initialize("0"); + ASSERT_EQ(this->mapi->GetDeviceId(), "lambda01"); ASSERT_EQ(pdet->GetId(), "lambda"); ASSERT_EQ(pdet->GetActiveDataPort()->GetId(), "port-1"); } TEST_F(TestXSPDAPI, TestAPIInitDeviceId) { - this->mockXSPDAPI->MockInitializationSeq(); - XSPD::Detector* pdet = this->mockXSPDAPI->Initialize("lambda01"); - ASSERT_EQ(this->mockXSPDAPI->GetDeviceId(), "lambda01"); + this->mapi->MockInitializationSeq(); + XSPD::Detector* pdet = this->mapi->Initialize("lambda01"); + ASSERT_EQ(this->mapi->GetDeviceId(), "lambda01"); ASSERT_EQ(pdet->GetId(), "lambda"); ASSERT_EQ(pdet->GetActiveDataPort()->GetId(), "port-1"); } TEST_F(TestXSPDAPI, TestGetValidEndpoint) { - this->mockXSPDAPI->MockInitialization(); - this->mockXSPDAPI->MockGetVarRequest("lambda/summed_frames"); - json response = this->mockXSPDAPI->Get("devices/lambda01/variables?path=lambda/summed_frames"); + this->mapi->MockInitialization(); + this->mapi->MockGetVarRequest("lambda/summed_frames"); + json response = this->mapi->Get("devices/lambda01/variables?path=lambda/summed_frames"); ASSERT_EQ(response["path"], "lambda/summed_frames"); ASSERT_EQ(response["value"], 1); } TEST_F(TestXSPDAPI, TestGetInvalidEndpoint) { - this->mockXSPDAPI->MockInitialization(); - this->mockXSPDAPI->MockGetRequest("invalid/endpoint"); - EXPECT_THAT([&]() { this->mockXSPDAPI->Get("invalid/endpoint"); }, + this->mapi->MockInitialization(); + this->mapi->MockGetRequest("invalid/endpoint"); + EXPECT_THAT([&]() { this->mapi->Get("invalid/endpoint"); }, testing::ThrowsMessage(testing::HasSubstr( "Failed to get data from localhost:8008/api/v1/invalid/endpoint"))); } TEST_F(TestXSPDAPI, TestReadVarFromRespValidInt) { json response = json{{"status", 1}}; - int status = this->mockXSPDAPI->ReadVarFromResp(response, "status", "status"); + int status = this->mapi->ReadVarFromResp(response, "status", "status"); ASSERT_EQ(status, 1); } TEST_F(TestXSPDAPI, TestReadVarFromRespValidString) { json response = json{{"message", "success"}}; - std::string message = - this->mockXSPDAPI->ReadVarFromResp(response, "message", "message"); + std::string message = this->mapi->ReadVarFromResp(response, "message", "message"); ASSERT_EQ(message, "success"); } TEST_F(TestXSPDAPI, TestReadVarFromRespKeyNotFound) { json response = json{{"status", 1}}; - EXPECT_THAT( - [&]() { this->mockXSPDAPI->ReadVarFromResp(response, "message", "message"); }, - testing::ThrowsMessage( - testing::HasSubstr("not found in response for variable"))); + EXPECT_THAT([&]() { this->mapi->ReadVarFromResp(response, "message", "message"); }, + testing::ThrowsMessage( + testing::HasSubstr("not found in response for variable"))); } TEST_F(TestXSPDAPI, TestReadVarFromRespEnumValid) { json response = json{{"path", "enumVar"}, {"enumKey", "ON"}}; XSPD::OnOff enumValue = - this->mockXSPDAPI->ReadVarFromResp(response, "enumVar", "enumKey"); + this->mapi->ReadVarFromResp(response, "enumVar", "enumKey"); ASSERT_EQ(enumValue, XSPD::OnOff::ON); } @@ -281,7 +276,7 @@ TEST_F(TestXSPDAPI, TestReadVarFromRespEnumInvalid) { json response = json{{"enumKey", "HI"}}; ASSERT_THAT( - [&]() { this->mockXSPDAPI->ReadVarFromResp(response, "enumVar", "enumKey"); }, + [&]() { this->mapi->ReadVarFromResp(response, "enumVar", "enumKey"); }, testing::ThrowsMessage(testing::HasSubstr("Failed to cast value"))); } @@ -289,7 +284,7 @@ TEST_F(TestXSPDAPI, TestReadVarFromRespVectorOfDoublesValid) { json response = json{{"values", json::array({1.1, 2.2, 3.3})}}; std::vector values = - this->mockXSPDAPI->ReadVarFromResp>(response, "var", "values"); + this->mapi->ReadVarFromResp>(response, "var", "values"); ASSERT_EQ((int) values.size(), 3); ASSERT_DOUBLE_EQ(values[0], 1.1); ASSERT_DOUBLE_EQ(values[1], 2.2); @@ -300,7 +295,7 @@ TEST_F(TestXSPDAPI, TestReadVarFromRespVectorOfIntsValid) { json response = json{{"values", json::array({1, 2, 3, 4})}}; std::vector values = - this->mockXSPDAPI->ReadVarFromResp>(response, "var", "values"); + this->mapi->ReadVarFromResp>(response, "var", "values"); ASSERT_EQ((int) values.size(), 4); ASSERT_EQ(values[0], 1); ASSERT_EQ(values[1], 2); @@ -311,41 +306,41 @@ TEST_F(TestXSPDAPI, TestReadVarFromRespVectorOfIntsValid) { TEST_F(TestXSPDAPI, TestReadVarFromRespPathDoesNotMatch) { json response = json{{"path", "some/other/path"}, {"value", 10}}; - ASSERT_THAT([&]() { this->mockXSPDAPI->ReadVarFromResp(response, "some/path", "value"); }, + ASSERT_THAT([&]() { this->mapi->ReadVarFromResp(response, "some/path", "value"); }, testing::ThrowsMessage(testing::HasSubstr( "Variable path mismatch: expected some/path, got some/other/path"))); } TEST_F(TestXSPDAPI, TestGetIntDetectorVar) { - XSPD::Detector* pdet = this->mockXSPDAPI->MockInitialization(); + XSPD::Detector* pdet = this->mapi->MockInitialization(); - this->mockXSPDAPI->MockGetVarRequest("lambda/bit_depth"); + this->mapi->MockGetVarRequest("lambda/bit_depth"); int intValue = pdet->GetVar("bit_depth"); ASSERT_EQ(intValue, 12); } TEST_F(TestXSPDAPI, TestGetBoolModuleVar) { - XSPD::Detector* pdet = this->mockXSPDAPI->MockInitialization(); - this->mockXSPDAPI->MockGetVarRequest("lambda/1/flatfield_enabled"); + XSPD::Detector* pdet = this->mapi->MockInitialization(); + this->mapi->MockGetVarRequest("lambda/1/flatfield_enabled"); bool boolValue = pdet->GetModules()[0]->GetVar("flatfield_enabled"); ASSERT_EQ(boolValue, false); // Update to true - this->mockXSPDAPI->UpdateSampleResp( - "devices/lambda01/variables?path=lambda/1/flatfield_enabled", json{{"value", "true"}}); - this->mockXSPDAPI->MockGetVarRequest("lambda/1/flatfield_enabled"); + this->mapi->UpdateSampleResp("devices/lambda01/variables?path=lambda/1/flatfield_enabled", + json{{"value", true}}); + this->mapi->MockGetVarRequest("lambda/1/flatfield_enabled"); boolValue = pdet->GetModules()[0]->GetVar("flatfield_enabled"); ASSERT_EQ(boolValue, true); } TEST_F(TestXSPDAPI, TestSettingHighThresholdFirstThrowsError) { - XSPD::Detector* pdet = this->mockXSPDAPI->MockInitialization(); + XSPD::Detector* pdet = this->mapi->MockInitialization(); - this->mockXSPDAPI->MockGetVarRequest("lambda/thresholds"); + this->mapi->MockGetVarRequest("lambda/thresholds"); ASSERT_THAT([&]() { pdet->SetThreshold(XSPD::Threshold::HIGH, 100); }, testing::ThrowsMessage( @@ -353,8 +348,8 @@ TEST_F(TestXSPDAPI, TestSettingHighThresholdFirstThrowsError) { } TEST_F(TestXSPDAPI, TestSetThresholdsLowLevel) { - XSPD::Detector* pdet = this->mockXSPDAPI->MockInitialization(); - this->mockXSPDAPI->MockSetVarRequest("lambda/thresholds&value=1.000000,2.000000"); + XSPD::Detector* pdet = this->mapi->MockInitialization(); + this->mapi->MockSetVarRequest("lambda/thresholds&value=1.000000,2.000000"); vector thresholds = pdet->SetVar>("thresholds", "1.000000,2.000000"); @@ -365,28 +360,48 @@ TEST_F(TestXSPDAPI, TestSetThresholdsLowLevel) { } TEST_F(TestXSPDAPI, TestSetThresholdsCorrectOrder) { - XSPD::Detector* pdet = this->mockXSPDAPI->MockInitialization(); + XSPD::Detector* pdet = this->mapi->MockInitialization(); - this->mockXSPDAPI->MockGetVarRequest("lambda/thresholds"); - this->mockXSPDAPI->MockSetVarRequest("lambda/thresholds&value=1.000000"); + this->mapi->MockGetVarRequest("lambda/thresholds"); + this->mapi->MockSetVarRequest("lambda/thresholds&value=1.000000"); double lowThreshold = pdet->SetThreshold(XSPD::Threshold::LOW, 1.0); ASSERT_DOUBLE_EQ(lowThreshold, 1.0); - this->mockXSPDAPI->MockGetVarRequest("lambda/thresholds"); - this->mockXSPDAPI->MockSetVarRequest("lambda/thresholds&value=1.000000,5.000000"); + this->mapi->MockGetVarRequest("lambda/thresholds"); + this->mapi->MockSetVarRequest("lambda/thresholds&value=1.000000,5.000000"); double highThreshold = pdet->SetThreshold(XSPD::Threshold::HIGH, 5.0); ASSERT_DOUBLE_EQ(highThreshold, 5.0); - this->mockXSPDAPI->MockGetVarRequest("lambda/thresholds"); - this->mockXSPDAPI->MockSetVarRequest("lambda/thresholds&value=1.000000,7.000000"); + this->mapi->MockGetVarRequest("lambda/thresholds"); + this->mapi->MockSetVarRequest("lambda/thresholds&value=1.000000,7.000000"); highThreshold = pdet->SetThreshold(XSPD::Threshold::HIGH, 7.0); ASSERT_DOUBLE_EQ(highThreshold, 7.0); - this->mockXSPDAPI->MockGetVarRequest("lambda/thresholds"); - this->mockXSPDAPI->MockSetVarRequest("lambda/thresholds&value=2.000000,7.000000"); + this->mapi->MockGetVarRequest("lambda/thresholds"); + this->mapi->MockSetVarRequest("lambda/thresholds&value=2.000000,7.000000"); lowThreshold = pdet->SetThreshold(XSPD::Threshold::LOW, 2.0); ASSERT_DOUBLE_EQ(lowThreshold, 2.0); } + +TEST_F(TestXSPDAPI, TestGetModuleFeatures) { + XSPD::Detector* pdet = this->mapi->MockInitialization(); + + XSPD::Module* pmod = pdet->GetModules()[0]; + + this->mapi->MockGetVarRequest("lambda/1/features"); + + vector features = pmod->GetFeatures(); + size_t expectedSize = 3; + ASSERT_EQ(features.size(), expectedSize); + ASSERT_TRUE(std::find(features.begin(), features.end(), XSPD::ModuleFeature::FEAT_HV) != + features.end()); + ASSERT_TRUE(std::find(features.begin(), features.end(), XSPD::ModuleFeature::FEAT_1_6_BIT) != + features.end()); + ASSERT_TRUE(std::find(features.begin(), features.end(), + XSPD::ModuleFeature::FEAT_EXTENDED_GATING) != features.end()); + ASSERT_TRUE(std::find(features.begin(), features.end(), + XSPD::ModuleFeature::FEAT_MEDIPIX_DAC_IO) == features.end()); +} diff --git a/xspdApp/tests/TestXSPDAPI.h b/xspdApp/tests/TestXSPDAPI.h index 6a1810e..16f8c59 100644 --- a/xspdApp/tests/TestXSPDAPI.h +++ b/xspdApp/tests/TestXSPDAPI.h @@ -19,11 +19,11 @@ using ::testing::StrictMock; class TestXSPDAPI : public ::testing::Test { protected: - void SetUp() override { mockXSPDAPI = new StrictMock(); } + void SetUp() override { mapi = new StrictMock(); } - void TearDown() override { delete mockXSPDAPI; } + void TearDown() override { delete mapi; } - StrictMock* mockXSPDAPI; + StrictMock* mapi; }; #endif // TEST_XSPDAPI_H diff --git a/xspdApp/tests/samples/xspd_sample_resp_sim.json b/xspdApp/tests/samples/xspd_sample_responses.json similarity index 53% rename from xspdApp/tests/samples/xspd_sample_resp_sim.json rename to xspdApp/tests/samples/xspd_sample_responses.json index 460e912..1eda431 100644 --- a/xspdApp/tests/samples/xspd_sample_resp_sim.json +++ b/xspdApp/tests/samples/xspd_sample_responses.json @@ -1,9 +1,9 @@ { - "localhost:8008/api": { + "api": { "api version": "1", - "xspd version": "1.5.2" + "xspd version": "1.6.0" }, - "localhost:8008/api/v1/devices": { + "api/v1/devices": { "devices": [ { "id": "lambda01", @@ -12,7 +12,7 @@ } ] }, - "localhost:8008/api/v1/devices/lambda01": { + "api/v1/devices/lambda01": { "id": "lambda01", "type": "xsp", "configfile": "/opt/xsp/config/system.yml", @@ -34,10 +34,10 @@ ] } }, - "localhost:8008/api/v1/devices/lambda01/variables?path=info": { + "api/v1/devices/lambda01/variables?path=info": { "path": "info", "value": { - "libxsp version": "2.7.5", + "libxsp version": "2.7.6", "id": "SYSTEM", "detectors": [ { @@ -67,7 +67,7 @@ ] } }, - "localhost:8008/api/v1/devices/lambda01/variables": [ + "api/v1/devices/lambda01/variables": [ { "path": "lambda/beam_energy", "description": "defines the current beam energy setting in keV" @@ -96,10 +96,18 @@ "path": "lambda/countrate_correction", "description": "enables/disables the countrate correction with 'ON' or 'OFF'" }, + { + "path": "lambda/countrate_correction_enabled", + "description": "enables/disables the countrate correction with true or false" + }, { "path": "lambda/flatfield_correction", "description": "enables/disables the flatfield correction with 'ON' or 'OFF'" }, + { + "path": "lambda/flatfield_enabled", + "description": "enables/disables the flatfield correction with true or false" + }, { "path": "lambda/gating_mode", "description": "enables/disables the gating mode with 'ON' or 'OFF'" @@ -120,6 +128,10 @@ "path": "lambda/saturation_flag", "description": "enables/disables the saturation flag with 'ON' or 'OFF'" }, + { + "path": "lambda/saturation_flag_enabled", + "description": "enables/disables the saturation flag with true or false" + }, { "path": "lambda/shuffle_mode", "description": @@ -183,7 +195,7 @@ }, { "path": "lambda/1/flatfield_enabled", - "description": "returns 'true' if a flatfield is applied, 'false' otherwise" + "description": "returns true if a flatfield is applied, false otherwise" }, { "path": "lambda/1/flatfield_error", @@ -221,6 +233,11 @@ "path": "lambda/1/interpolation", "description": "enables/disables the interpolation with 'ON' or 'OFF'" }, + { + "path": "lambda/1/interpolation_enabled", + "description": + "returns true if interpolation of extra large pixels is enabled, false otherwise" + }, { "path": "lambda/1/max_frames", "description": "defines the maximum number of frames that fit into the RAM buffer" @@ -239,7 +256,7 @@ }, { "path": "lambda/1/pixel_mask_enabled", - "description": "returns 'true' if a pixel mask is applied, 'false' otherwise" + "description": "returns true if a pixel mask is applied, false otherwise" }, { "path": "lambda/1/position", @@ -247,7 +264,7 @@ }, { "path": "lambda/1/ram_allocated", - "description": "returns whether ram is allocated" + "description": "returns true if ram is allocated, false otherwise" }, { "path": "lambda/1/rotation", @@ -299,91 +316,103 @@ "description": "returns the base64 encoded pixel mask" } ], - "localhost:8008/api/v1/devices/lambda01/variables?path=lambda/beam_energy": { + "api/v1/devices/lambda01/variables?path=lambda/beam_energy": { "path": "lambda/beam_energy", "value": 0.0 }, - "localhost:8008/api/v1/devices/lambda01/variables?path=lambda/bit_depth": { + "api/v1/devices/lambda01/variables?path=lambda/bit_depth": { "path": "lambda/bit_depth", "value": 12 }, - "localhost:8008/api/v1/devices/lambda01/variables?path=lambda/charge_summing": { + "api/v1/devices/lambda01/variables?path=lambda/charge_summing": { "path": "lambda/charge_summing", "value": "OFF" }, - "localhost:8008/api/v1/devices/lambda01/variables?path=lambda/compression_level": { + "api/v1/devices/lambda01/variables?path=lambda/compression_level": { "path": "lambda/compression_level", "value": 2 }, - "localhost:8008/api/v1/devices/lambda01/variables?path=lambda/compressor": { + "api/v1/devices/lambda01/variables?path=lambda/compressor": { "path": "lambda/compressor", "value": "none" }, - "localhost:8008/api/v1/devices/lambda01/variables?path=lambda/counter_mode": { + "api/v1/devices/lambda01/variables?path=lambda/counter_mode": { "path": "lambda/counter_mode", "value": "SINGLE" }, - "localhost:8008/api/v1/devices/lambda01/variables?path=lambda/countrate_correction": { + "api/v1/devices/lambda01/variables?path=lambda/countrate_correction": { "path": "lambda/countrate_correction", "value": "OFF" }, - "localhost:8008/api/v1/devices/lambda01/variables?path=lambda/flatfield_correction": { + "api/v1/devices/lambda01/variables?path=lambda/countrate_correction_enabled": { + "path": "lambda/countrate_correction_enabled", + "value": false + }, + "api/v1/devices/lambda01/variables?path=lambda/flatfield_correction": { "path": "lambda/flatfield_correction", "value": "OFF" }, - "localhost:8008/api/v1/devices/lambda01/variables?path=lambda/gating_mode": { + "api/v1/devices/lambda01/variables?path=lambda/flatfield_enabled": { + "path": "lambda/flatfield_enabled", + "value": false + }, + "api/v1/devices/lambda01/variables?path=lambda/gating_mode": { "path": "lambda/gating_mode", "value": "OFF" }, - "localhost:8008/api/v1/devices/lambda01/variables?path=lambda/n_frames": { + "api/v1/devices/lambda01/variables?path=lambda/n_frames": { "path": "lambda/n_frames", "value": 1 }, - "localhost:8008/api/v1/devices/lambda01/variables?path=lambda/n_modules": { + "api/v1/devices/lambda01/variables?path=lambda/n_modules": { "path": "lambda/n_modules", "value": 1 }, - "localhost:8008/api/v1/devices/lambda01/variables?path=lambda/roi_rows": { + "api/v1/devices/lambda01/variables?path=lambda/roi_rows": { "path": "lambda/roi_rows", "value": 256 }, - "localhost:8008/api/v1/devices/lambda01/variables?path=lambda/saturation_flag": { + "api/v1/devices/lambda01/variables?path=lambda/saturation_flag": { "path": "lambda/saturation_flag", "value": "OFF" }, - "localhost:8008/api/v1/devices/lambda01/variables?path=lambda/shuffle_mode": { + "api/v1/devices/lambda01/variables?path=lambda/saturation_flag_enabled": { + "path": "lambda/saturation_flag_enabled", + "value": false + }, + "api/v1/devices/lambda01/variables?path=lambda/shuffle_mode": { "path": "lambda/shuffle_mode", "value": "NO_SHUFFLE" }, - "localhost:8008/api/v1/devices/lambda01/variables?path=lambda/shutter_time": { + "api/v1/devices/lambda01/variables?path=lambda/shutter_time": { "path": "lambda/shutter_time", "value": 1.0 }, - "localhost:8008/api/v1/devices/lambda01/variables?path=lambda/status": { + "api/v1/devices/lambda01/variables?path=lambda/status": { "path": "lambda/status", "value": "ready" }, - "localhost:8008/api/v1/devices/lambda01/variables?path=lambda/summed_frames": { + "api/v1/devices/lambda01/variables?path=lambda/summed_frames": { "path": "lambda/summed_frames", "value": 1 }, - "localhost:8008/api/v1/devices/lambda01/variables?path=lambda/thresholds": { + "api/v1/devices/lambda01/variables?path=lambda/thresholds": { "path": "lambda/thresholds", "value": [] }, - "localhost:8008/api/v1/devices/lambda01/variables?path=lambda/trigger_mode": { + "api/v1/devices/lambda01/variables?path=lambda/trigger_mode": { "path": "lambda/trigger_mode", "value": "SOFTWARE" }, - "localhost:8008/api/v1/devices/lambda01/variables?path=lambda/type": { + "api/v1/devices/lambda01/variables?path=lambda/type": { "path": "lambda/type", "value": "Lambda" }, - "localhost:8008/api/v1/devices/lambda01/variables?path=lambda/user_data": { + "api/v1/devices/lambda01/variables?path=lambda/user_data": { "path": "lambda/user_data", "value": "" }, - "localhost:8008/api/v1/devices/lambda01/variables?path=lambda/1/chip_ids": { + "api/v1/devices/lambda01/variables?path=lambda/1/chip_ids": { "path": "lambda/1/chip_ids", "value": [ "w1-A01,CRN,0x00000111", @@ -400,95 +429,111 @@ "w12-A01,CRN,0x00000c11" ] }, - "localhost:8008/api/v1/devices/lambda01/variables?path=lambda/1/compression_level": { + "api/v1/devices/lambda01/variables?path=lambda/1/compression_level": { "path": "lambda/1/compression_level", "value": 2 }, - "localhost:8008/api/v1/devices/lambda01/variables?path=lambda/1/compressor": { + "api/v1/devices/lambda01/variables?path=lambda/1/compressor": { "path": "lambda/1/compressor", "value": "none" }, - "localhost:8008/api/v1/devices/lambda01/variables?path=lambda/1/features": { + "api/v1/devices/lambda01/variables?path=lambda/1/features": { "path": "lambda/1/features", "value": [ - "HV", - "1_6_BIT", - "EXTENDED_GATING" + "FEAT_HV", + "FEAT_1_6_BIT", + "FEAT_EXTENDED_GATING" ] }, - "localhost:8008/api/v1/devices/lambda01/variables?path=lambda/1/firmware_version": { + "api/v1/devices/lambda01/variables?path=lambda/1/firmware_version": { "path": "lambda/1/firmware_version", "value": "2.2.0 [ctrl=v1, data=v3, feat=0x4b]" }, - "localhost:8008/api/v1/devices/lambda01/variables?path=lambda/1/flatfield": { + "api/v1/devices/lambda01/variables?path=lambda/1/flatfield": { "path": "lambda/1/flatfield", - "value": [] + "value": [ + "", + "" + ] }, - "localhost:8008/api/v1/devices/lambda01/variables?path=lambda/1/flatfield_author": { + "api/v1/devices/lambda01/variables?path=lambda/1/flatfield_author": { "path": "lambda/1/flatfield_author", - "value": [] + "value": [ + "", + "" + ] }, - "localhost:8008/api/v1/devices/lambda01/variables?path=lambda/1/flatfield_enabled": { + "api/v1/devices/lambda01/variables?path=lambda/1/flatfield_enabled": { "path": "lambda/1/flatfield_enabled", - "value": "false" + "value": false }, - "localhost:8008/api/v1/devices/lambda01/variables?path=lambda/1/flatfield_error": { + "api/v1/devices/lambda01/variables?path=lambda/1/flatfield_error": { "path": "lambda/1/flatfield_error", - "value": [] + "value": [ + "", + "" + ] }, - "localhost:8008/api/v1/devices/lambda01/variables?path=lambda/1/flatfield_status": { + "api/v1/devices/lambda01/variables?path=lambda/1/flatfield_status": { "path": "lambda/1/flatfield_status", "value": "No flatfield measurement started" }, - "localhost:8008/api/v1/devices/lambda01/variables?path=lambda/1/flatfield_timestamp": { + "api/v1/devices/lambda01/variables?path=lambda/1/flatfield_timestamp": { "path": "lambda/1/flatfield_timestamp", - "value": [] + "value": [ + "", + "" + ] }, - "localhost:8008/api/v1/devices/lambda01/variables?path=lambda/1/frame_depth": { + "api/v1/devices/lambda01/variables?path=lambda/1/frame_depth": { "path": "lambda/1/frame_depth", "value": 12 }, - "localhost:8008/api/v1/devices/lambda01/variables?path=lambda/1/frame_height": { + "api/v1/devices/lambda01/variables?path=lambda/1/frame_height": { "path": "lambda/1/frame_height", "value": 516 }, - "localhost:8008/api/v1/devices/lambda01/variables?path=lambda/1/frame_width": { + "api/v1/devices/lambda01/variables?path=lambda/1/frame_width": { "path": "lambda/1/frame_width", "value": 1556 }, - "localhost:8008/api/v1/devices/lambda01/variables?path=lambda/1/frames_queued": { + "api/v1/devices/lambda01/variables?path=lambda/1/frames_queued": { "path": "lambda/1/frames_queued", "value": 0 }, - "localhost:8008/api/v1/devices/lambda01/variables?path=lambda/1/humidity": { + "api/v1/devices/lambda01/variables?path=lambda/1/humidity": { "path": "lambda/1/humidity", "value": 75.099991 }, - "localhost:8008/api/v1/devices/lambda01/variables?path=lambda/1/interpolation": { + "api/v1/devices/lambda01/variables?path=lambda/1/interpolation": { "path": "lambda/1/interpolation", "value": "ON" }, - "localhost:8008/api/v1/devices/lambda01/variables?path=lambda/1/max_frames": { + "api/v1/devices/lambda01/variables?path=lambda/1/interpolation_enabled": { + "path": "lambda/1/interpolation_enabled", + "value": true + }, + "api/v1/devices/lambda01/variables?path=lambda/1/max_frames": { "path": "lambda/1/max_frames", "value": 6930 }, - "localhost:8008/api/v1/devices/lambda01/variables?path=lambda/1/n_connectors": { + "api/v1/devices/lambda01/variables?path=lambda/1/n_connectors": { "path": "lambda/1/n_connectors", "value": 1 }, - "localhost:8008/api/v1/devices/lambda01/variables?path=lambda/1/n_subframes": { + "api/v1/devices/lambda01/variables?path=lambda/1/n_subframes": { "path": "lambda/1/n_subframes", "value": 1 }, - "localhost:8008/api/v1/devices/lambda01/variables?path=lambda/1/pixel_mask": { + "api/v1/devices/lambda01/variables?path=lambda/1/pixel_mask": { "path": "lambda/1/pixel_mask", "value": "" }, - "localhost:8008/api/v1/devices/lambda01/variables?path=lambda/1/pixel_mask_enabled": { + "api/v1/devices/lambda01/variables?path=lambda/1/pixel_mask_enabled": { "path": "lambda/1/pixel_mask_enabled", - "value": "false" + "value": false }, - "localhost:8008/api/v1/devices/lambda01/variables?path=lambda/1/position": { + "api/v1/devices/lambda01/variables?path=lambda/1/position": { "path": "lambda/1/position", "value": [ 0.0, @@ -496,239 +541,11 @@ 0.0 ] }, - "localhost:8008/api/v1/devices/lambda01/variables?path=lambda/1/ram_allocated": [ - { - "path": "lambda/beam_energy", - "description": "defines the current beam energy setting in keV" - }, - { - "path": "lambda/bit_depth", - "description": "defines the readout bit depth '1', '6', '12' or '24' bit" - }, - { - "path": "lambda/charge_summing", - "description": "enables/disables the charge summing mode with 'ON' or 'OFF'" - }, - { - "path": "lambda/compression_level", - "description": "defines the compression level from '1' to '4'" - }, - { - "path": "lambda/compressor", - "description": "defines the compressor 'zlib', 'blosc' or 'none'" - }, - { - "path": "lambda/counter_mode", - "description": "defines the counter mode 'SINGLE' or 'DUAL'" - }, - { - "path": "lambda/countrate_correction", - "description": "enables/disables the countrate correction with 'ON' or 'OFF'" - }, - { - "path": "lambda/flatfield_correction", - "description": "enables/disables the flatfield correction with 'ON' or 'OFF'" - }, - { - "path": "lambda/gating_mode", - "description": "enables/disables the gating mode with 'ON' or 'OFF'" - }, - { - "path": "lambda/n_frames", - "description": "defines the number of frames per acquisition" - }, - { - "path": "lambda/n_modules", - "description": "returns the number of modules of a detector" - }, - { - "path": "lambda/roi_rows", - "description": "defines the numbers of readout rows per chip" - }, - { - "path": "lambda/saturation_flag", - "description": "enables/disables the saturation flag with 'ON' or 'OFF'" - }, - { - "path": "lambda/shuffle_mode", - "description": - "defines the shuffle mode 'NO_SHUFFLE', 'AUTO_SHUFFLE', 'BIT_SHUFFLE' or 'BYTE_SHUFFLE'" - }, - { - "path": "lambda/shutter_time", - "description": "defines the shutter time in ms" - }, - { - "path": "lambda/status", - "description": "returns the detector status 'busy', 'ready' or 'connected'" - }, - { - "path": "lambda/summed_frames", - "description": "returns the number of summed frames" - }, - { - "path": "lambda/thresholds", - "description": "defines the detector thresholds in a list of floats" - }, - { - "path": "lambda/trigger_mode", - "description": "defines the trigger mode 'SOFTWARE', 'EXT_FRAMES' or 'EXT_SEQUENCE'" - }, - { - "path": "lambda/type", - "description": "returns the detector type" - }, - { - "path": "lambda/user_data", - "description": "returns the user data to a specified key" - }, - { - "path": "lambda/1/chip_ids", - "description": "returns a list of chip ids of the corresponding module" - }, - { - "path": "lambda/1/compression_level", - "description": "defines the compression level from '1' to '4'" - }, - { - "path": "lambda/1/compressor", - "description": "defines the compressor 'zlib', 'blosc' or 'none'" - }, - { - "path": "lambda/1/features", - "description": "returns the supported firmware features" - }, - { - "path": "lambda/1/firmware_version", - "description": "returns the firmware version in 'major.minor.patch' order" - }, - { - "path": "lambda/1/flatfield", - "description": "returns the flatfield data" - }, - { - "path": "lambda/1/flatfield_author", - "description": "returns the author of the flatfield" - }, - { - "path": "lambda/1/flatfield_enabled", - "description": "returns 'true' if a flatfield is applied, 'false' otherwise" - }, - { - "path": "lambda/1/flatfield_error", - "description": "returns the error of the flatfield" - }, - { - "path": "lambda/1/flatfield_status", - "description": "returns the status of the latest generate_flatfield command call" - }, - { - "path": "lambda/1/flatfield_timestamp", - "description": "returns the timestamp of the flatfield" - }, - { - "path": "lambda/1/frame_depth", - "description": "defines the frame depth '1', '6', '12' or '24' bit" - }, - { - "path": "lambda/1/frame_height", - "description": "returns the frame height in pixels" - }, - { - "path": "lambda/1/frame_width", - "description": "returns the frame width in pixels" - }, - { - "path": "lambda/1/frames_queued", - "description": "returns the number of queued frames" - }, - { - "path": "lambda/1/humidity", - "description": "returns the measured humidity from a detector module" - }, - { - "path": "lambda/1/interpolation", - "description": "enables/disables the interpolation with 'ON' or 'OFF'" - }, - { - "path": "lambda/1/max_frames", - "description": "defines the maximum number of frames that fit into the RAM buffer" - }, - { - "path": "lambda/1/n_connectors", - "description": "returns the number of connected sensors" - }, - { - "path": "lambda/1/n_subframes", - "description": "returns the number of subframes" - }, - { - "path": "lambda/1/pixel_mask", - "description": "returns the base64 encoded pixel mask of a module" - }, - { - "path": "lambda/1/pixel_mask_enabled", - "description": "returns 'true' if a pixel mask is applied, 'false' otherwise" - }, - { - "path": "lambda/1/position", - "description": "returns the module position [x,y,z]" - }, - { - "path": "lambda/1/ram_allocated", - "description": "returns whether ram is allocated" - }, - { - "path": "lambda/1/rotation", - "description": "returns the module rotation [alpha, beta, gamma]" - }, - { - "path": "lambda/1/saturation_threshold", - "description": "defines the actual saturation threshold in counts per second per pixel" - }, - { - "path": "lambda/1/sensor_current", - "description": "returns the measured sensor current from a detector module" - }, - { - "path": "lambda/1/shuffle_mode", - "description": - "defines the shuffle mode 'NO_SHUFFLE', 'AUTO_SHUFFLE', 'BIT_SHUFFLE' or 'BYTE_SHUFFLE'" - }, - { - "path": "lambda/1/status", - "description": "returns the module status 'busy', 'ready' or 'connected'" - }, - { - "path": "lambda/1/temperature", - "description": "returns the measured temperatures from a detector module" - }, - { - "path": "lambda/1/voltage", - "description": "returns the current high voltage in V" - }, - { - "path": "port-1/frame_depth", - "description": "defines the frame depth '1', '6', '12' or '24' bit" - }, - { - "path": "port-1/frame_height", - "description": "returns the frame height in pixels" - }, - { - "path": "port-1/frame_width", - "description": "returns the frame width in pixels" - }, - { - "path": "port-1/frames_queued", - "description": "returns the number of queued frames" - }, - { - "path": "port-1/pixel_mask", - "description": "returns the base64 encoded pixel mask" - } - ], - "localhost:8008/api/v1/devices/lambda01/variables?path=lambda/1/rotation": { + "api/v1/devices/lambda01/variables?path=lambda/1/ram_allocated": { + "path": "lambda/1/ram_allocated", + "value": true + }, + "api/v1/devices/lambda01/variables?path=lambda/1/rotation": { "path": "lambda/1/rotation", "value": [ 0.0, @@ -736,23 +553,23 @@ 0.0 ] }, - "localhost:8008/api/v1/devices/lambda01/variables?path=lambda/1/saturation_threshold": { + "api/v1/devices/lambda01/variables?path=lambda/1/saturation_threshold": { "path": "lambda/1/saturation_threshold", "value": 200000 }, - "localhost:8008/api/v1/devices/lambda01/variables?path=lambda/1/sensor_current": { + "api/v1/devices/lambda01/variables?path=lambda/1/sensor_current": { "path": "lambda/1/sensor_current", "value": 0.209991 }, - "localhost:8008/api/v1/devices/lambda01/variables?path=lambda/1/shuffle_mode": { + "api/v1/devices/lambda01/variables?path=lambda/1/shuffle_mode": { "path": "lambda/1/shuffle_mode", "value": "NO_SHUFFLE" }, - "localhost:8008/api/v1/devices/lambda01/variables?path=lambda/1/status": { + "api/v1/devices/lambda01/variables?path=lambda/1/status": { "path": "lambda/1/status", "value": "ready" }, - "localhost:8008/api/v1/devices/lambda01/variables?path=lambda/1/temperature": { + "api/v1/devices/lambda01/variables?path=lambda/1/temperature": { "path": "lambda/1/temperature", "value": [ 36.779999, @@ -760,31 +577,31 @@ 39.119995 ] }, - "localhost:8008/api/v1/devices/lambda01/variables?path=lambda/1/voltage": { + "api/v1/devices/lambda01/variables?path=lambda/1/voltage": { "path": "lambda/1/voltage", "value": 0.0 }, - "localhost:8008/api/v1/devices/lambda01/variables?path=port-1/frame_depth": { + "api/v1/devices/lambda01/variables?path=port-1/frame_depth": { "path": "port-1/frame_depth", "value": 12 }, - "localhost:8008/api/v1/devices/lambda01/variables?path=port-1/frame_height": { + "api/v1/devices/lambda01/variables?path=port-1/frame_height": { "path": "port-1/frame_height", "value": 516 }, - "localhost:8008/api/v1/devices/lambda01/variables?path=port-1/frame_width": { + "api/v1/devices/lambda01/variables?path=port-1/frame_width": { "path": "port-1/frame_width", "value": 1556 }, - "localhost:8008/api/v1/devices/lambda01/variables?path=port-1/frames_queued": { + "api/v1/devices/lambda01/variables?path=port-1/frames_queued": { "path": "port-1/frames_queued", "value": 0 }, - "localhost:8008/api/v1/devices/lambda01/variables?path=port-1/pixel_mask": { + "api/v1/devices/lambda01/variables?path=port-1/pixel_mask": { "path": "port-1/pixel_mask", "value": "" }, - "localhost:8008/api/v1/devices/lambda01/commands": [ + "api/v1/devices/lambda01/commands": [ { "path": "start", "description": "starts an acquisition on all detectors" diff --git a/xspdApp/tests/scripts/generate_sample_response_json.py b/xspdApp/tests/scripts/generate_sample_response_json.py index bb27c71..3e09a3e 100755 --- a/xspdApp/tests/scripts/generate_sample_response_json.py +++ b/xspdApp/tests/scripts/generate_sample_response_json.py @@ -8,40 +8,85 @@ import json import requests +from pathlib import Path +import logging +import argparse -SAMPLE_RESPONSE_DICT = {} -BASE_URI = "localhost:8008/api" +logging.basicConfig() +logger = logging.getLogger("gen_sample_responses") +logger.level = logging.INFO -def save_sample_endpoint_value(endpoint): - url = BASE_URI + endpoint +def get_full_endpoint(base_uri, endpoint): + return base_uri.split("/", 1)[-1] + endpoint + + +def get_sample_endpoint_value(base_uri, endpoint): + url = base_uri + endpoint + logger.info(f"Getting value of endpoint {endpoint}") response = requests.get("http://" + url) response.raise_for_status() - SAMPLE_RESPONSE_DICT[url] = response.json() - return response.json() + return {get_full_endpoint(base_uri, endpoint): response.json()} -def save_device_variable_values(device_id): +def get_device_variable_values(base_uri, device_id): + device_variables = {} var_endpoint = f"devices/{device_id}/variables" - save_sample_endpoint_value(var_endpoint + "?path=info") - variables = save_sample_endpoint_value(var_endpoint) - for variable in variables: + device_variables.update( + get_sample_endpoint_value(base_uri, var_endpoint + "?path=info") + ) + variables = get_sample_endpoint_value(base_uri, var_endpoint) + device_variables.update(variables) + for variable in variables[get_full_endpoint(base_uri, var_endpoint)]: variable_id = variable["path"] - save_sample_endpoint_value(f"{var_endpoint}?path={variable_id}") + device_variables.update( + get_sample_endpoint_value(base_uri, f"{var_endpoint}?path={variable_id}") + ) + return device_variables + + +def main(): + parser = argparse.ArgumentParser( + description="Utility for pulling all values from a running xspd instance into a json file" + ) + + parser.add_argument( + "-u", + "--uri", + default="localhost:8008", + help="Base URI on which xspd is running", + ) + + base_uri = vars(parser.parse_args())["uri"] + base_uri = base_uri + "/" if not base_uri.endswith("/") else base_uri + + sample_responses = {} + api_info = get_sample_endpoint_value(base_uri, "api") + base_uri += ( + "api/v" + api_info[get_full_endpoint(base_uri, "api")]["api version"] + "/" + ) -api_info = save_sample_endpoint_value("") -BASE_URI += "/v" + api_info["api version"] + "/" + all_device_info = get_sample_endpoint_value(base_uri, "devices") + sample_responses.update(api_info) + sample_responses.update(all_device_info) -all_device_info = save_sample_endpoint_value("devices") + for device in all_device_info[get_full_endpoint(base_uri, "devices")]["devices"]: + device_id = device["id"] + sample_responses.update( + get_sample_endpoint_value(base_uri, f"devices/{device_id}") + ) + sample_responses.update(get_device_variable_values(base_uri, device_id)) + sample_responses.update( + get_sample_endpoint_value(base_uri, f"devices/{device_id}/commands") + ) -for device in all_device_info["devices"]: - device_id = device["id"] - device_info = save_sample_endpoint_value(f"devices/{device_id}") - save_device_variable_values(device_id) - save_sample_endpoint_value(f"devices/{device_id}/commands") + with open( + Path(__file__).parent.absolute() / "../samples/xspd_sample_responses.json", "w" + ) as fp: + fp.write(json.dumps(sample_responses, indent=4)) -with open("xspd_sample_responses.json", "w") as fp: - fp.write(json.dumps(SAMPLE_RESPONSE_DICT, indent=4)) +if __name__ == "__main__": + main()