Skip to content

Commit

Permalink
Feature #2772 Apptainer documentation (#2783)
Browse files Browse the repository at this point in the history
* update version of action to latest

* per #2772, added instructions to run a METplus use case using Apptainer

* Apply suggestions from code review

Co-authored-by: Dan Adriaansen <dadriaan@ucar.edu>

* bugfix dtcenter/MET#2899 prevents differences in output from use case, so removing the 'disabled' item to run use case in GHA

* hotfix: remove quotes around input files because logic that obtains python embedding commands as input file arguments handles quotes

* fix tests to match new expected commands

---------

Co-authored-by: Dan Adriaansen <dadriaan@ucar.edu>
  • Loading branch information
georgemccabe and DanielAdriaansen authored Nov 13, 2024
1 parent dbff73d commit 5fadd22
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 12 deletions.
1 change: 0 additions & 1 deletion .github/parm/use_case_groups.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@
{
"category": "land_surface",
"index_list": "0",
"disabled": true,
"run": false
},
{
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/update_input_data.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
- run: |
branch_name=$(echo ${{ github.event.inputs.branch || github.ref }} | cut -d/ -f3)
echo "branch_name=$branch_name" >> "$GITHUB_ENV"
- uses: dtcenter/metplus-action-data-update@v2
- uses: dtcenter/metplus-action-data-update@v3
with:
docker_name: ${{ secrets.DOCKER_USERNAME }}
docker_pass: ${{ secrets.DOCKER_PASSWORD }}
Expand Down
83 changes: 80 additions & 3 deletions docs/Users_Guide/getting_started.rst
Original file line number Diff line number Diff line change
Expand Up @@ -377,11 +377,13 @@ the path to the METplus log file that was generated.
* Review the :ref:`metplus_final.conf<metplus_final_conf>` file to see all
of the settings that were used in the use case.

Containers
==========

.. _metplus-docker:

METplus in Docker
=================
-----------------

METplus is available on DockerHub. The METplus Docker image includes all of
the MET executables from the corresponding METplus Coordinated Release and
Expand All @@ -400,7 +402,7 @@ on DockerHub.
.. _docker-sample-input:

Sample Input Data
-----------------
^^^^^^^^^^^^^^^^^

Sample input data for all of the use cases provided with the METplus wrappers
are also available on DockerHub. These data are found in the
Expand All @@ -426,7 +428,7 @@ The input data will be available inside the container under
/data/input/METplus_Data.

Running METplus in Docker
-------------------------
^^^^^^^^^^^^^^^^^^^^^^^^^

The run_metplus.py script is in the user's path inside the container.
The use case configuration files can be found under
Expand All @@ -451,3 +453,78 @@ the corresponding category can be run::
Please note that use cases that have additional Python package dependencies
may not run successfully unless those packages are installed inside the
container or obtained elsewhere.


.. _metplus-apptainer:

METplus in Apptainer
--------------------

Apptainer (formerly Singularity) can also be used to run METplus.
Images can be pulled from DockerHub using Apptainer commands.

If running on the NCAR Casper cluster, be sure to first load the Apptainer module via::

module load apptainer

Navigate to a working directory and pull an image from DockerHub, e.g.::

apptainer pull docker://dtcenter/metplus:5.1-latest

This will create a *.sif* file in the current directory,
e.g. **metplus_5.1-latest.sif**.

See :ref:`metplus-docker` for information about available images on DockerHub.

.. _apptainer-sample-input:

Sample Input Data
^^^^^^^^^^^^^^^^^

The Docker data volumes that contain sample input data provided on DockerHub are
not compatible with Apptainer. Therefore, sample input data must be obtained from from the METplus Data website.
Navigate to the `METplus Data <https://dtcenter.ucar.edu/dfiles/code/METplus/METplus_Data>`_
website. Next, navigate to the directory that corresponds to the vX.Y version that
will be run, e.g. `v5.1 <https://dtcenter.ucar.edu/dfiles/code/METplus/METplus_Data/v5.1>`_
The names of sample data tar files include the corresponding use case category.

Download one or more of the sample data tar files and uncompress them into
a local directory. The directory that contains the uncompressed sample data
will need to be mounted to the container to make the data available inside it.

The **APPTAINER_BIND** environment variable can be used to mount directories to
the container. The local directory and the container directory will be separated
by a colon (:).

Mount the local directory (./input_data in this example) to the
/data/input/METplus_Data directory inside the container::

export APPTAINER_BIND="./input_data:/data/input/METplus_Data"


Running METplus in Apptainer
^^^^^^^^^^^^^^^^^^^^^^^^^^^^

The METplus wrappers inside the container come pre-configured so that
:ref:`sys_conf_input_base` is set to /data/input/METplus_Data.
Mounting the local data directory to this path will allow the use cases
to be run without the need to modify the default configuration.

The :ref:`sys_conf_output_base` value is set to /data/output by default.
This directory can also be mounted to a local directory so the output from
a use case run can be accessed locally. Multiple directory mounts can be specified
by separating them by comma::

export APPTAINER_BIND="./input_data:/data/input/METplus_Data,./output_data:/data/output"

In this example, the directory **./output_data** will be populated with the
output from the use case.

To run a use case, run the **apptainer exec** command with the **.sif**
file that was created by the **apptainer pull** command and the call to the
**run_metplus.py** script as arguments::

apptainer exec metplus_5.1-latest.sif /metplus/METplus/ush/run_metplus.py /metplus/METplus/parm/use_cases/met_tool_wrapper/GridStat/GridStat.conf

Note that the full path to the run_metplus.py script and the configuration file for the use case you are running must be provided.

Original file line number Diff line number Diff line change
Expand Up @@ -271,19 +271,19 @@ def test_plot_point_obs(metplus_config, config_overrides, env_var_values):
out_dir = wrapper.c_dict.get('OUTPUT_DIR')
expected_cmds = [
(f"{app_path} {verbosity} "
f'"{input_dir}/pb2nc/ndas.20120409.t12z.prepbufr.tm00.nc" '
f'{input_dir}/pb2nc/ndas.20120409.t12z.prepbufr.tm00.nc '
f"{out_dir}/nam_and_ndas.20120409.t12z.prepbufr_CONFIG.ps"),
(f"{app_path} {verbosity} "
f'"{input_dir}/pb2nc/ndas.20120410.t00z.prepbufr.tm00.nc" '
f'{input_dir}/pb2nc/ndas.20120410.t00z.prepbufr.tm00.nc '
f"{out_dir}/nam_and_ndas.20120410.t00z.prepbufr_CONFIG.ps"),
]

# add -point_obs argument if template has 2 items
if ('PLOT_POINT_OBS_INPUT_TEMPLATE' in config_overrides and
len(config_overrides['PLOT_POINT_OBS_INPUT_TEMPLATE'].split(',')) > 1):
common_str = f' -point_obs "{input_dir}/ascii2nc/trmm_'
expected_cmds[0] += f'{common_str}2012040912_3hr.nc"'
expected_cmds[1] += f'{common_str}2012041000_3hr.nc"'
common_str = f' -point_obs {input_dir}/ascii2nc/trmm_'
expected_cmds[0] += f'{common_str}2012040912_3hr.nc'
expected_cmds[1] += f'{common_str}2012041000_3hr.nc'

# add -plot_grid argument if provided
if 'PLOT_POINT_OBS_GRID_INPUT_TEMPLATE' in config_overrides:
Expand Down
4 changes: 2 additions & 2 deletions metplus/wrappers/plot_point_obs_wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ def create_c_dict(self):

def get_command(self):
return (f"{self.app_path} -v {self.c_dict['VERBOSITY']}"
f' "{self.infiles[0]}" {self.get_output_path()}'
f' {self.infiles[0]} {self.get_output_path()}'
f" {' '.join(self.args)}")

def find_input_files(self, time_info):
Expand Down Expand Up @@ -222,7 +222,7 @@ def set_command_line_arguments(self, time_info):
"""
# if more than 1 input file was found, add them with -point_obs
for infile in self.infiles[1:]:
self.args.append(f'-point_obs "{infile}"')
self.args.append(f'-point_obs {infile}')

if self.c_dict.get('GRID_INPUT_PATH'):
grid_file = do_string_sub(self.c_dict['GRID_INPUT_PATH'],
Expand Down

0 comments on commit 5fadd22

Please sign in to comment.