Skip to content

OpenRecon

Development pathComplete these setup sectionsContinue at
Local workstation1. Set up a local computer; 2. Fork and set up Neurocontainers locally4. Complete example
GitHub Codespaces3. Set up Neurocontainers in GitHub Codespaces4. Complete example

You need Git, Docker, Python 3.13, and Visual Studio Code. A GitHub account is required when you are ready to fork repositories, use Codespaces, or submit changes.

This was tested with Python 3.10 to 3.13.

Use WSL 2 with a Linux distribution such as Ubuntu. Install Docker Desktop with its WSL 2 backend and enable integration for that distribution. Install the VS Code WSL extension, open the checkout from WSL with code ., and run every command in this guide in the WSL terminal.

Keep the checkout in the WSL filesystem, for example under ~/src, rather than under /mnt/c; Docker bind mounts perform better there. Do not run the Bash build scripts from Command Prompt or PowerShell.

Install Python 3.13 inside the WSL distribution. If the distribution does not provide Python 3.13, use the uv option described under Linux below.

Install Docker Desktop and start it. Install Git, Python, and 7-Zip with your preferred package manager. Example with Homebrew (https://brew.sh):

Terminal window
# To install homebrew in case you don't have it yet:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
Terminal window
brew install git python@3.13 p7zip

Install Git, Python 3.13 with venv support, 7-Zip, and Docker Engine using your distribution’s instructions. Configure Docker so your normal user can run it, then log out and back in if the group membership changed.

For Debian or Ubuntu, the prerequisites are:

Terminal window
sudo apt update
sudo apt install -y git curl p7zip-full

If your distribution does not package Python 3.13, install it with uv:

Terminal window
curl -LsSf https://astral.sh/uv/install.sh | sh
export PATH="$HOME/.local/bin:$PATH"
uv python install 3.13

Open a new terminal and check each tool before cloning the source:

Terminal window
git --version
python3.13 --version
docker version
docker run --rm hello-world
docker buildx version
docker run --rm --platform linux/amd64 alpine uname -m

Configure the identity Git will record in your commits:

Terminal window
git config --global user.name "YOUR NAME"
git config --global user.email "YOUR GITHUB EMAIL"

The Python command must report 3.13.x, and the last Docker command should print x86_64. If docker version cannot reach the server, start Docker Desktop or the Linux Docker service before continuing.

2. Fork and set up Neurocontainers locally

Section titled “2. Fork and set up Neurocontainers locally”

Fork neurodesk/neurocontainers into your GitHub account, then clone your fork. Replace YOUR_GITHUB_USERNAME below:

Terminal window
git clone https://github.com/YOUR_GITHUB_USERNAME/neurocontainers.git
cd neurocontainers
git remote add upstream https://github.com/neurodesk/neurocontainers.git
git switch -c add-MYPROJECT-openrecon

Create an isolated Python environment and install these dependencies:

Terminal window
python3.13 -m venv .venv
source .venv/bin/activate
python --version # Must report Python 3.13.x
python -m pip install --upgrade pip
python -m pip install -r requirements.txt
python -m pip install -e .
sf-build --help

Activate the environment with source .venv/bin/activate whenever you open a new terminal.

3. Set up Neurocontainers in GitHub Codespaces

Section titled “3. Set up Neurocontainers in GitHub Codespaces”

Use this section instead of sections 1 and 2 when Docker and Python are not available on your computer.

  1. Fork neurodesk/neurocontainers.

  2. Make sure your fork’s main branch is up to date, then select Code > Codespaces > Create codespace on main. The repository’s development-container configuration installs Python 3.13, creates the env virtual environment, installs Neurocontainers, and connects the codespace to a Docker daemon.

  3. When setup finishes, create a new branch, activate the environment, and verify both Neurocontainers and Docker:

    Terminal window
    git switch -c add-MYPROJECT-openrecon
    source env/bin/activate
    python --version # Must report Python 3.13.x
    python -m builder --help
    sf-build --help
    docker info
    docker run --rm hello-world
  4. Continue with section 4. The openreconi2iexample recipe, fulltest.yaml, sf-login, and MRD server/client commands are the same as in a local Linux environment.

  5. Use the preinstalled H5Web extension to inspect .h5 outputs and niivue for .nii.

  6. Never upload identifiable DICOM data to the codespace or commit private test data.

A codespace is an interactive, time-limited development environment. GitHub’s default idle timeout is 30 minutes and the maximum user-configurable timeout is 4 hours; when a codespace stops, its running processes stop too. Use the pull-request workflow in section 9 for builds that must continue unattended.

4. Complete example: build and run openreconi2iexample

Section titled “4. Complete example: build and run openreconi2iexample”

Run this example before creating your own recipe. All commands in this section start in the root of your neurocontainers checkout with its Python 3.13 environment active. For a local checkout, run:

Terminal window
cd /PATH/TO/neurocontainers
source .venv/bin/activate
python --version # Must report Python 3.13.x

In GitHub Codespaces, the checkout is already under /workspaces and the configured environment is named env:

Terminal window
cd /workspaces/neurocontainers
source env/bin/activate
python --version # Must report Python 3.13.x

Validate the recipe and scanner label, then run its focused Python tests:

Terminal window
python builder/validation.py \
recipes/openreconi2iexample/build.yaml --verbose
python workflows/validate_openrecon_labels.py \
recipes/openreconi2iexample/OpenReconLabel.json
python -m pytest \
recipes/openreconi2iexample/test_openreconi2iexample.py -q

The archive is approximately 9 MB and contains 160 .IMA DICOM files. The conversion will create a much larger local MRD file, so keep generated data under local-test. The following exclusion is local to your checkout and does not modify the repository’s shared .gitignore:

Terminal window
grep -qxF 'recipes/openreconi2iexample/local-test/' .git/info/exclude || \
echo 'recipes/openreconi2iexample/local-test/' >> .git/info/exclude
mkdir -p recipes/openreconi2iexample/local-test

sf-login stages the recipe, builds openreconi2iexample:<version> for linux/amd64, mounts the recipe directory at /buildhostdirectory, and opens a shell in the new container:

Terminal window
sf-login openreconi2iexample --recreate --architecture x86_64

The first build can take a while. On Apple Silicon or another ARM64 host, Docker runs this x86_64 image through emulation.

Inside the container, verify the installed example and server:

Terminal window
openreconi2iexample
python3 /opt/code/python-ismrmrd-server/main.py --help | head

The first command should print openreconi2iexample followed by the current recipe version.

Convert the bundled DICOM data to an ISMRMRD HDF5 file

Section titled “Convert the bundled DICOM data to an ISMRMRD HDF5 file”

The recipe directory is mounted at /buildhostdirectory, so both committed test assets are available inside the container. First extract the archive there using Python’s standard-library ZIP support:

Terminal window
python3 -m zipfile -e \
/buildhostdirectory/GR_M_5_QSM_p2_1mmIso_TE20.zip \
/buildhostdirectory/local-test/dicom
find /buildhostdirectory/local-test/dicom -type f \
\( -iname '*.ima' -o -iname '*.dcm' \) | wc -l

The count should be 160. Now run the recipe-local dicom2mrd.py inside the container. It reads the DICOM tree recursively and writes image MRD data to the dataset group in an ISMRMRD HDF5 file:

Terminal window
python3 /buildhostdirectory/dicom2mrd.py \
-o /buildhostdirectory/local-test/input_data.h5 \
-g dataset \
/buildhostdirectory/local-test/dicom

The converter should report one series containing 160 images. Verify the resulting file /buildhostdirectory/local-test/input_data.h5 before starting the server by opening it in the H5Web hdf viewer inside VScode.

The generated HDF5 file remains on the host under recipes/openreconi2iexample/local-test/input_data.h5 after you exit the container.

Still inside the container, write the parameter payload that reproduces the scanner label’s default behaviour:

Terminal window
cat > /buildhostdirectory/local-test/openreconi2iexample.json <<'JSON'
{
"parameters": {
"sendoriginal": true,
"invert": true,
"segment": true,
"segmentheadergeometry": "2d_segment_header"
}
}
JSON

The MRD client automatically sends this file as additional configuration because its basename matches -c openreconi2iexample. Start the server in the background, send the input, and stop the server afterward:

Terminal window
python3 /opt/code/python-ismrmrd-server/main.py \
-v -r -H=0.0.0.0 -p=9002 -s -S=/tmp/share/saved_data \
> /buildhostdirectory/local-test/server.log 2>&1 &
server_pid=$!
trap 'kill "$server_pid" 2>/dev/null || true' EXIT
sleep 2
cd /buildhostdirectory/local-test
python3 /opt/code/python-ismrmrd-server/client.py \
-G dataset \
-o openrecon_output.h5 \
input_data.h5 \
-c openreconi2iexample
kill "$server_pid" 2>/dev/null || true
wait "$server_pid" 2>/dev/null || true
trap - EXIT

This explicit parameter payload sends original images, inverted images, and a simple foreground segmentation. For a straightforward single-series magnitude input, expect output groups image_99, image_100, and image_101. More complex inputs can be split into additional groups.

Open recipes/openreconi2iexample/local-test/openrecon_output.h5 with the VS Code H5Web extension to inspect the returned images.

Exit the container, run the deploy smoke test against the image, and prove that the expected local tag exists:

Terminal window
exit
sf-test openreconi2iexample --architecture x86_64

Build the example OpenRecon and FIRE packages

Section titled “Build the example OpenRecon and FIRE packages”

From the directory containing your neurocontainers checkout, clone the packaging repository and create its Python 3.13 environment:

Terminal window
cd ..
git clone https://github.com/neurodesk/openrecon.git
cd openrecon
python3.13 -m venv .venv
source .venv/bin/activate
python --version # Must report Python 3.13.x
python -m pip install --upgrade pip
python -m pip install jsonschema packaging

The checked-in recipes/openreconi2iexample/params.sh must name the same version you just built. Assert that it matches before starting the package build.

Build both scanner formats from the local Docker image:

Terminal window
cd recipes/openreconi2iexample
/bin/bash ../build.sh --local-cache

The OpenRecon zip is installable through the OpenRecon package mechanism; the FIRE directory contains its Ice tree and INSTALL_FIRE.txt.

Once this complete example works, return to your Neurocontainers checkout and adapt the recipe for your own application.

Use a short lowercase name containing only letters and numbers, for example myrecon. Published OpenRecon recipe names must not contain underscores.

For a new image-to-image application, start from openreconi2iexample. For a new kspace-to-complex-image application, start from sodiumgridding.

Terminal window
cp -R recipes/openreconi2iexample recipes/myrecon
mv recipes/myrecon/openreconi2iexample.py recipes/myrecon/myrecon.py
mv recipes/myrecon/test_openreconi2iexample.py recipes/myrecon/test_myrecon.py
code recipes/myrecon

Use VS Code’s search-and-replace to change openreconi2iexample to myrecon, then adapt the copied files.

Your recipe should include at least:

  • build.yaml: container name, version, x86_64 architecture, dependencies, files, and build directives;
  • your Python MRD application module;
  • OpenReconLabel.json: resource requirements, and user parameters;
  • OpenReconREADME.md: scanner-facing documentation that becomes the package README/PDF;
  • fulltest.yaml: CI runtime tests for the released container; and
  • focused tests for the application logic where practical.

The recipe must install the Python MRD server macro:

architectures:
- x86_64
build:
kind: neurodocker
base-image: ubuntu:22.04
pkg-manager: apt
directives:
- include: macros/openrecon/neurodocker.yaml

Declare application files in the top-level files list and copy them into /opt/code/python-ismrmrd-server in a build directive. Keep the following identities synchronized:

  • name and version in build.yaml;
  • name and version in fulltest.yaml;
  • the package id and the config choice/default in OpenReconLabel.json; and
  • the Python module name passed to the MRD client with -c.

The OpenRecon 1.1.0 schema allows at most 14 parameters, including config. Every choice parameter must have a non-empty default that exactly matches one of its value IDs.

Keep VERSION_WILL_BE_REPLACED_BY_SCRIPT in the label’s version and version-derived regulatory fields. The packaging build replaces this placeholder with the version from params.sh before validating and assembling the package.

Keep OpenReconLabel.json in the Neurocontainers recipe. Current release automation copies it into OpenRecon and creates params.sh; contributors no longer need to maintain a second copy manually. If OpenReconREADME.md is present, the automation also copies it to the openrecon package repository as README.md.

6. Validate, build, and test the Neurocontainer

Section titled “6. Validate, build, and test the Neurocontainer”

Run metadata validation and any focused tests first:

Terminal window
python builder/validation.py recipes/myrecon/build.yaml --verbose
python workflows/validate_openrecon_labels.py
python -m pytest recipes/myrecon/test_*.py -q

Build the scanner-compatible x86_64 image and open an interactive shell in it:

Terminal window
sf-login myrecon --recreate --architecture x86_64

On an Apple Silicon or ARM64 host, Docker emulates linux/amd64; the build can therefore be slower than a native x86_64 build. The recipe directory is mounted in the container at /buildhostdirectory.

Test the application through the MRD server

Section titled “Test the application through the MRD server”

Start with a known MRD .h5 input whenever possible. To convert legacy DICOM inside the container:

Terminal window
mkdir -p /buildhostdirectory/local-test
cd /opt/code/python-ismrmrd-server
python3 dicom2mrd.py \
-o /buildhostdirectory/local-test/input.h5 \
/buildhostdirectory/local-test/dicom

Enhanced DICOM conversion is still pending upstream in python-ismrmrd-server PR 15. Until it is merged, examples of the additional converters are available as enhanceddicom2mrd.py and nifti2mrd.py. If your application needs them, declare and copy them in build.yaml.

Inside the container, start the server and send the test dataset through your configuration:

Terminal window
python3 /opt/code/python-ismrmrd-server/main.py \
-v -r -H=0.0.0.0 -p=9002 -s -S=/tmp/share/saved_data &
sleep 2
python3 /opt/code/python-ismrmrd-server/client.py \
-G dataset \
-o /buildhostdirectory/local-test/output.h5 \
/buildhostdirectory/local-test/input.h5 \
-c myrecon

Confirm that the client reports the expected number and type of returned images. Inspect output.h5 with the vscode H5Web extension and inspect any NIfTI intermediates with a NIfTI-capable viewer (e.g. niivue). Test every OpenReconLabel.json option and important option combination.

Exit the container and run the builder’s deploy smoke test against the image you just built:

Terminal window
exit
sf-test myrecon --architecture x86_64

sf-test checks the built image’s deployment contract. Your fulltest.yaml is exercised by the current pull-request candidate workflow; it should contain meaningful application/runtime assertions.

First build the Neurocontainer as described above. The local Docker image must be tagged myrecon:<version>, which is the tag produced by sf-build and sf-login.

Clone the packaging repository next to your Neurocontainers checkout:

Terminal window
cd ..
git clone https://github.com/neurodesk/openrecon.git
cd openrecon
python3.13 -m venv .venv
source .venv/bin/activate
python --version # Must report Python 3.13.x
python -m pip install --upgrade pip
python -m pip install jsonschema packaging

Create recipes/myrecon and copy the scanner metadata from your Neurocontainers recipe:

Terminal window
mkdir -p recipes/myrecon
cp ../neurocontainers/recipes/myrecon/OpenReconLabel.json recipes/myrecon/
cp ../neurocontainers/recipes/myrecon/OpenReconREADME.md recipes/myrecon/README.md

Create recipes/myrecon/params.sh with the same name and version as build.yaml:

#!/bin/bash
export toolName=myrecon
export version=1.0.0
export baseDockerImage=vnmd/${toolName}_${version}

The build checks the local Docker cache first, including myrecon:1.0.0, and falls back to baseDockerImage only when no matching local image exists. From the package recipe directory, request both artifacts:

Terminal window
cd recipes/myrecon
/bin/bash ../build.sh --local-cache

The packager runs a privileged nested Docker build for linux/amd64 and needs substantial temporary disk space. It also renders README.md to PDF. If mdpdf is unavailable, the build installs the required Node/NVM tooling; --ignore-mdpdf is useful only when the recipe already supplies docs.pdf or README.pdf.

The build runs as linux/amd64 and produces:

recipes/myrecon/openrecon/OpenRecon_<vendor>_<name>_V<version>.zip
recipes/myrecon/fire/FIRE_<vendor>_<name>_V<version>/

The FIRE output is a directory containing an Ice tree and INSTALL_FIRE.txt. Keep the directory structure unchanged.

If you used the Codespaces setup in section 3, the commands above work without modification: from /workspaces/neurocontainers, cd .. moves to /workspaces, where you can clone the OpenRecon repository.

FIRE images can be large and Codespaces storage is small. Check df -h before building both packages, select a larger codespace if necessary, and stop or delete the codespace when you finish to avoid unnecessary usage.

Use the package produced in section 7 for local scanner testing. The same installation procedures apply to an artifact published later through the GitHub Actions flow in section 9.

Make sure that no protocol is open, because an open protocol can prevent installation of a new package.

NumarisX VA70 and above (for example, XB10)

Section titled “NumarisX VA70 and above (for example, XB10)”

For software versions NumarisX VA70 and above, such as NumarisX XB10, use the Numaris/Edge routine for installing OpenRecon applications. A short summary of the installation steps is provided below.

  1. Exit Kiosk mode of your MRAWP via the keyboard shortcut [Tab] + [Del] + [Num +].

  2. Create a folder under C:\Temp\, e.g. C:\Temp\OR\Packages.

  3. Copy the OpenRecon package to C:\Temp\OR\Packages.

  4. Press the Windows key and open an elevated admin CMD shell.

  5. Change directory to %MREDGEHOME%:

    Terminal window
    cd /d "%MREDGEHOME%"
  6. Start the installation of the OpenRecon package:

    Terminal window
    syngo.MR.Digi.Utils.Console.exe store --install-package "C:\Temp\OR\Packages\OpenRecon_package.zip"
  7. The installation will take a couple of minutes. Check the progress of the installation via:

    Terminal window
    syngo.MR.Digi.Utils.Console.exe store --list

Copy the OpenRecon zip file into C:\Program Files\Siemens\Numaris\OperationalManagement\FileTransfer\incoming.

Wait for the file to disappear.

Check whether it is being installed by watching C:\ProgramData\Siemens\Numaris\log\syngo.MR.HostInfra.OpenRecon.Watcher.

It should first create a 0 KB text file with the container name and version.

The text file then fills to about 100-200 KB.

Once the log file is written, you can open a protocol and check whether the package is available.

Run the sequence with OpenRecon enabled and check for errors in the log viewer at C:\ProgramData\Siemens\Numaris\log\OpenRecon.utr.

Unpack the generated FIRE zip and read its INSTALL_FIRE.txt before changing the scanner. The archive root contains an Ice folder laid out like %CustomerIceProgs%, normally under MriCustomer.

Copy or merge the package’s Ice folder into MriCustomer while preserving its paths. The bundle includes the FIRE workflow files, configuration, chroot image, startup settings, and shared directories required by the package. Stop or unmount an existing FIRE chroot before replacing its .img file.

FIRE installation is a scanner-administration operation. Follow your site’s scanner-version-specific procedure and change-control process in addition to the generated instructions.

9. Build and publish through GitHub Actions

Section titled “9. Build and publish through GitHub Actions”

Commit and open the Neurocontainers pull request

Section titled “Commit and open the Neurocontainers pull request”

From your Neurocontainers branch, review what will be published, then commit and push it to your fork:

Terminal window
git status --short
git diff --check
git add recipes/myrecon
git commit -m "Add myrecon OpenRecon recipe"
git push -u origin add-MYPROJECT-openrecon

Open a pull request from your fork to neurodesk/neurocontainers:main. Include:

  • what the application does and which image/acquisition type it expects;
  • the local build and MRD test commands you ran;
  • the source and permission status of any public test data;
  • expected returned series and important parameter combinations; and
  • limitations that a scanner tester must know.

The current PR container candidate workflow accepts fork pull requests. It validates the changed recipe and OpenRecon metadata, builds every declared architecture/variant, creates Docker and SIF candidates, runs the deploy and fulltest.yaml checks and uploads an immutable candidate artifact.

The current release sequence is:

  1. Neurocontainers promotes the exact tested candidate rather than rebuilding it.
  2. The image and release metadata are published.
  3. For a default x86_64 recipe containing OpenReconLabel.json, sync_openrecon.py creates or updates an OpenRecon metadata pull request. If the metadata is unchanged, it can dispatch a rebuild instead.
  4. After the OpenRecon pull request is reviewed and merged, its auto-build workflow runs the reusable build-apps workflow.
  5. That workflow builds both OpenRecon and FIRE artifacts, uploads both zips, and opens an issue containing download and installation instructions.

You therefore normally submit only the Neurocontainers pull request. Do not open a hand-written OpenRecon packaging pull request unless a maintainer asks for a packaging-only change or the automatic synchronization fails.

Sent image values must fit within a 4096-value range

Section titled “Sent image values must fit within a 4096-value range”

OpenRecon can send a maximum integer range of 4096 values back to the scanner.

If the returned images exceed that range, the values can wrap around instead of clipping. The symptom is that the sent images show repeating integer wraps and can look a bit like phase images.

Scale or clamp derived image data into the scanner-safe range before sending it from the MRD server.

Choice parameters need a non-empty default

Section titled “Choice parameters need a non-empty default”

Current Neurocontainers and OpenRecon packaging validators reject a choice parameter whose default is empty or does not match one of its value IDs. Older packages created without this check could install successfully but remain unselectable in the sequence tab.

For example, this can fail because "default": "" does not match any entry in values:

{
"id": "metricsregion",
"label": { "en": "Metrics Region" },
"type": "choice",
"values": [
{
"id": "wholebody",
"name": { "en": "wholebody" }
},
{
"id": "abdomen",
"name": { "en": "abdomen" }
},
{
"id": "pelvis",
"name": { "en": "pelvis" }
},
{
"id": "thigh",
"name": { "en": "thigh" }
},
{
"id": "leg",
"name": { "en": "leg" }
}
],
"default": "",
"information": { "en": "Region passed to MuscleMap metrics" }
}

Set the default to one of the available values IDs instead:

{
"id": "metricsregion",
"label": { "en": "Metrics Region" },
"type": "choice",
"values": [
{
"id": "wholebody",
"name": { "en": "wholebody" }
},
{
"id": "abdomen",
"name": { "en": "abdomen" }
},
{
"id": "pelvis",
"name": { "en": "pelvis" }
},
{
"id": "thigh",
"name": { "en": "thigh" }
},
{
"id": "leg",
"name": { "en": "leg" }
}
],
"default": "wholebody",
"information": { "en": "Region passed to MuscleMap metrics" }
}

This option has to be disabled in an OpenRecon sequence:

Prio Recon needs to be disabled

Right-click Sequence in the Scan Queue, then select Edit Properties (Alt+Enter) and Execution.

Make sure that you install the correct CUDA version in the container and that it does not get overwritten by a pip install. The current OpenRecon package build rejects a CUDA toolkit or PyTorch CUDA version newer than 11.8.

Always double-check in the container with:

Terminal window
# Check that the PyTorch CUDA version is no newer than 11.8.
python -c "import torch; print(torch.version.cuda)"

High-performance computing licence side effects

Section titled “High-performance computing licence side effects”

For OpenRecon to work, the N_High_End_Computing licence must be active on the scanner.

Activating this licence takes memory away from the main ICE recon system, so normal recons might run out of memory sooner. If you need this memory back, you can temporarily disable this licence and OpenRecon.

Turn the licence off by commenting it out. Add # in front of the relevant lines in C:\Program Files\Siemens\Numaris\bin\Common\Licensing\license.dat.

Restart the whole system. Restarting the workspace is not enough.

OpenRecon requires container versions. For example, on the scanner, version 1.2.3 only shows the major version in the selection box, but hovering over the name shows the full version:

Seeing the specific version of the container

OpenRecon will not install an update to a container with the same version.

Cleaning up packages on the scanner (on XA60/61)

Section titled “Cleaning up packages on the scanner (on XA60/61)”

After installing and testing different OpenRecon containers, old containers remain in the host registry and consume space on the host C: drive.

Download wip_OpenRecon_PackageRemover_Tool.exe from the Siemens MAGNETOM forum and follow the installation instructions.

At the end of a testing session, purge the old packages by running this in the powershell:

Terminal window
wip_OpenRecon_PackageRemover_Tool.exe --purge

Answer y for each package you want to purge.

Then run garbage collection to clean up the storage:

Terminal window
wip_OpenRecon_PackageRemover_Tool.exe --gc

This tool often breaks the OpenRecon watcher process, so installing new packages after cleanup may fail until the host is restarted. Reboot the host after cleanup before installing more OpenRecon packages.

For the deletion to work, and for the tool to see your OpenRecon package, the package needs to be labelled as Research. It will not touch OpenRecon tools labelled as Product.

Check that your OpenReconLabel.json file contains:

"content_qualification_type": "RESEARCH"