diff --git a/ush/eva/marine_eva_post.py b/ush/eva/marine_eva_post.py
deleted file mode 100755
index b537ddb3a..000000000
--- a/ush/eva/marine_eva_post.py
+++ /dev/null
@@ -1,69 +0,0 @@
-#!/usr/bin/env python3
-import argparse
-import datetime
-import logging
-import os
-import socket
-import yaml
-import glob
-
-# sets the cmap vmin/vmax for each variable
-# TODO: this should probably be in a yaml or something
-vminmax = {'seaSurfaceTemperature': {'vmin': -2.0, 'vmax': 2.0},
- 'seaIceFraction': {'vmin': -0.2, 'vmax': 0.2},
- 'seaSurfaceSalinity': {'vmin': -0.2, 'vmax': 0.2}, # TODO: this should be changed
- 'absoluteDynamicTopography': {'vmin': -0.2, 'vmax': 0.2},
- 'waterTemperature': {'vmin': -2.0, 'vmax': 2.0},
- 'salinity': {'vmin': -0.2, 'vmax': 0.2}}
-
-
-def marine_eva_post(inputyaml, outputdir, diagdir):
- logging.basicConfig(format='%(asctime)s:%(levelname)s:%(message)s', level=logging.INFO, datefmt='%Y-%m-%d %H:%M:%S')
- try:
- with open(inputyaml, 'r') as inputyaml_opened:
- input_yaml_dict = yaml.safe_load(inputyaml_opened)
- logging.info(f'Loading input YAML from {inputyaml}')
- except Exception as e:
- logging.error(f'Error occurred when attempting to load: {inputyaml}, error: {e}')
- for dataset in input_yaml_dict['datasets']:
- newfilenames = []
- for filename in dataset['filenames']:
- newfilename = os.path.join(diagdir, os.path.basename(filename))
- newfilenames.append(newfilename)
- dataset['filenames'] = newfilenames
- for graphic in input_yaml_dict['graphics']['figure_list']:
- # this assumes that there is only one variable, or that the
- # variables are all the same
- variable = graphic['batch figure']['variables'][0]
- for plot in graphic['plots']:
- for layer in plot['layers']:
- if layer['type'] == 'MapScatter':
- layer['vmin'] = vminmax[variable]['vmin']
- layer['vmax'] = vminmax[variable]['vmax']
-
- # first, let us prepend some comments that tell someone this output YAML was generated
- now = datetime.datetime.now()
- prepend_str = ''.join([
- f'# This YAML file automatically generated by marine_eva_post.py\n',
- f'# on {socket.gethostname()} at {now.strftime("%Y-%m-%dT%H:%M:%SZ")}\n',
- ])
-
- outputyaml = os.path.join(outputdir, os.path.basename(inputyaml))
- # open output file for writing and start the find/replace process
- try:
- logging.info(f'Writing modified YAML to {outputyaml}')
- with open(outputyaml, 'w') as yaml_out:
- yaml_out.write(prepend_str)
- yaml.dump(input_yaml_dict, yaml_out)
- except Exception as e:
- logging.error(f'Error occurred when attempting to write: {outputyaml}, error: {e}')
-
-
-if __name__ == "__main__":
-
- parser = argparse.ArgumentParser()
- parser.add_argument('-i', '--inputyaml', type=str, help='Input YAML to modify', required=True)
- parser.add_argument('-o', '--outputdir', type=str, help='Directory to send output YAML', required=True)
- parser.add_argument('-d', '--diagdir', type=str, help='Location of diag files', required=True)
- args = parser.parse_args()
- marine_eva_post(args.inputyaml, args.outputdir, args.diagdir)
diff --git a/ush/eva/marine_gdas_plots.yaml b/ush/eva/marine_gdas_plots.yaml
deleted file mode 100644
index 0a903d0c4..000000000
--- a/ush/eva/marine_gdas_plots.yaml
+++ /dev/null
@@ -1,222 +0,0 @@
-# template YAML file to create EVA YAML files
-# based on obs spaces listed in JEDI YAML files
-datasets:
- - name: experiment
- type: IodaObsSpace
- filenames:
- - @FILENAME@
- @CHANNELSKEY@
- groups:
- - name: ObsValue
- variables: &variables @VARIABLES@
- - name: ObsError
- - name: ombg
- - name: oman
- - name: hofx0
- - name: EffectiveQC0
- - name: MetaData
- - name: PreQC
-transforms:
-
- # bkg
- - transform: arithmetic
- new name: experiment::bkg::${variable}
- equals: experiment::ObsValue::${variable}-experiment::ombg::${variable}
- for:
- variable: *variables
-
- # Generate omb that passed QC for JEDI
- - transform: accept where
- new name: experiment::OmBQC::${variable}
- starting field: experiment::ombg::${variable}
- where:
- - experiment::EffectiveQC0::${variable} == 0
- for:
- variable: *variables
-
- # Generate oma that passed QC for JEDI
- - transform: accept where
- new name: experiment::OmAQC::${variable}
- starting field: experiment::oman::${variable}
- where:
- - experiment::EffectiveQC0::${variable} == 0
- for:
- variable: *variables
-
- # Generate oma that passed QC for JEDI
- - transform: accept where
- new name: experiment::hofxQC::${variable}
- starting field: experiment::hofx0::${variable}
- where:
- - experiment::EffectiveQC0::${variable} == 0
- for:
- variable: *variables
-
-
-
-
-
-graphics:
-
- plotting_backend: Emcpy
- figure_list:
-
- # ---------- Map Plots ----------
- # Map plot of OmBQC
- # --------
-
- - batch figure:
- variables: *variables
- @CHANNELSKEY@
- dynamic options:
- - type: vminvmaxcmap
- data variable: experiment::OmBQC::${variable}
- figure:
- layout: [1,1]
- figure size: [20,10]
- title: 'OmB post QC | @NAME@ @CYCLE@ | ${variable_title}'
- output name: map_plots/@NAME@/${variable}/@CHANNELVAR@/@NAME@_${variable}@CHANNELVAR@OmBQC.png
- tight_layout: true
- plots:
- - mapping:
- projection: plcarr
- domain: global
- add_map_features: ['coastline']
- add_grid:
- add_colorbar:
- label: '${variable}'
- layers:
- - type: MapScatter
- longitude:
- variable: experiment::MetaData::longitude
- latitude:
- variable: experiment::MetaData::latitude
- data:
- variable: experiment::OmBQC::${variable}
- @CHANNELKEY@
- markersize: 0.01
- label: '$(variable)'
- colorbar: true
- # below may need to be edited/removed
- cmap: 'seismic'
- vmin: ${dynamic_vmin}
- vmax: ${dynamic_vmax}
-
-
- # Histogram plots
- # ---------------
-
- # OmA pre and post QC
- - batch figure:
- variables: *variables
- figure:
- layout: [1,1]
- title: 'OmA pre- and post QC | @NAME@ | ${variable_title}'
- output name: histograms/@NAME@/${variable}/oma_pre_post_qc_${variable}.png
- plots:
- - add_xlabel: 'Observation minus anl pre- and post-QC'
- add_ylabel: 'Count'
- add_legend:
- loc: 'upper left'
- statistics:
- fields:
- - field_name: experiment::OmAQC::${variable}
- xloc: 0.5
- yloc: -0.10
- kwargs:
- fontsize: 6
- statistics_variables:
- - n
- - min
- - mean
- - max
- - std
- layers:
- - type: Histogram
- data:
- variable: experiment::OmAQC::${variable}
- color: 'blue'
- label: 'OmA (post QC)'
- bins: 100
- alpha: 0.5
- - type: Histogram
- data:
- variable: experiment::oman::${variable}
- color: 'red'
- label: 'OmA (pre QC)'
- bins: 100
- alpha: 0.5
-
- # diff between OmA and OmB
- - batch figure:
- variables: *variables
- figure:
- layout: [1,1]
- title: 'OmA and OmB, post-QC | @NAME@ | ${variable_title}'
- output name: histograms/@NAME@/${variable}/oma_omb_histogram_${variable}.png
- plots:
- - add_xlabel: 'OmA and OmB post-QC'
- add_ylabel: 'Count'
- add_legend:
- loc: 'upper left'
- statistics:
- fields:
- - field_name: experiment::OmAQC::${variable}
- xloc: 0.5
- yloc: -0.10
- kwargs:
- fontsize: 6
- statistics_variables:
- - n
- - min
- - mean
- - max
- - std
- layers:
- - type: Histogram
- data:
- variable: experiment::OmAQC::${variable}
- color: 'blue'
- label: 'OmA (post QC)'
- bins: 100
- alpha: 0.5
- - type: Histogram
- data:
- variable: experiment::OmBQC::${variable}
- color: 'red'
- label: 'OmB (post QC)'
- bins: 100
- alpha: 0.5
-
- - batch figure:
- variables: *variables
- @CHANNELSKEY@
- figure:
- layout: [1,1]
- title: 'Observations vs. JEDI h(x) | @NAME@ @CYCLE@ | ${variable_title}'
- output name: observation_scatter_plots/jedi_hofx_vs_obs_@CYCLE@_@NAME@_${variable}@CHANNELVAR@.png
- plots:
- - add_xlabel: 'Observation Value'
- add_ylabel: 'JEDI h(x)'
- add_grid:
- add_legend:
- loc: 'upper left'
- layers:
- - type: Scatter
- x:
- variable: experiment::ObsValue::${variable}
- y:
- variable: experiment::hofx0::${variable}
- @CHANNELKEY@
- markersize: 1
- color: 'black'
- label: 'JEDI h(x) versus obs (all obs)'
- - type: Scatter
- x:
- variable: experiment::ObsValue::${variable}
- y:
- variable: experiment::hofxQC::${variable}
- @CHANNELKEY@
- markersize: 1
- color: 'red'
- label: 'JEDI h(x) versus obs (passed QC in JEDI)'
diff --git a/ush/soca/soca_vrfy.py b/ush/soca/soca_vrfy.py
deleted file mode 100755
index 6ad0ec27e..000000000
--- a/ush/soca/soca_vrfy.py
+++ /dev/null
@@ -1,314 +0,0 @@
-#!/usr/bin/env python3
-
-# make plots for marine analysis
-
-import matplotlib.pyplot as plt
-import xarray as xr
-import cartopy
-import cartopy.crs as ccrs
-import numpy as np
-import os
-
-
-projs = {'North': ccrs.NorthPolarStereo(),
- 'South': ccrs.SouthPolarStereo(),
- 'Global': ccrs.Mollweide(central_longitude=-150)}
-
-
-def plotConfig(grid_file=[],
- data_file=[],
- layer_file=[],
- variable=[],
- PDY=os.getenv('PDY'),
- cyc=os.getenv('cyc'),
- exp=os.getenv('PSLOT'),
- levels=[],
- bounds=[],
- colormap=[],
- max_depth=np.nan,
- max_depths=[700.0, 5000.0],
- comout=[],
- variables_horiz={},
- variables_zonal={},
- variables_meridional={},
- lat=np.nan,
- lats=np.arange(-60, 60, 10),
- lon=np.nan,
- lons=np.arange(-280, 80, 30),
- proj='set me',
- projs=['Global']):
-
- # Map variable names to their units
- variable_units = {
- 'ave_ssh': 'meter',
- 'Temp': 'deg C',
- 'Salt': 'psu',
- 'aice_h': 'unitless',
- 'hi_h': 'meter',
- 'hs_h': 'meter',
- 'u': 'm/s',
- 'v': 'm/s'
- }
-
- """
- Prepares the configuration for the plotting functions below
- """
- config = {}
- config['comout'] = comout # output directory
- config['grid file'] = grid_file
- config['fields file'] = data_file
- config['layer file'] = layer_file
- config['PDY'] = PDY
- config['cyc'] = cyc
- config['exp'] = exp
- config['levels'] = [1]
- config['colormap'] = colormap
- config['bounds'] = bounds
- config['lats'] = lats # all the lats to plot
- config['lat'] = lat # the lat being currently plotted
- config['lons'] = lons # all the lons to plot
- config['lon'] = lon # the lon being currently plotted
- config['max depths'] = max_depths # all the max depths to plot
- config['max depth'] = max_depth # the max depth currently plotted
- config['horiz variables'] = variables_horiz # all the vars for horiz plots
- config['zonal variables'] = variables_zonal # all the vars for zonal plots
- config['meridional variables'] = variables_meridional # all the vars for meridional plots
- config['variable'] = variable # the variable currently plotted
- config['projs'] = projs # all the projections etc.
- config['proj'] = proj
-
- # Add units to the config for each variable
- config['variable_units'] = variable_units
- return config
-
-
-def plotHorizontalSlice(config):
- """
- Contourf of a horizontal slice of an ocean field
- """
- grid = xr.open_dataset(config['grid file'])
- data = xr.open_dataset(config['fields file'])
-
- dirname = os.path.join(config['comout'], config['variable'])
- os.makedirs(dirname, exist_ok=True)
-
- variable = config['variable']
- unit = config['variable_units'].get(config['variable'], 'unknown')
- exp = config['exp']
- PDY = config['PDY']
- cyc = config['cyc']
-
- if variable in ['Temp', 'Salt', 'u', 'v']:
- level = config['levels'][0]
- slice_data = np.squeeze(data[variable])[level, :, :]
- label_colorbar = f"{variable} ({unit}) Level {level}"
- figname = os.path.join(dirname, variable + '_Level_' + str(level))
- title = f"{exp} {PDY} {cyc} {variable} Level {level}"
- else:
- slice_data = np.squeeze(data[variable])
- label_colorbar = f"{variable} ({unit})"
- figname = os.path.join(dirname, variable + '_' + config['proj'])
- title = f"{exp} {PDY} {cyc} {variable}"
-
- bounds = config['horiz variables'][variable]
- slice_data = np.clip(slice_data, bounds[0], bounds[1])
-
- fig, ax = plt.subplots(figsize=(8, 5), subplot_kw={'projection': projs[config['proj']]})
-
- # Use pcolor to plot the data
- pcolor_plot = ax.pcolormesh(np.squeeze(grid.lon),
- np.squeeze(grid.lat),
- slice_data,
- vmin=bounds[0], vmax=bounds[1],
- transform=ccrs.PlateCarree(),
- cmap=config['colormap'],
- zorder=0)
-
- # Add colorbar for filled contours
- cbar = fig.colorbar(pcolor_plot, ax=ax, shrink=0.75, orientation='horizontal')
- cbar.set_label(label_colorbar)
-
- # Add contour lines with specified linewidths
- contour_levels = np.linspace(bounds[0], bounds[1], 5)
- ax.contour(np.squeeze(grid.lon),
- np.squeeze(grid.lat),
- slice_data,
- levels=contour_levels,
- colors='black',
- linewidths=0.1,
- transform=ccrs.PlateCarree(),
- zorder=2)
-
- try:
- ax.coastlines() # TODO: make this work on hpc
- except Exception as e:
- print(f"Warning: could not add coastlines. {e}")
- ax.set_title(title)
- if config['proj'] == 'South':
- ax.set_extent([-180, 180, -90, -50], ccrs.PlateCarree())
- if config['proj'] == 'North':
- ax.set_extent([-180, 180, 50, 90], ccrs.PlateCarree())
- # ax.add_feature(cartopy.feature.LAND) # TODO: make this work on hpc
- plt.savefig(figname, bbox_inches='tight', dpi=300)
- plt.close(fig)
-
-
-def plotZonalSlice(config):
- """
- Contourf of a zonal slice of an ocean field
- """
- variable = config['variable']
- unit = config['variable_units'].get(config['variable'], 'unknown')
- exp = config['exp']
- PDY = config['PDY']
- cyc = config['cyc']
- lat = float(config['lat'])
- grid = xr.open_dataset(config['grid file'])
- data = xr.open_dataset(config['fields file'])
- layer = xr.open_dataset(config['layer file'])
- lat_index = np.argmin(np.array(np.abs(np.squeeze(grid.lat)[:, 0] - lat)))
- slice_data = np.squeeze(np.array(data[variable]))[:, lat_index, :]
- depth = np.squeeze(np.array(layer['h']))[:, lat_index, :]
- depth[np.where(np.abs(depth) > 10000.0)] = 0.0
- depth = np.cumsum(depth, axis=0)
- bounds = config['zonal variables'][variable]
- slice_data = np.clip(slice_data, bounds[0], bounds[1])
- x = np.tile(np.squeeze(grid.lon[:, lat_index]), (np.shape(depth)[0], 1))
-
- fig, ax = plt.subplots(figsize=(8, 5))
-
- # Plot the filled contours
- contourf_plot = ax.contourf(x, -depth, slice_data,
- levels=np.linspace(bounds[0], bounds[1], 100),
- vmin=bounds[0], vmax=bounds[1],
- cmap=config['colormap'])
-
- # Add contour lines with specified linewidths
- contour_levels = np.linspace(bounds[0], bounds[1], 5)
- ax.contour(x, -depth, slice_data,
- levels=contour_levels,
- colors='black',
- linewidths=0.1)
-
- # Add colorbar for filled contours
- cbar = fig.colorbar(contourf_plot, ax=ax, shrink=0.5, orientation='horizontal')
- cbar.set_label(f"{config['variable']} ({unit}) Lat {lat}")
-
- # Set the colorbar ticks
- cbar.set_ticks(contour_levels)
- contourf_plot.set_clim(bounds[0], bounds[1])
-
- ax.set_ylim(-config['max depth'], 0)
- title = f"{exp} {PDY} {cyc} {variable} lat {int(lat)}"
- ax.set_title(title)
- dirname = os.path.join(config['comout'], config['variable'])
- os.makedirs(dirname, exist_ok=True)
- figname = os.path.join(dirname, config['variable'] +
- 'zonal_lat_' + str(int(lat)) + '_' + str(int(config['max depth'])) + 'm')
- plt.savefig(figname, bbox_inches='tight', dpi=300)
- plt.close(fig)
-
-
-def plotMeridionalSlice(config):
- """
- Contourf of a Meridional slice of an ocean field
- """
- variable = config['variable']
- unit = config['variable_units'].get(config['variable'], 'unknown')
- exp = config['exp']
- PDY = config['PDY']
- cyc = config['cyc']
- lon = float(config['lon'])
- grid = xr.open_dataset(config['grid file'])
- data = xr.open_dataset(config['fields file'])
- layer = xr.open_dataset(config['layer file'])
- lon_index = np.argmin(np.array(np.abs(np.squeeze(grid.lon)[0, :] - lon)))
- slice_data = np.squeeze(np.array(data[config['variable']]))[:, :, lon_index]
- depth = np.squeeze(np.array(layer['h']))[:, :, lon_index]
- depth[np.where(np.abs(depth) > 10000.0)] = 0.0
- depth = np.cumsum(depth, axis=0)
- bounds = config['meridional variables'][variable]
- slice_data = np.clip(slice_data, bounds[0], bounds[1])
- y = np.tile(np.squeeze(grid.lat)[:, lon_index], (np.shape(depth)[0], 1))
-
- fig, ax = plt.subplots(figsize=(8, 5))
-
- # Plot the filled contours
- contourf_plot = ax.contourf(y, -depth, slice_data,
- levels=np.linspace(bounds[0], bounds[1], 100),
- vmin=bounds[0], vmax=bounds[1],
- cmap=config['colormap'])
-
- # Add contour lines with specified linewidths
- contour_levels = np.linspace(bounds[0], bounds[1], 5)
- ax.contour(y, -depth, slice_data,
- levels=contour_levels,
- colors='black',
- linewidths=0.1)
-
- # Add colorbar for filled contours
- cbar = fig.colorbar(contourf_plot, ax=ax, shrink=0.5, orientation='horizontal')
- cbar.set_label(f"{config['variable']} ({unit}) Lon {lon}")
-
- # Set the colorbar ticks
- cbar.set_ticks(contour_levels)
- contourf_plot.set_clim(bounds[0], bounds[1])
-
- ax.set_ylim(-config['max depth'], 0)
- title = f"{exp} {PDY} {cyc} {variable} lon {int(lon)}"
- ax.set_title(title)
- dirname = os.path.join(config['comout'], config['variable'])
- os.makedirs(dirname, exist_ok=True)
- figname = os.path.join(dirname, config['variable'] +
- 'meridional_lon_' + str(int(lon)) + '_' + str(int(config['max depth'])) + 'm')
- plt.savefig(figname, bbox_inches='tight', dpi=300)
- plt.close(fig)
-
-
-class statePlotter:
-
- def __init__(self, config_dict):
- self.config = config_dict
-
- def plot(self):
- # Loop over variables, slices (horiz and vertical) and projections ... and whatever else is needed
-
- #######################################
- # zonal slices
-
- for lat in self.config['lats']:
- self.config['lat'] = lat
-
- for max_depth in self.config['max depths']:
- self.config['max depth'] = max_depth
-
- variableBounds = self.config['zonal variables']
- for variable in variableBounds.keys():
- bounds = variableBounds[variable]
- self.config.update({'variable': variable, 'bounds': bounds})
- plotZonalSlice(self.config)
-
- #######################################
- # Meridional slices
-
- for lon in self.config['lons']:
- self.config['lon'] = lon
-
- for max_depth in self.config['max depths']:
- self.config['max depth'] = max_depth
-
- variableBounds = self.config['meridional variables']
- for variable in variableBounds.keys():
- bounds = variableBounds[variable]
- self.config.update({'variable': variable, 'bounds': bounds})
- plotMeridionalSlice(self.config)
-
- #######################################
- # Horizontal slices
- for proj in self.config['projs']:
-
- variableBounds = self.config['horiz variables']
- for variable in variableBounds.keys():
- bounds = variableBounds[variable]
- self.config.update({'variable': variable, 'bounds': bounds, 'proj': proj})
- plotHorizontalSlice(self.config)
diff --git a/utils/soca/fig_gallery/README.md b/utils/soca/fig_gallery/README.md
deleted file mode 100644
index d021a7d81..000000000
--- a/utils/soca/fig_gallery/README.md
+++ /dev/null
@@ -1,38 +0,0 @@
-## 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`.
-
diff --git a/utils/soca/fig_gallery/gdassoca_obsstats.py b/utils/soca/fig_gallery/gdassoca_obsstats.py
deleted file mode 100644
index 00c60b971..000000000
--- a/utils/soca/fig_gallery/gdassoca_obsstats.py
+++ /dev/null
@@ -1,157 +0,0 @@
-#!/usr/bin/env python3
-
-
-# creates figures of timeseries from the csv outputs computed by gdassoca_obsstats.x
-import argparse
-from itertools import product
-import os
-import glob
-import pandas as pd
-from jinja2 import Template
-import matplotlib.pyplot as plt
-import matplotlib.dates as mdates
-
-colors = [
- "lightsteelblue",
- "lightgreen",
- "peachpuff",
- "lightpink",
- "lightgoldenrodyellow",
- "paleturquoise",
- "lightcoral",
- "palegreen",
- "palegoldenrod",
- "mistyrose",
- "lavender"
- "lightsalmon",
-]
-
-def get_inst(csv_file_name):
- """Extract the instrument name from the csv file name. gdas.t00z.ocn.sst_ahi_h08_l3c.stats.csv -> sst_ahi_h08_l3c"""
- return csv_file_name.split('.')[-3]
-
-class ObsStats:
- def __init__(self):
- self.data = pd.DataFrame()
-
- def read_csv(self, filepaths):
- # Iterate through the list of file paths and append their data
- for filepath in filepaths:
- new_data = pd.read_csv(filepath)
-
- # Convert date to datetime for easier plotting
- new_data['date'] = pd.to_datetime(new_data['date'], format='%Y%m%d%H')
- self.data = pd.concat([self.data, new_data], ignore_index=True)
- self.data.sort_values('date', inplace=True)
-
- def plot_timeseries(self, ocean, variable, inst="", dirout=""):
-
- # Filter data for the given ocean and variable
- filtered_data = self.data[(self.data['Ocean'] == ocean) & (self.data['Variable'] == variable)]
- if filtered_data.empty:
- print("No data available for the given ocean and variable combination.")
- return []
-
- # Get unique experiments
- experiments = filtered_data['Exp'].unique()
- experiments.sort()
- print(experiments)
-
- # Plot settings
- fig, axs = plt.subplots(3, 1, figsize=(10, 15), sharex=True)
- fig.suptitle(f'{inst} {variable} statistics, {ocean} ocean', fontsize=18, fontweight='bold')
-
-
- exp_counter = 0
- for exp in experiments:
- exp_data = self.data[(self.data['Ocean'] == ocean) &
- (self.data['Variable'] == variable) &
- (self.data['Exp'] == exp)]
-
- # Plot RMSE
- axs[0].plot(exp_data['date'], exp_data['RMSE'], marker='o', linestyle='-', color=colors[exp_counter], label=exp)
- axs[0].xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d %H'))
- axs[0].xaxis.set_major_locator(mdates.DayLocator())
- axs[0].tick_params(labelbottom=False)
- axs[0].set_ylabel('RMSE', fontsize=18, fontweight='bold')
- axs[0].legend()
- axs[0].grid(True)
-
- # Plot Bias
- axs[1].plot(exp_data['date'], exp_data['Bias'], marker='o', linestyle='-', color=colors[exp_counter], label=exp)
- axs[1].xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d %H'))
- axs[1].xaxis.set_major_locator(mdates.DayLocator())
- axs[1].tick_params(labelbottom=False)
- axs[1].set_ylabel('Bias', fontsize=18, fontweight='bold')
- axs[1].grid(True)
-
- # Plot Count
- axs[2].plot(exp_data['date'], exp_data['Count'], marker='o', linestyle='-', color=colors[exp_counter], label=exp)
- axs[2].xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d %H'))
- axs[2].xaxis.set_major_locator(mdates.DayLocator())
- axs[2].set_ylabel('Count', fontsize=18, fontweight='bold')
- axs[2].grid(True)
-
- exp_counter += 1
-
- # Improve layout and show plot
- plt.tight_layout(rect=[0, 0.03, 1, 0.95])
- plt.savefig(f'{dirout}/{inst}_{variable}_{ocean}.png')
- # close the figure
- plt.close(fig)
-
- return experiments
-
-if __name__ == "__main__":
- epilog = ["Usage examples: ./gdassoca_obsstats.py --exps cp1/COMROOT/cp1 cp2/COMROOT/cp2 --inst sst_abi_g16_l3c --dirout cp1vscp2"]
- parser = argparse.ArgumentParser(description="Observation space RMSE's and BIAS's",
- formatter_class=argparse.RawDescriptionHelpFormatter,
- epilog=os.linesep.join(epilog))
- parser.add_argument("--exps", nargs='+', required=True,
- help="Path to the experiment's COMROOT")
- parser.add_argument("--inst", required=True, help="The name of the instrument/platform (ex: sst_abi_g16_l3c) or a wild card (eg sst*)")
- parser.add_argument("--dirout", required=True, help="Output directory")
- args = parser.parse_args()
-
- insts = []
- inst = args.inst
- os.makedirs(args.dirout, exist_ok=True)
-
- # Get all instruments/obs spaces
- for exp in args.exps:
- wc = exp + f'/*.*/??/analysis/ocean/*{inst}*.stats.csv'
- flist = glob.glob(wc)
- for fname in flist:
- insts.append(get_inst(fname))
- insts = list(set(insts))
- insts.sort()
- print(insts)
-
- experiments = []
- for inst in insts:
- print(f"Processing {inst}")
- flist = []
- for exp in args.exps:
- wc = exp + f'/*.*/??/analysis/ocean/*{inst}*.stats.csv'
- flist.append(glob.glob(wc))
-
- flist = sum(flist, [])
- obsStats = ObsStats()
- obsStats.read_csv(flist)
- for var, ocean in product(['ombg_noqc', 'ombg_qc'],
- ['Global', 'Atlantic', 'Pacific', 'Indian', 'Arctic', 'Southern']):
- experiments.extend(obsStats.plot_timeseries(ocean, var, inst=inst, dirout=args.dirout))
-
- # Select unique elements of experiments
- experiments = list(set(experiments))
- experiments.sort()
-
- # Create the html document from the jinja2 template
- template_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'gdassoca_obsstats_template.html')
- template = Template(open(template_path).read())
- context = {'insts': insts, 'experiments': experiments}
- indexhtml = template.render(context)
-
- # Write the rendered HTML to a file
- with open(f'{args.dirout}/index.html', 'w') as f:
- f.write(indexhtml)
diff --git a/utils/soca/fig_gallery/gdassoca_obsstats_template.html b/utils/soca/fig_gallery/gdassoca_obsstats_template.html
deleted file mode 100644
index ba717da0d..000000000
--- a/utils/soca/fig_gallery/gdassoca_obsstats_template.html
+++ /dev/null
@@ -1,120 +0,0 @@
-
-
-
-
-
-
-
-
-
-
- Time Series of (Observation - Background) Statistics
-
-
- Experiments: {{ experiments|join(', ') }}
-
-
-
-
- Global
- Arctic
- Atlantic
- Indian
- Pacific
- Southern
-
-
-
-
- {% for inst in insts %}
- {{ inst }}
- {% endfor %}
-
-
-
-
-
-
-
-
diff --git a/utils/soca/fig_gallery/marine_vrfy_display/README b/utils/soca/fig_gallery/marine_vrfy_display/README
deleted file mode 100644
index dde23647d..000000000
--- a/utils/soca/fig_gallery/marine_vrfy_display/README
+++ /dev/null
@@ -1,29 +0,0 @@
-################################################
-# README for index_vrfy_marine.html
-################################################
-
-To use, follow these steps:
-
-----------------------------
-
-1. Login to Hera via X2Go and type on the command line:
-
- firefox index_vrfy_marine.html
-
-2. In the webpage,
- a. Enter the path to your main verification directory. See 2b for info on what to include in this path.
- b. Are your figures in your COMROOT or from HPSS?
- If COMROOT, the main path should include everything BEFORE /gdas.YearMonthDay subdirectories.
- If HPSS, the main path should include everything BEFORE /YearMonthDayHour subdirectories.
- Enter COMROOT or HPSS.
- c. Enter the date and cycle time you wish to display.
-
-3. Refresh the webpage tab by clicking the refresh button. You should still see your entered path and date/time.
-
-4. Navigate the dropdown menu on the left and click to display figures.
-
-----------------------------
-NOTES:
- N1: If you wish to look at figures from a different experiment or for a different date/time, repeat Steps 2-4.
-
-################################################
diff --git a/utils/soca/fig_gallery/marine_vrfy_display/default.css b/utils/soca/fig_gallery/marine_vrfy_display/default.css
deleted file mode 100644
index 4ff19b726..000000000
--- a/utils/soca/fig_gallery/marine_vrfy_display/default.css
+++ /dev/null
@@ -1,690 +0,0 @@
- html, body
- {
- height: 100%;
- }
-
- body
- {
- margin: 0px;
- padding: 0px;
- background: #202020;
- font-family: 'Source Sans Pro', sans-serif;
- font-size: 12pt;
- font-weight: 300;
- color: #444444;
- }
-
-
- h1, h2, h3
- {
- margin: 0;
- padding: 0;
- font-weight: 600;
- color: #333333;
- }
-
- p, ol, ul
- {
- margin-top: 0;
- }
-
- ol, ul
- {
- padding: 0;
- list-style: none;
- }
-
- p
- {
- line-height: 180%;
- }
-
- strong
- {
- }
-
- a
- {
- color: #2980b9;
- }
-
- a:hover
- {
- text-decoration: none;
- }
-
- .container
- {
- overflow: hidden;
- margin: 0em auto;
- width: 1350px;
- }
-
-/*********************************************************************************/
-/* Image Style */
-/*********************************************************************************/
-
- .image
- {
- display: inline-block;
- }
-
- .image img
- {
- display: block;
- width: 100%;
- }
-
- .image-full
- {
- display: block;
- width: 100%;
- margin: 0 0 2em 0;
- }
-
- .image-left
- {
- float: left;
- margin: 0 2em 2em 0;
- }
-
- .image-centered
- {
- display: block;
- margin: 0 0 2em 0;
- }
-
- .image-centered img
- {
- margin: 0 auto;
- width: auto;
- }
-
-/*********************************************************************************/
-/* List Styles */
-/*********************************************************************************/
-
- ul.style1
- {
- margin: 0 auto;
- padding: 0;
- width: 80%;
- overflow: hidden;
- list-style: none;
- text-align: left;
- color: #6c6c6c
- }
-
- ul.style1 li
- {
- padding: 1.6em 0em 0em 0em;
- margin: 0 0 2.5em 0;
- border-top: 1px solid rgba(0,0,0,.1);
- }
-
- ul.style1 li:first-child
- {
- border-top: none;
- }
-
- ul.style1 p
- {
- margin: 0;
- }
-
- ul.style1 a
- {
- display: block;
- text-decoration: none;
- color: #2D2D2D;
- }
-
- ul.style1 a:hover
- {
- text-decoration: underline;
- }
-
- ul.style1 h3
- {
- padding: 1em 0em 5px 0em;
- text-transform: uppercase;
- font-size: 1em;
- font-weight: 400;
- }
-
- ul.style1 .first
- {
- padding-top: 0;
- background: none;
- }
-
- ul.style1 .date
- {
- float: left;
- position: relative;
- width: 80px;
- height: 70px;
- margin: 0.5em 1.5em 0em 0.5em;
- padding: 1.5em 0em 1.5em 0em;
- box-shadow: 0px 0px 0px 5px rgba(255,255,255,0.1);
- line-height: normal;
- text-align: center;
- text-transform: uppercase;
- text-shadow: 0px 1px 0px rgba(0,0,0,.2);
- font-size: 1em;
- font-weight: 400;
- border-right: 1px solid rgba(0,0,0,.1);
- }
-
- ul.style1 .date:after
- {
- content: '';
- display: block;
- position: absolute;
- left: 0;
- top: 0;
- width: 100%;
- height: 100%;
- border-radius: 6px;
- }
-
- ul.style1 .date b
- {
- margin: 0;
- padding: 0;
- display: block;
- margin-top: -5px;
- font-size: 1.8em;
- font-weight: 700;
- }
-
- ul.style1 .date a
- {
- }
-
- ul.style1 .date a:hover
- {
- text-decoration: none;
- }
-
-
-/*********************************************************************************/
-/* Social Icon Styles */
-/*********************************************************************************/
-
- ul.contact
- {
- margin: 0;
- padding: 2em 0em 0em 0em;
- list-style: none;
- }
-
- ul.contact li
- {
- display: inline-block;
- padding: 0em 0.30em;
- font-size: 1em;
- }
-
- ul.contact li span
- {
- display: none;
- margin: 0;
- padding: 0;
- }
-
- ul.contact li a
- {
- color: #FFF;
- }
-
- ul.contact li a:before
- {
- display: inline-block;
- background: #3f3f3f;
- width: 40px;
- height: 40px;
- line-height: 40px;
- border-radius: 20px;
- text-align: center;
- color: #FFFFFF;
- }
-
- ul.contact li a.icon-twitter:before { background: #2DAAE4; }
- ul.contact li a.icon-facebook:before { background: #39599F; }
- ul.contact li a.icon-dribbble:before { background: #C4376B; }
- ul.contact li a.icon-tumblr:before { background: #31516A; }
- ul.contact li a.icon-rss:before { background: #F2600B; }
-
-/*********************************************************************************/
-/* Button Style */
-/*********************************************************************************/
-
- .button
- {
- display: inline-block;
- padding: 1em 3em 1em 2em;
- letter-spacing: 0.20em;
- text-decoration: none;
- text-transform: uppercase;
- font-weight: 400;
- font-size: 0.90em;
- color: #FFF;
- }
-
- .button:before
- {
- display: inline-block;
- background: #FFC31F;
- margin-right: 1em;
- width: 40px;
- height: 40px;
- line-height: 40px;
- border-radius: 20px;
- text-align: center;
- color: #272925;
- }
-
-/*********************************************************************************/
-/* 4-column */
-/*********************************************************************************/
-
- .box1,
- .box2,
- .box3,
- .box4
- {
- width: 235px;
- }
-
- .box1,
- .box2,
- .box3,
- {
- float: left;
- margin-right: 20px;
- }
-
- .box4
- {
- float: right;
- }
-
-/*********************************************************************************/
-/* 3-column */
-/*********************************************************************************/
-
- .boxA,
- .boxB,
- .boxC
- {
- width: 320px;
- }
-
- .boxA,
- .boxB,
- {
- float: left;
- margin-right: 20px;
- }
-
- .boxC
- {
- float: right;
- }
-
-/*********************************************************************************/
-/* 2-column */
-/*********************************************************************************/
-
- .tbox1,
- .tbox2
- {
- width: 575px;
- }
-
- .tbox1
- {
- float: left;
- }
-
- .tbox2
- {
- float: right;
- }
-
-/*********************************************************************************/
-/* Heading Titles */
-/*********************************************************************************/
-
- .title
- {
- margin-bottom: 3em;
- }
-
- .title h2
- {
- text-transform: lowercase;
- font-size: 2.8em;
- }
-
- .title .byline
- {
- font-size: 1.3em;
- color: #6F6F6F;
- }
-
-/*********************************************************************************/
-/* Header */
-/*********************************************************************************/
-
- #header
- {
- position: relative;
- float: left;
- width: 225px;
- padding: 3em 0em;
- }
-
-/*********************************************************************************/
-/* Logo */
-/*********************************************************************************/
-
- #logo
- {
- text-align: center;
- margin-bottom: 4em;
- }
-
- #logo h1
- {
- display: block;
- }
-
- #logo a
- {
- text-decoration: none;
- color: #FFF;
- }
-
- #logo span
- {
- padding-right: 0.5em;
- text-transform: uppercase;
- font-size: 0.90em;
- color: rgba(255,255,255,0.3);
- }
-
- #logo span a
- {
- color: rgba(255,255,255,0.5);
- }
-
- #logo img
- {
- display: inline-block;
- margin-bottom: 1em;
- border-radius: 50%;
- }
-
-/*********************************************************************************/
-/* Menu */
-/*********************************************************************************/
-
- #menu
- {
- }
-
- #menu ul
- {
- }
-
- #menu li
- {
- border-top: 1px solid rgba(255,255,255,0.4);
- }
-
- #menu li a, #menu li span
- {
- display: block;
- padding: 1em 1em;
- text-align: center;
- text-decoration: none;
- text-transform: uppercase;
- font-weight: 700;
- color: rgba(255,255,255,1);
- }
-
- #menu ul li a:hover {
- background-color: #2980b9;
- border-left: solid 10px #ffffff;
- }
-
- #menu li:hover a, #menu li.active a, #menu li.active span
- {
- }
-
- #menu .current_page_item a
- {
- background: #2980b9;
- color: rgba(255,255,255,1);
- }
-
- #menu .icon
- {
- }
-
-/*********************************************************************************/
-/* Dropdown */
-/*********************************************************************************/
- .dropbtn {
- position: relative;
- display: block;
- padding: 1em 1em;
- width: 100%;
- text-align: center;
- text-decoration: none;
- text-transform: uppercase;
- font-family: 'Source Sans Pro', sans-serif;
- font-size: 12pt;
- font-weight: 700;
- color: rgba(255,255,255,1);
- background-color: #112e51;
- border-top: 1px solid rgba(255,255,255,0.4);
- border-left: none;
- border-bottom: none;
- border-right: none;
- cursor: pointer;
- }
-
- #active {
- background-color: #2980b9;
- color: rgba(255,255,255,1);
- }
-
- .dropbtn:focus {
- background-color: #2980b9;
- border-left: solid 10px #ffffff;
- display: block;
- }
-
- .dropdown {
- position: relative;
- display: inline-block;
- width: 100%;
- }
-
- /* NESTED DROPDOWNS */
- /* The dropdown content (submenus) */
- .dropdown-content {
- display: none;
- left: 100%;
- top: -50%;
- position: absolute;
- background-color: #112e51;
- min-width: 160px;
- z-index: 1;
- }
-
- .dropdown-content a {
- display: block;
- color: rgba(255,255,255,1);
- padding: 1em 1em;
- border: 1px solid rgba(255,255,255,0.4);
- text-align: center;
- text-decoration: none;
- }
-
- .dropdown-content a:hover {
- background-color: #575757;
- }
-
- /* Style for the submenu */
- .submenu {
- display: none;
- position: relative;
- left: 100%;
- top: 1;
- background-color: #575757;
- min-width: 160px;
- }
-
- /* Show submenu when the parent item is clicked */
- .dropdown-item.open .submenu {
- display: block;
- }
-
- /* Show the deepter nested dropdown when the button is clicked */
- .dropdown.open .dropdown-content {
- display: block;
- }
-
- /* END NESTED DROPDOWNS */
-
- .show {display: block;}
-
-/*********************************************************************************/
-/* Banner */
-/*********************************************************************************/
-
- #banner
- {
- margin-bottom: 0em;
- }
-
-/*********************************************************************************/
-/* Page */
-/*********************************************************************************/
-
- #page
- {
- background: #112e51;
-/* background: #2a2a2a; */
- }
-
-/*********************************************************************************/
-/* Main */
-/*********************************************************************************/
-
- #main
- {
- overflow: hidden;
- float: right;
- width: 1125px;
- padding: 1em 0px 5em 0px;
- background: #FFF;
- border-top: 6px solid #2980b9;
- text-align: center;
- }
-
-/*********************************************************************************/
-/* Featured */
-/*********************************************************************************/
-
- #featured
- {
- overflow: hidden;
- margin-bottom: 3em;
- padding-top: 5em;
- border-top: 1px solid rgba(0,0,0,0.08);
- }
-
-/*********************************************************************************/
-/* Sidebar */
-/*********************************************************************************/
-
- #sidebar
- {
- }
-
-/*********************************************************************************/
-/* Footer */
-/*********************************************************************************/
-
- #footer
- {
- overflow: hidden;
- padding: 0em 0em;
- border-top: 1px solid rgba(0,0,0,0.08);
- font-weight: bolder;
- }
-
-/*********************************************************************************/
-/* Welcome */
-/*********************************************************************************/
-
- #welcome
- {
- overflow: hidden;
- padding: 0em 1em;
- border-top: 1px solid rgba(0,0,0,0.08);
- font-weight: bolder;
- }
-
-/*********************************************************************************/
-/* Contact */
-/*********************************************************************************/
-
- #contact
- {
- overflow: hidden;
- padding: 0em 0em;
- border-top: 1px solid rgba(0,0,0,0.08);
- font-weight: bolder;
- }
-
-/*********************************************************************************/
-/* Copyright */
-/*********************************************************************************/
-
- #copyright
- {
- overflow: hidden;
- padding: 1em 0em;
- border-top: 1px solid rgba(0,0,0,0.08);
- }
-
- #copyright span
- {
- display: block;
- letter-spacing: 0.20em;
- line-height: 2.5em;
- text-align: center;
- text-transform: uppercase;
- font-size: 0.8em;
- font-weight: normal;
- color: rgba(0,0,0,0.7);
- }
-
- #copyright a
- {
- text-decoration: none;
- color: rgba(0,0,0,0.9);
- }
-
- .fa
- {
- display: block;
- color: #000;
- background: red;
- }
diff --git a/utils/soca/fig_gallery/marine_vrfy_display/fonts.css b/utils/soca/fig_gallery/marine_vrfy_display/fonts.css
deleted file mode 100644
index f90cc4360..000000000
--- a/utils/soca/fig_gallery/marine_vrfy_display/fonts.css
+++ /dev/null
@@ -1,422 +0,0 @@
-@charset 'UTF-8';
-
-@font-face{font-family:'FontAwesome';src:url('font/fontawesome-webfont.eot?v=4.0.1');src:url('font/fontawesome-webfont.eot?#iefix&v=4.0.1') format('embedded-opentype'),url('font/fontawesome-webfont.woff?v=4.0.1') format('woff'),url('font/fontawesome-webfont.ttf?v=4.0.1') format('truetype'),url('font/fontawesome-webfont.svg?v=4.0.1#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}
-
-/*********************************************************************************/
-/* Icons */
-/* Powered by Font Awesome by Dave Gandy | http://fontawesome.io */
-/* Licensed under the SIL OFL 1.1 (font), MIT (CSS) */
-/*********************************************************************************/
-
- .fa
- {
- text-decoration: none;
- }
-
- .fa:before
- {
- display:inline-block;
- font-family: FontAwesome;
- font-size: 1.25em;
- text-decoration: none;
- font-style: normal;
- font-weight: normal;
- line-height: 1;
- -webkit-font-smoothing:antialiased;
- -moz-osx-font-smoothing:grayscale;
- }
-
- .fa-lg{font-size:1.3333333333333333em;line-height:.75em;vertical-align:-15%}
- .fa-2x{font-size:2em}
- .fa-3x{font-size:3em}
- .fa-4x{font-size:4em}
- .fa-5x{font-size:5em}
- .fa-fw{width:1.2857142857142858em;text-align:center}
- .fa-ul{padding-left:0;margin-left:2.142857142857143em;list-style-type:none}.fa-ul>li{position:relative}
- .fa-li{position:absolute;left:-2.142857142857143em;width:2.142857142857143em;top:.14285714285714285em;text-align:center}.fa-li.fa-lg{left:-1.8571428571428572em}
- .fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}
- .pull-right{float:right}
- .pull-left{float:left}
- .fa.pull-left{margin-right:.3em}
- .fa.pull-right{margin-left:.3em}
- .fa-spin{-webkit-animation:spin 2s infinite linear;-moz-animation:spin 2s infinite linear;-o-animation:spin 2s infinite linear;animation:spin 2s infinite linear}
- @-moz-keyframes spin{0%{-moz-transform:rotate(0deg)} 100%{-moz-transform:rotate(359deg)}}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0deg)} 100%{-webkit-transform:rotate(359deg)}}@-o-keyframes spin{0%{-o-transform:rotate(0deg)} 100%{-o-transform:rotate(359deg)}}@-ms-keyframes spin{0%{-ms-transform:rotate(0deg)} 100%{-ms-transform:rotate(359deg)}}@keyframes spin{0%{transform:rotate(0deg)} 100%{transform:rotate(359deg)}}.fa-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}
- .fa-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}
- .fa-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}
- .fa-flip-horizontal{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1);-webkit-transform:scale(-1, 1);-moz-transform:scale(-1, 1);-ms-transform:scale(-1, 1);-o-transform:scale(-1, 1);transform:scale(-1, 1)}
- .fa-flip-vertical{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1);-webkit-transform:scale(1, -1);-moz-transform:scale(1, -1);-ms-transform:scale(1, -1);-o-transform:scale(1, -1);transform:scale(1, -1)}
- .fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}
- .fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}
- .fa-stack-1x{line-height:inherit}
- .fa-stack-2x{font-size:2em}
- .fa-inverse{color:#fff}
- .fa-glass:before{content:"\f000"}
- .fa-music:before{content:"\f001"}
- .fa-search:before{content:"\f002"}
- .fa-envelope-o:before{content:"\f003"}
- .fa-heart:before{content:"\f004"}
- .fa-star:before{content:"\f005"}
- .fa-star-o:before{content:"\f006"}
- .fa-user:before{content:"\f007"}
- .fa-film:before{content:"\f008"}
- .fa-th-large:before{content:"\f009"}
- .fa-th:before{content:"\f00a"}
- .fa-th-list:before{content:"\f00b"}
- .fa-check:before{content:"\f00c"}
- .fa-times:before{content:"\f00d"}
- .fa-search-plus:before{content:"\f00e"}
- .fa-search-minus:before{content:"\f010"}
- .fa-power-off:before{content:"\f011"}
- .fa-signal:before{content:"\f012"}
- .fa-gear:before,.fa-cog:before{content:"\f013"}
- .fa-trash-o:before{content:"\f014"}
- .fa-home:before{content:"\f015"}
- .fa-file-o:before{content:"\f016"}
- .fa-clock-o:before{content:"\f017"}
- .fa-road:before{content:"\f018"}
- .fa-download:before{content:"\f019"}
- .fa-arrow-circle-o-down:before{content:"\f01a"}
- .fa-arrow-circle-o-up:before{content:"\f01b"}
- .fa-inbox:before{content:"\f01c"}
- .fa-play-circle-o:before{content:"\f01d"}
- .fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}
- .fa-refresh:before{content:"\f021"}
- .fa-list-alt:before{content:"\f022"}
- .fa-lock:before{content:"\f023"}
- .fa-flag:before{content:"\f024"}
- .fa-headphones:before{content:"\f025"}
- .fa-volume-off:before{content:"\f026"}
- .fa-volume-down:before{content:"\f027"}
- .fa-volume-up:before{content:"\f028"}
- .fa-qrcode:before{content:"\f029"}
- .fa-barcode:before{content:"\f02a"}
- .fa-tag:before{content:"\f02b"}
- .fa-tags:before{content:"\f02c"}
- .fa-book:before{content:"\f02d"}
- .fa-bookmark:before{content:"\f02e"}
- .fa-print:before{content:"\f02f"}
- .fa-camera:before{content:"\f030"}
- .fa-font:before{content:"\f031"}
- .fa-bold:before{content:"\f032"}
- .fa-italic:before{content:"\f033"}
- .fa-text-height:before{content:"\f034"}
- .fa-text-width:before{content:"\f035"}
- .fa-align-left:before{content:"\f036"}
- .fa-align-center:before{content:"\f037"}
- .fa-align-right:before{content:"\f038"}
- .fa-align-justify:before{content:"\f039"}
- .fa-list:before{content:"\f03a"}
- .fa-dedent:before,.fa-outdent:before{content:"\f03b"}
- .fa-indent:before{content:"\f03c"}
- .fa-video-camera:before{content:"\f03d"}
- .fa-picture-o:before{content:"\f03e"}
- .fa-pencil:before{content:"\f040"}
- .fa-map-marker:before{content:"\f041"}
- .fa-adjust:before{content:"\f042"}
- .fa-tint:before{content:"\f043"}
- .fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}
- .fa-share-square-o:before{content:"\f045"}
- .fa-check-square-o:before{content:"\f046"}
- .fa-move:before{content:"\f047"}
- .fa-step-backward:before{content:"\f048"}
- .fa-fast-backward:before{content:"\f049"}
- .fa-backward:before{content:"\f04a"}
- .fa-play:before{content:"\f04b"}
- .fa-pause:before{content:"\f04c"}
- .fa-stop:before{content:"\f04d"}
- .fa-forward:before{content:"\f04e"}
- .fa-fast-forward:before{content:"\f050"}
- .fa-step-forward:before{content:"\f051"}
- .fa-eject:before{content:"\f052"}
- .fa-chevron-left:before{content:"\f053"}
- .fa-chevron-right:before{content:"\f054"}
- .fa-plus-circle:before{content:"\f055"}
- .fa-minus-circle:before{content:"\f056"}
- .fa-times-circle:before{content:"\f057"}
- .fa-check-circle:before{content:"\f058"}
- .fa-question-circle:before{content:"\f059"}
- .fa-info-circle:before{content:"\f05a"}
- .fa-crosshairs:before{content:"\f05b"}
- .fa-times-circle-o:before{content:"\f05c"}
- .fa-check-circle-o:before{content:"\f05d"}
- .fa-ban:before{content:"\f05e"}
- .fa-arrow-left:before{content:"\f060"}
- .fa-arrow-right:before{content:"\f061"}
- .fa-arrow-up:before{content:"\f062"}
- .fa-arrow-down:before{content:"\f063"}
- .fa-mail-forward:before,.fa-share:before{content:"\f064"}
- .fa-resize-full:before{content:"\f065"}
- .fa-resize-small:before{content:"\f066"}
- .fa-plus:before{content:"\f067"}
- .fa-minus:before{content:"\f068"}
- .fa-asterisk:before{content:"\f069"}
- .fa-exclamation-circle:before{content:"\f06a"}
- .fa-gift:before{content:"\f06b"}
- .fa-leaf:before{content:"\f06c"}
- .fa-fire:before{content:"\f06d"}
- .fa-eye:before{content:"\f06e"}
- .fa-eye-slash:before{content:"\f070"}
- .fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}
- .fa-plane:before{content:"\f072"}
- .fa-calendar:before{content:"\f073"}
- .fa-random:before{content:"\f074"}
- .fa-comment:before{content:"\f075"}
- .fa-magnet:before{content:"\f076"}
- .fa-chevron-up:before{content:"\f077"}
- .fa-chevron-down:before{content:"\f078"}
- .fa-retweet:before{content:"\f079"}
- .fa-shopping-cart:before{content:"\f07a"}
- .fa-folder:before{content:"\f07b"}
- .fa-folder-open:before{content:"\f07c"}
- .fa-resize-vertical:before{content:"\f07d"}
- .fa-resize-horizontal:before{content:"\f07e"}
- .fa-bar-chart-o:before{content:"\f080"}
- .fa-twitter-square:before{content:"\f081"}
- .fa-facebook-square:before{content:"\f082"}
- .fa-camera-retro:before{content:"\f083"}
- .fa-key:before{content:"\f084"}
- .fa-gears:before,.fa-cogs:before{content:"\f085"}
- .fa-comments:before{content:"\f086"}
- .fa-thumbs-o-up:before{content:"\f087"}
- .fa-thumbs-o-down:before{content:"\f088"}
- .fa-star-half:before{content:"\f089"}
- .fa-heart-o:before{content:"\f08a"}
- .fa-sign-out:before{content:"\f08b"}
- .fa-linkedin-square:before{content:"\f08c"}
- .fa-thumb-tack:before{content:"\f08d"}
- .fa-external-link:before{content:"\f08e"}
- .fa-sign-in:before{content:"\f090"}
- .fa-trophy:before{content:"\f091"}
- .fa-github-square:before{content:"\f092"}
- .fa-upload:before{content:"\f093"}
- .fa-lemon-o:before{content:"\f094"}
- .fa-phone:before{content:"\f095"}
- .fa-square-o:before{content:"\f096"}
- .fa-bookmark-o:before{content:"\f097"}
- .fa-phone-square:before{content:"\f098"}
- .fa-twitter:before{content:"\f099"}
- .fa-facebook:before{content:"\f09a"}
- .fa-github:before{content:"\f09b"}
- .fa-unlock:before{content:"\f09c"}
- .fa-credit-card:before{content:"\f09d"}
- .fa-rss:before{content:"\f09e"}
- .fa-hdd-o:before{content:"\f0a0"}
- .fa-bullhorn:before{content:"\f0a1"}
- .fa-bell:before{content:"\f0f3"}
- .fa-certificate:before{content:"\f0a3"}
- .fa-hand-o-right:before{content:"\f0a4"}
- .fa-hand-o-left:before{content:"\f0a5"}
- .fa-hand-o-up:before{content:"\f0a6"}
- .fa-hand-o-down:before{content:"\f0a7"}
- .fa-arrow-circle-left:before{content:"\f0a8"}
- .fa-arrow-circle-right:before{content:"\f0a9"}
- .fa-arrow-circle-up:before{content:"\f0aa"}
- .fa-arrow-circle-down:before{content:"\f0ab"}
- .fa-globe:before{content:"\f0ac"}
- .fa-wrench:before{content:"\f0ad"}
- .fa-tasks:before{content:"\f0ae"}
- .fa-filter:before{content:"\f0b0"}
- .fa-briefcase:before{content:"\f0b1"}
- .fa-fullscreen:before{content:"\f0b2"}
- .fa-group:before{content:"\f0c0"}
- .fa-chain:before,.fa-link:before{content:"\f0c1"}
- .fa-cloud:before{content:"\f0c2"}
- .fa-flask:before{content:"\f0c3"}
- .fa-cut:before,.fa-scissors:before{content:"\f0c4"}
- .fa-copy:before,.fa-files-o:before{content:"\f0c5"}
- .fa-paperclip:before{content:"\f0c6"}
- .fa-save:before,.fa-floppy-o:before{content:"\f0c7"}
- .fa-square:before{content:"\f0c8"}
- .fa-reorder:before{content:"\f0c9"}
- .fa-list-ul:before{content:"\f0ca"}
- .fa-list-ol:before{content:"\f0cb"}
- .fa-strikethrough:before{content:"\f0cc"}
- .fa-underline:before{content:"\f0cd"}
- .fa-table:before{content:"\f0ce"}
- .fa-magic:before{content:"\f0d0"}
- .fa-truck:before{content:"\f0d1"}
- .fa-pinterest:before{content:"\f0d2"}
- .fa-pinterest-square:before{content:"\f0d3"}
- .fa-google-plus-square:before{content:"\f0d4"}
- .fa-google-plus:before{content:"\f0d5"}
- .fa-money:before{content:"\f0d6"}
- .fa-caret-down:before{content:"\f0d7"}
- .fa-caret-up:before{content:"\f0d8"}
- .fa-caret-left:before{content:"\f0d9"}
- .fa-caret-right:before{content:"\f0da"}
- .fa-columns:before{content:"\f0db"}
- .fa-unsorted:before,.fa-sort:before{content:"\f0dc"}
- .fa-sort-down:before,.fa-sort-asc:before{content:"\f0dd"}
- .fa-sort-up:before,.fa-sort-desc:before{content:"\f0de"}
- .fa-envelope:before{content:"\f0e0"}
- .fa-linkedin:before{content:"\f0e1"}
- .fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}
- .fa-legal:before,.fa-gavel:before{content:"\f0e3"}
- .fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}
- .fa-comment-o:before{content:"\f0e5"}
- .fa-comments-o:before{content:"\f0e6"}
- .fa-flash:before,.fa-bolt:before{content:"\f0e7"}
- .fa-sitemap:before{content:"\f0e8"}
- .fa-umbrella:before{content:"\f0e9"}
- .fa-paste:before,.fa-clipboard:before{content:"\f0ea"}
- .fa-lightbulb-o:before{content:"\f0eb"}
- .fa-exchange:before{content:"\f0ec"}
- .fa-cloud-download:before{content:"\f0ed"}
- .fa-cloud-upload:before{content:"\f0ee"}
- .fa-user-md:before{content:"\f0f0"}
- .fa-stethoscope:before{content:"\f0f1"}
- .fa-suitcase:before{content:"\f0f2"}
- .fa-bell-o:before{content:"\f0a2"}
- .fa-coffee:before{content:"\f0f4"}
- .fa-cutlery:before{content:"\f0f5"}
- .fa-file-text-o:before{content:"\f0f6"}
- .fa-building:before{content:"\f0f7"}
- .fa-hospital:before{content:"\f0f8"}
- .fa-ambulance:before{content:"\f0f9"}
- .fa-medkit:before{content:"\f0fa"}
- .fa-fighter-jet:before{content:"\f0fb"}
- .fa-beer:before{content:"\f0fc"}
- .fa-h-square:before{content:"\f0fd"}
- .fa-plus-square:before{content:"\f0fe"}
- .fa-angle-double-left:before{content:"\f100"}
- .fa-angle-double-right:before{content:"\f101"}
- .fa-angle-double-up:before{content:"\f102"}
- .fa-angle-double-down:before{content:"\f103"}
- .fa-angle-left:before{content:"\f104"}
- .fa-angle-right:before{content:"\f105"}
- .fa-angle-up:before{content:"\f106"}
- .fa-angle-down:before{content:"\f107"}
- .fa-desktop:before{content:"\f108"}
- .fa-laptop:before{content:"\f109"}
- .fa-tablet:before{content:"\f10a"}
- .fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}
- .fa-circle-o:before{content:"\f10c"}
- .fa-quote-left:before{content:"\f10d"}
- .fa-quote-right:before{content:"\f10e"}
- .fa-spinner:before{content:"\f110"}
- .fa-circle:before{content:"\f111"}
- .fa-mail-reply:before,.fa-reply:before{content:"\f112"}
- .fa-github-alt:before{content:"\f113"}
- .fa-folder-o:before{content:"\f114"}
- .fa-folder-open-o:before{content:"\f115"}
- .fa-expand-o:before{content:"\f116"}
- .fa-collapse-o:before{content:"\f117"}
- .fa-smile-o:before{content:"\f118"}
- .fa-frown-o:before{content:"\f119"}
- .fa-meh-o:before{content:"\f11a"}
- .fa-gamepad:before{content:"\f11b"}
- .fa-keyboard-o:before{content:"\f11c"}
- .fa-flag-o:before{content:"\f11d"}
- .fa-flag-checkered:before{content:"\f11e"}
- .fa-terminal:before{content:"\f120"}
- .fa-code:before{content:"\f121"}
- .fa-reply-all:before{content:"\f122"}
- .fa-mail-reply-all:before{content:"\f122"}
- .fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}
- .fa-location-arrow:before{content:"\f124"}
- .fa-crop:before{content:"\f125"}
- .fa-code-fork:before{content:"\f126"}
- .fa-unlink:before,.fa-chain-broken:before{content:"\f127"}
- .fa-question:before{content:"\f128"}
- .fa-info:before{content:"\f129"}
- .fa-exclamation:before{content:"\f12a"}
- .fa-superscript:before{content:"\f12b"}
- .fa-subscript:before{content:"\f12c"}
- .fa-eraser:before{content:"\f12d"}
- .fa-puzzle-piece:before{content:"\f12e"}
- .fa-microphone:before{content:"\f130"}
- .fa-microphone-slash:before{content:"\f131"}
- .fa-shield:before{content:"\f132"}
- .fa-calendar-o:before{content:"\f133"}
- .fa-fire-extinguisher:before{content:"\f134"}
- .fa-rocket:before{content:"\f135"}
- .fa-maxcdn:before{content:"\f136"}
- .fa-chevron-circle-left:before{content:"\f137"}
- .fa-chevron-circle-right:before{content:"\f138"}
- .fa-chevron-circle-up:before{content:"\f139"}
- .fa-chevron-circle-down:before{content:"\f13a"}
- .fa-html5:before{content:"\f13b"}
- .fa-css3:before{content:"\f13c"}
- .fa-anchor:before{content:"\f13d"}
- .fa-unlock-o:before{content:"\f13e"}
- .fa-bullseye:before{content:"\f140"}
- .fa-ellipsis-horizontal:before{content:"\f141"}
- .fa-ellipsis-vertical:before{content:"\f142"}
- .fa-rss-square:before{content:"\f143"}
- .fa-play-circle:before{content:"\f144"}
- .fa-ticket:before{content:"\f145"}
- .fa-minus-square:before{content:"\f146"}
- .fa-minus-square-o:before{content:"\f147"}
- .fa-level-up:before{content:"\f148"}
- .fa-level-down:before{content:"\f149"}
- .fa-check-square:before{content:"\f14a"}
- .fa-pencil-square:before{content:"\f14b"}
- .fa-external-link-square:before{content:"\f14c"}
- .fa-share-square:before{content:"\f14d"}
- .fa-compass:before{content:"\f14e"}
- .fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}
- .fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}
- .fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}
- .fa-euro:before,.fa-eur:before{content:"\f153"}
- .fa-gbp:before{content:"\f154"}
- .fa-dollar:before,.fa-usd:before{content:"\f155"}
- .fa-rupee:before,.fa-inr:before{content:"\f156"}
- .fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}
- .fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}
- .fa-won:before,.fa-krw:before{content:"\f159"}
- .fa-bitcoin:before,.fa-btc:before{content:"\f15a"}
- .fa-file:before{content:"\f15b"}
- .fa-file-text:before{content:"\f15c"}
- .fa-sort-alpha-asc:before{content:"\f15d"}
- .fa-sort-alpha-desc:before{content:"\f15e"}
- .fa-sort-amount-asc:before{content:"\f160"}
- .fa-sort-amount-desc:before{content:"\f161"}
- .fa-sort-numeric-asc:before{content:"\f162"}
- .fa-sort-numeric-desc:before{content:"\f163"}
- .fa-thumbs-up:before{content:"\f164"}
- .fa-thumbs-down:before{content:"\f165"}
- .fa-youtube-square:before{content:"\f166"}
- .fa-youtube:before{content:"\f167"}
- .fa-xing:before{content:"\f168"}
- .fa-xing-square:before{content:"\f169"}
- .fa-youtube-play:before{content:"\f16a"}
- .fa-dropbox:before{content:"\f16b"}
- .fa-stack-overflow:before{content:"\f16c"}
- .fa-instagram:before{content:"\f16d"}
- .fa-flickr:before{content:"\f16e"}
- .fa-adn:before{content:"\f170"}
- .fa-bitbucket:before{content:"\f171"}
- .fa-bitbucket-square:before{content:"\f172"}
- .fa-tumblr:before{content:"\f173"}
- .fa-tumblr-square:before{content:"\f174"}
- .fa-long-arrow-down:before{content:"\f175"}
- .fa-long-arrow-up:before{content:"\f176"}
- .fa-long-arrow-left:before{content:"\f177"}
- .fa-long-arrow-right:before{content:"\f178"}
- .fa-apple:before{content:"\f179"}
- .fa-windows:before{content:"\f17a"}
- .fa-android:before{content:"\f17b"}
- .fa-linux:before{content:"\f17c"}
- .fa-dribbble:before{content:"\f17d"}
- .fa-skype:before{content:"\f17e"}
- .fa-foursquare:before{content:"\f180"}
- .fa-trello:before{content:"\f181"}
- .fa-female:before{content:"\f182"}
- .fa-male:before{content:"\f183"}
- .fa-gittip:before{content:"\f184"}
- .fa-sun-o:before{content:"\f185"}
- .fa-moon-o:before{content:"\f186"}
- .fa-archive:before{content:"\f187"}
- .fa-bug:before{content:"\f188"}
- .fa-vk:before{content:"\f189"}
- .fa-weibo:before{content:"\f18a"}
- .fa-renren:before{content:"\f18b"}
- .fa-pagelines:before{content:"\f18c"}
- .fa-stack-exchange:before{content:"\f18d"}
- .fa-arrow-circle-o-right:before{content:"\f18e"}
- .fa-arrow-circle-o-left:before{content:"\f190"}
- .fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}
- .fa-dot-circle-o:before{content:"\f192"}
- .fa-wheelchair:before{content:"\f193"}
- .fa-vimeo-square:before{content:"\f194"}
- .fa-turkish-lira:before,.fa-try:before{content:"\f195"}
diff --git a/utils/soca/fig_gallery/marine_vrfy_display/index_vrfy_marine.html b/utils/soca/fig_gallery/marine_vrfy_display/index_vrfy_marine.html
deleted file mode 100644
index 80fd14b2d..000000000
--- a/utils/soca/fig_gallery/marine_vrfy_display/index_vrfy_marine.html
+++ /dev/null
@@ -1,1243 +0,0 @@
-
-
-
-
-
-GFS Experiment Verification
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Marine Figures
-
Add path to main verification directory:
-
-
- MAIN Verification Path:
-
-
-
Are the figures in your COMROOT or from HPSS? For example:
- If COMROOT, the MAIN path should include everything before /gdas.YearMonthDay subdirectories.
-
- If HPSS, the MAIN path should include everything before /YearMonthDayHour subdirectories.
-
-
- Enter COMROOT or HPSS:
-
-
-
-
Choose a date and cycle time:
-
-
-
-
- Year (YYYY):
-
-
-
-
- Month (MM):
-
-
-
-
- Day (DD):
-
-
-
-
- Hour (HH in UTC):
-
-
- After filling in the above boxes, refresh your tab. Then you can start using the menu on the left.
-
-
-
-
-
-
-
-
-
-
-
This page displays verification for the Global Forecast System (GFS) developer experiments.
-
DISCLAIMER: This web page is not "operational" and therefore not subject to 24-hr monitoring by NCEP's Central Operations staff.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/utils/soca/fig_gallery/run_vrfy.py b/utils/soca/fig_gallery/run_vrfy.py
deleted file mode 100644
index bd99cdb22..000000000
--- a/utils/soca/fig_gallery/run_vrfy.py
+++ /dev/null
@@ -1,71 +0,0 @@
-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."""
- 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__":
-
- # 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(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 = 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)
-
- # Submit the plotting job
- subprocess.run(f"sbatch {jobcard}", shell=True)
diff --git a/utils/soca/fig_gallery/vrfy_config.yaml b/utils/soca/fig_gallery/vrfy_config.yaml
deleted file mode 100644
index 0df76cf88..000000000
--- a/utils/soca/fig_gallery/vrfy_config.yaml
+++ /dev/null
@@ -1,16 +0,0 @@
-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"
diff --git a/utils/soca/fig_gallery/vrfy_jobcard.sh.j2 b/utils/soca/fig_gallery/vrfy_jobcard.sh.j2
deleted file mode 100644
index 59b8cdef2..000000000
--- a/utils/soca/fig_gallery/vrfy_jobcard.sh.j2
+++ /dev/null
@@ -1,58 +0,0 @@
-#!/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_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") }}
-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/vrfy_script.py b/utils/soca/fig_gallery/vrfy_script.py
deleted file mode 100644
index 214c6fa0a..000000000
--- a/utils/soca/fig_gallery/vrfy_script.py
+++ /dev/null
@@ -1,245 +0,0 @@
-import os
-import numpy as np
-import gen_eva_obs_yaml
-import marine_eva_post
-import diag_statistics
-from multiprocessing import Process
-from soca_vrfy import statePlotter, plotConfig
-import subprocess
-
-comout = os.getenv('COM_OCEAN_ANALYSIS')
-com_ice_history = os.getenv('COM_ICE_HISTORY_PREV')
-com_ocean_history = os.getenv('COM_OCEAN_HISTORY_PREV')
-cyc = os.getenv('cyc')
-RUN = os.getenv('RUN')
-
-bcyc = str((int(cyc) - 3) % 24).zfill(2)
-gcyc = str((int(cyc) - 6) % 24).zfill(2)
-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')
-
-# Get flags from environment variables (set in the bash driver)
-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'
-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 = []
-
-# 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(configs_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]},
- colormap='seismic',
- comout=os.path.join(comout, 'vrfy', 'recentering_error')), # recentering error
- plotConfig(grid_file=grid_file,
- data_file=os.path.join(comout, f'{RUN}.t{cyc}z.ocn.ssh_steric_stddev.nc'),
- variables_horiz={'ave_ssh': [0, 0.8]},
- colormap='gist_ncar',
- comout=os.path.join(comout, 'vrfy', 'bkgerr', 'ssh_steric_stddev')), # ssh steric stddev
- plotConfig(grid_file=grid_file,
- data_file=os.path.join(comout, f'{RUN}.t{cyc}z.ocn.ssh_unbal_stddev.nc'),
- variables_horiz={'ave_ssh': [0, 0.8]},
- colormap='gist_ncar',
- comout=os.path.join(comout, 'vrfy', 'bkgerr', 'ssh_unbal_stddev')), # ssh unbal stddev
- plotConfig(grid_file=grid_file,
- data_file=os.path.join(comout, f'{RUN}.t{cyc}z.ocn.ssh_total_stddev.nc'),
- variables_horiz={'ave_ssh': [0, 0.8]},
- colormap='gist_ncar',
- comout=os.path.join(comout, 'vrfy', 'bkgerr', 'ssh_total_stddev')), # ssh total stddev
- plotConfig(grid_file=grid_file,
- data_file=os.path.join(comout, f'{RUN}.t{cyc}z.ocn.steric_explained_variance.nc'),
- variables_horiz={'ave_ssh': [0, 1]},
- colormap='seismic',
- comout=os.path.join(comout, 'vrfy', 'bkgerr', 'steric_explained_variance'))] # steric explained variance
- configs.extend(config_ens)
-
-# 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'),
- lats=np.arange(-60, 60, 10),
- lons=np.arange(-280, 80, 30),
- variables_zonal={'Temp': [0, 2],
- 'Salt': [0, 0.2],
- 'u': [0, 0.5],
- 'v': [0, 0.5]},
- variables_meridional={'Temp': [0, 2],
- 'Salt': [0, 0.2],
- 'u': [0, 0.5],
- 'v': [0, 0.5]},
- variables_horiz={'Temp': [0, 2],
- 'Salt': [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
- configs.extend(config_bkgerr)
-
-# 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],
- 'hi_h': [0.0, 4.0],
- 'hs_h': [0.0, 0.5]},
- colormap='jet',
- projs=['North', 'South', 'Global'],
- comout=os.path.join(comout, 'vrfy', 'bkg')), # sea ice background
- plotConfig(grid_file=grid_file,
- layer_file=layer_file,
- data_file=os.path.join(com_ocean_history, f'{RUN}.ocean.t{gcyc}z.inst.f006.nc'),
- lats=np.arange(-60, 60, 10),
- lons=np.arange(-280, 80, 30),
- variables_zonal={'Temp': [-1.8, 34.0],
- 'Salt': [32, 40],
- 'u': [-1.0, 1.0],
- 'v': [-1.0, 1.0]},
- variables_meridional={'Temp': [-1.8, 34.0],
- '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],
- 'u': [-1.0, 1.0],
- 'v': [-1.0, 1.0]},
- colormap='nipy_spectral',
- comout=os.path.join(comout, 'vrfy', 'bkg'))]
- configs.extend(config_bkg)
-
-# 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'),
- lats=np.arange(-60, 60, 10),
- lons=np.arange(-280, 80, 30),
- variables_zonal={'Temp': [-0.5, 0.5],
- 'Salt': [-0.1, 0.1]},
- variables_horiz={'Temp': [-0.5, 0.5],
- 'Salt': [-0.1, 0.1],
- 'ave_ssh': [-0.1, 0.1]},
- variables_meridional={'Temp': [-0.5, 0.5],
- 'Salt': [-0.1, 0.1]},
- colormap='seismic',
- comout=os.path.join(comout, 'vrfy', 'incr')), # ocean increment
- plotConfig(grid_file=grid_file,
- data_file=os.path.join(comout, f'{RUN}.t'+cyc+'z.ice.incr.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'))] # 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)
-
-
-# Plot the marine verification figures
-def plot_marine_vrfy(config):
- ocnvrfyPlotter = statePlotter(config)
- ocnvrfyPlotter.plot()
-
-# Number of processes
-num_processes = len(configs)
-
-# Create a list to store the processes
-processes = []
-
-# Iterate over configs
-for config in configs[:num_processes]:
- process = Process(target=plot_marine_vrfy, args=(config,))
- process.start()
- processes.append(process)
-
-# Wait for all processes to finish
-for process in processes:
- process.join()
-
-# 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
-#######################################
-
-# As of 11/12/2024 not working
-# diag_statistics.get_diag_stats()