From 17bcff8503475c3fa66745c59730c7c831a163bb Mon Sep 17 00:00:00 2001 From: elliotfontaine Date: Fri, 19 Jul 2024 11:27:50 +0200 Subject: [PATCH 01/17] add empty pages and index for dev guide --- docs/source/development/add_config_option.rst | 8 ++++++++ docs/source/development/add_task.rst | 8 ++++++++ docs/source/development/coding_style.rst | 8 ++++++++ docs/source/development/index.rst | 20 +++++++++++++++++++ docs/source/development/workflow_design.rst | 8 ++++++++ docs/source/index.rst | 1 + 6 files changed, 53 insertions(+) create mode 100644 docs/source/development/add_config_option.rst create mode 100644 docs/source/development/add_task.rst create mode 100644 docs/source/development/coding_style.rst create mode 100644 docs/source/development/index.rst create mode 100644 docs/source/development/workflow_design.rst diff --git a/docs/source/development/add_config_option.rst b/docs/source/development/add_config_option.rst new file mode 100644 index 0000000..c77842a --- /dev/null +++ b/docs/source/development/add_config_option.rst @@ -0,0 +1,8 @@ +.. _development.add-config_option: + +==================================== +Adding an item to user configuration +==================================== + +.. attention:: + 🏗 Work in Progress 🏗 \ No newline at end of file diff --git a/docs/source/development/add_task.rst b/docs/source/development/add_task.rst new file mode 100644 index 0000000..a26088c --- /dev/null +++ b/docs/source/development/add_task.rst @@ -0,0 +1,8 @@ +.. _development.add-task: + +============================= +Adding a task to the workflow +============================= + +.. attention:: + 🏗 Work in Progress 🏗 \ No newline at end of file diff --git a/docs/source/development/coding_style.rst b/docs/source/development/coding_style.rst new file mode 100644 index 0000000..7e8f5b9 --- /dev/null +++ b/docs/source/development/coding_style.rst @@ -0,0 +1,8 @@ +.. _development.coding-style: + +========================================== +Coding Styles for Python, R, Bash and Cylc +========================================== + +.. attention:: + 🏗 Work in Progress 🏗 \ No newline at end of file diff --git a/docs/source/development/index.rst b/docs/source/development/index.rst new file mode 100644 index 0000000..bcaf80b --- /dev/null +++ b/docs/source/development/index.rst @@ -0,0 +1,20 @@ +.. _development: + +=========== +Development +=========== + +Here are discussed some of the choices made during the development of the project (coding styles for +different languages, pattern used in Cylc, etc). There are also some guidelines on how to add a new +task or a new configuration option to the workflow. + +.. toctree:: + :maxdepth: 2 + + workflow_design + coding_style + add_task + add_config_option + + + \ No newline at end of file diff --git a/docs/source/development/workflow_design.rst b/docs/source/development/workflow_design.rst new file mode 100644 index 0000000..10dbab1 --- /dev/null +++ b/docs/source/development/workflow_design.rst @@ -0,0 +1,8 @@ +.. _development.workflow-design: + +======================= +Workflow design choices +======================= + +.. attention:: + 🏗 Work in Progress 🏗 \ No newline at end of file diff --git a/docs/source/index.rst b/docs/source/index.rst index 6872053..161cd8a 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -57,6 +57,7 @@ If you want to use RTMet for real-time monitoring, there are a few additional re getting_started/index user_guide/index reference/index + development/index glossary contributing license From 6c057398e8c08c9ba4763eae5bb2aa12f982fcdc Mon Sep 17 00:00:00 2001 From: elliotfontaine Date: Fri, 19 Jul 2024 11:36:20 +0200 Subject: [PATCH 02/17] use `-base` versions of `cylc-flow` and `metomi-rose` for quicker build --- docs/requirements.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/requirements.txt b/docs/requirements.txt index 52e495c..476ea73 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,5 +1,5 @@ sphinx-rtd-theme==2.0.0 sphinx-design==0.6.0 -metomi-rose -cylc-flow +metomi-rose-base==8.3.0 +cylc-flow-base==2.3.0 cylc-sphinx-extensions From 615941eb60777009dfdf06473d36bf45a677dc93 Mon Sep 17 00:00:00 2001 From: elliotfontaine Date: Fri, 19 Jul 2024 11:39:44 +0200 Subject: [PATCH 03/17] fix version mix-up in `requirements.txt` --- docs/requirements.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/requirements.txt b/docs/requirements.txt index 476ea73..63b65de 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,5 +1,5 @@ sphinx-rtd-theme==2.0.0 sphinx-design==0.6.0 -metomi-rose-base==8.3.0 -cylc-flow-base==2.3.0 +cylc-flow-base==8.3.0 +metomi-rose-base==2.3.0 cylc-sphinx-extensions From fde48ca8a05ec605d31e9e88dfbb2882b8087ff5 Mon Sep 17 00:00:00 2001 From: elliotfontaine Date: Fri, 19 Jul 2024 11:47:59 +0200 Subject: [PATCH 04/17] undo: the `-base` versions of the packages actually don't exist on pipy --- docs/requirements.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/requirements.txt b/docs/requirements.txt index 63b65de..57c56f4 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,5 +1,5 @@ sphinx-rtd-theme==2.0.0 sphinx-design==0.6.0 -cylc-flow-base==8.3.0 -metomi-rose-base==2.3.0 +cylc-flow==8.3.0 +metomi-rose==2.3.0 cylc-sphinx-extensions From 901eb23882a85942770f7a4edecfadaf82398702 Mon Sep 17 00:00:00 2001 From: elliotfontaine Date: Fri, 19 Jul 2024 12:12:55 +0200 Subject: [PATCH 05/17] bullet points to discuss in design choices --- cylc-src/bioreactor-workflow/flow.cylc | 2 +- docs/source/development/workflow_design.rst | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/cylc-src/bioreactor-workflow/flow.cylc b/cylc-src/bioreactor-workflow/flow.cylc index 7c7ebe0..60e063e 100644 --- a/cylc-src/bioreactor-workflow/flow.cylc +++ b/cylc-src/bioreactor-workflow/flow.cylc @@ -8,7 +8,7 @@ URL = https://github.com/MetaboHUB-MetaToul-FluxoMet/RTMet # Create task families for conda environments. - %include 'envs/conda.cylc' +%include 'envs/conda.cylc' [scheduling] cycling mode = integer diff --git a/docs/source/development/workflow_design.rst b/docs/source/development/workflow_design.rst index 10dbab1..3a5d2aa 100644 --- a/docs/source/development/workflow_design.rst +++ b/docs/source/development/workflow_design.rst @@ -5,4 +5,19 @@ Workflow design choices ======================= .. attention:: - 🏗 Work in Progress 🏗 \ No newline at end of file + 🏗 Work in Progress 🏗 + +* Following Cylc's best practices +* Jinja2 templating +* Rose for configuration management +* Task inheritance to avoid code duplication +* Run setup is done at the first cyclepoint +* Tasks can run in specific conda environments +* `dataflow` and `qc` directories +* Data is stored in plain text `.csv` files +* Libraries/packages to be favored +* InfluxDB is an optional dependency + +Following Cylc's best practices +=============================== + From 2230cc2fcc1499a6895333006ca46cf9b469955a Mon Sep 17 00:00:00 2001 From: Elliot Fontaine <92150839+elliotfontaine@users.noreply.github.com> Date: Fri, 19 Jul 2024 13:30:08 +0200 Subject: [PATCH 06/17] use relative path for `rose-suite.conf` autodoc --- docs/source/reference/config_options.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/reference/config_options.rst b/docs/source/reference/config_options.rst index e6753a8..0318967 100644 --- a/docs/source/reference/config_options.rst +++ b/docs/source/reference/config_options.rst @@ -17,7 +17,7 @@ workflow directory. .. rose:file:: rose-suite.conf - .. autoconfig:: ../../cylc-src/bioreactor-workflow/rose-suite.conf + .. autoconfig:: cylc-src/bioreactor-workflow/rose-suite.conf Input Tables ============ From 278a11a4d4e593a45c30c0f3be0d9c0f44ebc861 Mon Sep 17 00:00:00 2001 From: Elliot Fontaine <92150839+elliotfontaine@users.noreply.github.com> Date: Fri, 19 Jul 2024 13:32:19 +0200 Subject: [PATCH 07/17] Revert "use relative path for `rose-suite.conf` autodoc" This reverts commit 2230cc2fcc1499a6895333006ca46cf9b469955a. --- docs/source/reference/config_options.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/reference/config_options.rst b/docs/source/reference/config_options.rst index 0318967..e6753a8 100644 --- a/docs/source/reference/config_options.rst +++ b/docs/source/reference/config_options.rst @@ -17,7 +17,7 @@ workflow directory. .. rose:file:: rose-suite.conf - .. autoconfig:: cylc-src/bioreactor-workflow/rose-suite.conf + .. autoconfig:: ../../cylc-src/bioreactor-workflow/rose-suite.conf Input Tables ============ From 28b9a4b0de27107ab29c6e7ea9489e15e38bea8b Mon Sep 17 00:00:00 2001 From: Elliot Fontaine <92150839+elliotfontaine@users.noreply.github.com> Date: Fri, 19 Jul 2024 16:24:02 +0200 Subject: [PATCH 08/17] improve task docstring and remove commented out code --- cylc-src/bioreactor-workflow/flow.cylc | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/cylc-src/bioreactor-workflow/flow.cylc b/cylc-src/bioreactor-workflow/flow.cylc index 60e063e..6843b95 100644 --- a/cylc-src/bioreactor-workflow/flow.cylc +++ b/cylc-src/bioreactor-workflow/flow.cylc @@ -35,10 +35,6 @@ annotate => upload_features quantify => upload_concentrations """ - # +P3/P1 = """ - # compute_fluxes => upload_fluxes - # compute_fluxes => upload_metadata - # """ {% endif %} [[queues]] [[[default]]] @@ -151,7 +147,8 @@ [[[meta]]] title = Trim Spectra description = """ - Remove the first and last `n_start` and `n_end` spectra from the mzML file. + Remove the first `n_start` and last `n_end` scans from the mzML file. This is useful + if the shape of the flowgram is not stable at the beginning or end of the run. """ categories = bioinformatics From 0cb1eab1d735658ae4ff8a8356b034020badcbec Mon Sep 17 00:00:00 2001 From: Elliot Fontaine <92150839+elliotfontaine@users.noreply.github.com> Date: Fri, 19 Jul 2024 16:24:25 +0200 Subject: [PATCH 09/17] use dracula theme for code blocks in docs --- docs/source/conf.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/source/conf.py b/docs/source/conf.py index 948c28d..8b85c16 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -46,6 +46,8 @@ "exec", ] +pygments_style = "dracula" # 🧛🏻‍♂️ + templates_path = ["_templates"] exclude_patterns = [] From acf329ed997d01fca046fe47decb632e6480bc32 Mon Sep 17 00:00:00 2001 From: Elliot Fontaine <92150839+elliotfontaine@users.noreply.github.com> Date: Fri, 19 Jul 2024 16:37:10 +0200 Subject: [PATCH 10/17] change index tree and refs (docs tree) --- docs/source/development/index.rst | 7 +++++++ .../getting_started/{tutorial.rst => basic_tutorial.rst} | 0 docs/source/getting_started/index.rst | 2 +- docs/source/reference/index.rst | 2 +- .../reference/{config_options.rst => user_config.rst} | 2 ++ 5 files changed, 11 insertions(+), 2 deletions(-) rename docs/source/getting_started/{tutorial.rst => basic_tutorial.rst} (100%) rename docs/source/reference/{config_options.rst => user_config.rst} (97%) diff --git a/docs/source/development/index.rst b/docs/source/development/index.rst index bcaf80b..8ec6fde 100644 --- a/docs/source/development/index.rst +++ b/docs/source/development/index.rst @@ -8,6 +8,13 @@ Here are discussed some of the choices made during the development of the projec different languages, pattern used in Cylc, etc). There are also some guidelines on how to add a new task or a new configuration option to the workflow. +.. note:: + It is assumed that you have a basic understanding of: + * Cylc, + * Python, R and Bash. + + For further information on Cylc, please consult their :ref:`cylc:user guide`. + .. toctree:: :maxdepth: 2 diff --git a/docs/source/getting_started/tutorial.rst b/docs/source/getting_started/basic_tutorial.rst similarity index 100% rename from docs/source/getting_started/tutorial.rst rename to docs/source/getting_started/basic_tutorial.rst diff --git a/docs/source/getting_started/index.rst b/docs/source/getting_started/index.rst index 2fe4380..302fb36 100644 --- a/docs/source/getting_started/index.rst +++ b/docs/source/getting_started/index.rst @@ -8,5 +8,5 @@ Getting Started :maxdepth: 2 installation - tutorial + basic_tutorial user_config \ No newline at end of file diff --git a/docs/source/reference/index.rst b/docs/source/reference/index.rst index f3691c4..7a4e34c 100644 --- a/docs/source/reference/index.rst +++ b/docs/source/reference/index.rst @@ -7,6 +7,6 @@ Reference .. toctree:: :maxdepth: 2 - config_options + user_config results data_processing \ No newline at end of file diff --git a/docs/source/reference/config_options.rst b/docs/source/reference/user_config.rst similarity index 97% rename from docs/source/reference/config_options.rst rename to docs/source/reference/user_config.rst index e6753a8..3fdeaff 100644 --- a/docs/source/reference/config_options.rst +++ b/docs/source/reference/user_config.rst @@ -1,3 +1,5 @@ +.. _reference.user-config: + =========================== Workflow User Configuration =========================== From ae0266738d2d0ae504fcc907cd9925999790b061 Mon Sep 17 00:00:00 2001 From: Elliot Fontaine <92150839+elliotfontaine@users.noreply.github.com> Date: Fri, 19 Jul 2024 16:39:49 +0200 Subject: [PATCH 11/17] explain design choices (jinja2, rose) --- docs/source/development/index.rst | 5 +- docs/source/development/workflow_design.rst | 98 +++++++++++++++++++++ docs/source/getting_started/user_config.rst | 2 +- 3 files changed, 102 insertions(+), 3 deletions(-) diff --git a/docs/source/development/index.rst b/docs/source/development/index.rst index 8ec6fde..1fdec00 100644 --- a/docs/source/development/index.rst +++ b/docs/source/development/index.rst @@ -5,8 +5,9 @@ Development =========== Here are discussed some of the choices made during the development of the project (coding styles for -different languages, pattern used in Cylc, etc). There are also some guidelines on how to add a new -task or a new configuration option to the workflow. +different languages, pattern used in Cylc, etc). + +You'll also find some guidelines on how to add a new task or configuration option to the workflow. .. note:: It is assumed that you have a basic understanding of: diff --git a/docs/source/development/workflow_design.rst b/docs/source/development/workflow_design.rst index 3a5d2aa..f2d10e9 100644 --- a/docs/source/development/workflow_design.rst +++ b/docs/source/development/workflow_design.rst @@ -21,3 +21,101 @@ Workflow design choices Following Cylc's best practices =============================== +Our workflow generally follows Cylc's :ref:`cylc:workflow design guide`. + +Some notable exceptions are: + * :ref:`cylc:self-contained workflows`: RTMet relies on a user-wide (or system-wide) conda + installation to handle most of its dependencies. This means they are vulnerable to external + changes. + * :ref:`cylc:workflow housekeeping`: Not implemented yet. + * :doc:`Automating Failure Recovery `: Not + implemented yet. + +Jinja2 templating +================= + +Jinja2 templating is used extensively in the workflow definition file, :file:`flow.cylc`. It allows +text to be generated dynamically, based on the values of variables passed to the template. + +Since the workflow source code contained in the :file:`flow.cylc` is basically text, Jinja2 templating +is a way for Cylc's devs to add logic without having to write a full-fledged programming language. + +User configuration options are passed down from the :rose:file:`rose-suite.conf` file to the workflow as +Jinja2 variables. Some of these variables are used for branching logic: + + +.. code-block:: jinja + :caption: Switching between input strategies + :emphasize-lines: 5-9 + + [scheduling] + cycling mode = integer + initial cycle point = 0 + [[xtriggers]] + {% if cfg__input_strategy == 'internal' %} + catch_raw = catch_raw_internal('%(point)s', '%(workflow_run_dir)s') + {% elif cfg__input_strategy == 'local' %} + catch_raw = catch_raw_local('%(point)s', '%(workflow_run_dir)s', {{ cfg__local_runs_dir }}) + {% endif %} + +Whole parts of the workflow can be enabled or disabled based on the value of a variable: + +.. code-block:: jinja + :caption: Enabling InfluxDB support + :emphasize-lines: 6-12 + + [scheduling] + [[graph]] + ... + R1/+P3 = quantify => compute_fluxes + +P4/P1 = quantify & compute_fluxes[-P1] => compute_fluxes + {% if cfg__toggle_influxdb %} + R1/^ = validate_cfg => create_bucket => is_setup + +P1/P1 = """ + annotate => upload_features + quantify => upload_concentrations + """ + {% endif %} + +Other Jinja2 variables are used to define environment variables for tasks: + +.. code-block:: jinja + :caption: Allowing the user to set the number of scans to trim + :emphasize-lines: 9-10 + + [runtime] + [[trim_spectra]] + inherit = None, CONDA_OPENMS + script = """ + trimms ${mzml} ${n_start} ${n_end} + """ + [[[environment]]] + mzml = ${MAIN_RESULTS_DIR}/${RAWFILE_STEM}.mzML + n_start = {{ cfg__trim_values[0] }} + n_end = {{ cfg__trim_values[1] }} + [[[meta]]] + title = Trim Spectra + description = """ + Remove the first `n_start` and last `n_end` scans from the mzML file. This is useful + if the shape of the flowgram is not stable at the beginning or end of the run. + """ + categories = bioinformatics + +.. seealso:: + :ref:`cylc:user guide jinja2` in Cylc's documentation. + +Rose for configuration management +================================= + +Rose is used for its :ref:`rose:rose suites` capabilities. It interfaces with our workflow using the +:ref:`cylc:cylc rose` plugin. + +Just think of it as workflow configuration being outsourced to another package, since Cylc doesn't +have it built-in (yet?) + +User configuration options are stored in the :rose:file:`rose-suite.conf` file at the root of the +workflow directory. They are passed down to the workflow as Jinja2 variables. + +.. seealso:: + * :ref:`tutorial.user-config` + * :ref:`reference.user-config` \ No newline at end of file diff --git a/docs/source/getting_started/user_config.rst b/docs/source/getting_started/user_config.rst index 280ff75..9c5cd15 100644 --- a/docs/source/getting_started/user_config.rst +++ b/docs/source/getting_started/user_config.rst @@ -26,7 +26,7 @@ Inside, you'll find :file:`rose-suite.conf`, which is a global configuration fil # ... Actually, you may find a tolerance of 10 ppm to be a bit too high. Open the file in a text editor, -and reduce the value to 1 ppm: +and reduce the value of :rose:conf:`rose-suite.conf[template variables]cfg__ppm_tol` to 1. .. code-block:: diff From 7a8aacbefe24e140eed8724a5c189ae88d9c31a1 Mon Sep 17 00:00:00 2001 From: Elliot Fontaine <92150839+elliotfontaine@users.noreply.github.com> Date: Mon, 22 Jul 2024 10:31:44 +0200 Subject: [PATCH 12/17] design choices explained --- cylc-src/bioreactor-workflow/flow.cylc | 2 +- docs/source/development/workflow_design.rst | 155 +++++++++++++++++--- 2 files changed, 138 insertions(+), 19 deletions(-) diff --git a/cylc-src/bioreactor-workflow/flow.cylc b/cylc-src/bioreactor-workflow/flow.cylc index 6843b95..7a48ee3 100644 --- a/cylc-src/bioreactor-workflow/flow.cylc +++ b/cylc-src/bioreactor-workflow/flow.cylc @@ -153,7 +153,7 @@ categories = bioinformatics [[get_timestamp]] - # Regex should be replaced with XML parsing. + # Regex could be replaced by pyOpenMS. script = """ RUN_TIMESTAMP=$(grep '*. This is both to avoid +conflicts with other environment variables and to make it clear that these are configuration items. .. seealso:: * :ref:`tutorial.user-config` - * :ref:`reference.user-config` \ No newline at end of file + * :ref:`reference.user-config` + +Task inheritance to avoid code duplication +========================================== + +Workflow tasks can inherit from other tasks, which mean script blocks (:strong:`[script]`, +:strong:`[pre-script]` and :strong:`[post-script]`) but also :strong:`[environment]` variables are taken +from the parent task. Our workflow uses this feature for: + +* Conda environment activation (see :ref:`below `) +* Sharing InfluxDB configuration (URL, token, organization, etc.) +* Format some of the intermediary tables in a :strong:`[post-script]` block (adding *datetime*, + *cycle* and *instrument_id* columns). + + +.. seealso:: + :ref:`cylc:sharing by inheritance` in Cylc's documentation. + +Run setup is done at the first cyclepoint +========================================= + +This include user configuration validation, input data validation, and other tasks that need to be +done before the main workflow starts: + +* :strong:`[validate_cfg]` +* :strong:`[validate_compounds_db]` +* :strong:`[validate_met_model]` (to be implemented) +* :strong:`[[INFLUXDB][create_bucket]]` + +Cyclepoint 0 is reserved for setup tasks. processing of .raw files starts at cyclepoint 1. + +.. _development.conda-envs: + +Tasks can run in specific conda environments +============================================ + +Conda environments activation is handled by a `pre-script`_. :file:`envs/conda.cylc` defines +family tasks, one for each conda environment: + +.. code-block:: cylc + :lineno-start: 10 + :caption: ``flow.cylc`` + + # Create task families for conda environments. + %include 'envs/conda.cylc' + +.. code-block:: jinja + :caption: ``conda.cylc`` + + {% set conda_envs = { + 'CONDA_TRFP': 'wf-trfp', + 'CONDA_BINNER': 'wf-binner', + 'CONDA_DATAMUNGING': 'wf-datamunging', + 'CONDA_INFLUX': 'wf-influx', + 'CONDA_OPENMS': 'wf-pyopenms', + } %} + + [runtime] + {% for env, conda_env_name in conda_envs.items() %} + [[{{env}}]] + pre-script = """ + set +eu + conda activate {{ conda_env_name }} + set -eu + """ + {% endfor %} + +Individual tasks in the workflow can then inherit from these families to run in the desired conda +environment: + +.. code-block:: cylc + :caption: ``flow.cylc`` + :emphasize-lines: 3 + + [runtime] + [[trim_spectra]] + inherit = None, CONDA_OPENMS + script = """ + trimms ${mzml} ${n_start} ${n_end} + """ + [[[environment]]] + mzml = ${MAIN_RESULTS_DIR}/${RAWFILE_STEM}.mzML + n_start = {{ cfg__trim_values[0] }} + n_end = {{ cfg__trim_values[1] }} + +.. warning:: + If you override the `pre-script`_ in a task while inheriting from a conda family task, you will + lose the conda environment activation. + +.. _pre-script: https://cylc.github.io/cylc-doc/8.3.0/html/reference/config/workflow.html#flow.cylc[runtime][%3Cnamespace%3E]pre-script + +:file:`dataflow/` and :file:`qc/` directories for results +========================================================= + +Our workflow follows the convention described in :ref:`cylc:shared task io paths`. In addition, +the :file:`share/cycle/{{n}}` directories are further divided into :file:`dataflow/` and :file:`qc/`. + +* :file:`dataflow/` contains the results of the main workflow tasks. It is used to pass data between + tasks. +* :file:`qc/` contains quality control results to be analyzed by the user: plots, statistics, etc. + +Data tables are stored in plain text CSV files +======================================================= + +Intermediary results in :file:`dataflow/` are stored in a delimiter-separated format, using semicolons +as separators. It allows for easy inspection and debugging, as well as compatibility with most +spreadsheet softwares. + +Furthermore, they can easily be edited using :command:`awk`/:command:`sed`/:command:`grep` +or :command:`csvkit` without the need to load them as dataframes in Python or R. + +Libraries/packages to be favored +================================ + +* Data wrangling: :bdg-link-success:`csvkit ` (CLI), + :bdg-link-success:`pandas ` (Python) and + :bdg-link-success:`tidyverse ` (R). +* Data validation: :bdg-link-success:`frictionless ` +* Editing/Querying mzML files: :bdg-link-success:`pyopenms ` + +InfluxDB is an optional dependency +================================== + +InfluxDB is used for real-time visualization of the results. It is not a strict requirement for the +workflow to run. It can be enabled by setting +:rose:file:`rose-suite.conf[template variables]cfg__toggle_influxdb` to :strong:`True`. + +Data is uploaded to InfluxDB using its Python API. :file:`influx_utils.py` contains functions to +convert our CSV files into the correct upload format. \ No newline at end of file From 4d4c8a3e3dcac6193516acdf5423b257ec6e8311 Mon Sep 17 00:00:00 2001 From: Elliot Fontaine <92150839+elliotfontaine@users.noreply.github.com> Date: Mon, 22 Jul 2024 14:32:55 +0200 Subject: [PATCH 13/17] write `adding task` tutorial for devs --- .../bioreactor-workflow/bin/get-instrument | 3 +- .../_static/graphs/added-task-graph.png | Bin 0 -> 113547 bytes docs/source/development/add_task.rst | 145 +++++++++++++++++- docs/source/development/workflow_design.rst | 4 +- 4 files changed, 147 insertions(+), 5 deletions(-) create mode 100644 docs/source/_static/graphs/added-task-graph.png diff --git a/cylc-src/bioreactor-workflow/bin/get-instrument b/cylc-src/bioreactor-workflow/bin/get-instrument index f286f32..b6a1a44 100755 --- a/cylc-src/bioreactor-workflow/bin/get-instrument +++ b/cylc-src/bioreactor-workflow/bin/get-instrument @@ -1,6 +1,7 @@ #!/usr/bin/env python -import os, sys +import os +import sys from pathlib import Path from pyopenms import MzMLFile, MSExperiment diff --git a/docs/source/_static/graphs/added-task-graph.png b/docs/source/_static/graphs/added-task-graph.png new file mode 100644 index 0000000000000000000000000000000000000000..99ac537f0c8cc005afadd89db50b8edc334235fe GIT binary patch literal 113547 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%0Ac@NiLk(5!?Tey>B>JXK46c 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 C)YfSL literal 0 HcmV?d00001 diff --git a/docs/source/development/add_task.rst b/docs/source/development/add_task.rst index a26088c..25661ea 100644 --- a/docs/source/development/add_task.rst +++ b/docs/source/development/add_task.rst @@ -4,5 +4,146 @@ Adding a task to the workflow ============================= -.. attention:: - 🏗 Work in Progress 🏗 \ No newline at end of file +In this tutorial, we will see how to add a new task to the workflow. We will use the example of a +task that extract the number of scans from a mzML file, using the pyOpenMS library. + +Adding a python script to the workflow executables +================================================== + +In :file:`cylc-src/bioreactor-workflow/bin/`, create a new file named :file:`get-scans-number` and +paste the following content: + +.. code-block:: python + :caption: :file:`bin/get-scans-number` + + #!/usr/bin/env python + + import os + import sys + from pathlib import Path + + from pyopenms import MzMLFile, MSExperiment + + MZML = os.getenv("mzml") + + + def main(): + """ + Usage: + ./get-instrument + + Get number of scans from mzML file. `$mzml` shell + environment variable must be set to the path of the file. + """ + exp = MSExperiment() + MzMLFile().load(MZML, exp) + sys.stdout.write(str(exp.getNrSpectra())) + + + if __name__ == "__main__": + if len(sys.argv) > 1: + sys.stderr.write(main.__doc__) + elif not MZML: + sys.stderr.write("$mzml environment variable not set.\n") + sys.exit() + elif not Path(MZML).exists(): + sys.stderr.write(f"mzML file not found: {MZML}\n") + sys.exit() + + main() + +Make the script executable: + +.. code-block:: console + + $ chmod +x get-scans-number + +Creating a new task in the [runtime] section +================================================ + +Open :file:`cylc-src/bioreactor-workflow/flow.cylc` and add the following task definition at the end: + +.. code-block:: cylc + :caption: :file:`flow.cylc` + :emphasize-lines: 3- + + [runtime] + # ... + [[get_scans_number]] + # The task will run in the wf-openms conda environment + # Adding None makes the task appear at the root in the TUI/GUI + inherit = None, CONDA_OPENMS + script = """ + echo "The script lauched by this task will extract the number of scans from the mzML file." + + get-scans-number > ${output_file} + + echo "The number of scans has been saved to ${output_file}" + echo "Number of scans: $(cat ${output_file})" + """ + [[[environment]]] + # The python script will use the $mzml environment + # variable to get the path of the file. + mzml = ${MAIN_RESULTS_DIR}/${RAWFILE_STEM}.mzML + output_file = ${MAIN_RESULTS_DIR}/scans_number.txt + +This task will run the :file:`get-scans-number` script and save the output to a file named +:file:`scans_number.txt` in the main results directory. This directory +(:file:`share/cycle/n/dataflow/`) is specific to each cyclepoint ``n``. + +Adding the task to the graph +============================ + +Add a new graph string to the :strong:`+P1/P1` recurrence, inside the :strong:`[graph]` section +of the workflow definition: + +.. code-block:: cylc + :caption: :file:`flow.cylc` + :emphasize-lines: 8 + + [[graph]] + R1/^ = validate_cfg => validate_compounds_db & validate_met_model => is_setup + R1/+P1 = convert_raw => get_instrument => extract_features + +P1/P1 = """ + is_setup[^] => _catch_raw + @catch_raw => _catch_raw => convert_raw => get_timestamp & + trim_spectra => extract_features => annotate => quantify + convert_raw => get_scans_number + """ + +The task will be executed for each cyclepoint (/P1) starting from the second one (+P1). It will run after the +:strong:`convert_raw` task as it depends on the mzML file generated by it. No other task depends on +the one we just added. + +You can check that the task has been added correctly by running: + +.. code-block:: console + + $ cylc graph bioreactor-workflow 0 1 + +.. figure:: /_static/graphs/added-task-graph.png + :alt: Graph with the new task added + :scale: 50% + :align: center + +Testing the new task +==================== + +Install and start a new run of the workflow, and add a mzML file to the :file:`raws/` directory. The task should +start immediately after the :strong:`convert_raw` task and generate a :file:`scans_number.txt` file +in the :file:`cylc-run/your_run_name/share/cycle/1/dataflow/` directory. + +.. code-block:: output + :caption: :file:`job.out` in logs + + Workflow : bioreactor-workflow/task-added + Job : 1/get_scans_number/01 (try 1) + User@Host: elliotfontaine@MBP-Elliot.local + + 2024-07-22T14:18:50+02:00 INFO - started + The script lauched by this task will extract the number of scans from the mzML file. + The number of scans has been saved to /Users/elliotfontaine/cylc-run/bioreactor-workflow/task-added/share/cycle/1/dataflow/scans_number.txt + Number of scans: 35 + 2024-07-22T14:18:52+02:00 INFO - succeeded + + diff --git a/docs/source/development/workflow_design.rst b/docs/source/development/workflow_design.rst index da1541a..9981ad7 100644 --- a/docs/source/development/workflow_design.rst +++ b/docs/source/development/workflow_design.rst @@ -223,7 +223,7 @@ or :command:`csvkit` without the need to load them as dataframes in Python or R. Libraries/packages to be favored ================================ -* Data wrangling: :bdg-link-success:`csvkit ` (CLI), +* Data wrangling: :bdg-link-success:`csvtk ` (CLI), :bdg-link-success:`pandas ` (Python) and :bdg-link-success:`tidyverse ` (R). * Data validation: :bdg-link-success:`frictionless ` @@ -234,7 +234,7 @@ InfluxDB is an optional dependency InfluxDB is used for real-time visualization of the results. It is not a strict requirement for the workflow to run. It can be enabled by setting -:rose:file:`rose-suite.conf[template variables]cfg__toggle_influxdb` to :strong:`True`. +:rose:conf:`rose-suite.conf[template variables]cfg__toggle_influxdb` to :strong:`True`. Data is uploaded to InfluxDB using its Python API. :file:`influx_utils.py` contains functions to convert our CSV files into the correct upload format. \ No newline at end of file From 463d5ebea015ab0b08ed8fcc8c617bdfd3e64497 Mon Sep 17 00:00:00 2001 From: Elliot Fontaine <92150839+elliotfontaine@users.noreply.github.com> Date: Mon, 22 Jul 2024 15:02:23 +0200 Subject: [PATCH 14/17] write `adding cfg option` tutorial for devs --- docs/source/development/add_config_option.rst | 56 ++++++++++++++++++- docs/source/development/add_task.rst | 2 +- 2 files changed, 55 insertions(+), 3 deletions(-) diff --git a/docs/source/development/add_config_option.rst b/docs/source/development/add_config_option.rst index c77842a..5f9d141 100644 --- a/docs/source/development/add_config_option.rst +++ b/docs/source/development/add_config_option.rst @@ -4,5 +4,57 @@ Adding an item to user configuration ==================================== -.. attention:: - 🏗 Work in Progress 🏗 \ No newline at end of file +.. note:: + Prerequisites: + * :ref:`tutorial.user-config` + * :ref:`reference.user-config` + * :ref:`development.add-task` + +Write a new item in :rose:file:`rose-suite.conf` +================================================ + +ThermoRawFileParser can output the metadata in text or json format. Right now, the workflow only +outputs metadata in json. We can give the user the option to choose between the two formats. + +At the end of the :strong:`[template variables]` section, add the following line: + +.. code-block:: ini + :caption: :file:`rose-suite.conf` + + # ... + cfg__raw_meta_format = txt + +Use the template variable in the workflow definition +==================================================== + +In the :strong:`[validate_cfg]` task, change the :strong:`metadata` environment variable to: + +.. code-block:: jinja + :caption: :file:`flow.cylc` + + [runtime] + [[convert_raw]] + [[[environment]]] + - metadata = json + + metadata = {{ cfg__raw_meta_format }} + +During run installation, the value will now be replaced by the one set in :rose:file:`rose-suite.conf`. +If you want to change the value at runtime, you can follow the instructions in :ref:`tutorial.user-config`. + +Adding validation for the new configuration item +================================================ + +Rose (the configuration manager) allows us to validate the user configuration. It is done at runtime +at cyclepoint 0 with the :strong:`[validate_cfg]` task. Let's add a new validation rule for our item. +Locate the :file:`meta/rose-meta.conf` file in the workflow source directory, and add the following: + +.. code-block:: ini + + [template variables=cfg__raw_meta_format] + compulsory=true + type=character + values='json', 'txt' + +The :strong:`[validate_cfg]` will now check that the value of :strong:`cfg__raw_meta_format` is +either 'json' or 'txt', and that the item is indeed present. + diff --git a/docs/source/development/add_task.rst b/docs/source/development/add_task.rst index 25661ea..43d3d76 100644 --- a/docs/source/development/add_task.rst +++ b/docs/source/development/add_task.rst @@ -30,7 +30,7 @@ paste the following content: def main(): """ Usage: - ./get-instrument + ./get-scans-number Get number of scans from mzML file. `$mzml` shell environment variable must be set to the path of the file. From 3c07e2d4d68188611fe65fdbf8accb66997481ba Mon Sep 17 00:00:00 2001 From: Elliot Fontaine <92150839+elliotfontaine@users.noreply.github.com> Date: Mon, 22 Jul 2024 15:42:06 +0200 Subject: [PATCH 15/17] write `coding style` guidelines --- docs/source/development/coding_style.rst | 74 +++++++++++++++++++++++- docs/source/substitutions.rst.include | 4 ++ 2 files changed, 75 insertions(+), 3 deletions(-) diff --git a/docs/source/development/coding_style.rst b/docs/source/development/coding_style.rst index 7e8f5b9..9ae4105 100644 --- a/docs/source/development/coding_style.rst +++ b/docs/source/development/coding_style.rst @@ -1,8 +1,76 @@ .. _development.coding-style: ========================================== -Coding Styles for Python, R, Bash and Cylc +Coding styles for Python, R, Bash and Cylc ========================================== -.. attention:: - 🏗 Work in Progress 🏗 \ No newline at end of file +Scripts: environment variables or command line arguments? +========================================================= + +When writing scripts (Python, R, Bash) for the workflow, you have the choice between loading +environment variables from inside the script, or parsing command line arguments. + +On a rule of thumb, use environment variables when you don't expect the script to be reused outside +the workflow, and command line arguments when you want to make the script more portable. + +Python +====== + +Python code should follow the `PEP 8`_ style guide. The `Black`_ code formatter should be used to +automatically format the code. + +You should also use a linter / static code analyser like `Pylint`_ to catch potential bugs, commented +out code, code smells, etc. + +R += +[TODO] + +Bash +==== +[TODO] + +Cylc +==== + +In general, follow Cylc :doc:`cylc:workflow-design-guide/style-guide`. When creating tasks, +set the :strong:`[meta]` title and description fields to describe what the task does. You can also +add custom field like :strong:`categories` if you want. + +Use uppercase for: + * family tasks (notably the conda ones, e.g. :strong:`CONDA_OPENMS`), + * global environment variables set in :strong:`[runtime][root]` and broadcasted ones (e.g. + :strong:`RAWFILE_STEM`). + +Use lowercase for: + * local environment variables set in :strong:`[environment]` blocks inside tasks. + * task names. + +Add :strong:`None` before the name of inherited family tasks to make the task in question appear at +the root when using the TUI or GUI. Otherwise, the task will be nested under the family task. The +exception are InfluxDB tasks, which are always nested under the :strong:`INFLUXDB` family task. + + +When using global environment variables or Jinja2 template variables to build CLI arguments, +do it in the :strong:`[environment]` block of the task, not in the script itself: + +.. code-block:: cylc + :caption: :file:`flow.cylc` + :emphasize-lines: 4, 7-9 + + [[trim_spectra]] + inherit = None, CONDA_OPENMS + script = """ + trimms ${mzml} ${n_start} ${n_end} + """ + [[[environment]]] + mzml = ${MAIN_RESULTS_DIR}/${RAWFILE_STEM}.mzML + n_start = {{ cfg__trim_values[0] }} + n_end = {{ cfg__trim_values[1] }} + [[[meta]]] + title = Trim Spectra + description = """ + Remove the first `n_start` and last `n_end` scans from the mzML file. This is useful + if the shape of the flowgram is not stable at the beginning or end of the run. + """ + categories = bioinformatics diff --git a/docs/source/substitutions.rst.include b/docs/source/substitutions.rst.include index 45a2f39..6a4aaf1 100644 --- a/docs/source/substitutions.rst.include +++ b/docs/source/substitutions.rst.include @@ -6,6 +6,10 @@ .. _Cylc Workflow Design Guide: https://cylc.github.io/cylc-doc/latest/html/workflow-design-guide/index.html .. _Cylc: https://cylc.github.io/ .. _fia: https://en.wikipedia.org/wiki/Flow_injection_analysis +.. _PEP 8: https://peps.python.org/pep-0008/ +.. _Black: https://black.readthedocs.io/en/stable/ +.. _Pylint: https://pylint.pycqa.org/en/latest/ + .. Substitutions From 76ac235efc584a1453bce9274c75b4d1d7075f6f Mon Sep 17 00:00:00 2001 From: Elliot Fontaine <92150839+elliotfontaine@users.noreply.github.com> Date: Mon, 22 Jul 2024 15:52:51 +0200 Subject: [PATCH 16/17] make this part more clear --- docs/source/development/coding_style.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/source/development/coding_style.rst b/docs/source/development/coding_style.rst index 9ae4105..2e1933b 100644 --- a/docs/source/development/coding_style.rst +++ b/docs/source/development/coding_style.rst @@ -4,14 +4,15 @@ Coding styles for Python, R, Bash and Cylc ========================================== -Scripts: environment variables or command line arguments? -========================================================= +:file:`bin/` scripts: environment variables or command line arguments? +====================================================================== When writing scripts (Python, R, Bash) for the workflow, you have the choice between loading environment variables from inside the script, or parsing command line arguments. On a rule of thumb, use environment variables when you don't expect the script to be reused outside -the workflow, and command line arguments when you want to make the script more portable. +the workflow, and command line arguments with strong input validation when you want to make the script +more portable. Python ====== From ad8e43e57e84c848b2e1e7d1c8c4688ff6810004 Mon Sep 17 00:00:00 2001 From: Elliot Fontaine <92150839+elliotfontaine@users.noreply.github.com> Date: Mon, 22 Jul 2024 16:03:45 +0200 Subject: [PATCH 17/17] clean up docs --- docs/source/development/add_config_option.rst | 4 +- docs/source/development/coding_style.rst | 42 +++++++++---------- docs/source/substitutions.rst.include | 3 -- 3 files changed, 23 insertions(+), 26 deletions(-) diff --git a/docs/source/development/add_config_option.rst b/docs/source/development/add_config_option.rst index 5f9d141..bb92d52 100644 --- a/docs/source/development/add_config_option.rst +++ b/docs/source/development/add_config_option.rst @@ -41,8 +41,8 @@ In the :strong:`[validate_cfg]` task, change the :strong:`metadata` environment During run installation, the value will now be replaced by the one set in :rose:file:`rose-suite.conf`. If you want to change the value at runtime, you can follow the instructions in :ref:`tutorial.user-config`. -Adding validation for the new configuration item -================================================ +Validate the new configuration item +=================================== Rose (the configuration manager) allows us to validate the user configuration. It is done at runtime at cyclepoint 0 with the :strong:`[validate_cfg]` task. Let's add a new validation rule for our item. diff --git a/docs/source/development/coding_style.rst b/docs/source/development/coding_style.rst index 2e1933b..324197b 100644 --- a/docs/source/development/coding_style.rst +++ b/docs/source/development/coding_style.rst @@ -1,8 +1,8 @@ .. _development.coding-style: -========================================== -Coding styles for Python, R, Bash and Cylc -========================================== +============ +Coding style +============ :file:`bin/` scripts: environment variables or command line arguments? ====================================================================== @@ -10,27 +10,10 @@ Coding styles for Python, R, Bash and Cylc When writing scripts (Python, R, Bash) for the workflow, you have the choice between loading environment variables from inside the script, or parsing command line arguments. -On a rule of thumb, use environment variables when you don't expect the script to be reused outside +As a rule of thumb, use environment variables when you don't expect the script to be reused outside the workflow, and command line arguments with strong input validation when you want to make the script more portable. -Python -====== - -Python code should follow the `PEP 8`_ style guide. The `Black`_ code formatter should be used to -automatically format the code. - -You should also use a linter / static code analyser like `Pylint`_ to catch potential bugs, commented -out code, code smells, etc. - -R -= -[TODO] - -Bash -==== -[TODO] - Cylc ==== @@ -75,3 +58,20 @@ do it in the :strong:`[environment]` block of the task, not in the script itself if the shape of the flowgram is not stable at the beginning or end of the run. """ categories = bioinformatics + +Python +====== + +Python code should follow the `PEP 8`_ style guide. The `Black`_ code formatter should be used to +automatically format the code. + +You should also use a linter / static code analyser like `Pylint`_ to catch potential bugs, commented +out code, code smells, etc. + +Bash +==== +[TODO] + +R += +[TODO] diff --git a/docs/source/substitutions.rst.include b/docs/source/substitutions.rst.include index 6a4aaf1..742a675 100644 --- a/docs/source/substitutions.rst.include +++ b/docs/source/substitutions.rst.include @@ -2,15 +2,12 @@ .. Hyperlinks -.. _Cylc User Guide: https://cylc.github.io/cylc-doc/latest/html/index.html -.. _Cylc Workflow Design Guide: https://cylc.github.io/cylc-doc/latest/html/workflow-design-guide/index.html .. _Cylc: https://cylc.github.io/ .. _fia: https://en.wikipedia.org/wiki/Flow_injection_analysis .. _PEP 8: https://peps.python.org/pep-0008/ .. _Black: https://black.readthedocs.io/en/stable/ .. _Pylint: https://pylint.pycqa.org/en/latest/ - .. Substitutions