Tool development using the Tool Maker
This guide helps you to quickly get started using the Tool Maker, a software included in the QMENTA SDK library, that will enable you to develop a tool that can be easily integrated in the QMENTA Platform. In the following sections we will show you step by step how to:
Set up the Tool Maker in your computer
Create a new tool to start working with the SDK
Test your tool locally
Test your tool locally within a docker container
Integrate your tool in the QMENTA Platform
The tool maker is a part of the QMENTA SDK library. When installing the SDK library in your computer, the Tool Maker will also be accessible via command line. No further set up is required to use the Tool Maker. In the following chapters you will see how the tool maker used to create the tool and imported to use it to its full potential.
Creating a new tool
The Tool Maker empowers you to create tools for the QMENTA Platform in a simple way. It will automatically generate all the files required for implementing your tool without having to worry about how they need to be configured. The first step is to call the graphic interface:
/home/myfolder$ tool_maker
It will show something similar to the following screenshot

The process involves specifying the identification of the tool, which will be used to create a dedicated folder for storing generated files.
The generated files include the main Python code (tool.py
), configuration files (settings.json
and results_configuration.json
), and
a test folder (local/test/
).
Usage:
Call the GUI for the tool.
Specify the tool ID as an underscore-separated, lowercase sentence (e.g.,
my_first_tool
,advanced_dwi_model
). It will be used to name the main tool folder and the docker image name by default.The tool files will be generated in the folder where the GUI was called (e.g.
/home/myfolder
), inside the/home/myfolder/local_tools/
directory which is automatically generated by the tool maker.
Generated Files:
/home/myfolder/local_tools/
└─ my_first_tool
├─ description.html
├─ local
│ ├─ Dockerfile
│ ├─ requirements.txt
│ └─ test
│ ├─ sample_data
│ └─ test_tool.py
└─ tool.py
tool.py
: Main Python code to execute the tool.description.html
: Description of the tool in html format. It will show in the front-end when selecting the tool. It should explain what the tool does and which are its requirements.local/test/
: Folder containing the required files for testing the tool.
Main python script: tool.py
This section outlines the process of creating tool from the automatically generated sample tool. The tool creator defines for you the Tool class and its methods, providing defaults and examples to replace with appropriate code. Comments and references are included to facilitate understanding of the tool creation process.
Begin populating the Tool class’ various elements. The following functions within the Tool class contribute to the QMENTA Platform’s front-end:
tools_input()
This method is used by the Tool Maker to complete the settings.json
file. This configuration
file provides the information to show the parameters when selecting your tool in the QMENTA Platform:

