From 9d794fc7da0425e266ba31e6107694877c3bc700 Mon Sep 17 00:00:00 2001 From: Guillaume Vernieres Date: Fri, 24 Jan 2025 18:36:05 -0600 Subject: [PATCH 1/6] submit from start pdy to end pdy --- .../run_marine_analysis_vrfy_manual.job | 45 ------ utils/soca/fig_gallery/run_vrfy.py | 72 ++++++++++ utils/soca/fig_gallery/vrfy_jobcard.sh.j2 | 58 ++++++++ ...analysis_vrfy_manual.py => vrfy_script.py} | 131 +++++++++--------- 4 files changed, 194 insertions(+), 112 deletions(-) delete mode 100644 utils/soca/fig_gallery/run_marine_analysis_vrfy_manual.job create mode 100644 utils/soca/fig_gallery/run_vrfy.py create mode 100644 utils/soca/fig_gallery/vrfy_jobcard.sh.j2 rename utils/soca/fig_gallery/{exgdas_global_marine_analysis_vrfy_manual.py => vrfy_script.py} (71%) diff --git a/utils/soca/fig_gallery/run_marine_analysis_vrfy_manual.job b/utils/soca/fig_gallery/run_marine_analysis_vrfy_manual.job deleted file mode 100644 index 38ce48ffc..000000000 --- a/utils/soca/fig_gallery/run_marine_analysis_vrfy_manual.job +++ /dev/null @@ -1,45 +0,0 @@ -#!/bin/bash -#SBATCH --job-name=marine_vrfy # Assign a name to the job (customize as needed) -#SBATCH --account=da-cpu -#SBATCH --qos=debug -#SBATCH -A da-cpu -#SBATCH --output=run_marine_vrfy_analysis.out -#SBATCH --nodes=1 # Request 1 node -#SBATCH --ntasks=40 # Request 40 total tasks (processors across nodes) -#SBATCH --partition=hera # Specify the partition (cluster) named "hera" -#SBATCH --cpus-per-task=1 # Set 1 CPU per task (equivalent to ppn=40 and tpp=1) -#SBATCH --mem=24GB # Request 24GB of memory -#SBATCH --time=00:30:00 # Set the walltime limit to 30 minutes - -# Define HOMEgfs -export HOMEgfs="/scratch1/NCEPDEV/da/Mindo.Choi/workflow_11122024/global-workflow/" - -# Load EVA module -module use ${HOMEgfs}sorc/gdas.cd/modulefiles -module load EVA/hera - -# Set PYTHONPATH using HOMEgfs -export PYTHONPATH="${HOMEgfs}sorc/gdas.cd/ush/:\ -${HOMEgfs}sorc/gdas.cd/ush/eva/:\ -${HOMEgfs}sorc/gdas.cd/ush/soca/:\ -$PYTHONPATH" - -# Set flags to control plotConfig in the Python script -export RUN_ENSENBLE_ANALYSIS=OFF # Check if ensemble run is ON -export RUN_BACKGROUND_ERROR_ANALYSIS=ON -export RUN_BACKGROUND_ANALYSIS=ON -export RUN_INCREMENT_ANLYSIS=ON - -# Define and export the environment variables -export cyc="00" -export RUN="gdas" -export PSLOT="gdas_test" -export PDY="20210827" - -# Define and export environment variables with paths -export COM_OCEAN_ANALYSIS="/scratch1/NCEPDEV/da/Mindo.Choi/sandbox/marine_vrfy/gdas.20210827/00/analysis/ocean" -export COM_ICE_HISTORY_PREV="/scratch1/NCEPDEV/da/Mindo.Choi/sandbox/marine_vrfy/gdas.20210826/18/model/ice/history" -export COM_OCEAN_HISTORY_PREV="/scratch1/NCEPDEV/da/Mindo.Choi/sandbox/marine_vrfy/gdas.20210826/18/model/ocean/history" - -# Excute Marine Verify Analysis -python3 ${HOMEgfs}sorc/gdas.cd/utils/soca/fig_gallery/exgdas_global_marine_analysis_vrfy_manual.py diff --git a/utils/soca/fig_gallery/run_vrfy.py b/utils/soca/fig_gallery/run_vrfy.py new file mode 100644 index 000000000..b879ae661 --- /dev/null +++ b/utils/soca/fig_gallery/run_vrfy.py @@ -0,0 +1,72 @@ +from jinja2 import Template +import subprocess +from datetime import datetime, timedelta + +def iterate_pdy_range(start_pdy, end_pdy): + """Generate a range of dates in YYYYMMDD format.""" + start_date = datetime.strptime(start_pdy, "%Y%m%d") + end_date = datetime.strptime(end_pdy, "%Y%m%d") + current_date = start_date + + while current_date <= end_date: + yield current_date.strftime("%Y%m%d") + current_date += timedelta(days=1) + + +def generate_jobcard(template_path, output_path, context): + # Read the Jinja2 template file + with open(template_path, 'r') as file: + template_content = file.read() + + # Create a Jinja2 template object + template = Template(template_content) + + # Render the template with custom values + rendered_script = template.render(**context) + + # Write the rendered script to the output file + with open(output_path, 'w') as file: + file.write(rendered_script) + + print(f"Bash script generated at: {output_path}") + +# Example usage +if __name__ == "__main__": + + # Define start and end dates + start_pdy = "20210701" + end_pdy = "20210702" + + # Iterate over the date range + for pdy in iterate_pdy_range(start_pdy, end_pdy): + for cyc in ["00", "06", "12", "18"]: + # Custom values to update in the template + context = { + "pdy": pdy, + "cyc": cyc, + "run": "gdas", + "pslot": "nomlb", + "homegdas": "/work2/noaa/da/gvernier/runs/mlb/GDASApp" + } + + # Additional context values for the job card + context.update({ + "base_exp_path": f"/work2/noaa/da/gvernier/runs/mlb/{context['pslot']}/COMROOT/{context['pslot']}", + "plot_ensemble_b": "OFF", + "plot_parametric_b": "OFF", + "plot_background": "OFF", + "plot_increment": "ON", + "plot_analysis": "OFF", + "eva_plots": "ON", + "qos": "batch", + "hpc": "hercules", + "eva_module": "EVA/orion", + }) + + # Prepare the job card + template_jobcard = "vrfy_jobcard.sh.j2" # Assumes a Jinja2 template file in the same directory + jobcard = f"vrfy_jobcard.{context['pslot']}.{context['pdy']}.{context['cyc']}.sh" + generate_jobcard(template_jobcard, jobcard, context) + + # Submit the plotting job + subprocess.run(f"sbatch {jobcard}", shell=True) diff --git a/utils/soca/fig_gallery/vrfy_jobcard.sh.j2 b/utils/soca/fig_gallery/vrfy_jobcard.sh.j2 new file mode 100644 index 000000000..a8d09c621 --- /dev/null +++ b/utils/soca/fig_gallery/vrfy_jobcard.sh.j2 @@ -0,0 +1,58 @@ +#!/bin/bash +#SBATCH --job-name={{ job_name | default("marine_vrfy") }} # Assign a name to the job (customize as needed) +#SBATCH --account={{ account | default("da-cpu") }} +#SBATCH --qos={{ qos | default("debug") }} +{% set OUTPUT = "vrfy_jobcard." + pslot + "." + pdy + "." + cyc + ".log" %} +#SBATCH --output={{ OUTPUT }} +#SBATCH --nodes={{ nodes | default(1) }} # Request 1 node +#SBATCH --tasks={{ ntasks | default(20) }} # Request total tasks (processors across nodes) +{% set HPC = hpc | default("hera") %} +{% if HPC == "hera" %} +#SBATCH --partition={{ partition | default("hera") }} # Specify the partition (cluster) +{% endif %} +#SBATCH --mem={{ memory | default("24GB") }} # Request memory +#SBATCH --time={{ walltime | default("00:30:00") }} # Set the walltime limit + +# Define HOMEgdas +export HOMEgdas="{{ homegdas }}" + +# Load EVA module +module use ${HOMEgdas}/modulefiles +module load {{ eva_module | default("EVA/hera") }} + +# Set PYTHONPATH using HOMEgfs +export PYTHONPATH="${HOMEgdas}/ush/:\ +${HOMEgdas}/ush/eva/:\ +${HOMEgdas}/ush/soca/:\ +$PYTHONPATH" + +# Set flags to control plotConfig in the Python script +export PLOT_ENSENBLE_B={{ plot_ensemble_b | default("OFF") }} # Check if ensemble run is ON +export PLOT_PARAMETRIC_B={{ plot_parametric_b | default("ON") }} +export PLOT_BACKGROUND={{ plot_background | default("ON") }} +export PLOT_INCREMENT={{ plot_increment | default("ON") }} +export PLOT_ANALYSIS={{ plot_analysis | default("OFF") }} +export PLOT_ANALYSIS={{ plot_analysis | default("OFF") }} +export EVA_PLOTS={{ eva_plots | default("OFF") }} + +# Define and export the environment variables +export cyc="{{ cyc }}" +export RUN="{{ run | default("gdas") }}" +export PSLOT="{{ pslot }}" +export PDY="{{ pdy }}" + +# Define base experiment path +BASE_EXP_PATH="{{ base_exp_path }}" # path to the gdas.pdy directory + +# Calculate previous date and cycle +PREV_CYC=$(date -d "{{ pdy }} {{ cyc }} -6 hours" +"%Y%m%d %H") +PREV_PDY=$(echo $PREV_CYC | cut -d' ' -f1) +PREV_CYC_HOUR=$(echo $PREV_CYC | cut -d' ' -f2) + +# Define and export environment variables with paths +export COM_OCEAN_ANALYSIS="${BASE_EXP_PATH}/gdas.{{ pdy }}/{{ cyc }}/analysis/ocean" +export COM_ICE_HISTORY_PREV="${BASE_EXP_PATH}/gdas.${PREV_PDY}/${PREV_CYC_HOUR}/model/ice/history" +export COM_OCEAN_HISTORY_PREV="${BASE_EXP_PATH}/gdas.${PREV_PDY}/${PREV_CYC_HOUR}/model/ocean/history" + +# Execute Marine Verify Analysis +python3 ${HOMEgdas}/utils/soca/fig_gallery/vrfy_script.py diff --git a/utils/soca/fig_gallery/exgdas_global_marine_analysis_vrfy_manual.py b/utils/soca/fig_gallery/vrfy_script.py similarity index 71% rename from utils/soca/fig_gallery/exgdas_global_marine_analysis_vrfy_manual.py rename to utils/soca/fig_gallery/vrfy_script.py index ccb37a55c..e0192b597 100644 --- a/utils/soca/fig_gallery/exgdas_global_marine_analysis_vrfy_manual.py +++ b/utils/soca/fig_gallery/vrfy_script.py @@ -20,33 +20,40 @@ # for eva diagdir = os.path.join(comout, 'diags') -HOMEgfs = os.getenv('HOMEgfs') +HOMEgdas = os.getenv('HOMEgdas') # Get flags from environment variables (set in the bash driver) -run_ensemble_analysis = os.getenv('RUN_ENSENBLE_ANALYSIS', 'OFF').upper() == 'ON' -run_bkgerr_analysis = os.getenv('RUN_BACKGROUND_ERROR_ANALYSIS', 'OFF').upper() == 'ON' -run_bkg_analysis = os.getenv('RUN_BACKGROUND_ANALYSIS', 'OFF').upper() == 'ON' -run_increment_analysis = os.getenv('RUN_INCREMENT_ANLYSIS', 'OFF').upper() == 'ON' +plot_ensemble_b = os.getenv('PLOT_ENSENBLE_B', 'OFF').upper() == 'ON' +plot_parametric_b = os.getenv('PLOT_PARAMETRIC_B', 'OFF').upper() == 'ON' +plot_background = os.getenv('PLOT_BACKGROUND', 'OFF').upper() == 'ON' +plot_increment = os.getenv('PLOT_INCREMENT', 'OFF').upper() == 'ON' +plot_analysis = os.getenv('PLOT_ANALYSIS', 'OFF').upper() == 'ON' +eva_plots = os.getenv('EVA_PLOTS', 'OFF').upper() == 'ON' # Initialize an empty list for the main config -configs = [plotConfig(grid_file=grid_file, - data_file=os.path.join(comout, f'{RUN}.t'+cyc+'z.ocnana.nc'), - variables_horiz={'ave_ssh': [-1.8, 1.3], - 'Temp': [-1.8, 34.0], - 'Salt': [32, 40]}, - colormap='nipy_spectral', - comout=os.path.join(comout, 'vrfy', 'ana')), # ocean surface analysis - plotConfig(grid_file=grid_file, - data_file=os.path.join(comout, f'{RUN}.t'+cyc+'z.iceana.nc'), - variables_horiz={'aice_h': [0.0, 1.0], - 'hi_h': [0.0, 4.0], - 'hs_h': [0.0, 0.5]}, - colormap='jet', - projs=['North', 'South', 'Global'], - comout=os.path.join(comout, 'vrfy', 'ana'))] # sea ice analysis - -# Define each config and add to main_config if its flag is True -if run_ensemble_analysis: +configs = [] + +# Analysis plotting configuration +if plot_analysis: + configs_ana = [plotConfig(grid_file=grid_file, + data_file=os.path.join(comout, f'{RUN}.t'+cyc+'z.ocnana.nc'), + variables_horiz={'ave_ssh': [-1.8, 1.3], + 'Temp': [-1.8, 34.0], + 'Salt': [32, 40]}, + colormap='nipy_spectral', + comout=os.path.join(comout, 'vrfy', 'ana')), # ocean surface analysis + plotConfig(grid_file=grid_file, + data_file=os.path.join(comout, f'{RUN}.t'+cyc+'z.iceana.nc'), + variables_horiz={'aice_h': [0.0, 1.0], + 'hi_h': [0.0, 4.0], + 'hs_h': [0.0, 0.5]}, + colormap='jet', + projs=['North', 'South', 'Global'], + comout=os.path.join(comout, 'vrfy', 'ana'))] # sea ice analysis + configs.extend(config_ana) + +# Ensemble B plotting configuration +if plot_ensemble_b: config_ens = [plotConfig(grid_file=grid_file, data_file=os.path.join(comout, f'{RUN}.t{cyc}z.ocn.recentering_error.nc'), variables_horiz={'ave_ssh': [-1, 1]}, @@ -74,7 +81,8 @@ comout=os.path.join(comout, 'vrfy', 'bkgerr', 'steric_explained_variance'))] # steric explained variance configs.extend(config_ens) -if run_bkgerr_analysis: +# Parametric B plotting configuration +if plot_parametric_b: config_bkgerr = [plotConfig(grid_file=grid_file, layer_file=layer_file, data_file=os.path.join(comout, os.path.pardir, os.path.pardir, @@ -98,7 +106,8 @@ comout=os.path.join(comout, 'vrfy', 'bkgerr'))] # ocn bkgerr stddev configs.extend(config_bkgerr) -if run_bkg_analysis: +# Background plotting configuration +if plot_background: config_bkg = [plotConfig(grid_file=grid_file, data_file=os.path.join(com_ice_history, f'{RUN}.ice.t{gcyc}z.inst.f006.nc'), variables_horiz={'aice_h': [0.0, 1.0], @@ -123,7 +132,8 @@ comout=os.path.join(comout, 'vrfy', 'bkg'))] configs.extend(config_bkg) -if run_increment_analysis: +# Increment plotting configuration +if plot_increment: config_incr = [plotConfig(grid_file=grid_file, layer_file=layer_file, data_file=os.path.join(comout, f'{RUN}.t'+cyc+'z.ocninc.nc'), @@ -146,26 +156,15 @@ 'hs_h': [-0.1, 0.1]}, colormap='seismic', projs=['North', 'South'], - comout=os.path.join(comout, 'vrfy', 'incr')), # sea ice increment - plotConfig(grid_file=grid_file, - data_file=os.path.join(comout, f'{RUN}.t'+cyc+'z.ice.incr.postproc.nc'), - lats=np.arange(-60, 60, 10), - variables_horiz={'aice_h': [-0.2, 0.2], - 'hi_h': [-0.5, 0.5], - 'hs_h': [-0.1, 0.1]}, - colormap='seismic', - projs=['North', 'South'], - comout=os.path.join(comout, 'vrfy', 'incr.postproc'))] # sea ice increment after postprocessing + comout=os.path.join(comout, 'vrfy', 'incr'))] # sea ice increment configs.extend(config_incr) -# plot marine analysis vrfy - +# Plot the marine verification figures def plot_marine_vrfy(config): ocnvrfyPlotter = statePlotter(config) ocnvrfyPlotter.plot() - # Number of processes num_processes = len(configs) @@ -182,34 +181,32 @@ def plot_marine_vrfy(config): for process in processes: process.join() -####################################### -# eva plots -####################################### - -evadir = os.path.join(HOMEgfs, 'sorc', f'{RUN}.cd', 'ush', 'eva') -marinetemplate = os.path.join(evadir, 'marine_gdas_plots.yaml') -varyaml = os.path.join(comout, 'yaml', 'var_original.yaml') - -# it would be better to refrence the dirs explicitly with the comout path -# but eva doesn't allow for specifying output directories -os.chdir(os.path.join(comout, 'vrfy')) -if not os.path.exists('preevayamls'): - os.makedirs('preevayamls') -if not os.path.exists('evayamls'): - os.makedirs('evayamls') - -gen_eva_obs_yaml.gen_eva_obs_yaml(varyaml, marinetemplate, 'preevayamls') - -files = os.listdir('preevayamls') -for file in files: - infile = os.path.join('preevayamls', file) - marine_eva_post.marine_eva_post(infile, 'evayamls', diagdir) - -files = os.listdir('evayamls') -for file in files: - infile = os.path.join('evayamls', file) - print('running eva on', infile) - subprocess.run(['eva', infile], check=True) +# Run EVA +if eva_plots: + evadir = os.path.join(HOMEgdas, 'ush', 'eva') + marinetemplate = os.path.join(evadir, 'marine_gdas_plots.yaml') + varyaml = os.path.join(comout, 'yaml', 'var.yaml') + + # it would be better to refrence the dirs explicitly with the comout path + # but eva doesn't allow for specifying output directories + os.chdir(os.path.join(comout, 'vrfy')) + if not os.path.exists('preevayamls'): + os.makedirs('preevayamls') + if not os.path.exists('evayamls'): + os.makedirs('evayamls') + + gen_eva_obs_yaml.gen_eva_obs_yaml(varyaml, marinetemplate, 'preevayamls') + + files = os.listdir('preevayamls') + for file in files: + infile = os.path.join('preevayamls', file) + marine_eva_post.marine_eva_post(infile, 'evayamls', diagdir) + + files = os.listdir('evayamls') + for file in files: + infile = os.path.join('evayamls', file) + print('running eva on', infile) + subprocess.run(['eva', infile], check=True) ####################################### # calculate diag statistics From 2b01f85b3557458928ab19c606e7ebc66128514e Mon Sep 17 00:00:00 2001 From: Guillaume Vernieres Date: Sat, 25 Jan 2025 09:52:54 -0600 Subject: [PATCH 2/6] moved user config to yaml --- utils/soca/fig_gallery/run_vrfy.py | 55 ++++++++++++------------- utils/soca/fig_gallery/vrfy_config.yaml | 16 +++++++ 2 files changed, 43 insertions(+), 28 deletions(-) create mode 100644 utils/soca/fig_gallery/vrfy_config.yaml diff --git a/utils/soca/fig_gallery/run_vrfy.py b/utils/soca/fig_gallery/run_vrfy.py index b879ae661..bd99cdb22 100644 --- a/utils/soca/fig_gallery/run_vrfy.py +++ b/utils/soca/fig_gallery/run_vrfy.py @@ -1,6 +1,10 @@ from jinja2 import Template import subprocess from datetime import datetime, timedelta +import yaml +import sys +import copy +import os def iterate_pdy_range(start_pdy, end_pdy): """Generate a range of dates in YYYYMMDD format.""" @@ -33,38 +37,33 @@ def generate_jobcard(template_path, output_path, context): # Example usage if __name__ == "__main__": - # Define start and end dates - start_pdy = "20210701" - end_pdy = "20210702" + # Get the YAML configuration file name from the input argument + if len(sys.argv) != 2: + print("Usage: python run_vrfy.py ") + sys.exit(1) + + config_file = sys.argv[1] + + # Read the YAML template from the file + with open(config_file, "r") as file: + yaml_template = file.read() + + # Load the template YAML as a dictionary + template_dict = yaml.safe_load(yaml_template) + + # Render the template with Jinja2 + template = Template(yaml_template) + config = yaml.safe_load(template.render(pslot=template_dict["pslot"])) # Iterate over the date range - for pdy in iterate_pdy_range(start_pdy, end_pdy): - for cyc in ["00", "06", "12", "18"]: - # Custom values to update in the template - context = { - "pdy": pdy, - "cyc": cyc, - "run": "gdas", - "pslot": "nomlb", - "homegdas": "/work2/noaa/da/gvernier/runs/mlb/GDASApp" - } - - # Additional context values for the job card - context.update({ - "base_exp_path": f"/work2/noaa/da/gvernier/runs/mlb/{context['pslot']}/COMROOT/{context['pslot']}", - "plot_ensemble_b": "OFF", - "plot_parametric_b": "OFF", - "plot_background": "OFF", - "plot_increment": "ON", - "plot_analysis": "OFF", - "eva_plots": "ON", - "qos": "batch", - "hpc": "hercules", - "eva_module": "EVA/orion", - }) + for pdy in iterate_pdy_range(config['start_pdy'], config['end_pdy']): + context = copy.deepcopy(config) + for cyc in config["cycs"]: + # Update the cycle's date + context.update({"pdy": pdy, "cyc": cyc}) # Prepare the job card - template_jobcard = "vrfy_jobcard.sh.j2" # Assumes a Jinja2 template file in the same directory + template_jobcard = os.path.join(context['homegdas'], 'utils', 'soca', 'fig_gallery', 'vrfy_jobcard.sh.j2') # Assumes a Jinja2 template file in the moegdas directory jobcard = f"vrfy_jobcard.{context['pslot']}.{context['pdy']}.{context['cyc']}.sh" generate_jobcard(template_jobcard, jobcard, context) diff --git a/utils/soca/fig_gallery/vrfy_config.yaml b/utils/soca/fig_gallery/vrfy_config.yaml new file mode 100644 index 000000000..0df76cf88 --- /dev/null +++ b/utils/soca/fig_gallery/vrfy_config.yaml @@ -0,0 +1,16 @@ +pslot: "nomlb" +start_pdy: '20210701' +end_pdy: '20210701' +cycs: ["00", "06", "12", "18"] +run: "gdas" +homegdas: "/work2/noaa/da/gvernier/runs/mlb/GDASApp" +base_exp_path: "/work2/noaa/da/gvernier/runs/mlb/{{ pslot }}/COMROOT/{{ pslot }}" +plot_ensemble_b: "OFF" +plot_parametric_b: "OFF" +plot_background: "OFF" +plot_increment: "ON" +plot_analysis: "OFF" +eva_plots: "ON" +qos: "batch" +hpc: "hercules" +eva_module: "EVA/orion" From 50ab6f18452907f7ae12417607510974f47b3aef Mon Sep 17 00:00:00 2001 From: Guillaume Vernieres Date: Sat, 25 Jan 2025 10:15:03 -0600 Subject: [PATCH 3/6] added a simple howto --- utils/soca/fig_gallery/README.md | 38 ++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 utils/soca/fig_gallery/README.md diff --git a/utils/soca/fig_gallery/README.md b/utils/soca/fig_gallery/README.md new file mode 100644 index 000000000..d021a7d81 --- /dev/null +++ b/utils/soca/fig_gallery/README.md @@ -0,0 +1,38 @@ +## How to generate the EVA and State space figures + +#### Create a scratch place to run `run_vrfy.py`. This script will generate a bunch of sbatch scripts and logs. +``` +mkdir /somewhere/scratch +cd /somewhere/scratch +ln -s /path/to/run_vrfy.py . # to be sorted out properly in the future +cp /path/to/vrfy_config.yaml . +module use ... +module load EVA/.... +``` +--- +#### Edit `vrfy_config.yaml` +It's actually read as a jinja template to render `pslot` if necessary. Anything that is a templated variable in `vrfy_jobcard.sh.j2` can be added to the yaml below. +```yaml +pslot: "nomlb" +start_pdy: '20210701' +end_pdy: '20210701' +cycs: ["00", "06", "12", "18"] +run: "gdas" +homegdas: "/work2/noaa/da/gvernier/runs/mlb/GDASApp" +base_exp_path: "/work2/noaa/da/gvernier/runs/mlb/{{ pslot }}/COMROOT/{{ pslot }}" +plot_ensemble_b: "OFF" +plot_parametric_b: "OFF" +plot_background: "OFF" +plot_increment: "ON" +plot_analysis: "OFF" +eva_plots: "ON" +qos: "batch" +hpc: "hercules" +eva_module: "EVA/orion" +``` + +--- +#### Run the application +```python run_vrfy.py vrfy_config.yaml``` +This will generate and submit the job cards for all the **cycles** defined by `cycs`, from `start_pdy` to `end_pdy`. + From e3fe07c6973e56eddc07a585b43787357b4a0de3 Mon Sep 17 00:00:00 2001 From: Guillaume Vernieres Date: Mon, 27 Jan 2025 11:31:17 -0500 Subject: [PATCH 4/6] manual merge of develop --- sorc/oops | 2 +- sorc/saber | 2 +- sorc/soca | 2 +- sorc/ufo | 2 +- ush/soca/soca_vrfy.py | 2 +- utils/soca/fig_gallery/vrfy_script.py | 51 +++++++++++++++++++++------ 6 files changed, 46 insertions(+), 15 deletions(-) diff --git a/sorc/oops b/sorc/oops index 60dd7b18a..3591b63a7 160000 --- a/sorc/oops +++ b/sorc/oops @@ -1 +1 @@ -Subproject commit 60dd7b18a0b425489424ee5881caa35d2a4d0317 +Subproject commit 3591b63a772d07beaccdc980cc2da87ffa704f14 diff --git a/sorc/saber b/sorc/saber index b22a04a5a..160bbf84e 160000 --- a/sorc/saber +++ b/sorc/saber @@ -1 +1 @@ -Subproject commit b22a04a5afc59d1f0a96ac916807bf37c4d3b3e1 +Subproject commit 160bbf84e90c6e590f5f0fba11123b80aa11b579 diff --git a/sorc/soca b/sorc/soca index 4d51dcabf..697e42645 160000 --- a/sorc/soca +++ b/sorc/soca @@ -1 +1 @@ -Subproject commit 4d51dcabf877017be61803338ac81185d0af7ac1 +Subproject commit 697e42645211854b79e5db2c86f71c58a3de0092 diff --git a/sorc/ufo b/sorc/ufo index 4673e7b1c..e51ced6a4 160000 --- a/sorc/ufo +++ b/sorc/ufo @@ -1 +1 @@ -Subproject commit 4673e7b1c5a0838c31154dd042556b461a1c1812 +Subproject commit e51ced6a4e7db01bf99096bb7a603ba5817cd101 diff --git a/ush/soca/soca_vrfy.py b/ush/soca/soca_vrfy.py index a4060fecd..6ad0ec27e 100755 --- a/ush/soca/soca_vrfy.py +++ b/ush/soca/soca_vrfy.py @@ -43,7 +43,7 @@ def plotConfig(grid_file=[], 'ave_ssh': 'meter', 'Temp': 'deg C', 'Salt': 'psu', - 'aice_h': 'meter', + 'aice_h': 'unitless', 'hi_h': 'meter', 'hs_h': 'meter', 'u': 'm/s', diff --git a/utils/soca/fig_gallery/vrfy_script.py b/utils/soca/fig_gallery/vrfy_script.py index e0192b597..696099145 100644 --- a/utils/soca/fig_gallery/vrfy_script.py +++ b/utils/soca/fig_gallery/vrfy_script.py @@ -18,6 +18,13 @@ grid_file = os.path.join(comout, f'{RUN}.t'+bcyc+'z.ocngrid.nc') layer_file = os.path.join(comout, f'{RUN}.t'+cyc+'z.ocninc.nc') +# Check if the file exists, then decide on grid_file +if os.path.exists(vrfy_grid_file): + grid_file = vrfy_grid_file +else: + TODO: Make this work on other HPC + grid_file = '/scratch1/NCEPDEV/da/common/validation/vrfy/gdas.t21z.ocngrid.nc' + # for eva diagdir = os.path.join(comout, 'diags') HOMEgdas = os.getenv('HOMEgdas') @@ -84,6 +91,15 @@ # Parametric B plotting configuration if plot_parametric_b: config_bkgerr = [plotConfig(grid_file=grid_file, + data_file=os.path.join(comout, os.path.pardir, os.path.pardir, + 'bmatrix', 'ice', f'{RUN}.t'+cyc+'z.ice.bkgerr_stddev.nc'), + variables_horiz={'aice_h': [0.0, 0.5], + 'hi_h': [0.0, 2.0], + 'hs_h': [0.0, 0.2]}, + colormap='jet', + projs=['North', 'South', 'Global'], + comout=os.path.join(comout, 'vrfy', 'bkgerr')), # sea ice bkgerr stddev + plotConfig(grid_file=grid_file, layer_file=layer_file, data_file=os.path.join(comout, os.path.pardir, os.path.pardir, 'bmatrix', 'ocean', f'{RUN}.t'+cyc+'z.ocean.bkgerr_stddev.nc'), @@ -91,16 +107,16 @@ lons=np.arange(-280, 80, 30), variables_zonal={'Temp': [0, 2], 'Salt': [0, 0.2], - 'u': [0, 0.2], - 'v': [0, 0.2]}, + 'u': [0, 0.5], + 'v': [0, 0.5]}, variables_meridional={'Temp': [0, 2], 'Salt': [0, 0.2], - 'u': [0, 0.2], - 'v': [0, 0.2]}, + 'u': [0, 0.5], + 'v': [0, 0.5]}, variables_horiz={'Temp': [0, 2], 'Salt': [0, 0.2], - 'u': [0, 0.2], - 'v': [0, 0.2], + 'u': [0, 0.5], + 'v': [0, 0.5], 'ave_ssh': [0, 0.1]}, colormap='jet', comout=os.path.join(comout, 'vrfy', 'bkgerr'))] # ocn bkgerr stddev @@ -122,12 +138,18 @@ lats=np.arange(-60, 60, 10), lons=np.arange(-280, 80, 30), variables_zonal={'Temp': [-1.8, 34.0], - 'Salt': [32, 40]}, + 'Salt': [32, 40], + 'u': [-1.0, 1.0], + 'v': [-1.0, 1.0]}, variables_meridional={'Temp': [-1.8, 34.0], - 'Salt': [32, 40]}, + 'Salt': [32, 40], + 'u': [-1.0, 1.0], + 'v': [-1.0, 1.0]}, variables_horiz={'ave_ssh': [-1.8, 1.3], 'Temp': [-1.8, 34.0], - 'Salt': [32, 40]}, + 'Salt': [32, 40], + 'u': [-1.0, 1.0], + 'v': [-1.0, 1.0]}, colormap='nipy_spectral', comout=os.path.join(comout, 'vrfy', 'bkg'))] configs.extend(config_bkg) @@ -156,7 +178,16 @@ 'hs_h': [-0.1, 0.1]}, colormap='seismic', projs=['North', 'South'], - comout=os.path.join(comout, 'vrfy', 'incr'))] # sea ice increment + comout=os.path.join(comout, 'vrfy', 'incr')), # sea ice increment + plotConfig(grid_file=grid_file, + data_file=os.path.join(comout, f'{RUN}.t'+cyc+'z.ice.incr.postproc.nc'), + lats=np.arange(-60, 60, 10), + variables_horiz={'aice_h': [-0.2, 0.2], + 'hi_h': [-0.5, 0.5], + 'hs_h': [-0.1, 0.1]}, + colormap='seismic', + projs=['North', 'South'], + comout=os.path.join(comout, 'vrfy', 'incr.postproc'))] # sea ice increment after postprocessing configs.extend(config_incr) From d2c3acca60c42babb253124a916517e9cab328e0 Mon Sep 17 00:00:00 2001 From: Guillaume Vernieres Date: Mon, 27 Jan 2025 11:57:57 -0500 Subject: [PATCH 5/6] fixed grid search logic --- utils/soca/fig_gallery/vrfy_script.py | 49 +++++++++++++++++++++------ 1 file changed, 39 insertions(+), 10 deletions(-) diff --git a/utils/soca/fig_gallery/vrfy_script.py b/utils/soca/fig_gallery/vrfy_script.py index e0192b597..24d8b3eb2 100644 --- a/utils/soca/fig_gallery/vrfy_script.py +++ b/utils/soca/fig_gallery/vrfy_script.py @@ -18,6 +18,11 @@ grid_file = os.path.join(comout, f'{RUN}.t'+bcyc+'z.ocngrid.nc') layer_file = os.path.join(comout, f'{RUN}.t'+cyc+'z.ocninc.nc') +# Check if the file exists, then decide on grid_file +if not os.path.exists(grid_file): + # TODO: Make this work on other HPC + grid_file = '/scratch1/NCEPDEV/da/common/validation/vrfy/gdas.t21z.ocngrid.nc' + # for eva diagdir = os.path.join(comout, 'diags') HOMEgdas = os.getenv('HOMEgdas') @@ -84,6 +89,15 @@ # Parametric B plotting configuration if plot_parametric_b: config_bkgerr = [plotConfig(grid_file=grid_file, + data_file=os.path.join(comout, os.path.pardir, os.path.pardir, + 'bmatrix', 'ice', f'{RUN}.t'+cyc+'z.ice.bkgerr_stddev.nc'), + variables_horiz={'aice_h': [0.0, 0.5], + 'hi_h': [0.0, 2.0], + 'hs_h': [0.0, 0.2]}, + colormap='jet', + projs=['North', 'South', 'Global'], + comout=os.path.join(comout, 'vrfy', 'bkgerr')), # sea ice bkgerr stddev + plotConfig(grid_file=grid_file, layer_file=layer_file, data_file=os.path.join(comout, os.path.pardir, os.path.pardir, 'bmatrix', 'ocean', f'{RUN}.t'+cyc+'z.ocean.bkgerr_stddev.nc'), @@ -91,16 +105,16 @@ lons=np.arange(-280, 80, 30), variables_zonal={'Temp': [0, 2], 'Salt': [0, 0.2], - 'u': [0, 0.2], - 'v': [0, 0.2]}, + 'u': [0, 0.5], + 'v': [0, 0.5]}, variables_meridional={'Temp': [0, 2], 'Salt': [0, 0.2], - 'u': [0, 0.2], - 'v': [0, 0.2]}, + 'u': [0, 0.5], + 'v': [0, 0.5]}, variables_horiz={'Temp': [0, 2], 'Salt': [0, 0.2], - 'u': [0, 0.2], - 'v': [0, 0.2], + 'u': [0, 0.5], + 'v': [0, 0.5], 'ave_ssh': [0, 0.1]}, colormap='jet', comout=os.path.join(comout, 'vrfy', 'bkgerr'))] # ocn bkgerr stddev @@ -122,12 +136,18 @@ lats=np.arange(-60, 60, 10), lons=np.arange(-280, 80, 30), variables_zonal={'Temp': [-1.8, 34.0], - 'Salt': [32, 40]}, + 'Salt': [32, 40], + 'u': [-1.0, 1.0], + 'v': [-1.0, 1.0]}, variables_meridional={'Temp': [-1.8, 34.0], - 'Salt': [32, 40]}, + 'Salt': [32, 40], + 'u': [-1.0, 1.0], + 'v': [-1.0, 1.0]}, variables_horiz={'ave_ssh': [-1.8, 1.3], 'Temp': [-1.8, 34.0], - 'Salt': [32, 40]}, + 'Salt': [32, 40], + 'u': [-1.0, 1.0], + 'v': [-1.0, 1.0]}, colormap='nipy_spectral', comout=os.path.join(comout, 'vrfy', 'bkg'))] configs.extend(config_bkg) @@ -156,7 +176,16 @@ 'hs_h': [-0.1, 0.1]}, colormap='seismic', projs=['North', 'South'], - comout=os.path.join(comout, 'vrfy', 'incr'))] # sea ice increment + comout=os.path.join(comout, 'vrfy', 'incr')), # sea ice increment + plotConfig(grid_file=grid_file, + data_file=os.path.join(comout, f'{RUN}.t'+cyc+'z.ice.incr.postproc.nc'), + lats=np.arange(-60, 60, 10), + variables_horiz={'aice_h': [-0.2, 0.2], + 'hi_h': [-0.5, 0.5], + 'hs_h': [-0.1, 0.1]}, + colormap='seismic', + projs=['North', 'South'], + comout=os.path.join(comout, 'vrfy', 'incr.postproc'))] # sea ice increment after postprocessing configs.extend(config_incr) From 24a29fd24b47ee2111e13399ada0f951ecf3c074 Mon Sep 17 00:00:00 2001 From: Guillaume Vernieres Date: Mon, 27 Jan 2025 12:10:45 -0500 Subject: [PATCH 6/6] fixed typo --- utils/soca/fig_gallery/vrfy_jobcard.sh.j2 | 2 +- utils/soca/fig_gallery/vrfy_script.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/utils/soca/fig_gallery/vrfy_jobcard.sh.j2 b/utils/soca/fig_gallery/vrfy_jobcard.sh.j2 index a8d09c621..59b8cdef2 100644 --- a/utils/soca/fig_gallery/vrfy_jobcard.sh.j2 +++ b/utils/soca/fig_gallery/vrfy_jobcard.sh.j2 @@ -27,7 +27,7 @@ ${HOMEgdas}/ush/soca/:\ $PYTHONPATH" # Set flags to control plotConfig in the Python script -export PLOT_ENSENBLE_B={{ plot_ensemble_b | default("OFF") }} # Check if ensemble run is ON +export PLOT_ENSEMBLE_B={{ plot_ensemble_b | default("OFF") }} export PLOT_PARAMETRIC_B={{ plot_parametric_b | default("ON") }} export PLOT_BACKGROUND={{ plot_background | default("ON") }} export PLOT_INCREMENT={{ plot_increment | default("ON") }} diff --git a/utils/soca/fig_gallery/vrfy_script.py b/utils/soca/fig_gallery/vrfy_script.py index 24d8b3eb2..ba6abd585 100644 --- a/utils/soca/fig_gallery/vrfy_script.py +++ b/utils/soca/fig_gallery/vrfy_script.py @@ -28,7 +28,7 @@ HOMEgdas = os.getenv('HOMEgdas') # Get flags from environment variables (set in the bash driver) -plot_ensemble_b = os.getenv('PLOT_ENSENBLE_B', 'OFF').upper() == 'ON' +plot_ensemble_b = os.getenv('PLOT_ENSEMBLE_B', 'OFF').upper() == 'ON' plot_parametric_b = os.getenv('PLOT_PARAMETRIC_B', 'OFF').upper() == 'ON' plot_background = os.getenv('PLOT_BACKGROUND', 'OFF').upper() == 'ON' plot_increment = os.getenv('PLOT_INCREMENT', 'OFF').upper() == 'ON'