From 6f120c1ff6bdb01ed255562ef0223a521c9ca84f Mon Sep 17 00:00:00 2001 From: Samuel Trahan Date: Thu, 29 Jan 2026 12:54:55 -0500 Subject: [PATCH 01/12] a script that copies a domain boundary to yaml --- ush/yamlify_domain_edge.py | 226 +++++++++++++++++++++++++++++++++++++ 1 file changed, 226 insertions(+) create mode 100755 ush/yamlify_domain_edge.py diff --git a/ush/yamlify_domain_edge.py b/ush/yamlify_domain_edge.py new file mode 100755 index 000000000..b0380d948 --- /dev/null +++ b/ush/yamlify_domain_edge.py @@ -0,0 +1,226 @@ +#!/usr/bin/env python +import netCDF4 as nc +import numpy as np +import argparse +import warnings +from collections import defaultdict + +""" +This program outputs the computational domain edge in a YAML format expected by the UFO Polygon Filter. +""" + +# Disable warnings +warnings.filterwarnings('ignore') + + +def normalize_lon(lon): + lon = np.asarray(lon) + return np.where(lon < 0.0, lon + 360.0, lon) + + +def to_plain_array(a): + # netCDF masked arrays to plain ndarray + return np.array(a.filled(np.nan)) if np.ma.isMaskedArray(a) else np.array(a) + + +def polygon_from_structured_edges(grid_ds): + """ + Build a domain boundary ring from a structured FV3-style grid using only + the outer perimeter (no triangulation). Works for variables named either + (grid_lat, grid_lon) or (grid_latt, grid_lont). + """ + vars_ = grid_ds.variables + # Accept common FV3 names + if 'grid_lat' in vars_ and 'grid_lon' in vars_: + glat = np.array(vars_['grid_lat'][:]) + glon = np.array(vars_['grid_lon'][:]) + elif 'grid_latt' in vars_ and 'grid_lont' in vars_: + glat = np.array(vars_['grid_latt'][:]) + glon = np.array(vars_['grid_lont'][:]) + else: + raise RuntimeError( + "Structured grid expected but did not find grid_lat/grid_lon or grid_latt/grid_lont." + ) + + if glat.ndim != 2 or glon.ndim != 2 or glat.shape != glon.shape: + raise RuntimeError("grid_lat/grid_lon must be 2-D arrays of the same shape.") + + # Normalize longitudes to [0,360) + glon = normalize_lon(glon) + + # Extract perimeter in CCW order: top > right > bottom > left + top = np.c_[glon[0, :], glat[0, :]] + right = np.c_[glon[1:, -1], glat[1:, -1]] + bottom = np.c_[glon[-1, -2::-1], glat[-1, -2::-1]] # exclude last to avoid dup + left = np.c_[glon[-2:0:-1, 0], glat[-2:0:-1, 0]] # exclude corners already used + + ring = np.vstack([top, right, bottom, left]) + return ring + + +def polygon_from_mpas_boundary(grid_ds, simplify_target=20000): + """ + Build the exact MPAS outer boundary by walking boundary edges. + Returns ring as (N,2) [lon_deg, lat_deg] in [0,360) lon (no seam shift yet). + simplify_target: if the ring has more vertices than this, subsample it. + """ + cellsOnEdge = to_plain_array(grid_ds.variables["cellsOnEdge"][:]) # (nEdges, 2), int + verticesOnEdge = to_plain_array(grid_ds.variables["verticesOnEdge"][:]) # (nEdges, 2), int + lonVertex = to_plain_array(grid_ds.variables["lonVertex"][:]) # (nVertices,) + latVertex = to_plain_array(grid_ds.variables["latVertex"][:]) + + # Convert to degrees; clean invalids + lonv = np.degrees(lonVertex) + latv = np.degrees(latVertex) + goodv = np.isfinite(lonv) & np.isfinite(latv) + if not goodv.all(): + # If any bad vertices exist, just ignore edges touching them + pass + + # Boundary edges have a missing neighbor (cell id == 0) + ce = cellsOnEdge.astype(np.int64) + boundary_mask = (ce[:, 0] == 0) | (ce[:, 1] == 0) + if not np.any(boundary_mask): + raise RuntimeError("No boundary edges found (is this a global mesh?).") + + # Convert to 0-based; drop invalids (<=0) and edges that touch bad vertices + bedges = verticesOnEdge[boundary_mask].astype(np.int64) # 1-based indices + v1 = bedges[:, 0] - 1 + v2 = bedges[:, 1] - 1 + ok = (v1 >= 0) & (v2 >= 0) + if not goodv.all(): + ok &= goodv[v1] & goodv[v2] + v1, v2 = v1[ok], v2[ok] + + # Build adjacency along boundary + adj = defaultdict(list) + for a, b in zip(v1, v2): + adj[a].append(b) + adj[b].append(a) + + # Each boundary vertex should have degree 2 (closed polygon). + # If not, we still try to walk and skip dead-ends. + visited_e = set() + loops = [] + for s in list(adj.keys()): + for nb in adj[s]: + e = (min(s, nb), max(s, nb)) + if e in visited_e: + continue + # Trace a loop starting with edge + ring_idx = [s, nb] + visited_e.add(e) + prev, cur = s, nb + while True: + nbs = adj[cur] + # Pick the neighbor that isn't the one we came from + nxt = nbs[0] if nbs[0] != prev else (nbs[1] if len(nbs) > 1 else None) + if nxt is None: + break + e2 = (min(cur, nxt), max(cur, nxt)) + if e2 in visited_e: + # closed? + if nxt == ring_idx[0]: + loops.append(ring_idx) + break + visited_e.add(e2) + ring_idx.append(nxt) + prev, cur = cur, nxt + if cur == ring_idx[0]: + loops.append(ring_idx) + break + + if not loops: + raise RuntimeError("Could not assemble a boundary loop from MPAS edges.") + + # Choose the largest loop (by vertex count) + ring_ids = max(loops, key=len) + + # Compose lon/lat; normalize lon to [0,360) + lon = lonv[ring_ids] + lat = latv[ring_ids] + lon = np.where(lon < 0.0, lon + 360.0, lon) + ring = np.c_[lon, lat] + + # Simplification wherein if the ring has more vertices than this, subsample it. + if simplify_target and ring.shape[0] > simplify_target: + stride = max(1, ring.shape[0] // simplify_target) + ring = ring[::stride] + + return ring + + +def build_domain_ring(grid_ds): + varsin = grid_ds.variables.keys() + if (('grid_lat' in varsin and 'grid_lon' in varsin) or ('grid_latt' in varsin and 'grid_lont' in varsin)): + ring = polygon_from_structured_edges(grid_ds) + elif {'cellsOnEdge', 'verticesOnEdge', 'lonVertex', 'latVertex'}.issubset(varsin): + ring = polygon_from_mpas_boundary(grid_ds, simplify_target=20000) + else: + raise RuntimeError("Unsupported grid file: need grid_lat/grid_lon (or grid_latt/grid_lont) or cells/verticesOnEdge") + + # Normalize and optionally fix the dateline seam + ring[:, 0] = normalize_lon(ring[:, 0]) + L = ring[:, 0] + span_direct = L.max() - L.min() + L_shift = np.where(L > 180.0, L - 360.0, L) + span_shift = L_shift.max() - L_shift.min() + lon_offset = -360 if span_shift < span_direct else 0 + if lon_offset == -360: + ring[:, 0] = L_shift + return ring + + +def print_ring(ring, lonlat, indent, columns=8): + nring = len(ring) + for i in range(nring): + if i % columns == 0 and i < nring - 1: + if i: + print(',') + print(indent, end='') + elif i: + print(', ', end='') + # A 3km-resolution MPAS domain had points that differed by + # .001 degrees, hence the resolution of .0001 + print('%8.4f'%ring[i][lonlat], end='') + + +# Parse command-line arguments +# Note: +# The grid file is what contains variables grid_lat/grid_lon +# OR latCell/lonCell for FV3 and MPAS respectively. +# Examples can be found in the following rrfs-test cases: +# - rrfs-data_fv3jedi_2022052619/Data/bkg/fv3_grid_spec.nc +# - mpas_2024052700/data/restart.2024-05-27_00.00.00.nc +parser = argparse.ArgumentParser() +parser.add_argument('-g', '--grid', type=str, help='grid file', required=True) +parser.add_argument('-i', '--indent', type=str, help='indent', required=False, default='') +args = parser.parse_args() + +# Assign filenames +grid_filename = args.grid # see note above. + +#print(f"Grid file: {grid_filename}") + +grid_ds = nc.Dataset(grid_filename, 'r') + +# Build ring +ring = build_domain_ring(grid_ds) +centroid = np.nanmean(ring, axis=0) + +indent=args.indent + +print(f'''{indent}- &POLY +{indent} filter: Polygon Check +{indent} action: +{indent} name: reduce obs space +{indent} inside point longitude: {centroid[0]:.4f} +{indent} inside point latitude: {centroid[1]:.4f}''') + +print(f'{indent} vertex longitudes: [') +print_ring(ring, 0, f'{indent} ') +print(f'\n{indent} ]') + +print(f'{indent} vertex latitudes: [') +print_ring(ring, 1, f'{indent} ') +print(f'\n{indent} ]') From ee1e5462923711c808c60fb68e4da8e6c033c106 Mon Sep 17 00:00:00 2001 From: Samuel Trahan Date: Thu, 29 Jan 2026 12:55:52 -0500 Subject: [PATCH 02/12] add polygon filter to jedivar.yaml --- parm/jedivar.yaml | 135 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 133 insertions(+), 2 deletions(-) diff --git a/parm/jedivar.yaml b/parm/jedivar.yaml index aed420c49..965a6544c 100644 --- a/parm/jedivar.yaml +++ b/parm/jedivar.yaml @@ -194,6 +194,7 @@ cost function: threshold: 12.0 action: name: reject + - *POLY - obs space: name: adpsfc_t181 distribution: @@ -267,6 +268,8 @@ cost function: action: name: reduce obs space + - filter: *POLY + # Duplicate Check # - filter: Temporal Thinning # filter variables: @@ -543,6 +546,8 @@ cost function: action: name: reduce obs space + - filter: *POLY + # Duplicate Check # - filter: Temporal Thinning # filter variables: @@ -817,6 +822,8 @@ cost function: action: name: reduce obs space + - filter: *POLY + # Duplicate Check - filter: Temporal Thinning filter variables: @@ -1095,6 +1102,8 @@ cost function: action: name: reduce obs space + - filter: *POLY + # Duplicate Check # - filter: Temporal Thinning # filter variables: @@ -1370,6 +1379,8 @@ cost function: action: name: reduce obs space + - filter: *POLY + # Duplicate Check # - filter: Temporal Thinning # filter variables: @@ -1650,6 +1661,8 @@ cost function: action: name: reduce obs space + - filter: *POLY + # Online regional domain check - filter: Bounds Check filter variables: @@ -1924,6 +1937,8 @@ cost function: # action: # name: reduce obs space + - filter: *POLY + # Online regional domain check - filter: Bounds Check filter variables: @@ -2195,6 +2210,8 @@ cost function: action: name: reduce obs space + - filter: *POLY + # Online regional domain check - filter: Bounds Check filter variables: @@ -2473,6 +2490,8 @@ cost function: # action: # name: reduce obs space + - filter: *POLY + # Online domain check - filter: Bounds Check filter variables: @@ -2790,6 +2809,8 @@ cost function: # action: # name: reduce obs space + - filter: *POLY + # Online domain check - filter: Bounds Check filter variables: @@ -3100,6 +3121,8 @@ cost function: action: name: reduce obs space + - filter: *POLY + # Online domain check - filter: Bounds Check filter variables: @@ -3413,6 +3436,8 @@ cost function: # action: # name: reduce obs space + - filter: *POLY + # Online regional domain check - filter: Bounds Check filter variables: @@ -3687,6 +3712,8 @@ cost function: # action: # name: reduce obs space + - filter: *POLY + # Online regional domain check - filter: Bounds Check filter variables: @@ -3961,6 +3988,8 @@ cost function: # action: # name: reduce obs space + - filter: *POLY + # Online regional domain check - filter: Bounds Check filter variables: @@ -4235,6 +4264,8 @@ cost function: # action: # name: reduce obs space + - filter: *POLY + # Online regional domain check - filter: Bounds Check filter variables: @@ -4505,6 +4536,8 @@ cost function: # action: # name: reduce obs space + - filter: *POLY + # Online regional domain check - filter: Bounds Check filter variables: @@ -4782,6 +4815,8 @@ cost function: # action: # name: reduce obs space + - filter: *POLY + # Online domain check - filter: Bounds Check filter variables: @@ -5092,6 +5127,8 @@ cost function: # action: # name: reduce obs space + - filter: *POLY + # Online domain check - filter: Bounds Check filter variables: @@ -5399,6 +5436,8 @@ cost function: # action: # name: reduce obs space + - filter: *POLY + # Online regional domain check - filter: Bounds Check filter variables: @@ -5673,6 +5712,8 @@ cost function: # action: # name: reduce obs space + - filter: *POLY + # Online regional domain check - filter: Bounds Check filter variables: @@ -5950,6 +5991,8 @@ cost function: # action: # name: reduce obs space + - filter: *POLY + # Online domain check - filter: Bounds Check filter variables: @@ -6257,6 +6300,8 @@ cost function: # action: # name: reduce obs space + - filter: *POLY + # Online regional domain check - filter: Bounds Check filter variables: @@ -6531,6 +6576,8 @@ cost function: # action: # name: reduce obs space + - filter: *POLY + # Online regional domain check - filter: Bounds Check filter variables: @@ -6805,6 +6852,8 @@ cost function: # action: # name: reduce obs space + - filter: *POLY + # Online regional domain check - filter: Bounds Check filter variables: @@ -7079,6 +7128,8 @@ cost function: # action: # name: reduce obs space + - filter: *POLY + # Online regional domain check - filter: Bounds Check filter variables: @@ -7353,6 +7404,8 @@ cost function: # action: # name: reduce obs space + - filter: *POLY + # Online regional domain check - filter: Bounds Check filter variables: @@ -7630,6 +7683,8 @@ cost function: # action: # name: reduce obs space + - filter: *POLY + # Online domain check - filter: Bounds Check filter variables: @@ -7940,6 +7995,8 @@ cost function: # action: # name: reduce obs space + - filter: *POLY + # Online domain check - filter: Bounds Check filter variables: @@ -8250,6 +8307,8 @@ cost function: # action: # name: reduce obs space + - filter: *POLY + # Online domain check - filter: Bounds Check filter variables: @@ -8560,6 +8619,8 @@ cost function: # action: # name: reduce obs space + - filter: *POLY + # Online domain check - filter: Bounds Check filter variables: @@ -8840,6 +8901,8 @@ cost function: name: assign error error parameter: 0.01 + - filter: *POLY + # Terrain Height Discrepancy Check - filter: Difference Check reference: MetaData/stationElevation @@ -8941,6 +9004,8 @@ cost function: # action: # name: reduce obs space + - filter: *POLY + # Online regional domain check - filter: Bounds Check filter variables: @@ -9215,6 +9280,8 @@ cost function: # action: # name: reduce obs space + - filter: *POLY + # Online regional domain check - filter: Bounds Check filter variables: @@ -9482,6 +9549,8 @@ cost function: # action: # name: reduce obs space + - filter: *POLY + # Online regional domain check - filter: Bounds Check filter variables: @@ -10337,6 +10406,8 @@ cost function: # action: # name: reduce obs space + - filter: *POLY + # Online regional domain check - filter: Bounds Check filter variables: @@ -10688,6 +10759,8 @@ cost function: # action: # name: reduce obs space + - filter: *POLY + # Online regional domain check - filter: Bounds Check filter variables: @@ -10962,6 +11035,8 @@ cost function: # action: # name: reduce obs space + - filter: *POLY + # Online regional domain check - filter: Bounds Check filter variables: @@ -11236,6 +11311,8 @@ cost function: # action: # name: reduce obs space + - filter: *POLY + # Online regional domain check - filter: Bounds Check filter variables: @@ -11511,6 +11588,8 @@ cost function: # action: # name: reduce obs space + - filter: *POLY + # Online regional domain check - filter: Bounds Check filter variables: @@ -11785,6 +11864,8 @@ cost function: # action: # name: reduce obs space + - filter: *POLY + # Online regional domain check - filter: Bounds Check filter variables: @@ -12059,6 +12140,8 @@ cost function: # action: # name: reduce obs space + - filter: *POLY + # Online regional domain check - filter: Bounds Check filter variables: @@ -12334,6 +12417,8 @@ cost function: # action: # name: reduce obs space + - filter: *POLY + # Online regional domain check - filter: Bounds Check filter variables: @@ -12604,6 +12689,8 @@ cost function: # action: # name: reduce obs space + - filter: *POLY + # Online regional domain check - filter: Bounds Check filter variables: @@ -12890,6 +12977,8 @@ cost function: # action: # name: reduce obs space + - filter: *POLY + # Online domain check - filter: Bounds Check filter variables: @@ -13206,6 +13295,8 @@ cost function: # action: # name: reduce obs space + - filter: *POLY + # Online domain check - filter: Bounds Check filter variables: @@ -13523,6 +13614,8 @@ cost function: # action: # name: reduce obs space + - filter: *POLY + # Online domain check - filter: Bounds Check filter variables: @@ -13839,6 +13932,8 @@ cost function: # action: # name: reduce obs space + - filter: *POLY + # Online domain check - filter: Bounds Check filter variables: @@ -14195,6 +14290,8 @@ cost function: # action: # name: reduce obs space + - filter: *POLY + # Online domain check - filter: Bounds Check udescriptor: "online_domain_check" @@ -14602,6 +14699,8 @@ cost function: # action: # name: reduce obs space + - filter: *POLY + # Online domain check - filter: Bounds Check udescriptor: "online_domain_check" @@ -15009,6 +15108,8 @@ cost function: # action: # name: reduce obs space + - filter: *POLY + # Online domain check - filter: Bounds Check udescriptor: "online_domain_check" @@ -15382,6 +15483,8 @@ cost function: # action: # name: reduce obs space + - filter: *POLY + # Online domain check - filter: Bounds Check udescriptor: "online_domain_check" @@ -15780,6 +15883,8 @@ cost function: action: name: reduce obs space + - filter: *POLY + # Online domain check - filter: Bounds Check udescriptor: "online_domain_check" @@ -16162,6 +16267,8 @@ cost function: action: name: reduce obs space + - filter: *POLY + # Duplicate Check - filter: Temporal Thinning udescriptor: "duplicate_check" @@ -16557,6 +16664,8 @@ cost function: - name: Thinning initial value: false force reinitialization: false + # domain boundary check + - *POLY obs post filters: #Thinning - filter: Gaussian Thinning @@ -17013,7 +17122,8 @@ cost function: - name: UseflagCheck initial value: false force reinitialization: false - + # domain boundary check + - *POLY obs post filters: # Step 0-B: Calculate derived variables # Calculate CLW retrieved from observation @@ -17602,7 +17712,8 @@ cost function: - name: UseflagCheck initial value: false force reinitialization: false - + # domain boundary check + - *POLY obs post filters: # Step 0-B: Calculate derived variables # Calculate CLW retrieved from observation @@ -18170,6 +18281,8 @@ cost function: maxvalue: 65. action: name: reduce obs space + # domain boundary check + - *POLY # Data Thinning - filter: Gaussian Thinning filter variables: @@ -18678,6 +18791,8 @@ cost function: maxvalue: 65. action: name: reduce obs space + # Domain boundary check + - *POLY # Data Thinning - filter: Gaussian Thinning filter variables: @@ -19204,6 +19319,8 @@ cost function: - name: UseflagCheck initial value: false force reinitialization: false + # Domain boundary check + - *POLY obs post filters: # Step 0-B: Calculate derived variables @@ -19759,6 +19876,8 @@ cost function: - name: Thinning initial value: false force reinitialization: false + # Domain boundary check + - *POLY obs post filters: #Thinning - filter: Gaussian Thinning @@ -20182,6 +20301,8 @@ cost function: - name: Thinning initial value: false force reinitialization: false + # Domain boundary check + - *POLY obs post filters: #Thinning - filter: Gaussian Thinning @@ -20642,6 +20763,11 @@ cost function: initial value: false force reinitialization: false + # -------------------------------------- + # Step "one half:" Domain boundary check + # -------------------------------------- + - *POLY + # ---------------------------------------------------------------- # Step 1 : Create Derived Variables for radiane to BT conversion # Assign channel wavenumbers in m-1 @@ -21190,6 +21316,11 @@ cost function: initial value: false force reinitialization: false + # -------------------------------------- + # Step "one half:" Domain boundary check + # -------------------------------------- + - *POLY + # ---------------------------------------------------------------- # Step 1 : Create Derived Variables for radiane to BT conversion # Assign channel wavenumbers in m-1 From 4a84e9b2f4b7d4006562e3909775aa4c834c3e6a Mon Sep 17 00:00:00 2001 From: Samuel Trahan Date: Thu, 29 Jan 2026 12:56:08 -0500 Subject: [PATCH 03/12] remove offline filter --- scripts/exrrfs_ioda_bufr.sh | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/scripts/exrrfs_ioda_bufr.sh b/scripts/exrrfs_ioda_bufr.sh index 24d390b4e..b8d9eda47 100755 --- a/scripts/exrrfs_ioda_bufr.sh +++ b/scripts/exrrfs_ioda_bufr.sh @@ -121,26 +121,15 @@ ln -sf abibufr "rap.t${cyc}z.gsrcsr.tm00.bufr_d" cp "rap.t${cyc}z.abi_g16.tm00.nc" "ioda_abi_g16.nc" cp "rap.t${cyc}z.abi_g18.tm00.nc" "ioda_abi_g18.nc" -# run offline IODA tools -${cpreq} "${USHrrfs}"/offline_domain_check.py . -${cpreq} "${USHrrfs}"/offline_domain_check_satrad.py . ${cpreq} "${USHrrfs}"/offline_ioda_tweak.py . ${cpreq} "${USHrrfs}"/offline_vad_thinning.py . for ioda_file in ioda*nc; do grid_file="${FIXrrfs}/${MESH_NAME}/${MESH_NAME}.static.nc" - #if [[ "${ioda_file}" == *abi* || "${ioda_file}" == *atms* || "${ioda_file}" == *cris* ]]; then - if [[ "${ioda_file}" == *abi* ]]; then - echo " ${ioda_file} ioda file detected: running offline_domain_check_satrad.py" - ./offline_domain_check_satrad.py -o "${ioda_file}" -g "${grid_file}" -s 0.005 - base_name=$(basename "$ioda_file" .nc) - mv "${base_name}_dc.nc" "${base_name}.nc" - elif [[ "${ioda_file}" == *atms* || "${ioda_file}" == *cris* ]]; then - echo " ${ioda_file} ioda file detected: temporarily skipping offline domain check" + if [[ "${ioda_file}" == *abi* || "${ioda_file}" == *atms* || "${ioda_file}" == *cris* ]]; then + echo " ${ioda_file} ioda tweak is skipped for abi, atms, and cris" else - ./offline_domain_check.py -o "${ioda_file}" -g "${grid_file}" -s 0.005 - base_name=$(basename "$ioda_file" .nc) - mv "${base_name}_dc.nc" "${base_name}.nc" + echo " ${ioda_file} running ioda tweak" ./offline_ioda_tweak.py -o "${ioda_file}" base_name=$(basename "$ioda_file" .nc) mv "${base_name}_llp.nc" "${base_name}.nc" From 04b8376931388ec341382771a0ad946993e8bee1 Mon Sep 17 00:00:00 2001 From: Samuel Trahan Date: Thu, 29 Jan 2026 12:57:54 -0500 Subject: [PATCH 04/12] copy polygon to jedivar.yaml (and enable some debugging) --- scripts/exrrfs_jedivar.sh | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/scripts/exrrfs_jedivar.sh b/scripts/exrrfs_jedivar.sh index 7b79b7271..481be58e6 100755 --- a/scripts/exrrfs_jedivar.sh +++ b/scripts/exrrfs_jedivar.sh @@ -136,10 +136,16 @@ case ${YAML_GEN_METHOD:-1} in ;; esac +if ( grep -E '\*POLY' jedivar.yaml > /dev/null ) ; then + cp jedivar.yaml no_polygon_jedivar.yaml + ${USHrrfs}/yamlify_domain_edge.py -g "invariant.nc" -i '' > polygon.yaml + cat polygon.yaml no_polygon_jedivar.yaml > jedivar.yaml +fi + if [[ ${start_type} == "warm" ]] || [[ ${start_type} == "cold" && ${COLDSTART_CYCS_DO_DA^^} == "TRUE" ]]; then # run mpasjedi_variational.x - #export OOPS_TRACE=1 - #export OOPS_DEBUG=1 + export OOPS_TRACE=1 + export OOPS_DEBUG=1 export OMP_NUM_THREADS=1 source prep_step From 07ebfa095a4559031461a74ad7e8ac1ea21b875e Mon Sep 17 00:00:00 2001 From: Samuel Trahan Date: Mon, 2 Feb 2026 10:51:05 -0500 Subject: [PATCH 05/12] fix syntax errors in jedivar.yaml --- parm/jedivar.yaml | 106 +++++++++++++++++++++++----------------------- 1 file changed, 53 insertions(+), 53 deletions(-) diff --git a/parm/jedivar.yaml b/parm/jedivar.yaml index 965a6544c..37465bdb6 100644 --- a/parm/jedivar.yaml +++ b/parm/jedivar.yaml @@ -268,7 +268,7 @@ cost function: action: name: reduce obs space - - filter: *POLY + - *POLY # Duplicate Check # - filter: Temporal Thinning @@ -546,7 +546,7 @@ cost function: action: name: reduce obs space - - filter: *POLY + - *POLY # Duplicate Check # - filter: Temporal Thinning @@ -822,7 +822,7 @@ cost function: action: name: reduce obs space - - filter: *POLY + - *POLY # Duplicate Check - filter: Temporal Thinning @@ -1102,7 +1102,7 @@ cost function: action: name: reduce obs space - - filter: *POLY + - *POLY # Duplicate Check # - filter: Temporal Thinning @@ -1379,7 +1379,7 @@ cost function: action: name: reduce obs space - - filter: *POLY + - *POLY # Duplicate Check # - filter: Temporal Thinning @@ -1661,7 +1661,7 @@ cost function: action: name: reduce obs space - - filter: *POLY + - *POLY # Online regional domain check - filter: Bounds Check @@ -1937,7 +1937,7 @@ cost function: # action: # name: reduce obs space - - filter: *POLY + - *POLY # Online regional domain check - filter: Bounds Check @@ -2210,7 +2210,7 @@ cost function: action: name: reduce obs space - - filter: *POLY + - *POLY # Online regional domain check - filter: Bounds Check @@ -2490,7 +2490,7 @@ cost function: # action: # name: reduce obs space - - filter: *POLY + - *POLY # Online domain check - filter: Bounds Check @@ -2809,7 +2809,7 @@ cost function: # action: # name: reduce obs space - - filter: *POLY + - *POLY # Online domain check - filter: Bounds Check @@ -3121,7 +3121,7 @@ cost function: action: name: reduce obs space - - filter: *POLY + - *POLY # Online domain check - filter: Bounds Check @@ -3436,7 +3436,7 @@ cost function: # action: # name: reduce obs space - - filter: *POLY + - *POLY # Online regional domain check - filter: Bounds Check @@ -3712,7 +3712,7 @@ cost function: # action: # name: reduce obs space - - filter: *POLY + - *POLY # Online regional domain check - filter: Bounds Check @@ -3988,7 +3988,7 @@ cost function: # action: # name: reduce obs space - - filter: *POLY + - *POLY # Online regional domain check - filter: Bounds Check @@ -4264,7 +4264,7 @@ cost function: # action: # name: reduce obs space - - filter: *POLY + - *POLY # Online regional domain check - filter: Bounds Check @@ -4536,7 +4536,7 @@ cost function: # action: # name: reduce obs space - - filter: *POLY + - *POLY # Online regional domain check - filter: Bounds Check @@ -4815,7 +4815,7 @@ cost function: # action: # name: reduce obs space - - filter: *POLY + - *POLY # Online domain check - filter: Bounds Check @@ -5127,7 +5127,7 @@ cost function: # action: # name: reduce obs space - - filter: *POLY + - *POLY # Online domain check - filter: Bounds Check @@ -5436,7 +5436,7 @@ cost function: # action: # name: reduce obs space - - filter: *POLY + - *POLY # Online regional domain check - filter: Bounds Check @@ -5712,7 +5712,7 @@ cost function: # action: # name: reduce obs space - - filter: *POLY + - *POLY # Online regional domain check - filter: Bounds Check @@ -5991,7 +5991,7 @@ cost function: # action: # name: reduce obs space - - filter: *POLY + - *POLY # Online domain check - filter: Bounds Check @@ -6300,7 +6300,7 @@ cost function: # action: # name: reduce obs space - - filter: *POLY + - *POLY # Online regional domain check - filter: Bounds Check @@ -6576,7 +6576,7 @@ cost function: # action: # name: reduce obs space - - filter: *POLY + - *POLY # Online regional domain check - filter: Bounds Check @@ -6852,7 +6852,7 @@ cost function: # action: # name: reduce obs space - - filter: *POLY + - *POLY # Online regional domain check - filter: Bounds Check @@ -7128,7 +7128,7 @@ cost function: # action: # name: reduce obs space - - filter: *POLY + - *POLY # Online regional domain check - filter: Bounds Check @@ -7404,7 +7404,7 @@ cost function: # action: # name: reduce obs space - - filter: *POLY + - *POLY # Online regional domain check - filter: Bounds Check @@ -7683,7 +7683,7 @@ cost function: # action: # name: reduce obs space - - filter: *POLY + - *POLY # Online domain check - filter: Bounds Check @@ -7995,7 +7995,7 @@ cost function: # action: # name: reduce obs space - - filter: *POLY + - *POLY # Online domain check - filter: Bounds Check @@ -8307,7 +8307,7 @@ cost function: # action: # name: reduce obs space - - filter: *POLY + - *POLY # Online domain check - filter: Bounds Check @@ -8619,7 +8619,7 @@ cost function: # action: # name: reduce obs space - - filter: *POLY + - *POLY # Online domain check - filter: Bounds Check @@ -8901,7 +8901,7 @@ cost function: name: assign error error parameter: 0.01 - - filter: *POLY + - *POLY # Terrain Height Discrepancy Check - filter: Difference Check @@ -9004,7 +9004,7 @@ cost function: # action: # name: reduce obs space - - filter: *POLY + - *POLY # Online regional domain check - filter: Bounds Check @@ -9280,7 +9280,7 @@ cost function: # action: # name: reduce obs space - - filter: *POLY + - *POLY # Online regional domain check - filter: Bounds Check @@ -9549,7 +9549,7 @@ cost function: # action: # name: reduce obs space - - filter: *POLY + - *POLY # Online regional domain check - filter: Bounds Check @@ -10406,7 +10406,7 @@ cost function: # action: # name: reduce obs space - - filter: *POLY + - *POLY # Online regional domain check - filter: Bounds Check @@ -10759,7 +10759,7 @@ cost function: # action: # name: reduce obs space - - filter: *POLY + - *POLY # Online regional domain check - filter: Bounds Check @@ -11035,7 +11035,7 @@ cost function: # action: # name: reduce obs space - - filter: *POLY + - *POLY # Online regional domain check - filter: Bounds Check @@ -11311,7 +11311,7 @@ cost function: # action: # name: reduce obs space - - filter: *POLY + - *POLY # Online regional domain check - filter: Bounds Check @@ -11588,7 +11588,7 @@ cost function: # action: # name: reduce obs space - - filter: *POLY + - *POLY # Online regional domain check - filter: Bounds Check @@ -11864,7 +11864,7 @@ cost function: # action: # name: reduce obs space - - filter: *POLY + - *POLY # Online regional domain check - filter: Bounds Check @@ -12140,7 +12140,7 @@ cost function: # action: # name: reduce obs space - - filter: *POLY + - *POLY # Online regional domain check - filter: Bounds Check @@ -12417,7 +12417,7 @@ cost function: # action: # name: reduce obs space - - filter: *POLY + - *POLY # Online regional domain check - filter: Bounds Check @@ -12689,7 +12689,7 @@ cost function: # action: # name: reduce obs space - - filter: *POLY + - *POLY # Online regional domain check - filter: Bounds Check @@ -12977,7 +12977,7 @@ cost function: # action: # name: reduce obs space - - filter: *POLY + - *POLY # Online domain check - filter: Bounds Check @@ -13295,7 +13295,7 @@ cost function: # action: # name: reduce obs space - - filter: *POLY + - *POLY # Online domain check - filter: Bounds Check @@ -13614,7 +13614,7 @@ cost function: # action: # name: reduce obs space - - filter: *POLY + - *POLY # Online domain check - filter: Bounds Check @@ -13932,7 +13932,7 @@ cost function: # action: # name: reduce obs space - - filter: *POLY + - *POLY # Online domain check - filter: Bounds Check @@ -14290,7 +14290,7 @@ cost function: # action: # name: reduce obs space - - filter: *POLY + - *POLY # Online domain check - filter: Bounds Check @@ -14699,7 +14699,7 @@ cost function: # action: # name: reduce obs space - - filter: *POLY + - *POLY # Online domain check - filter: Bounds Check @@ -15108,7 +15108,7 @@ cost function: # action: # name: reduce obs space - - filter: *POLY + - *POLY # Online domain check - filter: Bounds Check @@ -15483,7 +15483,7 @@ cost function: # action: # name: reduce obs space - - filter: *POLY + - *POLY # Online domain check - filter: Bounds Check @@ -15883,7 +15883,7 @@ cost function: action: name: reduce obs space - - filter: *POLY + - *POLY # Online domain check - filter: Bounds Check @@ -16267,7 +16267,7 @@ cost function: action: name: reduce obs space - - filter: *POLY + - *POLY # Duplicate Check - filter: Temporal Thinning From eac7d17c3363fd8b2c096631a5c2dd5f65657705 Mon Sep 17 00:00:00 2001 From: Samuel Trahan Date: Mon, 2 Feb 2026 10:51:27 -0500 Subject: [PATCH 06/12] fix syntax error in polygon --- ush/yamlify_domain_edge.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ush/yamlify_domain_edge.py b/ush/yamlify_domain_edge.py index b0380d948..c90814382 100755 --- a/ush/yamlify_domain_edge.py +++ b/ush/yamlify_domain_edge.py @@ -210,7 +210,7 @@ def print_ring(ring, lonlat, indent, columns=8): indent=args.indent -print(f'''{indent}- &POLY +print(f'''{indent}polygon: &POLY {indent} filter: Polygon Check {indent} action: {indent} name: reduce obs space From 3bc9699f51752c41b8f164b737b755736dbf1ff2 Mon Sep 17 00:00:00 2001 From: Samuel Trahan Date: Mon, 2 Feb 2026 11:33:32 -0500 Subject: [PATCH 07/12] Polygon Check filter from UFS PR --- sorc/_workaround_/PolygonCheck/CMakeLists.txt | 406 +++++ .../PolygonCheck/ObsPolygonCheck.cc | 134 ++ .../PolygonCheck/ObsPolygonCheck.h | 104 ++ .../PolygonCheck/filtersCMakeLists.txt | 1329 +++++++++++++++++ .../instantiateObsFilterFactory.h | 225 +++ .../PolygonCheck/polygon_check.yaml | 21 + sorc/build.rdas | 7 + 7 files changed, 2226 insertions(+) create mode 100644 sorc/_workaround_/PolygonCheck/CMakeLists.txt create mode 100644 sorc/_workaround_/PolygonCheck/ObsPolygonCheck.cc create mode 100644 sorc/_workaround_/PolygonCheck/ObsPolygonCheck.h create mode 100644 sorc/_workaround_/PolygonCheck/filtersCMakeLists.txt create mode 100644 sorc/_workaround_/PolygonCheck/instantiateObsFilterFactory.h create mode 100644 sorc/_workaround_/PolygonCheck/polygon_check.yaml diff --git a/sorc/_workaround_/PolygonCheck/CMakeLists.txt b/sorc/_workaround_/PolygonCheck/CMakeLists.txt new file mode 100644 index 000000000..993bcb480 --- /dev/null +++ b/sorc/_workaround_/PolygonCheck/CMakeLists.txt @@ -0,0 +1,406 @@ +# (C) Copyright 2017-2018 UCAR. +# +# This software is licensed under the terms of the Apache Licence Version 2.0 +# which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. + +set ( filters_files + BackgroundCheck.cc + BackgroundCheck.h + BayesianBackgroundQCFlags.cc + BayesianBackgroundQCFlags.h + BayesianBackgroundCheck.cc + BayesianBackgroundCheck.h + BlackList.cc + BlackList.h + ConventionalProfileProcessing.cc + ConventionalProfileProcessing.h + ConventionalProfileProcessingParameters.h + CopyFlagsFromExtendedToOriginalSpace.cc + CopyFlagsFromExtendedToOriginalSpace.h + CreateDiagnosticFlags.cc + CreateDiagnosticFlags.h + DiagnosticFlag.h + DifferenceCheck.cc + DifferenceCheck.h + EnsembleStatistics.cc + EnsembleStatistics.h + FilterBase.cc + FilterBase.h + FilterParametersBase.cc + FilterParametersBase.h + FilterUtils.cc + FilterUtils.h + FinalCheck.cc + FinalCheck.h + GenericFilterParameters.h + GeoVaLsWriter.cc + GeoVaLsWriter.h + getScalarOrFilterData.cc + getScalarOrFilterData.h + HistoryCheck.cc + HistoryCheck.h + HistoryCheckParameters.h + ImpactHeightCheck.cc + ImpactHeightCheck.h + ObsBoundsCheck.cc + ObsBoundsCheck.h + ObsProcessorBase.cc + ObsProcessorBase.h + MetOfficeBuddyCheck.cc + MetOfficeBuddyCheck.h + MetOfficeBuddyCheckParameters.h + MetOfficeBuddyCollector.cc + MetOfficeBuddyCollector.h + MetOfficeBuddyCollectorV1.cc + MetOfficeBuddyCollectorV1.h + MetOfficeBuddyCollectorV2.cc + MetOfficeBuddyCollectorV2.h + MetOfficeBuddyPair.h + MetOfficeBuddyPairFinder.cc + MetOfficeBuddyPairFinder.h + MetOfficeDuplicateCheck.cc + MetOfficeDuplicateCheck.h + MetOfficePressureConsistencyCheck.cc + MetOfficePressureConsistencyCheck.h + ModelBestFitPressure.cc + ModelBestFitPressure.h + ModelObThreshold.cc + ModelObThreshold.h + MWCLWCheck.cc + MWCLWCheck.h + ObsDiagnosticsWriter.cc + ObsDiagnosticsWriter.h + ObsDomainCheck.cc + ObsDomainCheck.h + ObsDerivativeCheck.cc + ObsDerivativeCheck.h + ObsDomainErrCheck.cc + ObsDomainErrCheck.h + ObsFilterData.cc + ObsFilterData.h + ObsPolygonCheck.cc + ObsPolygonCheck.h + ObsRefractivityGradientCheck.h + ObsRefractivityGradientCheck.cc + ParameterSubstitution.cc + ParameterSubstitution.h + PreQC.cc + PreQC.h + ProbabilityGrossErrorWholeReport.cc + ProbabilityGrossErrorWholeReport.h + ProcessAMVQI.cc + ProcessAMVQI.h + QCflags.h + QCmanager.cc + QCmanager.h + PerformAction.cc + PerformAction.h + ProfileAverageObsToModLevels.cc + ProfileAverageObsToModLevels.h + AverageObsToGeoValLevels.cc + AverageObsToGeoValLevels.h + ProfileBackgroundCheck.cc + ProfileBackgroundCheck.h + ProfileFewObsCheck.cc + ProfileFewObsCheck.h + ProfileMaxDifferenceCheck.cc + ProfileMaxDifferenceCheck.h + ProfileUnFlagObsCheck.cc + ProfileUnFlagObsCheck.h + SatName.h + SatName.cc + SatwindInversionCorrection.cc + SatwindInversionCorrection.h + SpikeAndStepCheck.cc + SpikeAndStepCheck.h + StuckCheck.cc + StuckCheck.h + StuckCheckParameters.h + SuperOb.h + SuperOb.cc + SuperRefractionCheckImpactParameter.h + SuperRefractionCheckImpactParameter.cc + SuperRefractionCheckNBAM.h + SuperRefractionCheckNBAM.cc + obsfunctions/DrawObsErrorFromFile.cc + obsfunctions/DrawObsErrorFromFile.h + obsfunctions/DrawValueFromFile.cc + obsfunctions/DrawValueFromFile.h + Thinning.cc + Thinning.h + TemporalThinning.cc + TemporalThinning.h + TemporalThinningParameters.h + TrackCheck.cc + TrackCheck.h + TrackCheckParameters.h + TrackCheckShip.cc + TrackCheckShip.h + TrackCheckShipDiagnostics.h + TrackCheckShipParameters.h + TrackCheckUtils.cc + TrackCheckUtils.h + TrackCheckUtilsParameters.cc + TrackCheckUtilsParameters.h + Variable.cc + Variable.h + VariableTransforms.cc + VariableTransforms.h + VariableTransformParametersBase.h + Variables.cc + Variables.h + VariableAssignment.cc + VariableAssignment.h + AcceptList.cc + AcceptList.h + Gaussian_Thinning.cc + Gaussian_Thinning.h + GaussianThinningParameters.cc + GaussianThinningParameters.h + PoissonDiskThinning.cc + PoissonDiskThinning.h + PoissonDiskThinningParameters.cc + PoissonDiskThinningParameters.h + processWhere.cc + processWhere.h + ObsAccessor.cc + ObsAccessor.h + PrintFilterData.cc + PrintFilterData.h + actions/AssignError.cc + actions/AssignError.h + actions/AcceptObs.cc + actions/AcceptObs.h + actions/FilterAction.cc + actions/FilterAction.h + actions/FilterActionBase.cc + actions/FilterActionBase.h + actions/FlagOriginalAndAveragedProfiles.cc + actions/FlagOriginalAndAveragedProfiles.h + actions/InflateError.cc + actions/InflateError.h + actions/PassivateObs.cc + actions/PassivateObs.h + actions/ReduceObsSpace.cc + actions/ReduceObsSpace.h + actions/RejectObs.cc + actions/RejectObs.h + actions/ROobserrInflation.cc + actions/ROobserrInflation.h + actions/SetFlag.cc + actions/SetFlag.h + actions/SetFlagBit.cc + actions/SetFlagBit.h + obsfunctions/AircraftBiasCorrectionTerm.cc + obsfunctions/AircraftBiasCorrectionTerm.h + obsfunctions/AverageTemperatureBelow.cc + obsfunctions/AverageTemperatureBelow.h + obsfunctions/BennartzScatIndex.cc + obsfunctions/BennartzScatIndex.h + obsfunctions/ChannelUseflagCheckRad.cc + obsfunctions/ChannelUseflagCheckRad.h + obsfunctions/CLWMatchIndexMW.cc + obsfunctions/CLWMatchIndexMW.h + obsfunctions/CLWRetMW.cc + obsfunctions/CLWRetMW.h + obsfunctions/TotalColumnVaporGuess.cc + obsfunctions/TotalColumnVaporGuess.h + obsfunctions/CLWRetMW_SSMIS.cc + obsfunctions/CLWRetMW_SSMIS.h + obsfunctions/CLWRetSymmetricMW.cc + obsfunctions/CLWRetSymmetricMW.h + obsfunctions/Conditional.cc + obsfunctions/Conditional.h + obsfunctions/AssignValueEqualChannels.cc + obsfunctions/AssignValueEqualChannels.h + obsfunctions/SetSeaIceEmiss.cc + obsfunctions/SetSeaIceEmiss.h + obsfunctions/SetSurfaceType.cc + obsfunctions/SetSurfaceType.h + obsfunctions/SIRetMW.cc + obsfunctions/SIRetMW.h + obsfunctions/SIRetSymmetricMW.cc + obsfunctions/SIRetSymmetricMW.h + obsfunctions/Emissivity_Diff_GMI.cc + obsfunctions/Emissivity_Diff_GMI.h + obsfunctions/HydrometeorCheckAMSUA.cc + obsfunctions/HydrometeorCheckAMSUA.h + obsfunctions/HydrometeorCheckATMS.cc + obsfunctions/HydrometeorCheckATMS.h + obsfunctions/HydrometeorCheckAMSUAclr.cc + obsfunctions/HydrometeorCheckAMSUAclr.h + obsfunctions/ImpactHeight.cc + obsfunctions/ImpactHeight.h + obsfunctions/InterChannelConsistencyCheck.cc + obsfunctions/InterChannelConsistencyCheck.h + obsfunctions/LiquidWaterPathGuess.cc + obsfunctions/LiquidWaterPathGuess.h + obsfunctions/BgdDepartureAnomaly.cc + obsfunctions/BgdDepartureAnomaly.h + obsfunctions/ObsErrorModelHumidity.cc + obsfunctions/ObsErrorModelHumidity.h + obsfunctions/ObsErrorModelStepwiseLinear.cc + obsfunctions/ObsErrorModelStepwiseLinear.h + obsfunctions/ObsErrorModelRamp.cc + obsfunctions/ObsErrorModelRamp.h + obsfunctions/ObsErrorModelQuad.cc + obsfunctions/ObsErrorModelQuad.h + obsfunctions/ObsFunction.cc + obsfunctions/ObsFunction.h + obsfunctions/ObsFunctionArithmetic.cc + obsfunctions/ObsFunctionArithmetic.h + obsfunctions/ObsFunctionBase.cc + obsfunctions/ObsFunctionBase.h + obsfunctions/CloudCostFunction.cc + obsfunctions/CloudCostFunction.h + obsfunctions/CloudDetectMinResidualAVHRR.cc + obsfunctions/CloudDetectMinResidualAVHRR.h + obsfunctions/CloudDetectMinResidualIR.cc + obsfunctions/CloudDetectMinResidualIR.h + obsfunctions/CloudFirstGuessMinimumResidual.cc + obsfunctions/CloudFirstGuessMinimumResidual.h + obsfunctions/MetOfficeAllSkyErrorModel.cc + obsfunctions/MetOfficeAllSkyErrorModel.h + obsfunctions/ModelHeightAdjustedWindVectorComponent.cc + obsfunctions/ModelHeightAdjustedWindVectorComponent.h + obsfunctions/ModelHeightAdjustedAirTemperature.cc + obsfunctions/ModelHeightAdjustedAirTemperature.h + obsfunctions/ModelHeightAdjustedRelativeHumidity.cc + obsfunctions/ModelHeightAdjustedRelativeHumidity.h + obsfunctions/ModelHeightAdjustedMarineWind.cc + obsfunctions/ModelHeightAdjustedMarineWind.h + obsfunctions/MPIRank.cc + obsfunctions/MPIRank.h + obsfunctions/ObsErrorBoundConventional.cc + obsfunctions/ObsErrorBoundConventional.h + obsfunctions/ObsErrorBoundIR.cc + obsfunctions/ObsErrorBoundIR.h + obsfunctions/ObsErrorBoundMW.cc + obsfunctions/ObsErrorBoundMW.h + obsfunctions/ObsErrorSatSpecHumidity.cc + obsfunctions/ObsErrorSatSpecHumidity.h + obsfunctions/ObsErrorFactorDuplicateCheck.cc + obsfunctions/ObsErrorFactorDuplicateCheck.h + obsfunctions/ObsErrorFactorPressureCheck.cc + obsfunctions/ObsErrorFactorPressureCheck.h + obsfunctions/ObsErrorFactorSituDependMW.cc + obsfunctions/ObsErrorFactorSituDependMW.h + obsfunctions/ObsErrorFactorSurfJacobianRad.cc + obsfunctions/ObsErrorFactorSurfJacobianRad.h + obsfunctions/ObsErrorFactorLatRad.cc + obsfunctions/ObsErrorFactorLatRad.h + obsfunctions/ObsErrorFactorQuotient.cc + obsfunctions/ObsErrorFactorQuotient.h + obsfunctions/ObsErrorFactorTopoRad.cc + obsfunctions/ObsErrorFactorTopoRad.h + obsfunctions/ObsErrorFactorTransmitTopRad.cc + obsfunctions/ObsErrorFactorTransmitTopRad.h + obsfunctions/ObsErrorFactorWavenumIR.cc + obsfunctions/ObsErrorFactorWavenumIR.h + obsfunctions/ObsErrorFactorSfcPressure.cc + obsfunctions/ObsErrorFactorSfcPressure.h + obsfunctions/ObsErrorFactorConventional.cc + obsfunctions/ObsErrorFactorConventional.h + obsfunctions/PotentialTemperatureFromTemperature.cc + obsfunctions/PotentialTemperatureFromTemperature.h + obsfunctions/NearSSTRetCheckIR.cc + obsfunctions/NearSSTRetCheckIR.h + obsfunctions/ObsFunctionElementMultiply.cc + obsfunctions/ObsFunctionElementMultiply.h + obsfunctions/ObsFunctionExponential.cc + obsfunctions/ObsFunctionExponential.h + obsfunctions/ObsFunctionScattering.cc + obsfunctions/ObsFunctionScattering.h + obsfunctions/ObsFunctionSelectStatistic.cc + obsfunctions/ObsFunctionSelectStatistic.h + obsfunctions/ObsFunctionStringManipulation.cc + obsfunctions/ObsFunctionStringManipulation.h + obsfunctions/ObsFunctionVelocity.cc + obsfunctions/ObsFunctionVelocity.h + obsfunctions/ObsFunctionVisibilityDiagnostic.cc + obsfunctions/ObsFunctionVisibilityDiagnostic.h + obsfunctions/OceanPressureToDepth.cc + obsfunctions/OceanPressureToDepth.h + obsfunctions/OrbitAngle.cc + obsfunctions/OrbitAngle.h + obsfunctions/SatwindIndivErrors.cc + obsfunctions/SatwindIndivErrors.h + obsfunctions/SatWindsLNVDCheck.cc + obsfunctions/SatWindsLNVDCheck.h + obsfunctions/WindsSPDBCheck.cc + obsfunctions/WindsSPDBCheck.h + obsfunctions/SatWindsErrnormCheck.cc + obsfunctions/SatWindsErrnormCheck.h + obsfunctions/ScatWindsAmbiguityCheck.cc + obsfunctions/ScatWindsAmbiguityCheck.h + obsfunctions/SCATRetMW.cc + obsfunctions/SCATRetMW.h + obsfunctions/SymmCldImpactIR.cc + obsfunctions/SymmCldImpactIR.h + obsfunctions/SolarZenith.cc + obsfunctions/SolarZenith.h + obsfunctions/StableLayersCloudTopPressure.cc + obsfunctions/StableLayersCloudTopPressure.h + obsfunctions/SunGlintAngle.cc + obsfunctions/SunGlintAngle.h + obsfunctions/SurfTypeCheckRad.cc + obsfunctions/SurfTypeCheckRad.h + obsfunctions/GeoCloudCreateCloudColumn.cc + obsfunctions/GeoCloudCreateCloudColumn.h + obsfunctions/SurfaceCloudCreateCloudColumn.cc + obsfunctions/SurfaceCloudCreateCloudColumn.h + obsfunctions/SurfaceCloudModelLevelCBH.cc + obsfunctions/SurfaceCloudModelLevelCBH.h + obsfunctions/TropopauseEstimate.cc + obsfunctions/TropopauseEstimate.h + obsfunctions/TropopauseHeight.cc + obsfunctions/TropopauseHeight.h + obsfunctions/WindDirAngleDiff.cc + obsfunctions/WindDirAngleDiff.h + obsfunctions/WindUVfromObsSpdHofxDir.cc + obsfunctions/WindUVfromObsSpdHofxDir.h + obsfunctions/LAMDomainCheck/LAMDomainCheck.cc + obsfunctions/LAMDomainCheck/LAMDomainCheck.h + obsfunctions/LAMDomainCheck/LAMDomainCheck.interface.h + obsfunctions/LAMDomainCheck/LAMDomainCheck.interface.F90 + obsfunctions/LAMDomainCheck/esg_grid_mod.F90 + obsfunctions/ProfileAverageObsPressure.cc + obsfunctions/ProfileAverageObsPressure.h + obsfunctions/ProfileLevelCount.cc + obsfunctions/ProfileLevelCount.h + obsfunctions/DateTimeOffset.cc + obsfunctions/DateTimeOffset.h + obsfunctions/FillAveragedProfileData.cc + obsfunctions/FillAveragedProfileData.h + obsfunctions/MetOfficeRelativeHumidityCorrection.cc + obsfunctions/MetOfficeRelativeHumidityCorrection.h + obsfunctions/RadarScanEdgeFlag.cc + obsfunctions/RadarScanEdgeFlag.h + obsfunctions/RecordNumberToObsSpace.cc + obsfunctions/RecordNumberToObsSpace.h + obsfunctions/ModelLevelIndex.cc + obsfunctions/ModelLevelIndex.h +) + +if( ${gsw_FOUND} ) + list( APPEND filters_files OceanVerticalStabilityCheck.cc + OceanVerticalStabilityCheck.h ) +endif( ${gsw_FOUND} ) + +if( ${rttov_FOUND} ) + add_subdirectory( rttovonedvarcheck ) + list( APPEND filters_files ${rttovonedvarcheck_src_files} ) +endif( ${rttov_FOUND} ) + +add_subdirectory( gnssroonedvarcheck ) +list( APPEND filters_files ${gnssroonedvarcheck_src_files} ) + +add_subdirectory( refractivityonedvarcheck ) +list( APPEND filters_files ${refractivityonedvarcheck_src_files} ) + +PREPEND( _p_filters_files "filters" ${filters_files} ) + +set ( filters_src_files + ${_p_filters_files} + PARENT_SCOPE +) diff --git a/sorc/_workaround_/PolygonCheck/ObsPolygonCheck.cc b/sorc/_workaround_/PolygonCheck/ObsPolygonCheck.cc new file mode 100644 index 000000000..d2be390a0 --- /dev/null +++ b/sorc/_workaround_/PolygonCheck/ObsPolygonCheck.cc @@ -0,0 +1,134 @@ +/* + * CC0 - No Copyright (Public Domain) + * + * The person who associated a work with this deed has dedicated the work to the public domain by waiving all of his or her rights to the work worldwide under copyright law, including all related and neighboring rights, to the extent allowed by law. + * + * You can copy, modify, distribute and perform the work, even for commercial purposes, all without asking permission. See Other Information below. + * + * Other Information + * In no way are the patent or trademark rights of any person affected by CC0, nor are the rights that other persons may have in the work or in how the work is used, such as publicity or privacy rights. + * + * The person who associated a work with this deed makes no warranties about the work, and disclaims liability for all uses of the work, to the fullest extent permitted by applicable law. + * + * When using or citing the work, you should not imply endorsement by the author or the affirmer. + */ + +#include "ufo/filters/ObsPolygonCheck.h" + +#include +#include +#include +#include +#include +#include "ioda/ObsSpace.h" +#include "oops/util/Logger.h" + +namespace ufo { + +// ----------------------------------------------------------------------------- + +ObsPolygonCheck::ObsPolygonCheck(ioda::ObsSpace & obsdb, const Parameters_ & parameters, + std::shared_ptr > flags, + std::shared_ptr > obserr) + : FilterBase(obsdb, parameters, flags, obserr), parameters_(parameters) +{ + oops::Log::trace() << "ObsPolygonCheck constructor" << std::endl; +} + +// ----------------------------------------------------------------------------- + +ObsPolygonCheck::~ObsPolygonCheck() { + oops::Log::trace() << "ObsPolygonCheck destructor" << std::endl; +} + +// ----------------------------------------------------------------------------- + +void ObsPolygonCheck::applyFilter(const std::vector &apply, + const Variables & filtervars, + std::vector> & flagged) const { + oops::Log::trace() << "ObsPolygonCheck applyFilter start" << std::endl; + + namespace bg = boost::geometry; + + // point_t = a boost::geometry point as a longitude-latitude pair in degrees + using point_t = bg::model::point>; + + // polygon_t = a closed polygon of those points + using polygon_t = bg::model::polygon; + + // Get from the parameters a point within the polygon. + const point_t insidePoint(parameters_.inside_point_longitude.value(), + parameters_.inside_point_latitude.value()); + + // Assemble a polygon from the list of longitudes and latitudes. + polygon_t poly; + const auto &vertex_latitudes = parameters_.vertex_latitudes.value(); + const auto &vertex_longitudes = parameters_.vertex_longitudes.value(); + const size_t nlon = vertex_longitudes.size(); + const size_t nlat = vertex_latitudes.size(); + if (nlon != nlat) { + std::ostringstream what; + what << "Mismatch between vertex longitude count (" << nlon + << ") and vertex latitude count (" << nlat << ")."; + throw ObsPolygonLatLonSizeMismatch(what.str()); + } + for (int i = 0; i < nlon; i++) + poly.outer().push_back(point_t(vertex_longitudes[i], vertex_latitudes[i])); + + // Ask boost::geometry to correct common problems in the polygon definition. + bg::correct(poly); + + // Scan for obvious errors that bg::correct couldn't correct. + if (std::string reason; !bg::is_valid(poly, reason)) { + std::ostringstream what; + what << "ObsPolygonCheck: unable to correct invalid polygon (" << reason << ")"; + throw ObsPolygonIsInvalid(what.str()); + } + + // Get the observation locations. + std::vector lats, lons; + obsdb_.get_db("MetaData", "latitude", lats); + obsdb_.get_db("MetaData", "longitude", lons); + + // Figure out which side is the inside by checking a point that is known to be inside. + const bool useThisSide = bg::within(insidePoint, poly); + + // Find all points that are on the opposite side from the "inside point" + const size_t nlocs = obsdb_.nlocs(); + std::vector notInside(nlocs, true); + size_t applyCount = 0; + size_t insideCount = 0; + for (size_t iloc = 0; iloc < nlocs; iloc++) + if (apply[iloc]) { + try { + applyCount++; + bool inside = useThisSide == bg::within(point_t(lons[iloc], lats[iloc]), poly); + notInside[iloc] = !inside; + if (inside) + insideCount++; + } catch(const bg::exception &ex) { + // We only catch boost geometry exceptions here; anything else is passed through. + oops::Log::error() << "ObsPolygonCheck: boost::geometry error: " << ex.what() << std::endl; + // The default value for all points is "not inside" so any erroring points will be rejected. + } + } + + for (auto &vec : flagged) + for (size_t iloc = 0; iloc < nlocs; iloc++) + if (apply[iloc]) + vec[iloc] = notInside[iloc]; + + oops::Log::trace() << "ObsPolygonCheck applyFilter complete (kept " << insideCount + << " of " << applyCount << " locations discarding " + << (applyCount - insideCount) << ")" << std::endl; +} + +// ----------------------------------------------------------------------------- + +void ObsPolygonCheck::print(std::ostream & os) const { + os << "ObsPolygonCheck: config = " << parameters_ << std::endl; +} + +// ----------------------------------------------------------------------------- + +} // namespace ufo diff --git a/sorc/_workaround_/PolygonCheck/ObsPolygonCheck.h b/sorc/_workaround_/PolygonCheck/ObsPolygonCheck.h new file mode 100644 index 000000000..7bb9c30a4 --- /dev/null +++ b/sorc/_workaround_/PolygonCheck/ObsPolygonCheck.h @@ -0,0 +1,104 @@ +/* + * CC0 - No Copyright (Public Domain) + * + * The person who associated a work with this deed has dedicated the work to the public domain by waiving all of his or her rights to the work worldwide under copyright law, including all related and neighboring rights, to the extent allowed by law. + * + * You can copy, modify, distribute and perform the work, even for commercial purposes, all without asking permission. See Other Information below. + * + * Other Information + * In no way are the patent or trademark rights of any person affected by CC0, nor are the rights that other persons may have in the work or in how the work is used, such as publicity or privacy rights. + * + * The person who associated a work with this deed makes no warranties about the work, and disclaims liability for all uses of the work, to the fullest extent permitted by applicable law. + * + * When using or citing the work, you should not imply endorsement by the author or the affirmer. + */ + +#ifndef UFO_FILTERS_OBSPOLYGONCHECK_H_ +#define UFO_FILTERS_OBSPOLYGONCHECK_H_ + +#include +#include +#include +#include +#include + +#include "oops/util/ObjectCounter.h" +#include "ufo/filters/FilterBase.h" +#include "ufo/filters/QCflags.h" + +namespace ioda { + template class ObsDataVector; + class ObsSpace; +} + +namespace ufo { + +class ObsPolygonCheckParameters : public FilterParametersBase { + OOPS_CONCRETE_PARAMETERS(ObsPolygonCheckParameters, FilterParametersBase) + + public: + oops::RequiredParameter> vertex_longitudes { + "vertex longitudes", + "Longitudes of vertices of the polygon.", + this}; + oops::RequiredParameter> vertex_latitudes { + "vertex latitudes", + "Latitudes of vertices of the polygon.", + this}; + oops::RequiredParameter inside_point_longitude { + "inside point longitude", + "Longitude of a point inside the polygon (used to determine which side is inside).", + this}; + oops::RequiredParameter inside_point_latitude { + "inside point latitude", + "Latitude of a point inside the polygon (used to determine which side is inside).", + this}; +}; + +/// ObsPolygonLatLonSizeMismatch: thrown when the parameters vertex_longitudes +/// and vertex_latitudes have different lengths. + +class ObsPolygonLatLonSizeMismatch: public std::invalid_argument { + public: + explicit ObsPolygonLatLonSizeMismatch(const std::string &message): + std::invalid_argument(message) + {} +}; + +/// ObsPolygonIsInvalid: thrown when boost::geometry::is_valid doesn't like a polygon. + +class ObsPolygonIsInvalid: public std::invalid_argument { + public: + explicit ObsPolygonIsInvalid(const std::string &message): + std::invalid_argument(message) + {} +}; + +/// PolygonCheck: find obs within a specified polygon. + +class ObsPolygonCheck : public FilterBase, + private util::ObjectCounter { + public: + /// The type of parameters accepted by the constructor of this filter. + /// This typedef is used by the FilterFactory. + typedef ObsPolygonCheckParameters Parameters_; + + static const std::string classname() {return "ufo::ObsPolygonCheck";} + + ObsPolygonCheck(ioda::ObsSpace &, const Parameters_ &, + std::shared_ptr >, + std::shared_ptr >); + ~ObsPolygonCheck(); + + private: + void print(std::ostream &) const override; + void applyFilter(const std::vector &, const Variables &, + std::vector> &) const override; + int qcFlag() const override {return QCflags::domain;} + + Parameters_ parameters_; +}; + +} // namespace ufo + +#endif // UFO_FILTERS_OBSPOLYGONCHECK_H_ diff --git a/sorc/_workaround_/PolygonCheck/filtersCMakeLists.txt b/sorc/_workaround_/PolygonCheck/filtersCMakeLists.txt new file mode 100644 index 000000000..3f4561f87 --- /dev/null +++ b/sorc/_workaround_/PolygonCheck/filtersCMakeLists.txt @@ -0,0 +1,1329 @@ +# (C) Copyright 2022 UCAR. +# +# This software is licensed under the terms of the Apache Licence Version 2.0 +# which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. + +# Unit tests for filters + +add_subdirectory(actions) +add_subdirectory(obsfunctions) + + +ufo_add_test( NAME test_ufo_amsua_seaice_qc + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/amsua_seaice_qc.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_assign_error_using_where + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/assign_error_using_where.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_ensemblestatistics + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_EnsembleObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/ensemblestatistics.yaml" + MPI 8 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_ensemblestatistics_channels + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_EnsembleObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/ensemblestatistics_channels.yaml" + MPI 8 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_filter_stage + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/filter_stage.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_filter_stage_mpi + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/filter_stage.yaml" + MPI 2 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_gnssrobendmetoffice_qc + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/gnssrobendmetoffice_qc.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_gnssrobendmetoffice_qc_profile + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/gnssrobendmetoffice_qc_profile.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_gnssrobendmetoffice_obserror + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/gnssrobendmetoffice_obserror.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_gnssrorefmetoffice_qc + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/gnssrorefmetoffice_qc.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_gnssrobndnbam_qc + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/gnssrobndnbam_qc.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_gnssrobndnbam_qc_geos + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/gnssrobndnbam_qc_geos.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_gnssrobndnbam_qc_action_obserr_inflation + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/gnssrobndnbam_qc_action_obserr_inflation.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_gnssro_obs_error + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/gnssro_obs_error.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) + +# +ufo_add_test( NAME test_ufo_gnssro_super_refraction_check + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/gnssro_super_refraction_check.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_metar_qc_filters + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/metar_qc_filters.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_obserror_assign_unittests + TIER 1 + ECBUILD + SOURCES ../../../mains/TestObsErrorAssign.cc + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/obserror_assign_unittests.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_obsfilterdata + TIER 1 + ECBUILD + SOURCES ../../../mains/TestObsFilterData.cc + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/obsfilterdata.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_ompsnp_npp_qc_L127 + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/ompsnp_npp_qc_L127.yaml" + MPI 4 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_print_filter_data + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/print_filter_data.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_print_filter_data_MPI2 + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/print_filter_data.yaml" + MPI 2 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_print_filter_data_MPI3 + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/print_filter_data.yaml" + MPI 3 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_print_filter_data_inefficient_distribution + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/print_filter_data_inefficient_distribution.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_print_filter_data_MPI2_rank0 + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/print_filter_data_MPI2_rank0.yaml" + MPI 2 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_print_filter_data_time_window_selection + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/print_filter_data_time_window_selection.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_print_filter_data_time_window_selection_MPI2 + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/print_filter_data_time_window_selection.yaml" + MPI 2 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_processwhere + TIER 1 + ECBUILD + SOURCES ../../../mains/TestProcessWhere.cc + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/processwhere.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_qc_acceptlist + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_acceptlist.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_qc_backgroundcheck + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_backgroundcheck.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_qc_backgroundcheck_ensemblestatistics + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_EnsembleObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_backgroundcheck_ensemblestatistics.yaml" + MPI 8 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_qc_bayesianbackgroundqcflags + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_bayesianbackgroundqcflags.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_qc_bayesian_background_check + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_bayesian_background_check.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_qc_boundscheck + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_boundscheck.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_qc_creatediagnosticflags + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_creatediagnosticflags.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_function_copy_flags_from_extended_to_original_space + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_copy_flags_from_ext_to_orig_space.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_qc_defer_to_post + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_defer_to_post.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_qc_derivative_dpdt + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_derivative_dpdt.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_qc_derivative_dxdt + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_derivative_dxdt.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_qc_differencecheck + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_differencecheck.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_qc_finalcheck + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_finalcheck.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_qc_gauss_thinning + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_gauss_thinning.yaml" + MPI 4 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_qc_gauss_thinning_mean + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_gauss_thinning_mean.yaml" + MPI 4 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_qc_gauss_thinning_mean_error + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_gauss_thinning_mean_error.yaml" + MPI 2 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_qc_gauss_thinning_median + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_gauss_thinning_median.yaml" + MPI 4 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_qc_gauss_thinning_ops + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_gauss_thinning_ops.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_qc_gauss_thinning_records_are_single_obs + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_gauss_thinning_records_are_single_obs.yaml" + MPI 4 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_qc_gauss_thinning_satrad + TIER 1 + ECBUILD + SOURCES ../../../mains/TestGaussianThinning.cc + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_gauss_thinning_satrad.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_qc_gauss_thinning_unittests + TIER 1 + ECBUILD + SOURCES ../../../mains/TestGaussianThinning.cc + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_gauss_thinning_unittests.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_qc_grosserrorwholereport + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_grosserrorwholereport.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_qc_historycheck + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_historycheck.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_qc_historycheck_mpi + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_historycheck.yaml" + MPI 4 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_qc_historycheck_unittests + TIER 1 + ECBUILD + SOURCES ../../../mains/TestHistoryCheck.cc + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_historycheck_unittests.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_qc_met_office_buddy_check + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_met_office_buddy_check.yaml" + MPI 4 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_qc_met_office_buddy_check_unittests + TIER 1 + ECBUILD + SOURCES ../../../mains/TestMetOfficeBuddyCheck.cc + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_met_office_buddy_check_unittests.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_qc_met_office_buddy_pair_finder + TIER 1 + ECBUILD + SOURCES ../../../mains/TestMetOfficeBuddyPairFinder.cc + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_met_office_buddy_pair_finder.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_qc_met_office_pressure_consistency_check + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_met_office_pressure_consistency_check.yaml" + MPI 2 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_qc_modelbestfitpressure + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_modelbestfitpressure.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_qc_modelobthreshold + TIER 2 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_modelobthreshold.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_qc_multichannel_thinning + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_multichannel_thinning.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_qc_oceancolor_preqc + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_oceancolor_preqc.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +if( ${gsw_FOUND} ) + ufo_add_test( NAME test_ufo_qc_ocean_vertical_stability_check + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_ocean_vertical_stability_check.yaml" + MPI 4 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +endif( ${gsw_FOUND} ) +# +ufo_add_test( NAME test_ufo_qc_poisson_disk_thinning + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_poisson_disk_thinning.yaml" + MPI 2 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_qc_poisson_disk_thinning_parallel + TIER 1 + ECBUILD + SOURCES ../../../mains/TestParallelPoissonDiskThinning.cc + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_poisson_disk_thinning_parallel.yaml" + MPI 2 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_qc_poisson_disk_thinning_unittests + TIER 1 + ECBUILD + SOURCES ../../../mains/TestPoissonDiskThinning.cc + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_poisson_disk_thinning_unittests.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_qc_met_office_duplicate_check + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_met_office_duplicate_check.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_qc_met_office_duplicate_check_parallel + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_met_office_duplicate_check.yaml" + MPI 4 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_qc_preqc + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_preqc.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_qc_preqc_halo + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_preqc_halo.yaml" + MPI 4 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_qc_processamvqi + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_processamvqi.yaml" + MPI 2 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_qc_average_obs_to_mod_levels + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_profile_average_obs_to_mod_levels.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_qc_profile_background_check + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_profile_background_check.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_qc_profile_fewobs_check + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_profile_fewobs_check.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_qc_profile_unflagobs_check + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_profile_unflagobs_check.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_qc_spike_and_step_check + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_spike_and_step_check.yaml" + MPI 4 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_qc_stuckcheck + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_stuckcheck.yaml" + MPI 4 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_qc_stuckcheck_unittests + TIER 1 + ECBUILD + SOURCES ../../../mains/TestStuckCheck.cc + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_stuckcheck_unittests.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_qc_thinning + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_thinning.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_qc_temporal_thinning + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_temporal_thinning.yaml" + MPI 2 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_qc_temporal_thinning_records_are_single_obs + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_temporal_thinning_records_are_single_obs.yaml" + MPI 4 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_qc_temporal_thinning_unittests + TIER 1 + ECBUILD + SOURCES ../../../mains/TestTemporalThinning.cc + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_temporal_thinning_unittests.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_qc_trackcheck + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_trackcheck.yaml" + MPI 4 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_qc_trackcheckship + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_trackcheckship.yaml" + MPI 4 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_qc_trackcheck_unittests + TIER 1 + ECBUILD + SOURCES ../../../mains/TestTrackCheck.cc + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_trackcheck_unittests.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_qc_trackcheckship_unittests + TIER 1 + ECBUILD + SOURCES ../../../mains/TestTrackCheckShip.cc + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_trackcheckship_unittests.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_qc_trackcheckship_mainloop_unittests + TIER 1 + ECBUILD + SOURCES ../../../mains/TestTrackCheckShipMainLoop.cc + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_trackcheckship_mainloop_unittests.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_qc_variableassignment + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/qc_variableassignment.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_satname + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/satname.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_satwind_inversion_correction + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/satwind_inversion_correction.yaml" + MPI 2 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_iasi_qc + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/iasi_qc.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_superob + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/superob.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_superob_4PE + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/superob.yaml" + MPI 4 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_superob_radar + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/superob_radar.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_superob_radar_4PE + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/superob_radar.yaml" + MPI 4 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_parameter_substitution + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/parameter_substitution.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# +ufo_add_test( NAME test_ufo_polygon_check + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/polygon_check.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) + +# Filters that require CRTM in ObsOperator + +if( crtm_FOUND ) +# + ufo_add_test( NAME test_ufo_airs_qc_filters + TIER 2 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/airs_qc_filters.yaml" + MPI 1 + LIBS ufo + LABELS crtm filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# + ufo_add_test( NAME test_ufo_amsr2_qc + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/amsr2_qc.yaml" + MPI 1 + LIBS ufo + LABELS crtm filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# + ufo_add_test( NAME test_ufo_amsr2_qc_halo + TIER 2 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/amsr2_qc_halo.yaml" + MPI 4 + LIBS ufo + LABELS crtm filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# + ufo_add_test( NAME test_ufo_amsua_qc + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/amsua_qc.yaml" + MPI 1 + LIBS ufo + LABELS crtm filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# + ufo_add_test( NAME test_ufo_amsua_allsky_gfs_gsi_qc + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/amsua_allsky_gfs_gsi_qc.yaml" + MPI 1 + LIBS ufo + LABELS crtm filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# + ufo_add_test( NAME test_ufo_amsua_allsky_gsi_qc + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/amsua_allsky_gsi_qc.yaml" + MPI 1 + LIBS ufo + LABELS crtm filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# + ufo_add_test( NAME test_ufo_amsua_qc_clwretmw + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/amsua_qc_clwretmw.yaml" + MPI 1 + LIBS ufo + LABELS crtm filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# + ufo_add_test( NAME test_ufo_amsua_qc_filters + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/amsua_qc_filters.yaml" + MPI 1 + LIBS ufo + LABELS crtm filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# + ufo_add_test( NAME test_ufo_amsua_qc_filters_geos + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/amsua_qc_filters_geos.yaml" + MPI 1 + LIBS ufo + LABELS crtm filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# + ufo_add_test( NAME test_ufo_amsua_qc_miss_val + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/amsua_qc_miss_val.yaml" + MPI 1 + LIBS ufo + LABELS crtm filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# + ufo_add_test( NAME test_ufo_atms_qc_filters + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/atms_qc_filters.yaml" + MPI 1 + LIBS ufo + LABELS crtm filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# + ufo_add_test( NAME test_ufo_atms_n20_qc_filters_geos + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/atms_n20_qc_filters_geos.yaml" + MPI 1 + LIBS ufo + LABELS crtm filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# + ufo_add_test( NAME test_ufo_cris_qc + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/cris_qc.yaml" + MPI 1 + LIBS ufo + LABELS crtm filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# + ufo_add_test( NAME test_ufo_cris_qc_filters + TIER 2 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/cris_qc_filters.yaml" + MPI 1 + LIBS ufo + LABELS crtm filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# + ufo_add_test( NAME test_ufo_cris_qc_land + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/cris_qc_land.yaml" + MPI 1 + LIBS ufo + LABELS crtm filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# + ufo_add_test( NAME test_ufo_amsr2_qc_filters + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/amsr2_skylab_filters.yaml" + MPI 1 + LIBS ufo + LABELS crtm filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ + TEST_DEPENDS ufo_get_ufo_test_data ufo_get_crtm_test_data ) +# + ufo_add_test( NAME test_ufo_tropics_qc_filters + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/tropics_skylab_filters.yaml" + MPI 1 + LIBS ufo + LABELS crtm filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# + ufo_add_test( NAME test_ufo_gmi_skylab_filters + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/gmi_skylab_filters.yaml" + MPI 1 + LIBS ufo + LABELS crtm filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# + ufo_add_test( NAME test_ufo_gmi_qc_filters + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/gmi_qc_filters.yaml" + MPI 1 + LIBS ufo + LABELS crtm filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# + ufo_add_test( NAME test_ufo_gmi_qc_filters_geos + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/gmi_qc_filters_geos.yaml" + MPI 1 + LIBS ufo + LABELS crtm filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# + ufo_add_test( NAME test_ufo_iasi_qc_filters + TIER 2 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/iasi_qc_filters.yaml" + MPI 1 + LIBS ufo + LABELS crtm filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# + ufo_add_test( NAME test_ufo_mhs_qc_filters_geos + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/mhs_qc_filters_geos.yaml" + MPI 1 + LIBS ufo + LABELS crtm filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# + ufo_add_test( NAME test_ufo_qc_flags_true + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/abi_g16_qc_flags.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +endif( crtm_FOUND ) + +# Filters that require RTTOV in ObsOperator + +if( ${rttov_FOUND} ) + ufo_add_test( NAME test_ufo_amsr2_rttov_qc + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/amsr2_rttov_qc.yaml" + MPI 1 + LIBS ufo + LABELS rttov filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# + ufo_add_test( NAME test_ufo_amsr2_rttov_ops_qc_rttovonedvarcheck + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/amsr2_rttov_ops_qc_rttovonedvarcheck.yaml" + MPI 1 + LIBS ufo + LABELS rttov filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# + ufo_add_test( NAME test_ufo_atms_rttov_qc + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/atms_rttov_qc.yaml" + MPI 1 + LIBS ufo + LABELS rttov filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# + ufo_add_test( NAME test_ufo_atms_rttov_ops_qc_rttovonedvarcheck + TIER 2 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/atms_rttov_ops_qc_rttovonedvarcheck.yaml" + MPI 1 + LIBS ufo + LABELS rttov filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# + ufo_add_test( NAME test_ufo_iasi_rttov_ops_qc_rttovonedvarcheck + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/iasi_rttov_ops_qc_rttovonedvarcheck.yaml" + MPI 2 + LIBS ufo + LABELS rttov filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) + + ufo_add_test( NAME test_ufo_mtgirs_reconrad_obsop_check + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/mtgirs_reconrad_obsop_check.yaml" + MPI 1 + LIBS ufo + LABELS rttov filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# + ufo_add_test( NAME test_ufo_ssmis_rttov_ops_qc_rttovonedvarcheck + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/ssmis_rttov_ops_qc_rttovonedvarcheck.yaml" + MPI 1 + LIBS ufo + LABELS rttov filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# + ufo_add_test( NAME test_ufo_opr_atovs_rttovonedvar_multiplatform + TIER 2 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/atovs_rttovonedvar_multiplatform.yaml" + MPI 1 + LIBS ufo + LABELS rttov filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# + ufo_add_test( NAME test_ufo_opr_atovs_rttovonedvar_transmittance + TIER 2 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/atovs_rttovonedvar_transmittance.yaml" + MPI 1 + LIBS ufo + LABELS rttov filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +# + ufo_add_test( NAME test_ufo_opr_atovs_rttovonedvar_transmittance_multiplatform + TIER 2 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/atovs_rttovonedvar_transmittance_multiplatform.yaml" + MPI 1 + LIBS ufo + LABELS rttov filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +endif( ${rttov_FOUND} ) + + +# Filters that require ROPP in ObsOperator + +if( ${ropp-ufo_FOUND} ) + + ufo_add_test( NAME test_ufo_gnssrobndropp1d_qc + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/test_ObsFilters.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/gnssrobndropp1d_qc.yaml" + MPI 1 + LIBS ufo + LABELS ropp-ufo filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) +endif( ${ropp-ufo_FOUND} ) + +ufo_add_test( NAME test_ufo_preprocess + TIER 1 + ECBUILD + COMMAND ${CMAKE_BINARY_DIR}/bin/ufo_preprocess.x + ARGS "${CMAKE_CURRENT_SOURCE_DIR}/preprocess.yaml" + MPI 1 + LIBS ufo + LABELS filters + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../ ) diff --git a/sorc/_workaround_/PolygonCheck/instantiateObsFilterFactory.h b/sorc/_workaround_/PolygonCheck/instantiateObsFilterFactory.h new file mode 100644 index 000000000..15816398b --- /dev/null +++ b/sorc/_workaround_/PolygonCheck/instantiateObsFilterFactory.h @@ -0,0 +1,225 @@ +/* + * (C) Copyright 2019-2024 UCAR + * + * This software is licensed under the terms of the Apache Licence Version 2.0 + * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. + */ + +#ifndef UFO_INSTANTIATEOBSFILTERFACTORY_H_ +#define UFO_INSTANTIATEOBSFILTERFACTORY_H_ + +#include "ufo/filters/AcceptList.h" +#include "ufo/filters/AverageObsToGeoValLevels.h" +#include "ufo/filters/BackgroundCheck.h" +#include "ufo/filters/BayesianBackgroundCheck.h" +#include "ufo/filters/BayesianBackgroundQCFlags.h" +#include "ufo/filters/BlackList.h" +#include "ufo/filters/ConventionalProfileProcessing.h" +#include "ufo/filters/CopyFlagsFromExtendedToOriginalSpace.h" +#include "ufo/filters/CreateDiagnosticFlags.h" +#include "ufo/filters/DifferenceCheck.h" +#include "ufo/filters/EnsembleStatistics.h" +#include "ufo/filters/FinalCheck.h" +#include "ufo/filters/Gaussian_Thinning.h" +#include "ufo/filters/GeoVaLsWriter.h" +#include "ufo/filters/gnssroonedvarcheck/GNSSROOneDVarCheck.h" +#include "ufo/filters/HistoryCheck.h" +#include "ufo/filters/ImpactHeightCheck.h" +#include "ufo/filters/MetOfficeBuddyCheck.h" +#include "ufo/filters/MetOfficeDuplicateCheck.h" +#include "ufo/filters/MetOfficePressureConsistencyCheck.h" +#include "ufo/filters/ModelBestFitPressure.h" +#include "ufo/filters/ModelObThreshold.h" +#include "ufo/filters/MWCLWCheck.h" +#include "ufo/filters/ObsBoundsCheck.h" +#include "ufo/filters/ObsDerivativeCheck.h" +#include "ufo/filters/ObsDiagnosticsWriter.h" +#include "ufo/filters/ObsDomainCheck.h" +#include "ufo/filters/ObsDomainErrCheck.h" +#include "ufo/filters/ObsPolygonCheck.h" +#include "ufo/filters/ObsRefractivityGradientCheck.h" +#include "ufo/filters/ParameterSubstitution.h" +#include "ufo/filters/PerformAction.h" +#include "ufo/filters/PoissonDiskThinning.h" +#include "ufo/filters/PreQC.h" +#include "ufo/filters/PrintFilterData.h" +#include "ufo/filters/ProbabilityGrossErrorWholeReport.h" +#include "ufo/filters/ProcessAMVQI.h" +#include "ufo/filters/ProfileAverageObsToModLevels.h" +#include "ufo/filters/ProfileBackgroundCheck.h" +#include "ufo/filters/ProfileFewObsCheck.h" +#include "ufo/filters/ProfileMaxDifferenceCheck.h" +#include "ufo/filters/ProfileUnFlagObsCheck.h" +#include "ufo/filters/QCmanager.h" +#include "ufo/filters/refractivityonedvarcheck/RefractivityOneDVarCheck.h" +#include "ufo/filters/SatName.h" +#include "ufo/filters/SatwindInversionCorrection.h" +#include "ufo/filters/SpikeAndStepCheck.h" +#include "ufo/filters/StuckCheck.h" +#include "ufo/filters/SuperOb.h" +#include "ufo/filters/SuperRefractionCheckImpactParameter.h" +#include "ufo/filters/SuperRefractionCheckNBAM.h" +#include "ufo/filters/TemporalThinning.h" +#include "ufo/filters/Thinning.h" +#include "ufo/filters/TrackCheck.h" +#include "ufo/filters/TrackCheckShip.h" +#include "ufo/filters/VariableAssignment.h" +#include "ufo/filters/VariableTransforms.h" +#include "ufo/ObsFilterBase.h" +#include "ufo/operators/gnssro/QC/BackgroundCheckRONBAM.h" +#include "ufo/operators/gnssro/QC/ROobserror.h" + +#if defined(GSW_FOUND) + #include "ufo/filters/OceanVerticalStabilityCheck.h" +#endif + +#if defined(RTTOV_FOUND) + #include "ufo/filters/rttovonedvarcheck/RTTOVOneDVarCheck.h" +#endif + +#include "ufo/ObsTraits.h" + +namespace ufo { +void instantiateObsFilterFactory() { + static FilterMaker + acceptListMaker("AcceptList"); + static FilterMaker + backgroundCheckMaker("Background Check"); + static FilterMaker + backgroundCheckRONBAMMaker("Background Check RONBAM"); + static FilterMaker + BayesianBackgroundCheckMaker("Bayesian Background Check"); + static FilterMaker + BayesianBackgroundQCFlagsMaker("Bayesian Background QC Flags"); + static FilterMaker + ProbabilityGrossErrorWholeReportMaker("Bayesian Whole Report"); + static FilterMaker + blackListMaker("BlackList"); // same as RejectList + static FilterMaker + boundsCheckMaker("Bounds Check"); + static FilterMaker + conventionalProfileProcessingMaker("Conventional Profile Processing"); + static FilterMaker + CreateDiagnosticFlagsMaker("Create Diagnostic Flags"); + static FilterMaker + CopyFlagsFromExtendedToOriginalSpaceMaker("Copy Flags From Extended To Original Space"); + static FilterMaker + DerivativeCheckMaker("Derivative Check"); + static FilterMaker + differenceCheckMaker("Difference Check"); + static FilterMaker + domainCheckMaker("Domain Check"); + static FilterMaker + domainErrCheckMaker("DomainErr Check"); + static FilterMaker + polygonCheckMaker("Polygon Check"); + static FilterMaker + finalCheckMaker("Final Check"); + static FilterMaker + gaussianThinningMaker("Gaussian Thinning"); + static FilterMaker + GNSSROOneDVarCheckMaker("GNSS-RO 1DVar Check"); + static FilterMaker + ImpactHeightCheckMaker("GNSSRO Impact Height Check"); + static FilterMaker + historyCheckMaker("History Check"); + static FilterMaker + MetOfficeBuddyCheckMaker("Met Office Buddy Check"); + static FilterMaker + MetOfficeDuplicateCheckMaker("Met Office Duplicate Check"); + static FilterMaker + MetOfficePressureConsistencyCheckMaker("Met Office Pressure Consistency Check"); + static FilterMaker + ModelBestFitPressureMaker("Model Best Fit Pressure"); + static FilterMaker + ModelObThresholdMaker("ModelOb Threshold"); + static FilterMaker + MWCLWCheckMaker("MWCLW Check"); + static FilterMaker + ObsRefractivityGradientCheckMaker("Obs Refractivity Gradient Check"); + static FilterMaker + parameterSubstitutionMaker("Parameter Substitution"); + static FilterMaker + performActionMaker("Perform Action"); + static FilterMaker + poissonDiskThinningMaker("Poisson Disk Thinning"); + static FilterMaker + preQCMaker("PreQC"); + static FilterMaker + printFilterDataMaker("Print Filter Data"); + static FilterMaker + ProcessAMVQIMaker("Process AMV QI"); + static FilterMaker + ProfileAverageObsToModLevelsMaker("Average Observations To Model Levels"); + static FilterMaker + AverageObsToGeoValLevelsMaker("Average Observations To GeoVals Model Levels"); + static FilterMaker + ProfileBackgroundCheckMaker("Profile Background Check"); + static FilterMaker + ProfileFewObsCheckMaker("Profile Few Observations Check"); + static FilterMaker + ProfileMaxDifferenceCheckMaker("Profile Max Difference Check"); + static FilterMaker + ProfileUnFlagObsCheckMaker("Profile Unflag Observations Check"); + static FilterMaker + rejectListMaker("RejectList"); // same as BlackList + static FilterMaker + RefractivityOneDVarCheckMaker("Refractivity 1DVar Check"); + static FilterMaker + ROobserrorMaker("ROobserror"); + static FilterMaker + qcManagerMaker("QCmanager"); + static FilterMaker + satnameCheckMaker("satname"); + static FilterMaker + SatwindInversionCorrectionMaker("Satwind Inversion Correction"); + static FilterMaker + ShipTrackCheckMaker("Ship Track Check"); + static FilterMaker + SpikeAndStepCheckMaker("Spike and Step Check"); + static FilterMaker + StuckCheckMaker("Stuck Check"); + static FilterMaker + SuperRefractionCheckImpactParameterCheckMaker("Impact Parameter Check"); + static FilterMaker + SuperObMaker("SuperOb"); + static FilterMaker + SuperRefractionCheckNBAMCheckMaker("Super Refraction Check NBAM"); + static FilterMaker + temporalThinningMaker("Temporal Thinning"); + static FilterMaker + thinningMaker("Thinning"); + static FilterMaker + TrackCheckMaker("Track Check"); + static FilterMaker + variableAssignmentMaker("Variable Assignment"); + static FilterMaker + VariableTransformsMaker("Variable Transforms"); + static FilterMaker GVWriterMaker("GOMsaver"); + static FilterMaker + YDIAGsaverMaker("YDIAGsaver"); + static FilterMaker + ensembleStatisticsMaker("Ensemble Statistics"); + + // Only include this filter if gsw is present + #if defined(GSW_FOUND) + static FilterMaker + OceanVerticalStabilityCheckMaker("Ocean Vertical Stability Check"); + #endif + + // Only include this filter if rttov is present + #if defined(RTTOV_FOUND) + static FilterMaker + RTTOVOneDVarCheckMaker("RTTOV OneDVar Check"); + #endif + + // For backward compatibility, register some filters under legacy names used in the past + static FilterMaker + legacyGaussianThinningMaker("Gaussian_Thinning"); + static FilterMaker + legacyTemporalThinningMaker("TemporalThinning"); +} + +} // namespace ufo + +#endif // UFO_INSTANTIATEOBSFILTERFACTORY_H_ diff --git a/sorc/_workaround_/PolygonCheck/polygon_check.yaml b/sorc/_workaround_/PolygonCheck/polygon_check.yaml new file mode 100644 index 000000000..efc33b841 --- /dev/null +++ b/sorc/_workaround_/PolygonCheck/polygon_check.yaml @@ -0,0 +1,21 @@ +time window: + begin: 2018-04-14T20:30:00Z + end: 2018-04-15T03:30:00Z + +observations: +- obs space: + name: Radiosonde + obsdatain: + engine: + type: H5File + obsfile: Data/ufo/testinput_tier_1/sondes_obs_2018041500_m.nc4 + simulated variables: [airTemperature, windEastward, windNorthward] + obs filters: + - filter: Polygon Check + inside point longitude: 51 + inside point latitude: 59 + vertex longitudes: [ 50, 50, 200, 200, 125, 50 ] + vertex latitudes: [ 20, 60, 60, 20, 50, 20 ] + action: + name: reduce obs space + passedBenchmark: 30 diff --git a/sorc/build.rdas b/sorc/build.rdas index a9ca3b0ae..050ac114f 100755 --- a/sorc/build.rdas +++ b/sorc/build.rdas @@ -63,6 +63,13 @@ cp ../_workaround_/RDASApp/saber/GridCheckHelper.cc sorc/saber/src/saber/gsi/uti cp ../_workaround_/RDASApp/saber/GSIParameters.h sorc/saber/src/saber/gsi/utils/GSIParameters.h cp ../_workaround_/RDASApp/saber/Geometry.cc sorc/saber/src/saber/interpolation/Geometry.cc +cp ../_workaround_/PolygonCheck/CMakeLists.txt sorc/RDASApp/sorc/ufo/src/ufo/filters/CMakeLists.txt +cp ../_workaround_/PolygonCheck/ObsPolygonCheck.cc sorc/RDASApp/sorc/ufo/src/ufo/filters/ObsPolygonCheck.cc +cp ../_workaround_/PolygonCheck/ObsPolygonCheck.h sorc/RDASApp/sorc/ufo/src/ufo/filters/ObsPolygonCheck.h +cp ../_workaround_/PolygonCheck/instantiateObsFilterFactory.h sorc/RDASApp/sorc/ufo/src/ufo/instantiateObsFilterFactory.h +cp ../_workaround_/PolygonCheck/filtersCMakeLists.txt sorc/RDASApp/sorc/ufo/test/testinput/unit_tests/filters/CMakeLists.txt +cp ../_workaround_/PolygonCheck/polygon_check.yaml sorc/RDASApp/sorc/ufo/test/testinput/unit_tests/filters/polygon_check.yaml + rm -rf build/ ./build.sh -m MPAS -t NO -w NO -b NO From e5e16ceaddc66ae82ce573d07d1f7bd21f9ffef1 Mon Sep 17 00:00:00 2001 From: Samuel Trahan Date: Mon, 2 Feb 2026 12:01:46 -0500 Subject: [PATCH 08/12] copy workaround files for polygon check --- sorc/build.rdas | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/sorc/build.rdas b/sorc/build.rdas index 050ac114f..f0299e989 100755 --- a/sorc/build.rdas +++ b/sorc/build.rdas @@ -43,6 +43,8 @@ EXEC4="${HOMErrfs}/sorc/RDASApp/build/bin/bufr2netcdf.x" EXEC5="${HOMErrfs}/sorc/RDASApp/build/bin/mpasjedi_hofx3d.x" cd "${HOMErrfs}/sorc/RDASApp" || exit 1 +set -e + # workaround for using the GSL surface operator # https://github.com/JCSDA-internal/ufo/pull/3622 by Sijie cp ../_workaround_/RDASApp/sfccorrected/* sorc/ufo/src/ufo/operators/sfccorrected/ @@ -63,12 +65,14 @@ cp ../_workaround_/RDASApp/saber/GridCheckHelper.cc sorc/saber/src/saber/gsi/uti cp ../_workaround_/RDASApp/saber/GSIParameters.h sorc/saber/src/saber/gsi/utils/GSIParameters.h cp ../_workaround_/RDASApp/saber/Geometry.cc sorc/saber/src/saber/interpolation/Geometry.cc -cp ../_workaround_/PolygonCheck/CMakeLists.txt sorc/RDASApp/sorc/ufo/src/ufo/filters/CMakeLists.txt -cp ../_workaround_/PolygonCheck/ObsPolygonCheck.cc sorc/RDASApp/sorc/ufo/src/ufo/filters/ObsPolygonCheck.cc -cp ../_workaround_/PolygonCheck/ObsPolygonCheck.h sorc/RDASApp/sorc/ufo/src/ufo/filters/ObsPolygonCheck.h -cp ../_workaround_/PolygonCheck/instantiateObsFilterFactory.h sorc/RDASApp/sorc/ufo/src/ufo/instantiateObsFilterFactory.h -cp ../_workaround_/PolygonCheck/filtersCMakeLists.txt sorc/RDASApp/sorc/ufo/test/testinput/unit_tests/filters/CMakeLists.txt -cp ../_workaround_/PolygonCheck/polygon_check.yaml sorc/RDASApp/sorc/ufo/test/testinput/unit_tests/filters/polygon_check.yaml +cp ../_workaround_/PolygonCheck/CMakeLists.txt sorc/ufo/src/ufo/filters/CMakeLists.txt +cp ../_workaround_/PolygonCheck/ObsPolygonCheck.cc sorc/ufo/src/ufo/filters/ObsPolygonCheck.cc +cp ../_workaround_/PolygonCheck/ObsPolygonCheck.h sorc/ufo/src/ufo/filters/ObsPolygonCheck.h +cp ../_workaround_/PolygonCheck/instantiateObsFilterFactory.h sorc/ufo/src/ufo/instantiateObsFilterFactory.h +cp ../_workaround_/PolygonCheck/filtersCMakeLists.txt sorc/ufo/test/testinput/unit_tests/filters/CMakeLists.txt +cp ../_workaround_/PolygonCheck/polygon_check.yaml sorc/ufo/test/testinput/unit_tests/filters/polygon_check.yaml + +set +e rm -rf build/ ./build.sh -m MPAS -t NO -w NO -b NO From 45fa8f007f3fa5869394dde41f3e078b80e92eae Mon Sep 17 00:00:00 2001 From: Samuel Trahan Date: Mon, 2 Feb 2026 12:16:43 -0500 Subject: [PATCH 09/12] make linter happier --- scripts/exrrfs_ioda_bufr.sh | 1 - scripts/exrrfs_jedivar.sh | 2 +- ush/yamlify_domain_edge.py | 10 ++++------ 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/scripts/exrrfs_ioda_bufr.sh b/scripts/exrrfs_ioda_bufr.sh index b8d9eda47..c37ad0fe9 100755 --- a/scripts/exrrfs_ioda_bufr.sh +++ b/scripts/exrrfs_ioda_bufr.sh @@ -125,7 +125,6 @@ ${cpreq} "${USHrrfs}"/offline_ioda_tweak.py . ${cpreq} "${USHrrfs}"/offline_vad_thinning.py . for ioda_file in ioda*nc; do - grid_file="${FIXrrfs}/${MESH_NAME}/${MESH_NAME}.static.nc" if [[ "${ioda_file}" == *abi* || "${ioda_file}" == *atms* || "${ioda_file}" == *cris* ]]; then echo " ${ioda_file} ioda tweak is skipped for abi, atms, and cris" else diff --git a/scripts/exrrfs_jedivar.sh b/scripts/exrrfs_jedivar.sh index 481be58e6..8eff02a84 100755 --- a/scripts/exrrfs_jedivar.sh +++ b/scripts/exrrfs_jedivar.sh @@ -138,7 +138,7 @@ esac if ( grep -E '\*POLY' jedivar.yaml > /dev/null ) ; then cp jedivar.yaml no_polygon_jedivar.yaml - ${USHrrfs}/yamlify_domain_edge.py -g "invariant.nc" -i '' > polygon.yaml + "${USHrrfs}/yamlify_domain_edge.py" -g "invariant.nc" -i '' > polygon.yaml cat polygon.yaml no_polygon_jedivar.yaml > jedivar.yaml fi diff --git a/ush/yamlify_domain_edge.py b/ush/yamlify_domain_edge.py index c90814382..bc826d535 100755 --- a/ush/yamlify_domain_edge.py +++ b/ush/yamlify_domain_edge.py @@ -182,7 +182,7 @@ def print_ring(ring, lonlat, indent, columns=8): print(', ', end='') # A 3km-resolution MPAS domain had points that differed by # .001 degrees, hence the resolution of .0001 - print('%8.4f'%ring[i][lonlat], end='') + print('%8.4f' % ring[i][lonlat], end='') # Parse command-line arguments @@ -200,15 +200,13 @@ def print_ring(ring, lonlat, indent, columns=8): # Assign filenames grid_filename = args.grid # see note above. -#print(f"Grid file: {grid_filename}") - grid_ds = nc.Dataset(grid_filename, 'r') # Build ring ring = build_domain_ring(grid_ds) centroid = np.nanmean(ring, axis=0) -indent=args.indent +indent = args.indent print(f'''{indent}polygon: &POLY {indent} filter: Polygon Check @@ -219,8 +217,8 @@ def print_ring(ring, lonlat, indent, columns=8): print(f'{indent} vertex longitudes: [') print_ring(ring, 0, f'{indent} ') -print(f'\n{indent} ]') +print(f'\n{indent} ]') print(f'{indent} vertex latitudes: [') print_ring(ring, 1, f'{indent} ') -print(f'\n{indent} ]') +print(f'\n{indent} ]') From 51f78849d1f9be5875c3611c11fa632bff1bbab9 Mon Sep 17 00:00:00 2001 From: Samuel Trahan Date: Mon, 2 Feb 2026 12:19:33 -0500 Subject: [PATCH 10/12] yamllint exceptions for *POLY --- parm/jedivar.yaml | 128 +++++++++++++++++++++++----------------------- 1 file changed, 64 insertions(+), 64 deletions(-) diff --git a/parm/jedivar.yaml b/parm/jedivar.yaml index 37465bdb6..b706ac59a 100644 --- a/parm/jedivar.yaml +++ b/parm/jedivar.yaml @@ -194,7 +194,7 @@ cost function: threshold: 12.0 action: name: reject - - *POLY + - *POLY # yamllint disable-line rule:anchors - obs space: name: adpsfc_t181 distribution: @@ -268,7 +268,7 @@ cost function: action: name: reduce obs space - - *POLY + - *POLY # yamllint disable-line rule:anchors # Duplicate Check # - filter: Temporal Thinning @@ -546,7 +546,7 @@ cost function: action: name: reduce obs space - - *POLY + - *POLY # yamllint disable-line rule:anchors # Duplicate Check # - filter: Temporal Thinning @@ -822,7 +822,7 @@ cost function: action: name: reduce obs space - - *POLY + - *POLY # yamllint disable-line rule:anchors # Duplicate Check - filter: Temporal Thinning @@ -1102,7 +1102,7 @@ cost function: action: name: reduce obs space - - *POLY + - *POLY # yamllint disable-line rule:anchors # Duplicate Check # - filter: Temporal Thinning @@ -1379,7 +1379,7 @@ cost function: action: name: reduce obs space - - *POLY + - *POLY # yamllint disable-line rule:anchors # Duplicate Check # - filter: Temporal Thinning @@ -1661,7 +1661,7 @@ cost function: action: name: reduce obs space - - *POLY + - *POLY # yamllint disable-line rule:anchors # Online regional domain check - filter: Bounds Check @@ -1937,7 +1937,7 @@ cost function: # action: # name: reduce obs space - - *POLY + - *POLY # yamllint disable-line rule:anchors # Online regional domain check - filter: Bounds Check @@ -2210,7 +2210,7 @@ cost function: action: name: reduce obs space - - *POLY + - *POLY # yamllint disable-line rule:anchors # Online regional domain check - filter: Bounds Check @@ -2490,7 +2490,7 @@ cost function: # action: # name: reduce obs space - - *POLY + - *POLY # yamllint disable-line rule:anchors # Online domain check - filter: Bounds Check @@ -2809,7 +2809,7 @@ cost function: # action: # name: reduce obs space - - *POLY + - *POLY # yamllint disable-line rule:anchors # Online domain check - filter: Bounds Check @@ -3121,7 +3121,7 @@ cost function: action: name: reduce obs space - - *POLY + - *POLY # yamllint disable-line rule:anchors # Online domain check - filter: Bounds Check @@ -3436,7 +3436,7 @@ cost function: # action: # name: reduce obs space - - *POLY + - *POLY # yamllint disable-line rule:anchors # Online regional domain check - filter: Bounds Check @@ -3712,7 +3712,7 @@ cost function: # action: # name: reduce obs space - - *POLY + - *POLY # yamllint disable-line rule:anchors # Online regional domain check - filter: Bounds Check @@ -3988,7 +3988,7 @@ cost function: # action: # name: reduce obs space - - *POLY + - *POLY # yamllint disable-line rule:anchors # Online regional domain check - filter: Bounds Check @@ -4264,7 +4264,7 @@ cost function: # action: # name: reduce obs space - - *POLY + - *POLY # yamllint disable-line rule:anchors # Online regional domain check - filter: Bounds Check @@ -4536,7 +4536,7 @@ cost function: # action: # name: reduce obs space - - *POLY + - *POLY # yamllint disable-line rule:anchors # Online regional domain check - filter: Bounds Check @@ -4815,7 +4815,7 @@ cost function: # action: # name: reduce obs space - - *POLY + - *POLY # yamllint disable-line rule:anchors # Online domain check - filter: Bounds Check @@ -5127,7 +5127,7 @@ cost function: # action: # name: reduce obs space - - *POLY + - *POLY # yamllint disable-line rule:anchors # Online domain check - filter: Bounds Check @@ -5436,7 +5436,7 @@ cost function: # action: # name: reduce obs space - - *POLY + - *POLY # yamllint disable-line rule:anchors # Online regional domain check - filter: Bounds Check @@ -5712,7 +5712,7 @@ cost function: # action: # name: reduce obs space - - *POLY + - *POLY # yamllint disable-line rule:anchors # Online regional domain check - filter: Bounds Check @@ -5991,7 +5991,7 @@ cost function: # action: # name: reduce obs space - - *POLY + - *POLY # yamllint disable-line rule:anchors # Online domain check - filter: Bounds Check @@ -6300,7 +6300,7 @@ cost function: # action: # name: reduce obs space - - *POLY + - *POLY # yamllint disable-line rule:anchors # Online regional domain check - filter: Bounds Check @@ -6576,7 +6576,7 @@ cost function: # action: # name: reduce obs space - - *POLY + - *POLY # yamllint disable-line rule:anchors # Online regional domain check - filter: Bounds Check @@ -6852,7 +6852,7 @@ cost function: # action: # name: reduce obs space - - *POLY + - *POLY # yamllint disable-line rule:anchors # Online regional domain check - filter: Bounds Check @@ -7128,7 +7128,7 @@ cost function: # action: # name: reduce obs space - - *POLY + - *POLY # yamllint disable-line rule:anchors # Online regional domain check - filter: Bounds Check @@ -7404,7 +7404,7 @@ cost function: # action: # name: reduce obs space - - *POLY + - *POLY # yamllint disable-line rule:anchors # Online regional domain check - filter: Bounds Check @@ -7683,7 +7683,7 @@ cost function: # action: # name: reduce obs space - - *POLY + - *POLY # yamllint disable-line rule:anchors # Online domain check - filter: Bounds Check @@ -7995,7 +7995,7 @@ cost function: # action: # name: reduce obs space - - *POLY + - *POLY # yamllint disable-line rule:anchors # Online domain check - filter: Bounds Check @@ -8307,7 +8307,7 @@ cost function: # action: # name: reduce obs space - - *POLY + - *POLY # yamllint disable-line rule:anchors # Online domain check - filter: Bounds Check @@ -8619,7 +8619,7 @@ cost function: # action: # name: reduce obs space - - *POLY + - *POLY # yamllint disable-line rule:anchors # Online domain check - filter: Bounds Check @@ -8901,7 +8901,7 @@ cost function: name: assign error error parameter: 0.01 - - *POLY + - *POLY # yamllint disable-line rule:anchors # Terrain Height Discrepancy Check - filter: Difference Check @@ -9004,7 +9004,7 @@ cost function: # action: # name: reduce obs space - - *POLY + - *POLY # yamllint disable-line rule:anchors # Online regional domain check - filter: Bounds Check @@ -9280,7 +9280,7 @@ cost function: # action: # name: reduce obs space - - *POLY + - *POLY # yamllint disable-line rule:anchors # Online regional domain check - filter: Bounds Check @@ -9549,7 +9549,7 @@ cost function: # action: # name: reduce obs space - - *POLY + - *POLY # yamllint disable-line rule:anchors # Online regional domain check - filter: Bounds Check @@ -10406,7 +10406,7 @@ cost function: # action: # name: reduce obs space - - *POLY + - *POLY # yamllint disable-line rule:anchors # Online regional domain check - filter: Bounds Check @@ -10759,7 +10759,7 @@ cost function: # action: # name: reduce obs space - - *POLY + - *POLY # yamllint disable-line rule:anchors # Online regional domain check - filter: Bounds Check @@ -11035,7 +11035,7 @@ cost function: # action: # name: reduce obs space - - *POLY + - *POLY # yamllint disable-line rule:anchors # Online regional domain check - filter: Bounds Check @@ -11311,7 +11311,7 @@ cost function: # action: # name: reduce obs space - - *POLY + - *POLY # yamllint disable-line rule:anchors # Online regional domain check - filter: Bounds Check @@ -11588,7 +11588,7 @@ cost function: # action: # name: reduce obs space - - *POLY + - *POLY # yamllint disable-line rule:anchors # Online regional domain check - filter: Bounds Check @@ -11864,7 +11864,7 @@ cost function: # action: # name: reduce obs space - - *POLY + - *POLY # yamllint disable-line rule:anchors # Online regional domain check - filter: Bounds Check @@ -12140,7 +12140,7 @@ cost function: # action: # name: reduce obs space - - *POLY + - *POLY # yamllint disable-line rule:anchors # Online regional domain check - filter: Bounds Check @@ -12417,7 +12417,7 @@ cost function: # action: # name: reduce obs space - - *POLY + - *POLY # yamllint disable-line rule:anchors # Online regional domain check - filter: Bounds Check @@ -12689,7 +12689,7 @@ cost function: # action: # name: reduce obs space - - *POLY + - *POLY # yamllint disable-line rule:anchors # Online regional domain check - filter: Bounds Check @@ -12977,7 +12977,7 @@ cost function: # action: # name: reduce obs space - - *POLY + - *POLY # yamllint disable-line rule:anchors # Online domain check - filter: Bounds Check @@ -13295,7 +13295,7 @@ cost function: # action: # name: reduce obs space - - *POLY + - *POLY # yamllint disable-line rule:anchors # Online domain check - filter: Bounds Check @@ -13614,7 +13614,7 @@ cost function: # action: # name: reduce obs space - - *POLY + - *POLY # yamllint disable-line rule:anchors # Online domain check - filter: Bounds Check @@ -13932,7 +13932,7 @@ cost function: # action: # name: reduce obs space - - *POLY + - *POLY # yamllint disable-line rule:anchors # Online domain check - filter: Bounds Check @@ -14290,7 +14290,7 @@ cost function: # action: # name: reduce obs space - - *POLY + - *POLY # yamllint disable-line rule:anchors # Online domain check - filter: Bounds Check @@ -14699,7 +14699,7 @@ cost function: # action: # name: reduce obs space - - *POLY + - *POLY # yamllint disable-line rule:anchors # Online domain check - filter: Bounds Check @@ -15108,7 +15108,7 @@ cost function: # action: # name: reduce obs space - - *POLY + - *POLY # yamllint disable-line rule:anchors # Online domain check - filter: Bounds Check @@ -15483,7 +15483,7 @@ cost function: # action: # name: reduce obs space - - *POLY + - *POLY # yamllint disable-line rule:anchors # Online domain check - filter: Bounds Check @@ -15883,7 +15883,7 @@ cost function: action: name: reduce obs space - - *POLY + - *POLY # yamllint disable-line rule:anchors # Online domain check - filter: Bounds Check @@ -16267,7 +16267,7 @@ cost function: action: name: reduce obs space - - *POLY + - *POLY # yamllint disable-line rule:anchors # Duplicate Check - filter: Temporal Thinning @@ -16665,7 +16665,7 @@ cost function: initial value: false force reinitialization: false # domain boundary check - - *POLY + - *POLY # yamllint disable-line rule:anchors obs post filters: #Thinning - filter: Gaussian Thinning @@ -17123,7 +17123,7 @@ cost function: initial value: false force reinitialization: false # domain boundary check - - *POLY + - *POLY # yamllint disable-line rule:anchors obs post filters: # Step 0-B: Calculate derived variables # Calculate CLW retrieved from observation @@ -17713,7 +17713,7 @@ cost function: initial value: false force reinitialization: false # domain boundary check - - *POLY + - *POLY # yamllint disable-line rule:anchors obs post filters: # Step 0-B: Calculate derived variables # Calculate CLW retrieved from observation @@ -18282,7 +18282,7 @@ cost function: action: name: reduce obs space # domain boundary check - - *POLY + - *POLY # yamllint disable-line rule:anchors # Data Thinning - filter: Gaussian Thinning filter variables: @@ -18792,7 +18792,7 @@ cost function: action: name: reduce obs space # Domain boundary check - - *POLY + - *POLY # yamllint disable-line rule:anchors # Data Thinning - filter: Gaussian Thinning filter variables: @@ -19320,7 +19320,7 @@ cost function: initial value: false force reinitialization: false # Domain boundary check - - *POLY + - *POLY # yamllint disable-line rule:anchors obs post filters: # Step 0-B: Calculate derived variables @@ -19877,7 +19877,7 @@ cost function: initial value: false force reinitialization: false # Domain boundary check - - *POLY + - *POLY # yamllint disable-line rule:anchors obs post filters: #Thinning - filter: Gaussian Thinning @@ -20302,7 +20302,7 @@ cost function: initial value: false force reinitialization: false # Domain boundary check - - *POLY + - *POLY # yamllint disable-line rule:anchors obs post filters: #Thinning - filter: Gaussian Thinning @@ -20766,7 +20766,7 @@ cost function: # -------------------------------------- # Step "one half:" Domain boundary check # -------------------------------------- - - *POLY + - *POLY # yamllint disable-line rule:anchors # ---------------------------------------------------------------- # Step 1 : Create Derived Variables for radiane to BT conversion @@ -21319,7 +21319,7 @@ cost function: # -------------------------------------- # Step "one half:" Domain boundary check # -------------------------------------- - - *POLY + - *POLY # yamllint disable-line rule:anchors # ---------------------------------------------------------------- # Step 1 : Create Derived Variables for radiane to BT conversion From 3f6456a3c11d6a4f0bd44c45be4e3e857b6c23f9 Mon Sep 17 00:00:00 2001 From: Samuel Trahan Date: Mon, 2 Feb 2026 12:39:40 -0500 Subject: [PATCH 11/12] note which files and lines should be removed --- .../PolygonCheck/FIXME_DELETE_THIS_DIRECTORY | 6 ++++++ sorc/build.rdas | 13 +++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 sorc/_workaround_/PolygonCheck/FIXME_DELETE_THIS_DIRECTORY diff --git a/sorc/_workaround_/PolygonCheck/FIXME_DELETE_THIS_DIRECTORY b/sorc/_workaround_/PolygonCheck/FIXME_DELETE_THIS_DIRECTORY new file mode 100644 index 000000000..01ad7d253 --- /dev/null +++ b/sorc/_workaround_/PolygonCheck/FIXME_DELETE_THIS_DIRECTORY @@ -0,0 +1,6 @@ +# This directory must be deleted before the PR is merged. +# It serves only to copy the JEDI UFO changes into this PR for testing. + +# Files come from here: + +# - https://github.com/JCSDA/ufo/pull/78 diff --git a/sorc/build.rdas b/sorc/build.rdas index f0299e989..be5c200ec 100755 --- a/sorc/build.rdas +++ b/sorc/build.rdas @@ -43,8 +43,6 @@ EXEC4="${HOMErrfs}/sorc/RDASApp/build/bin/bufr2netcdf.x" EXEC5="${HOMErrfs}/sorc/RDASApp/build/bin/mpasjedi_hofx3d.x" cd "${HOMErrfs}/sorc/RDASApp" || exit 1 -set -e - # workaround for using the GSL surface operator # https://github.com/JCSDA-internal/ufo/pull/3622 by Sijie cp ../_workaround_/RDASApp/sfccorrected/* sorc/ufo/src/ufo/operators/sfccorrected/ @@ -65,6 +63,15 @@ cp ../_workaround_/RDASApp/saber/GridCheckHelper.cc sorc/saber/src/saber/gsi/uti cp ../_workaround_/RDASApp/saber/GSIParameters.h sorc/saber/src/saber/gsi/utils/GSIParameters.h cp ../_workaround_/RDASApp/saber/Geometry.cc sorc/saber/src/saber/interpolation/Geometry.cc +#----------------------------------------------------------------------- +# These lines should not be merged. They contain the files from this PR: +# +# - https://github.com/JCSDA/ufo/pull/78 +# +# FIXME: Delete this section before merging the PR. + +set -e + cp ../_workaround_/PolygonCheck/CMakeLists.txt sorc/ufo/src/ufo/filters/CMakeLists.txt cp ../_workaround_/PolygonCheck/ObsPolygonCheck.cc sorc/ufo/src/ufo/filters/ObsPolygonCheck.cc cp ../_workaround_/PolygonCheck/ObsPolygonCheck.h sorc/ufo/src/ufo/filters/ObsPolygonCheck.h @@ -74,6 +81,8 @@ cp ../_workaround_/PolygonCheck/polygon_check.yaml sorc/ufo/test/testinput/unit_ set +e +#----------------------------------------------------------------------- + rm -rf build/ ./build.sh -m MPAS -t NO -w NO -b NO From a983a4e74063201c555a637028c6963289505a66 Mon Sep 17 00:00:00 2001 From: Samuel Trahan Date: Mon, 2 Feb 2026 16:49:21 -0500 Subject: [PATCH 12/12] Changes from review of ufo code --- .../PolygonCheck/ObsPolygonCheck.cc | 39 ++++++++++--------- .../PolygonCheck/ObsPolygonCheck.h | 21 ++++++---- 2 files changed, 35 insertions(+), 25 deletions(-) diff --git a/sorc/_workaround_/PolygonCheck/ObsPolygonCheck.cc b/sorc/_workaround_/PolygonCheck/ObsPolygonCheck.cc index d2be390a0..7ca130d75 100644 --- a/sorc/_workaround_/PolygonCheck/ObsPolygonCheck.cc +++ b/sorc/_workaround_/PolygonCheck/ObsPolygonCheck.cc @@ -19,6 +19,7 @@ #include #include #include + #include #include "ioda/ObsSpace.h" #include "oops/util/Logger.h" @@ -70,19 +71,23 @@ void ObsPolygonCheck::applyFilter(const std::vector &apply, std::ostringstream what; what << "Mismatch between vertex longitude count (" << nlon << ") and vertex latitude count (" << nlat << ")."; - throw ObsPolygonLatLonSizeMismatch(what.str()); + throw ObsPolygonLatLonSizeMismatch(what.str(), Here()); } - for (int i = 0; i < nlon; i++) - poly.outer().push_back(point_t(vertex_longitudes[i], vertex_latitudes[i])); + poly.outer().reserve(nlon); + for (size_t i = 0; i < nlon; i++) + poly.outer().emplace_back(vertex_longitudes[i], vertex_latitudes[i]); // Ask boost::geometry to correct common problems in the polygon definition. + // As of boost 1.91, the only practical effect is to close open rings. + // It will also correct the vertex ordering, but vertex ordering on a + // sphere is ignored. bg::correct(poly); - // Scan for obvious errors that bg::correct couldn't correct. + // Check for polygons that the boost::geometry library doesn't know how to handle. if (std::string reason; !bg::is_valid(poly, reason)) { std::ostringstream what; - what << "ObsPolygonCheck: unable to correct invalid polygon (" << reason << ")"; - throw ObsPolygonIsInvalid(what.str()); + what << "ObsPolygonCheck: boost::geometry does not like your polygon (\"" << reason << "\")"; + throw ObsPolygonIsInvalid(what.str(), Here()); } // Get the observation locations. @@ -91,6 +96,9 @@ void ObsPolygonCheck::applyFilter(const std::vector &apply, obsdb_.get_db("MetaData", "longitude", lons); // Figure out which side is the inside by checking a point that is known to be inside. + // As of version 1.91, boost::geometry ignores the clockwise vs. counterclockwise when + // deciding which side of a polygon is the inside in spherical geometry. Hence, + // we need this "inside point" to determine which side is the inside. const bool useThisSide = bg::within(insidePoint, poly); // Find all points that are on the opposite side from the "inside point" @@ -98,20 +106,15 @@ void ObsPolygonCheck::applyFilter(const std::vector &apply, std::vector notInside(nlocs, true); size_t applyCount = 0; size_t insideCount = 0; - for (size_t iloc = 0; iloc < nlocs; iloc++) + for (size_t iloc = 0; iloc < nlocs; iloc++) { if (apply[iloc]) { - try { - applyCount++; - bool inside = useThisSide == bg::within(point_t(lons[iloc], lats[iloc]), poly); - notInside[iloc] = !inside; - if (inside) - insideCount++; - } catch(const bg::exception &ex) { - // We only catch boost geometry exceptions here; anything else is passed through. - oops::Log::error() << "ObsPolygonCheck: boost::geometry error: " << ex.what() << std::endl; - // The default value for all points is "not inside" so any erroring points will be rejected. - } + applyCount++; + const bool inside = useThisSide == bg::within(point_t(lons[iloc], lats[iloc]), poly); + notInside[iloc] = !inside; + if (inside) + insideCount++; } + } for (auto &vec : flagged) for (size_t iloc = 0; iloc < nlocs; iloc++) diff --git a/sorc/_workaround_/PolygonCheck/ObsPolygonCheck.h b/sorc/_workaround_/PolygonCheck/ObsPolygonCheck.h index 7bb9c30a4..b78409e2f 100644 --- a/sorc/_workaround_/PolygonCheck/ObsPolygonCheck.h +++ b/sorc/_workaround_/PolygonCheck/ObsPolygonCheck.h @@ -22,6 +22,7 @@ #include #include +#include #include "oops/util/ObjectCounter.h" #include "ufo/filters/FilterBase.h" #include "ufo/filters/QCflags.h" @@ -58,23 +59,29 @@ class ObsPolygonCheckParameters : public FilterParametersBase { /// ObsPolygonLatLonSizeMismatch: thrown when the parameters vertex_longitudes /// and vertex_latitudes have different lengths. -class ObsPolygonLatLonSizeMismatch: public std::invalid_argument { +class ObsPolygonLatLonSizeMismatch: public eckit::BadValue { public: - explicit ObsPolygonLatLonSizeMismatch(const std::string &message): - std::invalid_argument(message) + explicit ObsPolygonLatLonSizeMismatch(const std::string &message, + const eckit::CodeLocation &location = {}): + eckit::BadValue(message, location) {} }; /// ObsPolygonIsInvalid: thrown when boost::geometry::is_valid doesn't like a polygon. -class ObsPolygonIsInvalid: public std::invalid_argument { +class ObsPolygonIsInvalid: public eckit::BadValue { public: - explicit ObsPolygonIsInvalid(const std::string &message): - std::invalid_argument(message) + explicit ObsPolygonIsInvalid(const std::string &message, + const eckit::CodeLocation &location = {}): + eckit::BadValue(message, location) {} }; -/// PolygonCheck: find obs within a specified polygon. +/// PolygonCheck: flags all obs that aren't inside a specified +/// polygon; uses the boost::geometry library. The boost::geometry +/// library doesn't know which side is the inside of the polygon when +/// using spherical geometry. Hence, the caller must provide an +/// "inside point." Points on the other side of the polygon are flagged. class ObsPolygonCheck : public FilterBase, private util::ObjectCounter {