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()