It will convert the different functions into the proper JSON file to be used in the tool in the QMENTA Platform. The possible settings to be configured in a tool are:
Input container (
add_input_container
):
Note
The Data button allows you to select uploaded sessions in your project as inputs. a pop-up window will appear. You may select one or multiple sessions as input.
The Analysis button allows you to select a finished analysis in your project as inputs. To enable this,
add the argument tool_codes_set_as_input
and add the tool codes from the tools you want your current
tool to get their inputs from.
Checkbox (
add_input_checkbox
):Input string (
add_input_string
):
Input decimal number (
add_input_decimal
):
Input integer number (
add_input_integer
):
Input dropdown menu (
add_input_single_choice
):
Input multiple choice (
add_input_multiple_choice
):
Other methods implemented in the Tool class are utilized to add information or format the settings section of the tool:
Indent (
add_indent
):
Horizontal line (
add_line
):
Heading (
add_heading
):
Information textbox (
add_info
):
To gain a better understanding of how to write these methods, refer to the SDK template generated when launching the interface. Replace the values appropriately based on your tool’s requirements. Additionally, consult the code documentation, especially the add_input_container documentation, for detailed instructions. For comprehensive information about input parameters, please consult the SDK documentation section
run()
This section outlines the key functionalities within the tool script,
focusing on data processing and result production. The run()
method encompasses the data processing segment of the
script, where results are generated, and the SDK may be employed to
upload result files and set metadata values. To streamline input
handling, utilize the self.prepare_inputs(context, logger)
command,
which automatically downloads and stores all tool inputs in the self
object. Access file handlers using the container_id
and
file_filter_condition_name:
c_files_handlers_list = self.inputs.input_data.c_files
Where
input_data
is the container_id andc_files
is the file_filter_condition_name.
The variable c_files_handlers_list is a list of handlers, with each element representing a file object. Refer to the SDK documentation for available functionalities
Retrieve the path of a file (e.g., from the first object in the list) using:
input_data_path = file_handlers_list[0].file_path
More information about data handling can be found in the SDK example generated by the Tool Maker.
Upon identifying local files, proceed with processing. After generating output files, use the following command to upload them to the QMENTA Platform:
context.upload_file(
source_file_path=result_file,
destination_path="T1_final.nii.gz",
modality=str(Modality.DTI),
tags={"eddy"},
file_info={},
)
Add information to the session’s metadata directly from the tool and verify it in the QMENTA Platform frontend:
context.set_metadata_value(key="metadata_key", value=100)
tools_output()
This method is employed by the Tool Maker to complete the results_configuration.json. Further details about this tool section are available in the SDK documentation section. This method is optional.
# Main object to create the results configuration object.
result_conf = ResultsConfiguration()
Adjust the layout of results using the following methods:
Split()
: Divide the window horizontally or vertically to present different elements simultaneously. To create a split, specify which elements are going to be shown in thechildren
parameter. Each children must have the parameterregion
defined, which allocates the element in the screen. It can be:Region.left: for vertical screen splits defined with OrientationLayout.vertical
Region.right: for vertical screen splits defined with OrientationLayout.vertical
Region.top: for horizontal screen splits defined with OrientationLayout.horizontal
Region.bottom: for horizontal screen splits defined with OrientationLayout.horizontal
Region.center: for any screen splits defines a central position. If element A is “center” and element B is “left”, element A’s will become, “right”.
split_1 = Split(
orientation=OrientationLayout.vertical, children=[papaya_1, papaya_2], button_label="Images"
)

Two papaya viewers in a vertical split. The button label is defined because this element goes into a Tab element. The tab’s “button_label” property is a label that will appear to select between different viewer elements in the QMENTA Platform.
Tab()
: Configure a layout with tabs to showcase different results. Buttons with labels allow users to select different tabs, and elements in each tab must have thebutton_label
parameter defined.
# Remember to add the button_label in the child objects of the tab.
tab_1 = Tab(children=[split_1, html_online])

