Workflow App
============
Setup
-----
To use the workflow app, first install the Lung Modelling package. See :ref:`installation`
for instructions.
Once the package is installed, initialize a user-editable configuration by running:
.. code-block:: shell
python -m lung_modelling initialize_user_config=True
This should create a folder named user_config in your working directory. The user
config folder contains .yaml files will all the editable configuration parameters
for the existing workflow tasks. See the `Hydra documentation `_
for detailed information on how this works.
Running Example Workflow
------------------------
To test the package on example data, first download the `example data file `_
and unzip it:
.. code-block::
tar -xf covid_lung_segmentation.zip
Run the batch workflow with the example settings:
.. code-block::
python -m lung_modelling user_config=example_workflow
This will bring up a file select dialog. Select the folder covid_lung_lobe_segmentation. The example workflow will
run, producing a shapeworks project in the pooled_derivative -> optimize_meshes_sw folder.
Dataset Configuration
---------------------
To run the workflow app on your own dataset, your dataset must be structured in a specific way (following the SPARC data
structure). It must also contain a file called dataset_config.json, explained below. An example of the structure is as
follows:
.. code-block::
dataset_name/
|--- dataset_config.json
|--- primary
| |--- subject_directory_1
| |--- subject_data.nii
|--- derivative
| |--- subject_directory_1
| |--- raw_mesh
| |--- lobe_1.stl
A top level directory with the dataset name has sub directories primary and
derivative. Initial data is stored in the primary directory, separated into
individual subject directories. Generated data is placed in the derivative
directory, with a structure mirroring that of the primary. Any number of sub
directories can exist before the data files.
The dataset structure along with information about the files contained in the
dataset must be specified in a file named dataset_config.json. An example of this is shown below:
.. code-block:: json
{
"primary_directory": "primary",
"derivative_directory": "derivative",
"pooled_primary_directory": "pooled_primary",
"pooled_derivative_directory": "pooled_derivative",
"directory_index_glob": "directory_index*.csv",
"data_folder_depth": 2,
"subject_id_folder_depth": 2,
"lung_image_glob": "*.nii",
"lobe_mapping": {"rul": 3, "rml": 4, "rll": 5, "lul": 1,
"lll": 2}
}
In the above example, the first 6 items are generic and the final 3 are dataset specific, which can
be added as necessary and accessed by the workflow tasks.
**primary_directory** refers to the name of the directory holding the primary
data in the dataset.
**derivative_directory** refers to the name of the directory in which to place
generated data.
**pooled_primary_directory** refers to the name of the directory holding primary data files which contain
data on two or more subjects from the dataset (e.g., a subject demographic data dictionary)
**pooled_derivative_directory** refers to the name of the directory in which to place
data generated from two or more subjects combined into a single output file.
**directory_index_glob** refers to a glob used to find a pre-built directory
index of the dataset if it exists.
**data_folder_depth** is the number of folders between the top level dataset
folder and the data files. (e.g., the dataset structure may be: primary -> subject_id -> study_phase -> imaging_mode,
with data residing in the imaging mode folder, a depth of 4)
**subject_id_folder_depth** is the number of folders between the top level dataset
folder and a folder with a name that can be used as a unique identifier for a single
subject
**lung_image_glob** refers to a glob used to find lung image data files
**lobe_mapping** specifies the value used to indicate each lung lobe in the
lung lobe image files.
Workflow Configuration
----------------------
A workflow is specified using a workflow configuration file in yaml format. This file is selected when running the
run_workflow app by placing it in the user_config directory and setting the user_config parameter from the command line
(see run example workflow).
This file specifies both the tasks which will make up the workflow and all the settings or parameters that each task
requires.
There are three main sections to the workflow configuration file: The general settings, the tasks list, and the
run_tasks list.
Below is an example of a workflow configuration file.
.. code-block:: yaml
dataset_root: null
log_level: "INFO"
use_multiprocessing: False
tasks:
initialize:
dataset_config_filename: "dataset_config.json"
use_directory_index: False
skip_dirs: [ ]
select_dirs: [ ]
extract_whole_lungs_sw:
task: "ExtractWholeLungsSW"
results_directory: "extract_whole_lungs_sw"
output_filenames: { left_lung: [ "lul", "lll" ], right_lung: [ "rul", "rml", "rll" ] }
params: { maximumRMSError: 0.009999999776482582, numberOfIterations: 30 }
create_meshes_sw:
task: "CreateMeshesSW"
source_directory: "extract_whole_lungs_sw"
results_directory: "create_meshes_whole_lungs_sw"
image_glob: "*.nii"
params: {
pad: True,
step_size: 1,
decimate: True,
decimate_target_faces: 100000,
subdivide_passes: 0,
volume_preservation: True,
remesh: True,
remesh_target_points: 40000,
adaptivity: 0,
smooth: True,
smooth_iterations: 10,
relaxation: 1,
fill_holes: True,
hole_size: 100,
remove_shared_faces: True,
isolate_mesh: True }
reference_selection_mesh_sw:
task: "ReferenceSelectionMeshSW"
source_directory: "create_meshes_whole_lungs_sw"
results_directory: "reference_selection_mesh_whole_lungs_sw"
mesh_transform_sw:
task: "MeshTransformSW"
source_directory_initialize: "reference_selection_mesh_whole_lungs_sw"
source_directories: ["create_meshes_whole_lungs_sw"]
results_directory: "mesh_transform_sw"
params: { iterations: 100 }
mesh_landmarks_lungs:
task: "MeshLandmarksCoarse"
source_directory: "create_meshes_whole_lungs_sw"
results_directory: "mesh_landmarks_coarse_lungs"
params: { }
optimize_meshes_sw:
task: "OptimizeMeshesSW"
source_directory_transform: "mesh_transform_sw"
source_directories_mesh: [ "create_meshes_whole_lungs_sw" ]
source_directories_original: [ "extract_whole_lungs_sw"]
source_directories_landmarks: [ "mesh_landmarks_coarse_lungs" ]
image_globs: [ "*.nii"]
results_directory: "optimize_meshes_sw"
params: {
checkpointing_interval: 200,
keep_checkpoints: 0,
iterations_per_split: 2000,
optimization_iterations: 2000,
starting_regularization: 2000,
ending_regularization: 100,
relative_weighting: 4,
initial_relative_weighting: 0.03,
save_init_splits: 0,
verbosity: 0,
use_normals: 1,
normals_strength: 10.0,
procrustes: 0,
procrustes_scaling: 1,
procrustes_rotation_translation: 1,
number_of_particles: [ 128, 128],
use_geodesic_distance: 0,
use_landmarks: 1
}
logging:
run_tasks: [ "smooth_whole_lungs_sw", "create_meshes_sw", "reference_selection_mesh_sw", "mesh_transform_sw",
"mesh_landmarks_lungs", "optimize_meshes_sw" ]
**datset_root**: Root directory for the dataset on which to run the workflow. If set to null a directory select dialog
will be created. This can also be overwritten from the command line (e.g., user_config.dataset_root="C:/path/to/dataset").
**log_level**: Log level for loguru logs
**use_multiprocessing**: Flag to turn on or off the use of multiprocessing to run EachItemTask tasks in parallel
**tasks**: A list of yaml dictionaries specifying the configuration for tasks to be included in the workflow. The key of
each dictionary entry can be any string, and is used to refer to the task config in the run_tasks list. The "task"
element must refer to the class name of a class implementing EachItemTask or AllItemsTask. The remaining elements refer
to the input parameters of each task. (The sub dictionary params can be used to group parameters that effect the core
functioning of the task, but this is not enforced).
**run_tasks**: A list of tasks specified by the task labels in the tasks dictionary. This specifies which tasks will be
run and in which order. (initialize is always run first, and logging is always run last in the workflow. They do not
need the "task" name element.
Workflow Run Logs
-----------------
A completed workflow run is saved in the dataset_root->logging directory.
This includes the workflow configuration file and a list of all installed python packages with version numbers.
The lung_modelling package uses setuptools-scm to provide up to date version numbers.
If the package is installed from github or run unedited from a cloned github repository, the version number will allow
identification of which commit was used during the logged run.
------------------------------------------------------------------------------------------------------------------------
App Dataflow Diagrams
---------------------
The following diagrams illustrate the main functions of the workflow app and workflow manager.
Initialization
**************
When the workflow app is run, a workflow manager class is instantiated, and the initialization task is run. This takes
information from the workflow configuration file to build a list of directories that the tasks will make use of.
.. image:: _static/initialization_no_title.png
:class: rst-image
Task Registration
*****************
The tasks specified in the workflow configuration file are found in the task library, and instantiated using the
specified parameters.
.. image:: _static/task_registration_no_title.png
:class: rst-image
Running Parallel Tasks
**********************
If multiprocessing is enabled, tasks which only need access to one directory (those implementing the each_item_task
interface) can be dispatched to parallel processes. The work methods of these tasks are wrapped in an exception monitor
decorator so that any exceptions can be reported to the parent process.
.. image:: _static/running_parallel_tasks_no_title.png
:class: rst-image
Running Non-Parallel Tasks
**************************
Tasks which need access to all directories (all_items_tasks) have their work functions run. These are also done in a
try/catch block so errors can be logged.
.. image:: _static/running_non_parallel_tasks_no_title.png
:class: rst-image