diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..f9dbd80d --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +cmake-build-debug/ +cmake-build-release/ +build*/ diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 9dc517f1..c90b2f6f 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -2,11 +2,11 @@ stages: - build - test - synthesis + - release build:x86:gcc: stage: build variables: - GIT_SUBMODULE_STRATEGY: recursive CC: gcc CXX: g++ tags: @@ -23,7 +23,6 @@ build:x86:gcc: build:x86:gcc_writer: stage: build variables: - GIT_SUBMODULE_STRATEGY: recursive CC: gcc CXX: g++ tags: @@ -40,7 +39,6 @@ build:x86:gcc_writer: build:x86:driver: stage: build variables: - GIT_SUBMODULE_STRATEGY: recursive CC: gcc CXX: g++ tags: @@ -49,18 +47,16 @@ build:x86:driver: needs: [] artifacts: paths: - - "jfjoch_driver_*.tar.gz" + - "jfjoch_driver.tar.gz" expire_in: 1 week script: - cd fpga/pcie_driver - make - bash pack.sh - - mv jfjoch_driver_*.tar.gz ../.. + - mv jfjoch_driver.tar.gz ../.. build:x86:vitis_hls: stage: build - variables: - GIT_SUBMODULE_STRATEGY: recursive tags: - x86 needs: [] @@ -83,8 +79,6 @@ build:x86:vitis_hls: build:x86:frontend: stage: build - variables: - GIT_SUBMODULE_STRATEGY: recursive tags: - x86 needs: [] @@ -93,17 +87,16 @@ build:x86:frontend: - npm install - npm run build - cd build - - zip -r ../../frontend.${CI_COMMIT_SHORT_SHA}.zip * + - tar czf ../../jfjoch_frontend.tar.gz * artifacts: paths: - - frontend.${CI_COMMIT_SHORT_SHA}.zip + - jfjoch_frontend.tar.gz expire_in: 1 week test:x86:gcc: stage: test timeout: 90m variables: - GIT_SUBMODULE_STRATEGY: recursive CTEST_OUTPUT_ON_FAILURE: 1 CC: gcc CXX: g++ @@ -112,18 +105,16 @@ test:x86:gcc: tags: - gcc - x86 - - ib script: - source /opt/rh/gcc-toolset-12/enable - mkdir -p build - cd build - cmake -DCMAKE_BUILD_TYPE=Release .. - - make -j48 CatchTest CompressionBenchmark HDF5DatasetWriteTest + - make -j48 jfjoch_test HDF5DatasetWriteTest - cd tests - - ./CatchTest -r junit -o report.xml + - ./jfjoch_test -r junit -o report.xml - cd ../tools - ./HDF5DatasetWriteTest ../../tests/test_data/compression_benchmark.h5 - - numactl -m 0 -N 0 ./CompressionBenchmark ../../tests/test_data/compression_benchmark.h5 artifacts: expire_in: 1 week reports: @@ -133,7 +124,6 @@ test:x86:crystfel: stage: test timeout: 90m variables: - GIT_SUBMODULE_STRATEGY: recursive CTEST_OUTPUT_ON_FAILURE: 1 CC: gcc CXX: g++ @@ -157,7 +147,6 @@ test:x86:xds_durin: stage: test timeout: 90m variables: - GIT_SUBMODULE_STRATEGY: recursive CTEST_OUTPUT_ON_FAILURE: 1 CC: gcc CXX: g++ @@ -181,7 +170,6 @@ test:x86:xds_neggia: stage: test timeout: 90m variables: - GIT_SUBMODULE_STRATEGY: recursive CTEST_OUTPUT_ON_FAILURE: 1 CC: gcc CXX: g++ @@ -205,7 +193,6 @@ test:x86:xia2.ssx: stage: test timeout: 90m variables: - GIT_SUBMODULE_STRATEGY: recursive CTEST_OUTPUT_ON_FAILURE: 1 CC: gcc CXX: g++ @@ -229,43 +216,43 @@ test:x86:xia2.ssx: synthesis:vivado_pcie_100g: stage: synthesis + dependencies: [] variables: - GIT_SUBMODULE_STRATEGY: recursive CC: gcc CXX: g++ - allow_failure: true rules: - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH - if: $CI_PIPELINE_SOURCE == "push" + allow_failure: true changes: - fpga/hls/* - fpga/hdl/* - fpga/scripts/* - fpga/xdc/* - - fpga/include/jfjoch_fpga.h + - fpga/pcie_driver/jfjoch_fpga.h tags: - vivado artifacts: paths: - - "*.mcs" + - "jfjoch_fpga_pcie_100g.mcs" expire_in: 1 week script: - source /opt/rh/gcc-toolset-12/enable - source /opt/Xilinx/Vivado/2022.1/settings64.sh + - touch jfjoch_fpga_pcie_100g.mcs - mkdir -p build - cd build - /usr/bin/cmake .. - - make pcie_100g - - mv fpga/*.mcs .. - needs: ["build:x86:gcc", "build:x86:vitis_hls", "test:x86:gcc"] + - make -j4 pcie_100g + - mv fpga/jfjoch_fpga_pcie_100g.mcs .. + needs: ["build:x86:gcc", "test:x86:gcc"] synthesis:vivado_pcie_8x10g: stage: synthesis + dependencies: [] variables: - GIT_SUBMODULE_STRATEGY: recursive CC: gcc CXX: g++ - allow_failure: true rules: - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH - if: $CI_PIPELINE_SOURCE == "push" @@ -274,19 +261,47 @@ synthesis:vivado_pcie_8x10g: - fpga/hdl/* - fpga/scripts/* - fpga/xdc/* - - fpga/include/jfjoch_fpga.h + - fpga/pcie_driver/jfjoch_fpga.h + allow_failure: true tags: - vivado artifacts: paths: - - "*.mcs" + - "jfjoch_fpga_pcie_8x10g.mcs" expire_in: 1 week script: - source /opt/rh/gcc-toolset-12/enable - source /opt/Xilinx/Vivado/2022.1/settings64.sh + - touch jfjoch_fpga_pcie_8x10g.mcs - mkdir -p build - cd build - /usr/bin/cmake .. - - make pcie_8x10g - - mv fpga/*.mcs .. - needs: [ "build:x86:gcc", "build:x86:vitis_hls", "test:x86:gcc" ] + - make -j4 pcie_8x10g + - mv fpga/jfjoch_fpga_pcie_8x10g.mcs .. + needs: [ "build:x86:gcc", "test:x86:gcc" ] + +release: + stage: release + rules: + - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH + when: manual + tags: + - x86 + dependencies: + - synthesis:vivado_pcie_8x10g + - synthesis:vivado_pcie_100g + - build:x86:frontend + - build:x86:driver + script: + - export PACKAGE_VERSION=`head -n1 VERSION` + - export PACKAGE_REGISTRY_URL="${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/jungfraujoch/${PACKAGE_VERSION}" + - 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file jfjoch_driver.tar.gz "${PACKAGE_REGISTRY_URL}/jfjoch_driver.tar.gz"' + - 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file jfjoch_frontend.tar.gz "${PACKAGE_REGISTRY_URL}/jfjoch_frontend.tar.gz"' + - 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file jfjoch_fpga_pcie_100g.mcs "${PACKAGE_REGISTRY_URL}/jfjoch_fpga_pcie_100g.mcs"' + - 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file jfjoch_fpga_pcie_8x10g.mcs "${PACKAGE_REGISTRY_URL}/jfjoch_fpga_pcie_8x10g.mcs"' + - > + release-cli create --name "Release $PACKAGE_VERSION" --tag-name $PACKAGE_VERSION + --assets-link "{\"name\":\"jfjoch_driver.tar.gz\",\"url\":\"${PACKAGE_REGISTRY_URL}/jfjoch_driver.tar.gz\"}" + --assets-link "{\"name\":\"jfjoch_frontend.tar.gz\",\"url\":\"${PACKAGE_REGISTRY_URL}/jfjoch_frontend.tar.gz\"}" + --assets-link "{\"name\":\"jfjoch_fpga_pcie_8x10g.mcs\",\"url\":\"${PACKAGE_REGISTRY_URL}/jfjoch_fpga_pcie_8x10g.mcs\"}" + --assets-link "{\"name\":\"jfjoch_fpga_pcie_100g.mcs\",\"url\":\"${PACKAGE_REGISTRY_URL}/jfjoch_fpga_pcie_100g.mcs\"}" diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 28d8adb2..00000000 --- a/.gitmodules +++ /dev/null @@ -1,19 +0,0 @@ -[submodule "image_analysis/fast-feedback-indexer"] - path = image_analysis/fast-feedback-indexer - url = https://github.com/paulscherrerinstitute/fast-feedback-indexer/ -[submodule "frame_serialize/tinycbor"] - path = frame_serialize/tinycbor - url = https://github.com/intel/tinycbor -[submodule "compression/zstd"] - path = compression/zstd - url = https://github.com/facebook/zstd -[submodule "detector_control/slsDetectorPackage"] - path = detector_control/slsDetectorPackage - url = https://github.com/fleon-psi/slsDetectorPackage - branch = "jfjoch-shmem" -[submodule "compression/bitshuffle_hperf"] - path = compression/bitshuffle_hperf - url = https://github.com/kalcutter/bitshuffle -[submodule "broker/pistache"] - path = broker/pistache - url = https://github.com/fleon-psi/pistache diff --git a/CMakeLists.txt b/CMakeLists.txt index ddbdb688..5e2022a4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,6 +9,9 @@ SET(CMAKE_CXX_STANDARD_REQUIRED True) SET(CMAKE_CXX_FLAGS_RELEASE "-O3 -march=native -mtune=native -Wno-deprecated-enum-enum-conversion") SET(CMAKE_C_FLAGS_RELEASE "-O3 -march=native -mtune=native") +SET(ZSTD_LEGACY_SUPPORT OFF) +SET(ZSTD_MULTITHREAD_SUPPORT OFF) + INCLUDE(CheckLanguage) CHECK_LANGUAGE(CUDA) @@ -28,19 +31,38 @@ SET(JFJOCH_WRITER_ONLY OFF CACHE BOOL "Compile HDF5 writer only") INCLUDE_DIRECTORIES(include) INCLUDE(CheckIncludeFile) -#This is to supress error in TORCH - -IF ((NOT EXISTS /usr/bin/python) AND (EXISTS /usr/bin/python3)) - SET(PYTHON_EXECUTABLE /usr/bin/python3) -ENDIF() - -FIND_PACKAGE(Torch HINTS /opt/libtorch/share/cmake/Torch/) FIND_LIBRARY(NUMA_LIBRARY NAMES numa DOC "NUMA Library") CHECK_INCLUDE_FILE(numaif.h HAS_NUMAIF) CHECK_INCLUDE_FILE(numa.h HAS_NUMA_H) -LIST(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") -#FIND_PACKAGE(ZeroMQ 4 REQUIRED) +include(FetchContent) + +FetchContent_Declare( + pistache_http + GIT_REPOSITORY https://github.com/fleon-psi/pistache + GIT_TAG 51553b92cc7bb25ac792462722ddd4fae33d14b1 +) + +FetchContent_Declare( + zstd + GIT_REPOSITORY https://github.com/facebook/zstd + GIT_TAG 794ea1b0afca0f020f4e57b6732332231fb23c70 + SOURCE_SUBDIR build/cmake +) + +FetchContent_Declare( + sls_detector_package + GIT_REPOSITORY https://github.com/fleon-psi/slsDetectorPackage + GIT_TAG bae261433241ff2f458350e26ab026f00f01c427 +) + +FetchContent_Declare( + catch2 + GIT_REPOSITORY https://github.com/catchorg/Catch2 + GIT_TAG 4e8d92b +) + +FetchContent_MakeAvailable(pistache_http zstd sls_detector_package catch2) ADD_SUBDIRECTORY(jungfrau) ADD_SUBDIRECTORY(compression) @@ -48,7 +70,6 @@ ADD_SUBDIRECTORY(common) ADD_SUBDIRECTORY(writer) ADD_SUBDIRECTORY(frame_serialize) -ADD_SUBDIRECTORY(broker/pistache) ADD_SUBDIRECTORY(detector_control) IF (JFJOCH_WRITER_ONLY) MESSAGE(STATUS "Compiling HDF5 writer only") @@ -62,8 +83,7 @@ ELSE() ADD_SUBDIRECTORY(tests) ADD_SUBDIRECTORY(tools) ADD_SUBDIRECTORY(preview) - ADD_SUBDIRECTORY(resonet) - SET(jfjoch_executables jfjoch_broker jfjoch_writer CatchTest CompressionBenchmark HDF5DatasetWriteTest jfjoch_udp_simulator sls_detector_put sls_detector_get) + SET(jfjoch_executables jfjoch_broker jfjoch_writer jfjoch_test CompressionBenchmark HDF5DatasetWriteTest jfjoch_udp_simulator sls_detector_put sls_detector_get) ENDIF() ADD_CUSTOM_COMMAND(OUTPUT frontend_ui/build/index.html diff --git a/Dockerfile b/Dockerfile index 717e31ee..053da655 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,3 +1,5 @@ +# MAX IV docker config + FROM harbor.maxiv.lu.se/dockerhub/library/ubuntu:22.04 RUN set -ex; \ diff --git a/README.md b/README.md index 3bc4ee5e..140dd18f 100644 --- a/README.md +++ b/README.md @@ -39,26 +39,25 @@ Required: * JPEG library (turbo-jpeg is also OK) Optional: -* CUDA compiler version 11 or newer - required for MX indexing and ML resolution estimation +* CUDA compiler version 11 or newer - required for MX fast feedback indexer * NUMA library - to pin threads to nodes/CPUs * Node.js - to make frontend -* libtorch - for resolution estimation using model from Stanford - see below -Provided as GIT submodules: +Automatically downloaded by CMake: * SLS Detector Package - see [github.com/slsdetectorgroup/slsDetectorPackage](https://github.com/slsdetectorgroup/slsDetectorPackage) -* tinycbor (Intel) - see [github.com/intel/tinycbor](https://github.com/intel/tinycbor) * Zstandard (Facebook) - see [github.com/facebook/zstd](https://github.com/facebook/zstd) * Pistache webserver - see [github.com/pistacheio/pistache](https://github.com/pistacheio/pistache) * Fast feedback indexer (Hans-Christian Stadler, PSI) - see [github.com/paulscherrerinstitute/fast-feedback-indexer](https://github.com/paulscherrerinstitute/fast-feedback-indexer) -* fast replacement for Bitshuffle pre-compression filter (Kal Cutter, DECTRIS) - see [github.com/kalcutter/bitshuffle](https://github.com/kalcutter/bitshuffle) +* Catch2 testing library - see [github.com/catchorg/Catch2](https://github.com/catchorg/Catch2) -For license check LICENSE file in respective directory +Please follow the link provided above to check for LICENSE file Directly included in the repository: * JSON parser/writer from N. Lohmann - see [github.com/nlohmann/json](https://github.com/nlohmann/json) -* Catch2 testing library - see [github.com/catchorg/Catch2](https://github.com/catchorg/Catch2) * Xilinx arbitrary precision arithmetic headers - see [github.com/Xilinx/HLS_arbitrary_Precision_Types](https://github.com/Xilinx/HLS_arbitrary_Precision_Types) * Bitshuffle filter from K. Masui - see [github.com/kiyo-masui/bitshuffle](https://github.com/kiyo-masui/bitshuffle) +* Fast replacement for Bitshuffle pre-compression filter (Kal Cutter, DECTRIS) - see [github.com/kalcutter/bitshuffle](https://github.com/kalcutter/bitshuffle) +* Tinycbor (Intel) - see [github.com/intel/tinycbor](https://github.com/intel/tinycbor) * LZ4 compression by Y.Collet - see [github.com/lz4/lz4](https://github.com/lz4/lz4) * Spdlog logging library - see [github.com/gabime/spdlog](https://github.com/gabime/spdlog) * ZeroMQ library (through slsDetectorPackage) - see [github.com/zeromq/libzmq](https://github.com/zeromq/libzmq) @@ -68,15 +67,14 @@ For license check LICENSE file in respective directory ### Software components * `jfjoch_broker` in `broker` - main service running on the Jungfraujoch server, responsible for control of the detector and data acquisition; - Example configuration `jfjoch_broker` for the modules is given in configuration files present in `etc` directory. + Example configuration `jfjoch_broker` for the modules is given in configuration files present in `etc` directory. See [details](broker/README.md). * `jfjoch_writer` in `writer` - HDF5 writer; HDF5 writer is designed to work on the same or separate server system. It has rather limited requirements in terms of performance and memory. - The goal is to separate data acquisition node with custom FPGA hardware and file system node with stronger security/stability requirements. + The goal is to separate data acquisition node with custom FPGA hardware and file system node with stronger security/stability requirements. See [details](writer/README.md). ### Compilation Use the following commands: ``` -git submodule update --init --recursive mkdir build cd build cmake .. @@ -85,10 +83,9 @@ make jfjoch ### Compilation (writer only) In most use cases it is better to have a separate machine, with access to distributed file system, for writing. -Such machine needs only a HDF5 writer service with less dependencies. For compilation use the following commands: +Such machine needs only a HDF5 writer service with fewer dependencies. For compilation use the following commands: ``` -git submodule update --init --recursive mkdir build cd build cmake -DJFJOCH_WRITER_ONLY=ON .. @@ -96,8 +93,7 @@ make jfjoch ``` ## Versions -**FPGA release** is as hexadecimal number indicted in the [jfjoch_fpga.h](fpga/pcie_driver/jfjoch_fpga.h) as JFJOCH_FPGA_RELEASE constant. -It is also included in the name of FPGA firmware file (.mcs) and kernel driver archive. This number indicated breaking changes in the FPGA firmware interface. +**FPGA release** is as hexadecimal number indicted in the [jfjoch_fpga.h](fpga/pcie_driver/jfjoch_fpga.h) as JFJOCH_FPGA_RELEASE constant. This number indicated breaking changes in the FPGA firmware interface. FPGA release has to be consistent between FPGA firmware, kernel driver and `jfjoch_broker` - both kernel driver and software won't work in case of version mismatch. Commits to `main` branch with the same FPGA release version are OK to mix between components. @@ -113,7 +109,6 @@ Frontend is written in TypeScript. For details see [frontend_ui/](frontend_ui) d Jungfraujoch Cmake scripts have an option to start frontend build with the following command: ``` -git submodule update --init --recursive mkdir build cd build cmake .. @@ -123,25 +118,11 @@ Contrary to standard CMake way, frontend will be built in "source" `frontend_ui/ ## Tests -Automated test routine is then accessible as `tests/CatchTest`. There are also benchmark routines: +Automated test routine is then accessible as `tests/jfjoch_test`. There are also benchmark routines: -* `CompressionBenchmark` to measure compression bandwidth (single threaded) * `HDF5DatasetWriteTest` to measure HDF5 dataset writing speed (single threaded) * `jfjoch_spot_finding_test` to apply spot finding and indexing routines in Jungfraujoch to an example dataset - this is equivalent to FPGA spot finding algorithm, but NOT performance equivalent as it is particularly not-efficient * `jfjoch_action_test` to test quality/performance of FPGA card(s) and software routines In addition, tests are executed to verify that datasets written by Jungfraujoch are readable with XDS Durin plugin, XDS Neggia plygin and CrystFEL. Input files for these programs are placed in `xds_durin`, `xds_neggia` and `crystfel` folders. See `.gitlab-ci.yml` for details. - -## Resolution estimation - -Resolution estimation can be done with a recent deep learning model by D. Mendez et al. -(see [Acta Cryst D, 80, 26-43](https://doi.org/10.1107/S2059798323010586)), adapted to Jungfraujoch. -Model used in the original paper is located in the [resonet/](resonet) directory, after converting to TorchScript format. - -To use the feature it is necessary to install [libtorch](https://pytorch.org/) library, preferably in `/opt/libtorch` location. The C++11 ABI version needs to be chosen. -For RHEL 8 systems, please download older version 2.1.0, as version 2.2.0 requires newer `glibc` library than available with the operating system. -Version 2.1.0 can be downloaded with the following command: -``` -wget https://download.pytorch.org/libtorch/cu121/libtorch-cxx11-abi-shared-with-deps-2.1.0%2Bcu121.zip -``` diff --git a/VERSION b/VERSION new file mode 100644 index 00000000..9c218192 --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +1.0.0-rc.1 diff --git a/broker/CMakeLists.txt b/broker/CMakeLists.txt index b06cde1d..250abfdb 100644 --- a/broker/CMakeLists.txt +++ b/broker/CMakeLists.txt @@ -1,4 +1,5 @@ AUX_SOURCE_DIRECTORY(gen/model MODEL_SOURCES) + ADD_LIBRARY(JFJochAPI STATIC ${MODEL_SOURCES} gen/api/DefaultApi.cpp gen/api/DefaultApi.h) TARGET_LINK_LIBRARIES(JFJochAPI pistache_static) @@ -15,5 +16,3 @@ ADD_EXECUTABLE(jfjoch_broker jfjoch_broker.cpp) TARGET_LINK_LIBRARIES(jfjoch_broker JFJochBroker) INSTALL(TARGETS jfjoch_broker RUNTIME) - - diff --git a/broker/JFJochBrokerHttp.cpp b/broker/JFJochBrokerHttp.cpp index 6a97b8f3..bcd9135e 100644 --- a/broker/JFJochBrokerHttp.cpp +++ b/broker/JFJochBrokerHttp.cpp @@ -316,6 +316,8 @@ inline PreviewJPEGSettings Convert(const org::openapitools::server::model::Previ ret.saturation_value = input.getSaturation(); ret.show_roi = input.isShowRoi(); ret.show_indexed = input.isShowIndexed(); + if (input.resolutionRingIsSet()) + ret.resolution_ring = input.getResolutionRing(); return ret; } @@ -649,10 +651,6 @@ void JFJochBrokerHttp::preview_image_tiff_get(Pistache::Http::ResponseWriter &re response.send(Pistache::Http::Code::Not_Found); } -void JFJochBrokerHttp::plot_resolution_estimate_histogram_get(Pistache::Http::ResponseWriter &response) { - GenericPlot(PlotType::ResEstimation, 0, response); -} - void JFJochBrokerHttp::config_internal_generator_image_put(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter &response) { int64_t image_number = 0; diff --git a/broker/JFJochBrokerHttp.h b/broker/JFJochBrokerHttp.h index 728d7609..48b2e497 100644 --- a/broker/JFJochBrokerHttp.h +++ b/broker/JFJochBrokerHttp.h @@ -7,11 +7,12 @@ #include #include #include +#include #include "../common/Logger.h" #include "JFJochStateMachine.h" #include "gen/api/DefaultApi.h" -#include "pistache/include/pistache/http.h" + class JFJochBrokerHttp : public org::openapitools::server::api::DefaultApi { Logger logger{"JFJochBroker"}; @@ -74,8 +75,6 @@ class JFJochBrokerHttp : public org::openapitools::server::api::DefaultApi { void plot_rad_int_per_file_get(Pistache::Http::ResponseWriter &response) override; - void plot_resolution_estimate_histogram_get(Pistache::Http::ResponseWriter &response) override; - void statistics_calibration_get(Pistache::Http::ResponseWriter &response) override; void statistics_data_collection_get(Pistache::Http::ResponseWriter &response) override; diff --git a/broker/JFJochBrokerParser.cpp b/broker/JFJochBrokerParser.cpp index c45f854c..96138912 100644 --- a/broker/JFJochBrokerParser.cpp +++ b/broker/JFJochBrokerParser.cpp @@ -319,7 +319,6 @@ void ParseFacilityConfiguration(const nlohmann::json &input, const std::string& "omega_axis must be float array of 3"); } - experiment.NeuralNetModelPath(GET_STR(j, "neural_net_model", "")); if (j.contains("pedestal_g0_frames")) experiment.PedestalG0Frames(GET_I64(j, "pedestal_g0_frames")); if (j.contains("pedestal_g1_frames")) diff --git a/broker/README.md b/broker/README.md index bdf21713..be5903b6 100644 --- a/broker/README.md +++ b/broker/README.md @@ -15,11 +15,16 @@ Till this happens, it is recommended to go through example files in the [etc/](. ## Setting up a local test for Jungfraujoch For development, it is possible to setup a local installation of Jungfraujoch. This will work without FPGA installed in the computer and allows to test Jungfraujoch software layer, including -ZeroMQ streaming and file writing. There are few necessary steps: +ZeroMQ streaming and file writing. + +The workflow simulates FPGA behavior, by running high-level synthesis code on the CPU - the performance is therefore +very low, as fixed-point calculations have large performance penalty on CPU. In the CPU simulation mode, one can simulate +using only a single FPGA device. + +To run the test: ### Compile Jungfraujoch with frontend ``` -git submodule update --init --recursive mkdir build cd build cmake .. @@ -38,6 +43,7 @@ Start writer: cd build/writer ./jfjoch_writer tcp://127.0.0.1:5500 ``` + ### Run tests To run test a Python script is provided: ``` @@ -45,3 +51,7 @@ cd tests/test_data python jfjoch_broker_test.py ``` The script will initialize Jungfraujoch, import test image and start data collection. + +### Expected result +You can observe online data analysis by opening the following web page: [http://localhost:5232](http://localhost:5232). +Also in the `build/writer` subdirectory a dataset with images should be written. diff --git a/broker/gen/api/DefaultApi.cpp b/broker/gen/api/DefaultApi.cpp index 1a9ce8ea..d223829b 100644 --- a/broker/gen/api/DefaultApi.cpp +++ b/broker/gen/api/DefaultApi.cpp @@ -56,7 +56,6 @@ void DefaultApi::setupRoutes() { Routes::Get(*router, base + "/plot/rad_int_per_file", Routes::bind(&DefaultApi::plot_rad_int_per_file_get_handler, this)); Routes::Get(*router, base + "/plot/receiver_delay", Routes::bind(&DefaultApi::plot_receiver_delay_get_handler, this)); Routes::Get(*router, base + "/plot/receiver_free_send_buffers", Routes::bind(&DefaultApi::plot_receiver_free_send_buffers_get_handler, this)); - Routes::Get(*router, base + "/plot/resolution_estimate_histogram", Routes::bind(&DefaultApi::plot_resolution_estimate_histogram_get_handler, this)); Routes::Get(*router, base + "/plot/roi_max_count", Routes::bind(&DefaultApi::plot_roi_max_count_get_handler, this)); Routes::Get(*router, base + "/plot/roi_sum", Routes::bind(&DefaultApi::plot_roi_sum_get_handler, this)); Routes::Get(*router, base + "/plot/roi_valid_pixels", Routes::bind(&DefaultApi::plot_roi_valid_pixels_get_handler, this)); @@ -672,26 +671,6 @@ void DefaultApi::plot_receiver_free_send_buffers_get_handler(const Pistache::Res response.send(Pistache::Http::Code::Internal_Server_Error, e.what()); } -} -void DefaultApi::plot_resolution_estimate_histogram_get_handler(const Pistache::Rest::Request &, Pistache::Http::ResponseWriter response) { - try { - - - try { - this->plot_resolution_estimate_histogram_get(response); - } catch (Pistache::Http::HttpError &e) { - response.send(static_cast(e.code()), e.what()); - return; - } catch (std::exception &e) { - const std::pair errorInfo = this->handleOperationException(e); - response.send(errorInfo.first, errorInfo.second); - return; - } - - } catch (std::exception &e) { - response.send(Pistache::Http::Code::Internal_Server_Error, e.what()); - } - } void DefaultApi::plot_roi_max_count_get_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response) { try { diff --git a/broker/gen/api/DefaultApi.h b/broker/gen/api/DefaultApi.h index 98da5387..4530c04f 100644 --- a/broker/gen/api/DefaultApi.h +++ b/broker/gen/api/DefaultApi.h @@ -80,7 +80,6 @@ private: void plot_rad_int_per_file_get_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response); void plot_receiver_delay_get_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response); void plot_receiver_free_send_buffers_get_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response); - void plot_resolution_estimate_histogram_get_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response); void plot_roi_max_count_get_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response); void plot_roi_sum_get_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response); void plot_roi_valid_pixels_get_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response); @@ -293,13 +292,6 @@ private: /// Binning of frames for the plot (0 = default binning) (optional, default to 0) virtual void plot_receiver_free_send_buffers_get(const std::optional &binning, Pistache::Http::ResponseWriter &response) = 0; /// - /// Generate resolution estimate histogram - /// - /// - /// Generate histogram of crystal resolutions from 1.0 to 5.0 A based on ML model - /// - virtual void plot_resolution_estimate_histogram_get(Pistache::Http::ResponseWriter &response) = 0; - /// /// Generate plot of ROI max count /// /// diff --git a/broker/gen/model/Preview_settings.cpp b/broker/gen/model/Preview_settings.cpp index 3c79ea55..68090ecb 100644 --- a/broker/gen/model/Preview_settings.cpp +++ b/broker/gen/model/Preview_settings.cpp @@ -30,6 +30,8 @@ Preview_settings::Preview_settings() m_Jpeg_qualityIsSet = false; m_Show_indexed = false; m_Show_indexedIsSet = false; + m_Resolution_ring = 0.0f; + m_Resolution_ringIsSet = false; } @@ -90,7 +92,26 @@ bool Preview_settings::validate(std::stringstream& msg, const std::string& pathP } } + + if (resolutionRingIsSet()) + { + const float& value = m_Resolution_ring; + const std::string currentValuePath = _pathPrefix + ".resolutionRing"; + + if (value < static_cast(0.1)) + { + success = false; + msg << currentValuePath << ": must be greater than or equal to 0.1;"; + } + if (value > static_cast(100.0)) + { + success = false; + msg << currentValuePath << ": must be less than or equal to 100.0;"; + } + + } + return success; } @@ -112,7 +133,10 @@ bool Preview_settings::operator==(const Preview_settings& rhs) const ((!jpegQualityIsSet() && !rhs.jpegQualityIsSet()) || (jpegQualityIsSet() && rhs.jpegQualityIsSet() && getJpegQuality() == rhs.getJpegQuality())) && - ((!showIndexedIsSet() && !rhs.showIndexedIsSet()) || (showIndexedIsSet() && rhs.showIndexedIsSet() && isShowIndexed() == rhs.isShowIndexed())) + ((!showIndexedIsSet() && !rhs.showIndexedIsSet()) || (showIndexedIsSet() && rhs.showIndexedIsSet() && isShowIndexed() == rhs.isShowIndexed())) && + + + ((!resolutionRingIsSet() && !rhs.resolutionRingIsSet()) || (resolutionRingIsSet() && rhs.resolutionRingIsSet() && getResolutionRing() == rhs.getResolutionRing())) ; } @@ -134,6 +158,8 @@ void to_json(nlohmann::json& j, const Preview_settings& o) j["jpeg_quality"] = o.m_Jpeg_quality; if(o.showIndexedIsSet()) j["show_indexed"] = o.m_Show_indexed; + if(o.resolutionRingIsSet()) + j["resolution_ring"] = o.m_Resolution_ring; } @@ -160,6 +186,11 @@ void from_json(const nlohmann::json& j, Preview_settings& o) j.at("show_indexed").get_to(o.m_Show_indexed); o.m_Show_indexedIsSet = true; } + if(j.find("resolution_ring") != j.end()) + { + j.at("resolution_ring").get_to(o.m_Resolution_ring); + o.m_Resolution_ringIsSet = true; + } } @@ -239,6 +270,23 @@ void Preview_settings::unsetShow_indexed() { m_Show_indexedIsSet = false; } +float Preview_settings::getResolutionRing() const +{ + return m_Resolution_ring; +} +void Preview_settings::setResolutionRing(float const value) +{ + m_Resolution_ring = value; + m_Resolution_ringIsSet = true; +} +bool Preview_settings::resolutionRingIsSet() const +{ + return m_Resolution_ringIsSet; +} +void Preview_settings::unsetResolution_ring() +{ + m_Resolution_ringIsSet = false; +} } // namespace org::openapitools::server::model diff --git a/broker/gen/model/Preview_settings.h b/broker/gen/model/Preview_settings.h index fe63c3e3..c8311cc5 100644 --- a/broker/gen/model/Preview_settings.h +++ b/broker/gen/model/Preview_settings.h @@ -90,6 +90,13 @@ public: void setShowIndexed(bool const value); bool showIndexedIsSet() const; void unsetShow_indexed(); + /// + /// + /// + float getResolutionRing() const; + void setResolutionRing(float const value); + bool resolutionRingIsSet() const; + void unsetResolution_ring(); friend void to_json(nlohmann::json& j, const Preview_settings& o); friend void from_json(const nlohmann::json& j, Preview_settings& o); @@ -104,6 +111,8 @@ protected: bool m_Jpeg_qualityIsSet; bool m_Show_indexed; bool m_Show_indexedIsSet; + float m_Resolution_ring; + bool m_Resolution_ringIsSet; }; diff --git a/broker/jfjoch_api.yaml b/broker/jfjoch_api.yaml index 6a550386..01e9ba67 100644 --- a/broker/jfjoch_api.yaml +++ b/broker/jfjoch_api.yaml @@ -623,7 +623,11 @@ components: show_indexed: type: boolean description: "Preview indexed images only" - + resolution_ring: + type: number + format: float + minimum: 0.1 + maximum: 100.0 error_message: type: object required: @@ -1441,17 +1445,6 @@ paths: application/json: schema: $ref: '#/components/schemas/plots' - /plot/resolution_estimate_histogram: - get: - summary: Generate resolution estimate histogram - description: Generate histogram of crystal resolutions from 1.0 to 5.0 A based on ML model - responses: - "200": - description: Everything OK - content: - application/json: - schema: - $ref: '#/components/schemas/plots' /plot/rad_int: get: summary: Generate radial integration profile diff --git a/broker/pistache b/broker/pistache deleted file mode 160000 index 51553b92..00000000 --- a/broker/pistache +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 51553b92cc7bb25ac792462722ddd4fae33d14b1 diff --git a/broker/redoc-static.html b/broker/redoc-static.html index f2adc855..ce9ee474 100644 --- a/broker/redoc-static.html +++ b/broker/redoc-static.html @@ -12,336 +12,336 @@ margin: 0; } - -

Jungfraujoch (1.0.1)

Download OpenAPI specification:Download

Jungfraujoch Broker Web API

-

Initialize detector and data acquisition

Jungfraujoch (1.0.1)

Download OpenAPI specification:Download

Jungfraujoch Broker Web API

+

Initialize detector and data acquisition

Should be used in two cases:

+" class="sc-iKOmoZ sc-cCzLxZ WVNwY VEBGS">

Should be used in two cases:

  • Detector is in Inactive state
  • Detector is in Error state @@ -381,425 +381,421 @@ During operation of the detector it is recommended to use the POST /pedest If storage cells are used, the execution time might be few minutes.

This is async function - one needs to use POST /wait_till_done to ensure operation is done.

-

Responses

Response samples

Content type
application/json
{
  • "msg": "Detector in wrong state",
  • "reason": "WrongDAQState"
}

Collect dark current for the detector

Responses

Response samples

Content type
application/json
{
  • "msg": "Detector in wrong state",
  • "reason": "WrongDAQState"
}

Collect dark current for the detector

Updates calibration of the JUNGFRAU detector. Must be in Idle state.

+" class="sc-iKOmoZ sc-cCzLxZ WVNwY VEBGS">

Updates calibration of the JUNGFRAU detector. Must be in Idle state.

X-ray shutter must be closed. Recommended to run once per hour for long integration times (> 100 us).

This is async function - one needs to use POST /wait_till_done to ensure operation is done.

-

Responses

Response samples

Content type
application/json
{
  • "msg": "Detector in wrong state",
  • "reason": "WrongDAQState"
}

Start detector

Responses

Response samples

Content type
application/json
{
  • "msg": "Detector in wrong state",
  • "reason": "WrongDAQState"
}

Start detector

Start data acquisition. +" class="sc-iKOmoZ sc-cCzLxZ WVNwY VEBGS">

Start data acquisition. Detector must be in Idle state. Doesn't run calibration procedure. This is async function - one needs to use POST /wait_till_done to ensure operation is done.

-
Request Body schema: application/json
images_per_trigger
integer <int64> >= 1
Default: 1
Request Body schema: application/json
images_per_trigger
integer <int64> >= 1
Default: 1

For standard synchrotron data collection - this is number of images collected per one TTL trigger +" class="sc-iKOmoZ sc-cCzLxZ WVNwY jaVotg">

For standard synchrotron data collection - this is number of images collected per one TTL trigger For XFEL (pulsed source) - this number is ignored and set to 1 For storage cell mode - this number is ignored and set to number of storage cells

-
ntrigger
integer <int64> >= 1
Default: 1

Number of TTL trigger that the detector is expected to receive during data collection

-
summation
integer <int64> [ 1 .. 256 ]
Default: 1
ntrigger
integer <int64> >= 1
Default: 1

Number of TTL trigger that the detector is expected to receive during data collection

+
summation
integer <int64> [ 1 .. 256 ]
Default: 1

FPGA frame summation. For summation above two 32-bit pixel format will be used, unless explicitly specified. +" class="sc-iKOmoZ sc-cCzLxZ WVNwY jaVotg">

FPGA frame summation. For summation above two 32-bit pixel format will be used, unless explicitly specified. Frame summation factor applies only to conversion mode (assumed as 1 for raw data). In XFEL mode: summation happens for frames collected with multiple triggers. Ignored for storage cells (assumed as 1).

-
beam_x_pxl
required
number <float>
beam_x_pxl
required
number <float>

/entry/detector/beam_center_x in NXmx +" class="sc-iKOmoZ sc-cCzLxZ WVNwY jaVotg">

/entry/detector/beam_center_x in NXmx Beam center in X direction [pixels]

-
beam_y_pxl
required
number <float>
beam_y_pxl
required
number <float>

/entry/detector/beam_center_y in NXmx +" class="sc-iKOmoZ sc-cCzLxZ WVNwY jaVotg">

/entry/detector/beam_center_y in NXmx Beam center in X direction [pixels]

-
detector_distance_mm
required
number <float> >= 0

/entry/detector/distance in NXmx Detector distance [mm]

-
photon_energy_keV
required
number <float> >= 0
detector_distance_mm
required
number <float> >= 0

/entry/detector/distance in NXmx Detector distance [mm]

+
photon_energy_keV
required
number <float> >= 0

Used to calculate /entry/beam/incident_wavelength in NXmx +" class="sc-iKOmoZ sc-cCzLxZ WVNwY jaVotg">

Used to calculate /entry/beam/incident_wavelength in NXmx Incident photon energy in keV

-
file_prefix
string
Default: ""

Prefix for filenames. If left empty, no file will be saved.

-
images_per_file
integer <int64> >= 0
Default: 1000

Number of files in a single HDF5 data file (0 = write all images to a single data file).

-
space_group_number
integer <int64> [ 0 .. 194 ]
Default: 0
sample_name
required
string
file_prefix
string
Default: ""

Prefix for filenames. If left empty, no file will be saved.

+
images_per_file
integer <int64> >= 0
Default: 1000

Number of files in a single HDF5 data file (0 = write all images to a single data file).

+
space_group_number
integer <int64> [ 0 .. 194 ]
Default: 0
sample_name
required
string

/entry/sample/name in NXmx +" class="sc-iKOmoZ sc-cCzLxZ WVNwY jaVotg">

/entry/sample/name in NXmx Sample name

-
fpga_output
string
Default: "auto"
Enum: "auto" "int32" "int16" "uint32" "uint16"

FPGA output data type

-
compression
string
Default: "bslz4"
Enum: "bslz4" "bszstd" "bszstd_rle" "none"
total_flux
number <float>
fpga_output
string
Default: "auto"
Enum: "auto" "int32" "int16" "uint32" "uint16"

FPGA output data type

+
compression
string
Default: "bslz4"
Enum: "bslz4" "bszstd" "bszstd_rle" "none"
total_flux
number <float>

/entry/beam/total_flux in NXmx +" class="sc-iKOmoZ sc-cCzLxZ WVNwY jaVotg">

/entry/beam/total_flux in NXmx Flux incident on beam plane in photons per second. In other words this is the flux integrated over area. [photons/s]

-
transmission
number <float> [ 0 .. 1 ]
transmission
number <float> [ 0 .. 1 ]

/entry/instrument/attenuator/attenuator_transmission +" class="sc-iKOmoZ sc-cCzLxZ WVNwY jaVotg">

/entry/instrument/attenuator/attenuator_transmission Transmission of attenuator (filter) [no units]

-
object (rotation_axis)

Definition of a crystal rotation axis

-
header_appendix
string

Header appendix, added as user_data to start message

-
image_appendix
string

Image appendix, added as user_data to image message

-
photon_energy_multiplier
number <float> [ 0.015625 .. 4 ]
Default: 1

For JUNGFRAU conversion it is possible to multiply energy by a given factor to get fractional/multiplied photon counts

-
data_reduction_factor_serialmx
number <float> [ 0 .. 1 ]
Default: 1
object (rotation_axis)

Definition of a crystal rotation axis

+
header_appendix
string

Header appendix, added as user_data to start message

+
image_appendix
string

Image appendix, added as user_data to image message

+
photon_energy_multiplier
number <float> [ 0.015625 .. 4 ]
Default: 1

For JUNGFRAU conversion it is possible to multiply energy by a given factor to get fractional/multiplied photon counts

+
data_reduction_factor_serialmx
number <float> [ 0 .. 1 ]
Default: 1

Rate at which non-indexed images are accepted to be forwarded to writer. +" class="sc-iKOmoZ sc-cCzLxZ WVNwY jaVotg">

Rate at which non-indexed images are accepted to be forwarded to writer. Value of 1.0 (default) means that all images are written. Values below zero mean that non-indexed images will be accepted with a given probability.

-
object

Units of angstrom and degree

-

Responses

Request samples

Content type
application/json
{
  • "images_per_trigger": 1,
  • "ntrigger": 1,
  • "summation": 1,
  • "beam_x_pxl": 0.1,
  • "beam_y_pxl": 0.1,
  • "detector_distance_mm": 0.1,
  • "photon_energy_keV": 0.1,
  • "file_prefix": "",
  • "images_per_file": 1000,
  • "space_group_number": 0,
  • "sample_name": "string",
  • "fpga_output": "auto",
  • "compression": "bslz4",
  • "total_flux": 0.1,
  • "transmission": 1,
  • "omega": {
    },
  • "header_appendix": "string",
  • "image_appendix": "string",
  • "photon_energy_multiplier": 1,
  • "data_reduction_factor_serialmx": 1,
  • "unit_cell": {
    }
}

Response samples

Content type
application/json
{
  • "msg": "Detector in wrong state",
  • "reason": "WrongDAQState"
}

Wait for acquisition done

object

Units of angstrom and degree

+

Responses

Request samples

Content type
application/json
{
  • "images_per_trigger": 1,
  • "ntrigger": 1,
  • "summation": 1,
  • "beam_x_pxl": 0.1,
  • "beam_y_pxl": 0.1,
  • "detector_distance_mm": 0.1,
  • "photon_energy_keV": 0.1,
  • "file_prefix": "",
  • "images_per_file": 1000,
  • "space_group_number": 0,
  • "sample_name": "string",
  • "fpga_output": "auto",
  • "compression": "bslz4",
  • "total_flux": 0.1,
  • "transmission": 1,
  • "omega": {
    },
  • "header_appendix": "string",
  • "image_appendix": "string",
  • "photon_energy_multiplier": 1,
  • "data_reduction_factor_serialmx": 1,
  • "unit_cell": {
    }
}

Response samples

Content type
application/json
{
  • "msg": "Detector in wrong state",
  • "reason": "WrongDAQState"
}

Wait for acquisition done

Block execution of external script till initialization, data collection or pedestal is finished. +" class="sc-iKOmoZ sc-cCzLxZ WVNwY VEBGS">

Block execution of external script till initialization, data collection or pedestal is finished. Running this command does not affect (cancel) running data collection, it is only to ensure synchronous execution of other software.

To not block web server for a long period of time, the procedure is provided with a timeout of 5 seconds.

-

Responses

Response samples

Content type
application/json
{
  • "msg": "Detector in wrong state",
  • "reason": "WrongDAQState"
}

Send soft trigger to the detector

Generate soft trigger

-

Responses

Cancel running data collection

Responses

Response samples

Content type
application/json
{
  • "msg": "Detector in wrong state",
  • "reason": "WrongDAQState"
}

Send soft trigger to the detector

Generate soft trigger

+

Responses

Cancel running data collection

Command will inform FPGA network card to stop pedestal or data collection at the current stage. +" class="sc-iKOmoZ sc-cCzLxZ WVNwY VEBGS">

Command will inform FPGA network card to stop pedestal or data collection at the current stage. Any frame that is currently being processed by CPU will be finished and sent to writer. Given the command is making sure to gracefully stop data acquisition and detector, it might take some time to switch back after command finished to Idle state.

If data collection is not running, the command has no effect.

-

Responses

Prepare detector to turn off

Responses

Prepare detector to turn off

Should be in Idle or Error state. +" class="sc-iKOmoZ sc-cCzLxZ WVNwY VEBGS">

Should be in Idle or Error state. Command deactivates data acquisition and turns off detector high voltage and ASIC. Should be used always before turning off power from the detector.

-

Responses

Response samples

Content type
application/json
{
  • "msg": "Detector in wrong state",
  • "reason": "WrongDAQState"
}

Change detector configuration

Responses

Response samples

Content type
application/json
{
  • "msg": "Detector in wrong state",
  • "reason": "WrongDAQState"
}

Change detector configuration

Detector settings are ones that have effect on calibration, i.e., pedestal has to be collected again after changing these settings. +" class="sc-iKOmoZ sc-cCzLxZ WVNwY VEBGS">

Detector settings are ones that have effect on calibration, i.e., pedestal has to be collected again after changing these settings. This can only be done when detector is Idle, Error or Inactive states. If detector is in Idle state , pedestal procedure will be executed automatically - there must be no X-rays on the detector during the operation. If detector is in Inactive or Error states, new settings will be saved, but no calibration will be executed.

-
Request Body schema: application/json
frame_time_us
required
integer <int64> >= 450

Interval between consecutive frames.

-
count_time_us
integer <int64>

Integration time of the detector. If not provided count time will be set to maximum value for a given frame time.

-
storage_cell_count
integer <int64> [ 1 .. 16 ]
Default: 1
internal_frame_generator
boolean
Default: false

Use internal frame generator in FPGA instead of getting data from a real detector

-
internal_frame_generator_images
integer <int64> [ 1 .. 128 ]
Default: 1
collect_raw_data
boolean
Default: false

Turn off conversion of pixel read-out to photon count

-
pedestal_g0_frames
integer <int64> >= 0
pedestal_g1_frames
integer <int64> >= 0
pedestal_g2_frames
integer <int64> >= 0
storage_cell_delay_us
number <float>

Delay between two storage cells [us]

-
detector_trigger_delay_us
number <float>

Delay between TTL trigger and acquisition start [us]

-
fixed_gain_g1
boolean
Default: false

Fix gain to G1 (can be useful for storage cells)

-
use_gain_hg0
boolean
Default: false

Use high G0 (for low energy applications)

-

Responses

Request samples

Content type
application/json
{
  • "frame_time_us": 450,
  • "count_time_us": 0,
  • "storage_cell_count": 1,
  • "internal_frame_generator": false,
  • "internal_frame_generator_images": 1,
  • "collect_raw_data": false,
  • "pedestal_g0_frames": 0,
  • "pedestal_g1_frames": 0,
  • "pedestal_g2_frames": 0,
  • "storage_cell_delay_us": 0.1,
  • "detector_trigger_delay_us": 0.1,
  • "fixed_gain_g1": false,
  • "use_gain_hg0": false
}

Response samples

Content type
application/json
{
  • "msg": "Detector in wrong state",
  • "reason": "WrongDAQState"
}

Get detector configuration

Can be done anytime

-

Responses

Response samples

Content type
application/json
{
  • "frame_time_us": 450,
  • "count_time_us": 0,
  • "storage_cell_count": 1,
  • "internal_frame_generator": false,
  • "internal_frame_generator_images": 1,
  • "collect_raw_data": false,
  • "pedestal_g0_frames": 0,
  • "pedestal_g1_frames": 0,
  • "pedestal_g2_frames": 0,
  • "storage_cell_delay_us": 0.1,
  • "detector_trigger_delay_us": 0.1,
  • "fixed_gain_g1": false,
  • "use_gain_hg0": false
}

Configure spot finding

Can be done anytime, also while data collection is running

-
Request Body schema: application/json
enable
required
boolean
Default: true

Enable spot finding

-
indexing
required
boolean
Default: true

Enable indexing

-
signal_to_noise_threshold
required
number <float> >= 0
photon_count_threshold
required
integer <int64> >= 0
min_pix_per_spot
required
integer <int64> >= 1
max_pix_per_spot
required
integer <int64> >= 1
high_resolution_limit
required
number <float>
low_resolution_limit
required
number <float>
indexing_tolerance
required
number <float> [ 0 .. 1 ]

Acceptance tolerance for spots after the indexing run - the larger the number, the more spots will be accepted

-

Responses

Request samples

Content type
application/json
{
  • "enable": true,
  • "indexing": true,
  • "signal_to_noise_threshold": 0.1,
  • "photon_count_threshold": 0,
  • "min_pix_per_spot": 1,
  • "max_pix_per_spot": 1,
  • "high_resolution_limit": 0.1,
  • "low_resolution_limit": 0.1,
  • "indexing_tolerance": 1
}

Get data processing configuration

Can be done anytime

-

Responses

Response samples

Content type
application/json
{
  • "enable": true,
  • "indexing": true,
  • "signal_to_noise_threshold": 0.1,
  • "photon_count_threshold": 0,
  • "min_pix_per_spot": 1,
  • "max_pix_per_spot": 1,
  • "high_resolution_limit": 0.1,
  • "low_resolution_limit": 0.1,
  • "indexing_tolerance": 1
}

Configure radial integration

Can be done when detector is Inactive or Idle

-
Request Body schema: application/json
polarization_factor
number <float> [ -1 .. 1 ]

If polarization factor is provided, than polarization correction is enabled.

-
solid_angle_corr
required
boolean
Default: true

Apply solid angle correction for radial integration

-
high_q_recipA
required
number <float>
low_q_recipA
required
number <float>
q_spacing
required
number <float>

Responses

Request samples

Content type
application/json
{
  • "polarization_factor": -1,
  • "solid_angle_corr": true,
  • "high_q_recipA": 0.1,
  • "low_q_recipA": 0.1,
  • "q_spacing": 0.1
}

Response samples

Content type
application/json
{
  • "msg": "Detector in wrong state",
  • "reason": "WrongDAQState"
}

Get radial integration configuration

Can be done anytime

-

Responses

Response samples

Content type
application/json
{
  • "polarization_factor": -1,
  • "solid_angle_corr": true,
  • "high_q_recipA": 0.1,
  • "low_q_recipA": 0.1,
  • "q_spacing": 0.1
}

Load binary image for internal FPGA generator

Request Body schema: application/json
frame_time_us
required
integer <int64> >= 450

Interval between consecutive frames.

+
count_time_us
integer <int64>

Integration time of the detector. If not provided count time will be set to maximum value for a given frame time.

+
storage_cell_count
integer <int64> [ 1 .. 16 ]
Default: 1
internal_frame_generator
boolean
Default: false

Use internal frame generator in FPGA instead of getting data from a real detector

+
internal_frame_generator_images
integer <int64> [ 1 .. 128 ]
Default: 1
collect_raw_data
boolean
Default: false

Turn off conversion of pixel read-out to photon count

+
pedestal_g0_frames
integer <int64> >= 0
pedestal_g1_frames
integer <int64> >= 0
pedestal_g2_frames
integer <int64> >= 0
storage_cell_delay_us
number <float>

Delay between two storage cells [us]

+
detector_trigger_delay_us
number <float>

Delay between TTL trigger and acquisition start [us]

+
fixed_gain_g1
boolean
Default: false

Fix gain to G1 (can be useful for storage cells)

+
use_gain_hg0
boolean
Default: false

Use high G0 (for low energy applications)

+

Responses

Request samples

Content type
application/json
{
  • "frame_time_us": 450,
  • "count_time_us": 0,
  • "storage_cell_count": 1,
  • "internal_frame_generator": false,
  • "internal_frame_generator_images": 1,
  • "collect_raw_data": false,
  • "pedestal_g0_frames": 0,
  • "pedestal_g1_frames": 0,
  • "pedestal_g2_frames": 0,
  • "storage_cell_delay_us": 0.1,
  • "detector_trigger_delay_us": 0.1,
  • "fixed_gain_g1": false,
  • "use_gain_hg0": false
}

Response samples

Content type
application/json
{
  • "msg": "Detector in wrong state",
  • "reason": "WrongDAQState"
}

Get detector configuration

Can be done anytime

+

Responses

Response samples

Content type
application/json
{
  • "frame_time_us": 450,
  • "count_time_us": 0,
  • "storage_cell_count": 1,
  • "internal_frame_generator": false,
  • "internal_frame_generator_images": 1,
  • "collect_raw_data": false,
  • "pedestal_g0_frames": 0,
  • "pedestal_g1_frames": 0,
  • "pedestal_g2_frames": 0,
  • "storage_cell_delay_us": 0.1,
  • "detector_trigger_delay_us": 0.1,
  • "fixed_gain_g1": false,
  • "use_gain_hg0": false
}

Configure spot finding

Can be done anytime, also while data collection is running

+
Request Body schema: application/json
enable
required
boolean
Default: true

Enable spot finding

+
indexing
required
boolean
Default: true

Enable indexing

+
signal_to_noise_threshold
required
number <float> >= 0
photon_count_threshold
required
integer <int64> >= 0
min_pix_per_spot
required
integer <int64> >= 1
max_pix_per_spot
required
integer <int64> >= 1
high_resolution_limit
required
number <float>
low_resolution_limit
required
number <float>
indexing_tolerance
required
number <float> [ 0 .. 1 ]

Acceptance tolerance for spots after the indexing run - the larger the number, the more spots will be accepted

+

Responses

Request samples

Content type
application/json
{
  • "enable": true,
  • "indexing": true,
  • "signal_to_noise_threshold": 0.1,
  • "photon_count_threshold": 0,
  • "min_pix_per_spot": 1,
  • "max_pix_per_spot": 1,
  • "high_resolution_limit": 0.1,
  • "low_resolution_limit": 0.1,
  • "indexing_tolerance": 1
}

Get data processing configuration

Can be done anytime

+

Responses

Response samples

Content type
application/json
{
  • "enable": true,
  • "indexing": true,
  • "signal_to_noise_threshold": 0.1,
  • "photon_count_threshold": 0,
  • "min_pix_per_spot": 1,
  • "max_pix_per_spot": 1,
  • "high_resolution_limit": 0.1,
  • "low_resolution_limit": 0.1,
  • "indexing_tolerance": 1
}

Configure radial integration

Can be done when detector is Inactive or Idle

+
Request Body schema: application/json
polarization_factor
number <float> [ -1 .. 1 ]

If polarization factor is provided, than polarization correction is enabled.

+
solid_angle_corr
required
boolean
Default: true

Apply solid angle correction for radial integration

+
high_q_recipA
required
number <float>
low_q_recipA
required
number <float>
q_spacing
required
number <float>

Responses

Request samples

Content type
application/json
{
  • "polarization_factor": -1,
  • "solid_angle_corr": true,
  • "high_q_recipA": 0.1,
  • "low_q_recipA": 0.1,
  • "q_spacing": 0.1
}

Response samples

Content type
application/json
{
  • "msg": "Detector in wrong state",
  • "reason": "WrongDAQState"
}

Get radial integration configuration

Can be done anytime

+

Responses

Response samples

Content type
application/json
{
  • "polarization_factor": -1,
  • "solid_angle_corr": true,
  • "high_q_recipA": 0.1,
  • "low_q_recipA": 0.1,
  • "q_spacing": 0.1
}

Load binary image for internal FPGA generator

Load image for internal FPGA generator. This can only happen in Idle state of the detector. +" class="sc-iKOmoZ sc-cCzLxZ WVNwY VEBGS">

Load image for internal FPGA generator. This can only happen in Idle state of the detector. Requires binary blob with 16-bit integer numbers of size of detector in raw/converted coordinates (depending on detector settings).

-
query Parameters
number
integer <int64> [ 0 .. 127 ]

Image number to upload

-
Request Body schema: application/octet-stream
string <binary>

Responses

Select detector

query Parameters
number
integer <int64> [ 0 .. 127 ]

Image number to upload

+
Request Body schema: application/octet-stream
string <binary>

Responses

Select detector

Jungfraujoch allows to control multiple detectors and/or region-of-interests. +" class="sc-iKOmoZ sc-cCzLxZ WVNwY VEBGS">

Jungfraujoch allows to control multiple detectors and/or region-of-interests. The command allows to choose one detector from the list (ID has to be consistent with one provided by GET response). Changing detector will set detector to Inactive state and will require reinitialization.

-
Request Body schema: application/json
id
required
integer <int64>

Responses

Request samples

Content type
application/json
{
  • "id": 1
}

Response samples

Content type
application/json
{
  • "msg": "Detector in wrong state",
  • "reason": "WrongDAQState"
}

List available detectors

Configured detectors that can be selected by used

-

Responses

Response samples

Content type
application/json
{
  • "detectors": [
    ],
  • "current_id": 0
}

Get Jungfraujoch status

Status of the data acquisition

-

Responses

Response samples

Content type
application/json
{
  • "state": "Inactive",
  • "progress": 1,
  • "indexing_rate": 0.1
}

Return XFEL pulse IDs for the current data acquisition

Return array of XFEL pulse IDs - (-1) if image not recorded

-

Responses

Response samples

Content type
application/json
[
  • 0
]

Return XFEL event codes for the current data acquisition

Return array of XFEL event codes

-

Responses

Response samples

Content type
application/json
[
  • 0
]

Get detector status

Status of the JUNGFRAU detector

-

Responses

Response samples

Content type
application/json
{
  • "state": "Idle",
  • "powerchip": "On",
  • "server_version": "string",
  • "number_of_triggers_left": 0,
  • "fpga_temp_degC": [
    ],
  • "high_voltage_V": [
    ]
}

Get box ROIs

Responses

Response samples

Content type
application/json
{
  • "rois": [
    ]
}

Upload box ROIs

Request Body schema: application/json
Array of objects (roi_box) <= 32 items

Responses

Request samples

Content type
application/json
{
  • "rois": [
    ]
}

Response samples

Content type
application/json
{
  • "msg": "Detector in wrong state",
  • "reason": "WrongDAQState"
}

Get circular ROI

Responses

Response samples

Content type
application/json
{
  • "rois": [
    ]
}

Upload circular ROI

Request Body schema: application/json
required
Array of objects (roi_circle) <= 32 items

Responses

Request samples

Content type
application/json
{
  • "rois": [
    ]
}

Response samples

Content type
application/json
{
  • "msg": "Detector in wrong state",
  • "reason": "WrongDAQState"
}

Generate background estimate plot

Mean intensity for d = 3 - 5 A per image; binning is configurable

-
query Parameters
binning
integer

Binning of frames for the plot (0 = default binning)

-

Responses

Response samples

Content type
application/json
{
  • "title": "string",
  • "plot": [
    ]
}

Generate spot count plot

Number of spots per image; binning is configurable

-
query Parameters
binning
integer

Binning of frames for the plot (0 = default binning)

-

Responses

Response samples

Content type
application/json
{
  • "title": "string",
  • "plot": [
    ]
}

Generate indexing rate plot

Image indexing rate; binning is configurable

-
query Parameters
binning
integer

Binning of frames for the plot (0 = default binning)

-

Responses

Response samples

Content type
application/json
{
  • "title": "string",
  • "plot": [
    ]
}

Generate error pixels plot

Count of error (mean) and saturated (mean/max) pixels per image; binning is configurable

-
query Parameters
binning
integer

Binning of frames for the plot (0 = default binning)

-

Responses

Response samples

Content type
application/json
{
  • "title": "string",
  • "plot": [
    ]
}

Generate strong pixels plot

Count of strong pixels per image (from spot finding); binning is configurable

-
query Parameters
binning
integer

Binning of frames for the plot (0 = default binning)

-

Responses

Response samples

Content type
application/json
{
  • "title": "string",
  • "plot": [
    ]
}

Generate ROI sum plot

Sum of ROI rectangle per image; binning is configurable

-
query Parameters
binning
integer

Binning of frames for the plot (0 = default binning)

-

Responses

Response samples

Content type
application/json
{
  • "title": "string",
  • "plot": [
    ]
}

Generate plot of ROI max count

Max count of ROI per image; binning is configurable

-
query Parameters
binning
integer

Binning of frames for the plot (0 = default binning)

-

Responses

Response samples

Content type
application/json
{
  • "title": "string",
  • "plot": [
    ]
}

Generate plot of ROI valid pixels

Number of pixels within a ROI area; pixels with special values (overload, bad pixel) are excluded; multipixels are counted just once; binning is configurable

-
query Parameters
binning
integer

Binning of frames for the plot (0 = default binning)

-

Responses

Response samples

Content type
application/json
{
  • "title": "string",
  • "plot": [
    ]
}

Generate receiver delay plot

Amount of frames the receiver is behind the FPGA for each image - used for internal debugging; binning is configurable

-
query Parameters
binning
integer

Binning of frames for the plot (0 = default binning)

-

Responses

Response samples

Content type
application/json
{
  • "title": "string",
  • "plot": [
    ]
}

Generate receiver free send buffer plot

Amount of send buffers available during frame processing - used for internal debugging; binning is configurable

-
query Parameters
binning
integer

Binning of frames for the plot (0 = default binning)

-

Responses

Response samples

Content type
application/json
{
  • "title": "string",
  • "plot": [
    ]
}

Generate image collection efficiency plot

Ratio of collected and expected packets per image; binning is configurable

-
query Parameters
binning
integer

Binning of frames for the plot (0 = default binning)

-

Responses

Response samples

Content type
application/json
{
  • "title": "string",
  • "plot": [
    ]
}

Generate indexing rate per file

Indexing rate per each of data files; useful for example for time resolved data

-

Responses

Response samples

Content type
application/json
{
  • "title": "string",
  • "plot": [
    ]
}

Generate resolution estimate histogram

Generate histogram of crystal resolutions from 1.0 to 5.0 A based on ML model

-

Responses

Response samples

Content type
application/json
{
  • "title": "string",
  • "plot": [
    ]
}

Generate radial integration profile

Generate average radial integration profile

-

Responses

Response samples

Content type
application/json
{
  • "title": "string",
  • "plot": [
    ]
}

Generate radial integration profiles per file

Radial integration plots for both the whole dataset and per file; useful for time-resolved measurements

-

Responses

Response samples

Content type
application/json
{
  • "title": "string",
  • "plot": [
    ]
}

Get data collection statistics

Results of the last data collection

-

Responses

Response samples

Content type
application/json
{
  • "file_prefix": "string",
  • "images_expected": 0,
  • "images_collected": 0,
  • "images_sent": 0,
  • "images_discarded_lossy_compression": 0,
  • "max_image_number_sent": 0,
  • "collection_efficiency": 1,
  • "compression_ratio": 5.3,
  • "cancelled": true,
  • "max_receiver_delay": 0,
  • "indexing_rate": 0.1,
  • "detector_width": 0,
  • "detector_height": 0,
  • "detector_pixel_depth": 2,
  • "bkg_estimate": 0.1
}

Get calibration statistics

Statistics are provided for each module/storage cell separately

-

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Get last preview image in JPEG format using custom settings

Request Body schema: application/json
saturation
required
integer <int64> [ 0 .. 65535 ]

Saturation value to set contrast in the preview image

-
show_spots
boolean
Default: true

Show spot finding results on the image

-
show_roi
boolean
Default: false

Show ROI areas on the image

-
jpeg_quality
integer <int64> [ 0 .. 100 ]

Quality of JPEG image (100 - highest; 0 - lowest)

-
show_indexed
boolean

Preview indexed images only

-

Responses

Request samples

Content type
application/json
{
  • "saturation": 65535,
  • "show_spots": true,
  • "show_roi": false,
  • "jpeg_quality": 100,
  • "show_indexed": true
}

Response samples

Content type
application/json
{
  • "msg": "Detector in wrong state",
  • "reason": "WrongDAQState"
}

Get last preview image in JPEG format using default settings

Responses

Get last preview image in TIFF format

Responses

Get last preview image in TIFF format for calibration with PyFAI/Dioptas

Image is reduced to unsigned 16-bit images, all bad pixels are set to 65535 and image is mirrored in vertical direction

-

Responses

Get pedestal G0 in TIFF format

query Parameters
gain_level
required
integer

Gain level (0, 1, 2)

-
sc
integer

Storage cell number

-

Responses

+
Request Body schema: application/json
id
required
integer <int64>

Responses

Request samples

Content type
application/json
{
  • "id": 1
}

Response samples

Content type
application/json
{
  • "msg": "Detector in wrong state",
  • "reason": "WrongDAQState"
}

List available detectors

Configured detectors that can be selected by used

+

Responses

Response samples

Content type
application/json
{
  • "detectors": [
    ],
  • "current_id": 0
}

Get Jungfraujoch status

Status of the data acquisition

+

Responses

Response samples

Content type
application/json
{
  • "state": "Inactive",
  • "progress": 1,
  • "indexing_rate": 0.1
}

Return XFEL pulse IDs for the current data acquisition

Return array of XFEL pulse IDs - (-1) if image not recorded

+

Responses

Response samples

Content type
application/json
[
  • 0
]

Return XFEL event codes for the current data acquisition

Return array of XFEL event codes

+

Responses

Response samples

Content type
application/json
[
  • 0
]

Get detector status

Status of the JUNGFRAU detector

+

Responses

Response samples

Content type
application/json
{
  • "state": "Idle",
  • "powerchip": "On",
  • "server_version": "string",
  • "number_of_triggers_left": 0,
  • "fpga_temp_degC": [
    ],
  • "high_voltage_V": [
    ]
}

Get box ROIs

Responses

Response samples

Content type
application/json
{
  • "rois": [
    ]
}

Upload box ROIs

Request Body schema: application/json
Array of objects (roi_box) <= 32 items

Responses

Request samples

Content type
application/json
{
  • "rois": [
    ]
}

Response samples

Content type
application/json
{
  • "msg": "Detector in wrong state",
  • "reason": "WrongDAQState"
}

Get circular ROI

Responses

Response samples

Content type
application/json
{
  • "rois": [
    ]
}

Upload circular ROI

Request Body schema: application/json
required
Array of objects (roi_circle) <= 32 items

Responses

Request samples

Content type
application/json
{
  • "rois": [
    ]
}

Response samples

Content type
application/json
{
  • "msg": "Detector in wrong state",
  • "reason": "WrongDAQState"
}

Generate background estimate plot

Mean intensity for d = 3 - 5 A per image; binning is configurable

+
query Parameters
binning
integer

Binning of frames for the plot (0 = default binning)

+

Responses

Response samples

Content type
application/json
{
  • "title": "string",
  • "plot": [
    ]
}

Generate spot count plot

Number of spots per image; binning is configurable

+
query Parameters
binning
integer

Binning of frames for the plot (0 = default binning)

+

Responses

Response samples

Content type
application/json
{
  • "title": "string",
  • "plot": [
    ]
}

Generate indexing rate plot

Image indexing rate; binning is configurable

+
query Parameters
binning
integer

Binning of frames for the plot (0 = default binning)

+

Responses

Response samples

Content type
application/json
{
  • "title": "string",
  • "plot": [
    ]
}

Generate error pixels plot

Count of error (mean) and saturated (mean/max) pixels per image; binning is configurable

+
query Parameters
binning
integer

Binning of frames for the plot (0 = default binning)

+

Responses

Response samples

Content type
application/json
{
  • "title": "string",
  • "plot": [
    ]
}

Generate strong pixels plot

Count of strong pixels per image (from spot finding); binning is configurable

+
query Parameters
binning
integer

Binning of frames for the plot (0 = default binning)

+

Responses

Response samples

Content type
application/json
{
  • "title": "string",
  • "plot": [
    ]
}

Generate ROI sum plot

Sum of ROI rectangle per image; binning is configurable

+
query Parameters
binning
integer

Binning of frames for the plot (0 = default binning)

+

Responses

Response samples

Content type
application/json
{
  • "title": "string",
  • "plot": [
    ]
}

Generate plot of ROI max count

Max count of ROI per image; binning is configurable

+
query Parameters
binning
integer

Binning of frames for the plot (0 = default binning)

+

Responses

Response samples

Content type
application/json
{
  • "title": "string",
  • "plot": [
    ]
}

Generate plot of ROI valid pixels

Number of pixels within a ROI area; pixels with special values (overload, bad pixel) are excluded; multipixels are counted just once; binning is configurable

+
query Parameters
binning
integer

Binning of frames for the plot (0 = default binning)

+

Responses

Response samples

Content type
application/json
{
  • "title": "string",
  • "plot": [
    ]
}

Generate receiver delay plot

Amount of frames the receiver is behind the FPGA for each image - used for internal debugging; binning is configurable

+
query Parameters
binning
integer

Binning of frames for the plot (0 = default binning)

+

Responses

Response samples

Content type
application/json
{
  • "title": "string",
  • "plot": [
    ]
}

Generate receiver free send buffer plot

Amount of send buffers available during frame processing - used for internal debugging; binning is configurable

+
query Parameters
binning
integer

Binning of frames for the plot (0 = default binning)

+

Responses

Response samples

Content type
application/json
{
  • "title": "string",
  • "plot": [
    ]
}

Generate image collection efficiency plot

Ratio of collected and expected packets per image; binning is configurable

+
query Parameters
binning
integer

Binning of frames for the plot (0 = default binning)

+

Responses

Response samples

Content type
application/json
{
  • "title": "string",
  • "plot": [
    ]
}

Generate indexing rate per file

Indexing rate per each of data files; useful for example for time resolved data

+

Responses

Response samples

Content type
application/json
{
  • "title": "string",
  • "plot": [
    ]
}

Generate radial integration profile

Generate average radial integration profile

+

Responses

Response samples

Content type
application/json
{
  • "title": "string",
  • "plot": [
    ]
}

Generate radial integration profiles per file

Radial integration plots for both the whole dataset and per file; useful for time-resolved measurements

+

Responses

Response samples

Content type
application/json
{
  • "title": "string",
  • "plot": [
    ]
}

Get data collection statistics

Results of the last data collection

+

Responses

Response samples

Content type
application/json
{
  • "file_prefix": "string",
  • "images_expected": 0,
  • "images_collected": 0,
  • "images_sent": 0,
  • "images_discarded_lossy_compression": 0,
  • "max_image_number_sent": 0,
  • "collection_efficiency": 1,
  • "compression_ratio": 5.3,
  • "cancelled": true,
  • "max_receiver_delay": 0,
  • "indexing_rate": 0.1,
  • "detector_width": 0,
  • "detector_height": 0,
  • "detector_pixel_depth": 2,
  • "bkg_estimate": 0.1
}

Get calibration statistics

Statistics are provided for each module/storage cell separately

+

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Get last preview image in JPEG format using custom settings

Request Body schema: application/json
saturation
required
integer <int64> [ 0 .. 65535 ]

Saturation value to set contrast in the preview image

+
show_spots
boolean
Default: true

Show spot finding results on the image

+
show_roi
boolean
Default: false

Show ROI areas on the image

+
jpeg_quality
integer <int64> [ 0 .. 100 ]

Quality of JPEG image (100 - highest; 0 - lowest)

+
show_indexed
boolean

Preview indexed images only

+
resolution_ring
number <float> [ 0.1 .. 100 ]

Responses

Request samples

Content type
application/json
{
  • "saturation": 65535,
  • "show_spots": true,
  • "show_roi": false,
  • "jpeg_quality": 100,
  • "show_indexed": true,
  • "resolution_ring": 0.1
}

Response samples

Content type
application/json
{
  • "msg": "Detector in wrong state",
  • "reason": "WrongDAQState"
}

Get last preview image in JPEG format using default settings

Responses

Get last preview image in TIFF format

Responses

Get last preview image in TIFF format for calibration with PyFAI/Dioptas

Image is reduced to unsigned 16-bit images, all bad pixels are set to 65535 and image is mirrored in vertical direction

+

Responses

Get pedestal G0 in TIFF format

query Parameters
gain_level
required
integer

Gain level (0, 1, 2)

+
sc
integer

Storage cell number

+

Responses