Tabs appear as buttons on the QMENTA Platform, click on them to switch to the desired tab.
Add the tools to visualize files using the function add_visualization
. The different objects that can be included are:
PapayaViewer()
: Online 3D volume viewer to visualize DICOM or NIfTI files. Add as many layers as you want, they are going to be loaded in the order that you add them. You can use modality or tag of the output file to select the file to be shown in the viewer.
papaya_1 = PapayaViewer(title="Tissue segmentation over T1", width="50%", region=Region.center)
papaya_1.add_file(file="T1brain.nii.gz", coloring=Coloring.grayscale) # using the file name
papaya_1.add_file(file="tissueSegmentation.nii.gz", coloring=Coloring.custom)
# Add the papaya element as a visualization in the results configuration object.
result_conf.add_visualization(new_element=papaya_1)
papaya_2 = PapayaViewer(title="Labels segmentation over T1", width="50%", region=Region.right)
papaya_2.add_file(file="m'T1'", coloring=Coloring.grayscale) # using the file modality
papaya_2.add_file(file="t'seg'", coloring=Coloring.custom_random) # using file tag
# Add the papaya element as a visualization in the results configuration object.
result_conf.add_visualization(new_element=papaya_2)
To include an online HTML report, leverage the HtmlInject
class.
HtmlInject()
: HTML file will be presented in the QMENTA Platform for online reporting. Images used in this HTML must be uploaded into the output container and their paths defined in the HTML code must match the path in the output container.
html_online = HtmlInject(width="100%", region=Region.center, button_label="Report")
html_online.add_html(file="online_report.html")
# Add the html inject element as a visualization in the results configuration object.
result_conf.add_visualization(new_element=html_online)
To finish, the configuration file gets written using the following method.
# Call the function generate_results_configuration_file to create the final object that will be saved in the tool path
result_conf.generate_results_configuration_file(
build_screen=tab_1, tool_path=self.tool_path, testing_configuration=False
)
Please refer to the example in the generated tool.py
sample to see this example implemented.
Local Testing Guidelines
Local testing of your tool is a crucial step in the tool development
process. When launching the Tool Maker for the first time, an example is
generated, resulting in a local/test/
folder containing all necessary
components. To conduct local testing, follow these steps:
Populate the
local/test/sample_data/
folder with the required input data.Adapt the test input requirements to align with the defined
tools_input()
method in your tool.Utilize the
file_filter_condition_name
in theTestFileInput
objects to specify the file/s for input.
For example, if I have the following add_input_container(...)
definition:
self.add_input_container(
title="Morphology input files",
info="Requirements: T1 and T2 flair",
anchor=1,
batch=1,
container_id="input_morphology",
mandatory=1,
file_list=[
InputFile(
file_filter_condition_name="dicom_t1_condition",
filter_file=FilterFile(
modality=Modality.T1
regex=".*.zip",
),
mandatory=1,
min_files=1,
max_files=1,
),
InputFile(
file_filter_condition_name="dicom_t2_condition",
filter_file=FilterFile(
modality=Modality.T2,
tags=[Tag("flair"),
regex=".*.zip",
),
mandatory=1,
min_files=1,
max_files=1,
),
]
)
The definition of my TestFileInput
could be:
"input_morphology": {
"files":[
TestFileInput(
path="T1mprage.zip",
file_filter_condition_name="dicom_t1_condition",
mandatory=1
),
TestFileInput(
path="T2f.zip",
file_filter_condition_name="dicom_t2_condition",
mandatory=1
)
],
"mandatory": 1,
}
And the files T1mprage.zip and T2f.zip they should be stored in the
local/test/sample_data/
folder. To run the test, you can use pytest with
the following command:
pytest path_to_test_file::TestTool::test_basic_call
Test Folder Structure
The tool maker generates three folders within a folder named after your test (e.g., test_basic_call
):

The
input_folder/
is a simulation of the input container of the QMENTA Platform. The Tool Maker will structure the files specified in the estFileInput objects in folders named after their container id, in this caseinput_morphology
.The
execution_folder/
produces runtime files, copying files from the input_folder/ to simulate tool behavior.The
output_folder/
: local representation of the output container, saving files for upload as final results.
A file named settings.json is generated during local testing, capturing
the input definitions from the tools_input()
functions and processing
them into a JSON format.
Running the tools_outputs()
function, in addition to run()
, updates the
results configuration JSON of the tool.
Test in docker container
The docker container test can be launched after the local testing is
performed properly. The docker is going to be run locally in your
computer. By using the same test name (e.g. test_basic_call
) it will
utilize the same input folder and output folder as the local test to
perform it.
pytest path_to_test_file::TestToolDocker::test_basic_call
The DockerFile that is generated in the test/ folder will be used to run the docker.
You can confirm using the command $ docker images
that the image has
actually been created.

The notation for associating a local Docker image with a repository on a registry is: username/repository:tag. However, for clarity reasons, this documentation uses the following syntax to name images: username/tool_name:version
Before pushing the docker image to the docker repository, apply proper tagging to the docker image
`bash
docker tag tool_id:version docker_username/tool_id:version
`
Push the docker image to a docker registry, such as |Docker Hub|.
`bash
docker push docker_username/tool_id:version
`
Learn more about working with Docker |Docker documentation|.
Integrate your tool in the QMENTA Platform
You can integrate your new tool using the API or the QMENTA frontend. If you have generated the tool using the Tool Maker and tested it, you have all the files you need to integrate it into the QMENTA Platform using the following command from the SDK:
$ tool_publisher

This is the user interface to publish the tool. Provide the required
information and click on Publish
. The tool should be accessible now
through the frontend. You can also create/edit the tool using the
QMENTA Platform front-end, please refer to the SDK documentation
section.
Integrate your workflow in the QMENTA Platform
A workflow allows you to concatenate several tools to create a more complex tool. Here is an example of a workflow in the QMENTA Platform:
Workflow Development
The workflow is composed of multiple files that need to be manually created. For the workflow publisher to function correctly and automatically publish the workflow to the platform, these files must adhere to the specified naming conventions, otherwise the files will not be detected.
Settings (settings.json)
The information on how to write the settings can be found in the SDK documentation website: Parameters and Input Files — QMENTA SDK Build An example can be found here: settigs.json
Result Configuration (results_configuration.json)
All you need to know about writing the result configuration in the QMENTA Platform can be found in the SDK documentation page: Adding a tool to the QMENTA Platform — QMENTA SDK Build
Description (description.html)
The description file is an html file that contains the overall information about the tool. You can add your logo here as well. See the following example:
Model (model.flow)
Example of a model
start {
feed : [
"input_t1" => DICOM2NIFTIA("input"),
"input_t2" => DICOM2NIFTIB("input")
],
x:0,
y:50
}
end E {
x : 100,
y : 50
}
analysis DICOM2NIFTIA {
type: "qmenta_dicom2nifti:1.7",
qa: False,
output: [COMBINE("input_0")],
x: 25,
y: 75,
settings: {
input: "c_input((m'T2',t'flair'))"
}
}
analysis DICOM2NIFTIB {
type: "qmenta_dicom2nifti:1.7",
qa: False,
output: [COMBINE("input_1")],
x: 25,
y: 25,
settings: {
input: "c_input(m'T1')"
}
}
analysis COMBINE {
type : "qmenta_combine_containers:1.4",
qa : False,
output : [ FLAIR_STAR("input") ],
x : 50,
y : 50
}
analysis FLAIR_STAR {
type : "qmenta_flair_star:1.0",
qa : False,
output : [ E ],
x : 75,
y : 50,
parent_output: True,
settings: {
input: "(c_FLAIR((m'T2',t'flair')) AND c_EPI(m'T1'))"
}
}
How it will be seen in the QMENTA Platform:

Each part of the model node syntax explained:
analysis FLAIR_STAR {
type : "qmenta_flair_star:1.0",
qa : False,
output : [ E ],
x : 75,
y : 50,
parent_output: True,
settings: {
input: "(c_FLAIR((m'T2',t'flair')) AND c_EPI(m'T1'))"
}
}
analysis FLAIR_STAR: - This line indicates a new box in the workflow. - FLAIR_STAR is the node name that will appear in the workflow. - It is the reference ID (must be unique in the workflow) to reference the node.
type : “qmenta_flair_star:1.0”: - Here is the tool ID and the version that must match an existing box in the QMENTA Platform.
qa : False: - Boolean parameter to indicate if it is a QA step. - When the tool finishes successfully, the workflow will wait for the user to change the analysis QC status to PASS to resume the analysis. - If the QC status is marked as FAIL, the workflow will stop and be marked as Exception.
output : [ E ]: - This tells the workflow where the output container must be sent next. - In this case, it is the node E, which means it is the End of the workflow.
output: [COMBINE(“input_0”)]: - In this case, the output of the tool is sent to the node assigned with the ID COMBINE. - That node has a box with an input type of setting with an ID named input_0, which will receive the data and process it with the corresponding file filter.
x : 75, y : 50: - Coordinates relative to the other nodes that are used to create the workflow (as seen in the image above).
parent_output: True: - This value is only added in the last box that will run in the workflow. - Once this box finishes, the workflow will know it has reached the end. - One node must have this setting; otherwise, the workflow will never be marked as successfully completed.
settings: {input: “(c_FLAIR((m’T2’,t’flair’)) AND c_EPI(m’T1’))”}: - The settings of each box in each node can be overwritten. - In this case, the input setting with ID input is changed to accept other kinds of data than the default ones by the box. - Other parameters can be added in this dictionary, but they must match the setting parameters of the box in that node.
The start and the end node, work a little bit differently.
start {
feed : [
"input_t1" => DICOM2NIFTIA("input"),
"input_t2" => DICOM2NIFTIB("input")
],
x:0,
y:50
}
The start node has a feed field which describes the connectivity of its input to the first box. In this case, the workflow has 2 inputs and they are connected to different nodes. The first nodes have dicom to nifti tools, with input setting with id “input”.
end E {
x : 100,
y : 50
}
The node “E” only requires the coordinates where to place the node in the workflow of the QMENTA Platform.
Workflow publishing
You can integrate your new workflow using the API or the QMENTA frontend. If you have the required files for the workflow you can use this tool to integrate it into the QMENTA Platform using the following command from the SDK:
$ workflow_publisher

This is the user interface to publish the tool. Provide the required
information and click on Publish
. The tool should be accessible now
through the frontend. You can also create/edit the tool using the
QMENTA Platform front-end, please refer to the SDK documentation
section.