From c78860291efe269d275efc786a6d7926f6323c37 Mon Sep 17 00:00:00 2001 From: John Halley Gotway Date: Wed, 14 Feb 2024 14:43:24 -0700 Subject: [PATCH] Feature #2395 wdir (#2820) * Per #2395, add new columns to VL1L2, VAL1L2, and VCNT line types for wind direction statistics. Work still in progress. * Per #2395, write the new VCNT columns to the output and document the additions to the VL1L2, VAL1L2, and VCNT columns. * Per #2395, add the definition of new statistics to Appendix G. * Per #2395, update file version history. * Per #2395, tweak warning message about zero wind vectors and update grid-stat and point-stat to log calls to the do_vl1l2() function. * Per #2395, refine the weights for wind direction stats, ignoring the undefined directions. * Update src/tools/core/stat_analysis/aggr_stat_line.cc * Update src/tools/core/stat_analysis/parse_stat_line.cc * Update src/tools/core/stat_analysis/aggr_stat_line.cc --- data/table_files/met_header_columns_V12.0.txt | 6 +- docs/Users_Guide/appendixG.rst | 167 +++++++++---- docs/Users_Guide/point-stat.rst | 30 +++ internal/test_unit/hdr/met_12_0.hdr | 6 +- src/basic/vx_util/stat_column_defs.h | 16 +- src/libcode/vx_stat_out/stat_columns.cc | 60 ++++- src/libcode/vx_statistics/met_stats.cc | 228 ++++++++++++------ src/libcode/vx_statistics/met_stats.h | 32 +-- src/tools/core/grid_stat/grid_stat.cc | 3 + src/tools/core/point_stat/point_stat.cc | 3 + .../core/stat_analysis/aggr_stat_line.cc | 17 ++ .../core/stat_analysis/parse_stat_line.cc | 8 + 12 files changed, 421 insertions(+), 155 deletions(-) diff --git a/data/table_files/met_header_columns_V12.0.txt b/data/table_files/met_header_columns_V12.0.txt index bf218d00bc..7ed1e5a187 100644 --- a/data/table_files/met_header_columns_V12.0.txt +++ b/data/table_files/met_header_columns_V12.0.txt @@ -27,9 +27,9 @@ V12.0 : STAT : RELP : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID V12.0 : STAT : SAL1L2 : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID_END OBS_LEAD OBS_VALID_BEG OBS_VALID_END FCST_VAR FCST_UNITS FCST_LEV OBS_VAR OBS_UNITS OBS_LEV OBTYPE VX_MASK INTERP_MTHD INTERP_PNTS FCST_THRESH OBS_THRESH COV_THRESH ALPHA LINE_TYPE TOTAL FABAR OABAR FOABAR FFABAR OOABAR MAE V12.0 : STAT : SL1L2 : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID_END OBS_LEAD OBS_VALID_BEG OBS_VALID_END FCST_VAR FCST_UNITS FCST_LEV OBS_VAR OBS_UNITS OBS_LEV OBTYPE VX_MASK INTERP_MTHD INTERP_PNTS FCST_THRESH OBS_THRESH COV_THRESH ALPHA LINE_TYPE TOTAL FBAR OBAR FOBAR FFBAR OOBAR MAE V12.0 : STAT : SSVAR : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID_END OBS_LEAD OBS_VALID_BEG OBS_VALID_END FCST_VAR FCST_UNITS FCST_LEV OBS_VAR OBS_UNITS OBS_LEV OBTYPE VX_MASK INTERP_MTHD INTERP_PNTS FCST_THRESH OBS_THRESH COV_THRESH ALPHA LINE_TYPE TOTAL N_BIN BIN_i BIN_N VAR_MIN VAR_MAX VAR_MEAN FBAR OBAR FOBAR FFBAR OOBAR FBAR_NCL FBAR_NCU FSTDEV FSTDEV_NCL FSTDEV_NCU OBAR_NCL OBAR_NCU OSTDEV OSTDEV_NCL OSTDEV_NCU PR_CORR PR_CORR_NCL PR_CORR_NCU ME ME_NCL ME_NCU ESTDEV ESTDEV_NCL ESTDEV_NCU MBIAS MSE BCMSE RMSE -V12.0 : STAT : VAL1L2 : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID_END OBS_LEAD OBS_VALID_BEG OBS_VALID_END FCST_VAR FCST_UNITS FCST_LEV OBS_VAR OBS_UNITS OBS_LEV OBTYPE VX_MASK INTERP_MTHD INTERP_PNTS FCST_THRESH OBS_THRESH COV_THRESH ALPHA LINE_TYPE TOTAL UFABAR VFABAR UOABAR VOABAR UVFOABAR UVFFABAR UVOOABAR FA_SPEED_BAR OA_SPEED_BAR -V12.0 : STAT : VL1L2 : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID_END OBS_LEAD OBS_VALID_BEG OBS_VALID_END FCST_VAR FCST_UNITS FCST_LEV OBS_VAR OBS_UNITS OBS_LEV OBTYPE VX_MASK INTERP_MTHD INTERP_PNTS FCST_THRESH OBS_THRESH COV_THRESH ALPHA LINE_TYPE TOTAL UFBAR VFBAR UOBAR VOBAR UVFOBAR UVFFBAR UVOOBAR F_SPEED_BAR O_SPEED_BAR -V12.0 : STAT : VCNT : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID_END OBS_LEAD OBS_VALID_BEG OBS_VALID_END FCST_VAR FCST_UNITS FCST_LEV OBS_VAR OBS_UNITS OBS_LEV OBTYPE VX_MASK INTERP_MTHD INTERP_PNTS FCST_THRESH OBS_THRESH COV_THRESH ALPHA LINE_TYPE TOTAL FBAR FBAR_BCL FBAR_BCU OBAR OBAR_BCL OBAR_BCU FS_RMS FS_RMS_BCL FS_RMS_BCU OS_RMS OS_RMS_BCL OS_RMS_BCU MSVE MSVE_BCL MSVE_BCU RMSVE RMSVE_BCL RMSVE_BCU FSTDEV FSTDEV_BCL FSTDEV_BCU OSTDEV OSTDEV_BCL OSTDEV_BCU FDIR FDIR_BCL FDIR_BCU ODIR ODIR_BCL ODIR_BCU FBAR_SPEED FBAR_SPEED_BCL FBAR_SPEED_BCU OBAR_SPEED OBAR_SPEED_BCL OBAR_SPEED_BCU VDIFF_SPEED VDIFF_SPEED_BCL VDIFF_SPEED_BCU VDIFF_DIR VDIFF_DIR_BCL VDIFF_DIR_BCU SPEED_ERR SPEED_ERR_BCL SPEED_ERR_BCU SPEED_ABSERR SPEED_ABSERR_BCL SPEED_ABSERR_BCU DIR_ERR DIR_ERR_BCL DIR_ERR_BCU DIR_ABSERR DIR_ABSERR_BCL DIR_ABSERR_BCU ANOM_CORR ANOM_CORR_NCL ANOM_CORR_NCU ANOM_CORR_BCL ANOM_CORR_BCU ANOM_CORR_UNCNTR ANOM_CORR_UNCNTR_BCL ANOM_CORR_UNCNTR_BCU +V12.0 : STAT : VAL1L2 : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID_END OBS_LEAD OBS_VALID_BEG OBS_VALID_END FCST_VAR FCST_UNITS FCST_LEV OBS_VAR OBS_UNITS OBS_LEV OBTYPE VX_MASK INTERP_MTHD INTERP_PNTS FCST_THRESH OBS_THRESH COV_THRESH ALPHA LINE_TYPE TOTAL UFABAR VFABAR UOABAR VOABAR UVFOABAR UVFFABAR UVOOABAR FA_SPEED_BAR OA_SPEED_BAR DIRA_ME DIRA_MAE DIRA_MSE +V12.0 : STAT : VL1L2 : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID_END OBS_LEAD OBS_VALID_BEG OBS_VALID_END FCST_VAR FCST_UNITS FCST_LEV OBS_VAR OBS_UNITS OBS_LEV OBTYPE VX_MASK INTERP_MTHD INTERP_PNTS FCST_THRESH OBS_THRESH COV_THRESH ALPHA LINE_TYPE TOTAL UFBAR VFBAR UOBAR VOBAR UVFOBAR UVFFBAR UVOOBAR F_SPEED_BAR O_SPEED_BAR DIR_ME DIR_MAE DIR_MSE +V12.0 : STAT : VCNT : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID_END OBS_LEAD OBS_VALID_BEG OBS_VALID_END FCST_VAR FCST_UNITS FCST_LEV OBS_VAR OBS_UNITS OBS_LEV OBTYPE VX_MASK INTERP_MTHD INTERP_PNTS FCST_THRESH OBS_THRESH COV_THRESH ALPHA LINE_TYPE TOTAL FBAR FBAR_BCL FBAR_BCU OBAR OBAR_BCL OBAR_BCU FS_RMS FS_RMS_BCL FS_RMS_BCU OS_RMS OS_RMS_BCL OS_RMS_BCU MSVE MSVE_BCL MSVE_BCU RMSVE RMSVE_BCL RMSVE_BCU FSTDEV FSTDEV_BCL FSTDEV_BCU OSTDEV OSTDEV_BCL OSTDEV_BCU FDIR FDIR_BCL FDIR_BCU ODIR ODIR_BCL ODIR_BCU FBAR_SPEED FBAR_SPEED_BCL FBAR_SPEED_BCU OBAR_SPEED OBAR_SPEED_BCL OBAR_SPEED_BCU VDIFF_SPEED VDIFF_SPEED_BCL VDIFF_SPEED_BCU VDIFF_DIR VDIFF_DIR_BCL VDIFF_DIR_BCU SPEED_ERR SPEED_ERR_BCL SPEED_ERR_BCU SPEED_ABSERR SPEED_ABSERR_BCL SPEED_ABSERR_BCU DIR_ERR DIR_ERR_BCL DIR_ERR_BCU DIR_ABSERR DIR_ABSERR_BCL DIR_ABSERR_BCU ANOM_CORR ANOM_CORR_NCL ANOM_CORR_NCU ANOM_CORR_BCL ANOM_CORR_BCU ANOM_CORR_UNCNTR ANOM_CORR_UNCNTR_BCL ANOM_CORR_UNCNTR_BCU DIR_ME DIR_ME_BCL DIR_ME_BCU DIR_MAE DIR_MAE_BCL DIR_MAE_BCU DIR_MSE DIR_MSE_BCL DIR_MSE_BCU DIR_RMSE DIR_RMSE_BCL DIR_RMSE_BCU V12.0 : STAT : GENMPR : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID_END OBS_LEAD OBS_VALID_BEG OBS_VALID_END FCST_VAR FCST_UNITS FCST_LEV OBS_VAR OBS_UNITS OBS_LEV OBTYPE VX_MASK INTERP_MTHD INTERP_PNTS FCST_THRESH OBS_THRESH COV_THRESH ALPHA LINE_TYPE TOTAL INDEX STORM_ID PROB_LEAD PROB_VAL AGEN_INIT AGEN_FHR AGEN_LAT AGEN_LON AGEN_DLAND BGEN_LAT BGEN_LON BGEN_DLAND GEN_DIST GEN_TDIFF INIT_TDIFF DEV_CAT OPS_CAT V12.0 : STAT : SSIDX : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID_END OBS_LEAD OBS_VALID_BEG OBS_VALID_END FCST_VAR FCST_UNITS FCST_LEV OBS_VAR OBS_UNITS OBS_LEV OBTYPE VX_MASK INTERP_MTHD INTERP_PNTS FCST_THRESH OBS_THRESH COV_THRESH ALPHA LINE_TYPE FCST_MODEL REF_MODEL N_INIT N_TERM N_VLD SS_INDEX diff --git a/docs/Users_Guide/appendixG.rst b/docs/Users_Guide/appendixG.rst index c2811fe4fa..821a4a4c5d 100644 --- a/docs/Users_Guide/appendixG.rst +++ b/docs/Users_Guide/appendixG.rst @@ -46,7 +46,6 @@ In the same manner, we can compare the directions of two different nonzero vecto __________________________ - Now let us specialize this discussion of vectors to verification of wind vector data. We will denote the forecast wind vector by :math:`\mathbf{F}`, and the observed wind vector by **O**. These are two-dimensional horizontal vectors with *u* and *v* components as follows: .. math:: \mathbf{F} = (u_f,v_f) \text{ and } \mathbf{O} = (u_o,v_o) @@ -71,35 +70,33 @@ Now let us look at the definitions of the vector statistics produced by MET: _________________________ - FBAR and OBAR are the average values of the forecast and observed wind speed. .. math:: - \text{FBAR} = \frac{1}{N} \sum_i s_{fi} - - \text{OBAR} = {1 \over N} \sum_i s_{oi} + \text{FBAR} = \frac{1}{N} \sum_i s_{fi} -_________________________ + \text{OBAR} = {1 \over N} \sum_i s_{oi} +_________________________ FS_RMS and OS_RMS are the root-mean-square values of the forecast and observed wind speeds. .. only:: latex - .. math:: - - \text{FS\_RMS} = [ \frac{1}{N} \sum_i s_{fi}^2]^{1/2} + .. math:: + + \text{FS\_RMS} = [ \frac{1}{N} \sum_i s_{fi}^2]^{1/2} - \text{OS\_RMS} = [\frac{1}{N} \sum_i s_{oi}^2]^{1/2} + \text{OS\_RMS} = [\frac{1}{N} \sum_i s_{oi}^2]^{1/2} .. only:: html - .. math:: - - \text{FS_RMS} = [ \frac{1}{N} \sum_i s_{fi}^2]^{1/2} + .. math:: - \text{OS_RMS} = [\frac{1}{N} \sum_i s_{oi}^2]^{1/2} + \text{FS_RMS} = [ \frac{1}{N} \sum_i s_{fi}^2]^{1/2} + + \text{OS_RMS} = [\frac{1}{N} \sum_i s_{oi}^2]^{1/2} ___________________________ @@ -107,13 +104,12 @@ MSVE and RMSVE are, respectively, the mean squared, and root mean squared, lengt .. math:: - \text{MSVE} = \frac{1}{N} \sum_i | \mathbf{F}_i - \mathbf{O}_i|^2 + \text{MSVE} = \frac{1}{N} \sum_i | \mathbf{F}_i - \mathbf{O}_i|^2 - \text{RMSVE} = \sqrt{MSVE} + \text{RMSVE} = \sqrt{MSVE} ____________________________ - FSTDEV and OSTDEV are the standard deviations of the forecast and observed wind speeds. .. math:: \text{FSTDEV } = \frac{1}{N} \sum_i (s_{fi} - \text{FBAR})^2 = \frac{1}{N} \sum_i s_{fi}^2 - \text{FBAR}^2 @@ -125,91 +121,84 @@ ___________________________ FDIR and ODIR are the direction (angle) of :math:`\mathbf{F}_a \text{ and } \mathbf{O}_a` with respect to the grid directions. .. math:: \text{FDIR } = \text{ direction angle of } \mathbf{F}_a - - \text{ODIR} = \text{ direction angle of } \mathbf{O}_a -________________________ + \text{ODIR} = \text{ direction angle of } \mathbf{O}_a +________________________ FBAR_SPEED and OBAR_SPEED are the lengths of the average forecast and observed wind vectors. Note that this is *not* the same as the average forecast and observed wind speeds (*ie.,* the length of an average vector :math:`\neq` the average length of the vector). .. only:: latex - .. math:: - - \text{FBAR\_SPEED } = | \mathbf{F}_a | - - \text{OBAR\_SPEED } = | \mathbf{O}_a | + .. math:: + + \text{FBAR\_SPEED } = | \mathbf{F}_a | + + \text{OBAR\_SPEED } = | \mathbf{O}_a | .. only:: html - .. math:: - - \text{FBAR_SPEED } = | \mathbf{F}_a | - - \text{OBAR_SPEED } = | \mathbf{O}_a | + .. math:: + \text{FBAR_SPEED } = | \mathbf{F}_a | -________________________ + \text{OBAR_SPEED } = | \mathbf{O}_a | +________________________ VDIFF_SPEED is the length (*ie. speed*) of the vector difference between the average forecast and average observed wind vectors. .. only:: latex - .. math:: \text{VDIFF\_SPEED } = | \mathbf{F}_a - \mathbf{O}_a | + .. math:: \text{VDIFF\_SPEED } = | \mathbf{F}_a - \mathbf{O}_a | .. only:: html - .. math:: \text{VDIFF_SPEED } = | \mathbf{F}_a - \mathbf{O}_a | + .. math:: \text{VDIFF_SPEED } = | \mathbf{F}_a - \mathbf{O}_a | .. only:: latex - Note that this is *not* the same as the difference in lengths (speeds) of the average forecast and observed wind vectors. That quantity is called SPEED_ERR (see below). There is a relationship between these two statistics however: using some of the results obtained in the introduction to this appendix, we can say that :math:`| | \mathbf{F}_a | - | \mathbf{O}_a | | \leq | \mathbf{F}_a - \mathbf{O}_a |` or, equivalently, that :math:`\vert \text{SPEED\_ERR } \vert \leq \text{VDIFF\_SPEED. }` + Note that this is *not* the same as the difference in lengths (speeds) of the average forecast and observed wind vectors. That quantity is called SPEED_ERR (see below). There is a relationship between these two statistics however: using some of the results obtained in the introduction to this appendix, we can say that :math:`| | \mathbf{F}_a | - | \mathbf{O}_a | | \leq | \mathbf{F}_a - \mathbf{O}_a |` or, equivalently, that :math:`\vert \text{SPEED\_ERR } \vert \leq \text{VDIFF\_SPEED. }` .. only:: html - Note that this is *not* the same as the difference in lengths (speeds) of the average forecast and observed wind vectors. That quantity is called SPEED_ERR (see below). There is a relationship between these two statistics however: using some of the results obtained in the introduction to this appendix, we can say that :math:`| | \mathbf{F}_a | - | \mathbf{O}_a | | \leq | \mathbf{F}_a - \mathbf{O}_a |` or, equivalently, that :math:`\vert \text{SPEED_ERR } \vert \leq \text{VDIFF_SPEED. }` + Note that this is *not* the same as the difference in lengths (speeds) of the average forecast and observed wind vectors. That quantity is called SPEED_ERR (see below). There is a relationship between these two statistics however: using some of the results obtained in the introduction to this appendix, we can say that :math:`| | \mathbf{F}_a | - | \mathbf{O}_a | | \leq | \mathbf{F}_a - \mathbf{O}_a |` or, equivalently, that :math:`\vert \text{SPEED_ERR } \vert \leq \text{VDIFF_SPEED. }` _________________________ - -VDIFF_DIR is the direction of the vector difference of the average forecast and average observed wind vectors. Note that this is {\it not} the same as the difference in direction of the average forecast and average observed wind vectors. This latter quantity would be FDIR :math:`-` ODIR. +VDIFF_DIR is the direction of the vector difference of the average forecast and average observed wind vectors. Note that this is *not* the same as the difference in direction of the average forecast and average observed wind vectors. This latter quantity would be FDIR :math:`-` ODIR. .. only:: latex - .. math:: \text{VDIFF\_DIR } = \text{ direction of } (\mathbf{F}_a - \mathbf{O}_a) + .. math:: \text{VDIFF\_DIR } = \text{ direction of } (\mathbf{F}_a - \mathbf{O}_a) .. only:: html - .. math:: \text{VDIFF_DIR } = \text{ direction of } (\mathbf{F}_a - \mathbf{O}_a) + .. math:: \text{VDIFF_DIR } = \text{ direction of } (\mathbf{F}_a - \mathbf{O}_a) _________________________ - SPEED_ERR is the difference in the lengths (speeds) of the average forecast and average observed wind vectors. (See the discussion of VDIFF_SPEED above.) .. only:: latex - .. math:: \text{SPEED\_ERR } = | \mathbf{F}_a | - | \mathbf{O}_a | = \text{ FBAR\_SPEED } - \text{ OBAR\_SPEED } + .. math:: \text{SPEED\_ERR } = | \mathbf{F}_a | - | \mathbf{O}_a | = \text{ FBAR\_SPEED } - \text{ OBAR\_SPEED } .. only:: html - .. math:: \text{SPEED_ERR } = | \mathbf{F}_a | - | \mathbf{O}_a | = \text{ FBAR_SPEED } - \text{ OBAR_SPEED } - + .. math:: \text{SPEED_ERR } = | \mathbf{F}_a | - | \mathbf{O}_a | = \text{ FBAR_SPEED } - \text{ OBAR_SPEED } ___________________________ - SPEED_ABSERR is the absolute value of SPEED_ERR. Note that we have SPEED_ABSERR :math:`\leq` VDIFF_SPEED (see the discussion of VDIFF_SPEED above). .. only:: latex - .. math:: \text{SPEED\_ABSERR } = \vert \text{SPEED\_ERR } \vert + .. math:: \text{SPEED\_ABSERR } = \vert \text{SPEED\_ERR } \vert .. only:: html - .. math:: \text{SPEED_ABSERR } = \vert \text{SPEED_ERR } \vert + .. math:: \text{SPEED_ABSERR } = \vert \text{SPEED_ERR } \vert __________________________ @@ -217,20 +206,96 @@ DIR_ERR is the signed angle between the directions of the average forecast and a .. only:: latex - .. math:: \text{DIR\_ERR } = \text{ direction between } N(\mathbf{F}_a) \text{ and } N(\mathbf{O}_a) + .. math:: \text{DIR\_ERR } = \text{ direction between } N(\mathbf{F}_a) \text{ and } N(\mathbf{O}_a) .. only:: html - .. math:: \text{DIR_ERR } = \text{ direction between } N(\mathbf{F}_a) \text{ and } N(\mathbf{O}_a) + .. math:: \text{DIR_ERR } = \text{ direction between } N(\mathbf{F}_a) \text{ and } N(\mathbf{O}_a) __________________________ - + DIR_ABSERR is the absolute value of DIR_ERR. In other words, it's an unsigned angle rather than a signed angle. .. only:: latex - .. math:: \text{DIR\_ABSERR } = \vert \text{DIR\_ERR } \vert + .. math:: \text{DIR\_ABSERR } = \vert \text{DIR\_ERR } \vert + +.. only:: html + + .. math:: \text{DIR_ABSERR } = \vert \text{DIR_ERR } \vert + +__________________________ + +The following statistics are computed by comparing the forecast and observed wind directions for each individual matched pair. + +For each point, the directed angle difference in degrees is computed between the forecast and observed wind vectors and rescaled to the range from -180, exclusive, to 180, inclusive. + +.. math:: + + N(\mathbf{F}_i) - N(\mathbf{O}_i) \in (-180, 180] + +Note however that the direction of the zero vector is undefined. Points for which the forecast or observed wind direction is undefined are excluded from the analysis and result in a warning message being printed. The "wind_thresh" and "wind_logic" configuration options, described in :numref:`config_options`, can be used to filter the wind vectors down to a subset that meet the specified wind speed threshold. + +__________________________ + +DIR_ME is the average of the signed difference between the forecast and observed wind directions. + +.. only:: latex + + .. math:: + + \text{DIR\_ME} = \frac{1}{N} \sum_i (N(\mathbf{F}_i) - N(\mathbf{O}_i)) .. only:: html - .. math:: \text{DIR_ABSERR } = \vert \text{DIR_ERR } \vert + .. math:: + + \text{DIR_ME} = \frac{1}{N} \sum_i (N(\mathbf{F}_i) - N(\mathbf{O}_i)) + +__________________________ + +DIR_MAE is the average of the absolute value of the difference between the forecast and observed wind directions. + +.. only:: latex + + .. math:: + + \text{DIR\_MAE} = \frac{1}{N} \sum_i | N(\mathbf{F}_i) - N(\mathbf{O}_i) | + +.. only:: html + + .. math:: + + \text{DIR_MAE} = \frac{1}{N} \sum_i | N(\mathbf{F}_i) - N(\mathbf{O}_i) | + +__________________________ + +DIR_MSE is the average of the squared difference between the forecast and observed wind directions. + +.. only:: latex + + .. math:: + + \text{DIR\_MSE} = \frac{1}{N} \sum_i (N(\mathbf{F}_i) - N(\mathbf{O}_i))^2 + +.. only:: html + + .. math:: + + \text{DIR_MSE} = \frac{1}{N} \sum_i (N(\mathbf{F}_i) - N(\mathbf{O}_i))^2 + +__________________________ + +DIR_RMSE is the square root of the average squared difference between the forecast and observed wind directions. + +.. only:: latex + + .. math:: + + \text{DIR\_RMSE} = \sqrt{DIR\_MSE} + +.. only:: html + + .. math:: + + \text{DIR_RMSE} = \sqrt{DIR\_MSE} diff --git a/docs/Users_Guide/point-stat.rst b/docs/Users_Guide/point-stat.rst index 4258e8057f..d5f895a8aa 100644 --- a/docs/Users_Guide/point-stat.rst +++ b/docs/Users_Guide/point-stat.rst @@ -1285,6 +1285,15 @@ The first set of header columns are common to all of the output files generated * - 34 - O_SPEED_BAR - Mean observed wind speed + * - 35 + - DIR_ME + - Mean wind direction difference, from -180 to 180 degrees + * - 36 + - DIR_MAE + - Mean absolute wind direction difference + * - 37 + - DIR_MSE + - Mean squared wind direction difference .. _table_PS_format_info_VAL1L2: @@ -1331,6 +1340,15 @@ The first set of header columns are common to all of the output files generated * - 34 - OA_SPEED_BAR - Mean observed wind speed anomaly + * - 35 + - DIRA_ME + - Mean wind direction anomaly difference, from -180 to 180 degrees + * - 36 + - DIRA_MAE + - Mean absolute wind direction anomaly difference + * - 37 + - DIRA_MSE + - Mean squared wind direction anomaly difference .. _table_PS_format_info_VCNT: @@ -1410,6 +1428,18 @@ The first set of header columns are common to all of the output files generated * - 85-87 - ANOM_CORR_UNCNTR, :raw-html:`
` ANOM_CORR_UNCNTR_BCL, :raw-html:`
` ANOM_CORR_UNCNTR_BCU - Uncentered vector Anomaly Correlation excluding mean error including bootstrap upper and lower confidence limits + * - 88-90 + - DIR_ME, :raw-html:`
` DIR_ME_BCL, :raw-html:`
` DIR_ME_BCU + - Mean direction difference, from -180 to 180 degrees, including bootstrap upper and lower confidence limits + * - 91-93 + - DIR_MAE, :raw-html:`
` DIR_MAE_BCL, :raw-html:`
` DIR_MAE_BCU + - Mean absolute direction difference including bootstrap upper and lower confidence limits + * - 94-96 + - DIR_MSE, :raw-html:`
` DIR_MSE_BCL, :raw-html:`
` DIR_MSE_BCU + - Mean squared direction difference including bootstrap upper and lower confidence limits + * - 97-99 + - DIR_RMSE, :raw-html:`
` DIR_RMSE_BCL, :raw-html:`
` DIR_RMSE_BCU + - Root mean squared direction difference including bootstrap upper and lower confidence limits .. _table_PS_format_info_MPR: diff --git a/internal/test_unit/hdr/met_12_0.hdr b/internal/test_unit/hdr/met_12_0.hdr index 888df0f61d..d6bf9fb0b9 100644 --- a/internal/test_unit/hdr/met_12_0.hdr +++ b/internal/test_unit/hdr/met_12_0.hdr @@ -27,9 +27,9 @@ RELP : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID_END OBS_L SAL1L2 : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID_END OBS_LEAD OBS_VALID_BEG OBS_VALID_END FCST_VAR FCST_UNITS FCST_LEV OBS_VAR OBS_UNITS OBS_LEV OBTYPE VX_MASK INTERP_MTHD INTERP_PNTS FCST_THRESH OBS_THRESH COV_THRESH ALPHA LINE_TYPE TOTAL FABAR OABAR FOABAR FFABAR OOABAR MAE SL1L2 : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID_END OBS_LEAD OBS_VALID_BEG OBS_VALID_END FCST_VAR FCST_UNITS FCST_LEV OBS_VAR OBS_UNITS OBS_LEV OBTYPE VX_MASK INTERP_MTHD INTERP_PNTS FCST_THRESH OBS_THRESH COV_THRESH ALPHA LINE_TYPE TOTAL FBAR OBAR FOBAR FFBAR OOBAR MAE SSVAR : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID_END OBS_LEAD OBS_VALID_BEG OBS_VALID_END FCST_VAR FCST_UNITS FCST_LEV OBS_VAR OBS_UNITS OBS_LEV OBTYPE VX_MASK INTERP_MTHD INTERP_PNTS FCST_THRESH OBS_THRESH COV_THRESH ALPHA LINE_TYPE TOTAL N_BIN BIN_i BIN_N VAR_MIN VAR_MAX VAR_MEAN FBAR OBAR FOBAR FFBAR OOBAR FBAR_NCL FBAR_NCU FSTDEV FSTDEV_NCL FSTDEV_NCU OBAR_NCL OBAR_NCU OSTDEV OSTDEV_NCL OSTDEV_NCU PR_CORR PR_CORR_NCL PR_CORR_NCU ME ME_NCL ME_NCU ESTDEV ESTDEV_NCL ESTDEV_NCU MBIAS MSE BCMSE RMSE -VL1L2 : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID_END OBS_LEAD OBS_VALID_BEG OBS_VALID_END FCST_VAR FCST_UNITS FCST_LEV OBS_VAR OBS_UNITS OBS_LEV OBTYPE VX_MASK INTERP_MTHD INTERP_PNTS FCST_THRESH OBS_THRESH COV_THRESH ALPHA LINE_TYPE TOTAL UFBAR VFBAR UOBAR VOBAR UVFOBAR UVFFBAR UVOOBAR F_SPEED_BAR O_SPEED_BAR -VAL1L2 : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID_END OBS_LEAD OBS_VALID_BEG OBS_VALID_END FCST_VAR FCST_UNITS FCST_LEV OBS_VAR OBS_UNITS OBS_LEV OBTYPE VX_MASK INTERP_MTHD INTERP_PNTS FCST_THRESH OBS_THRESH COV_THRESH ALPHA LINE_TYPE TOTAL UFABAR VFABAR UOABAR VOABAR UVFOABAR UVFFABAR UVOOABAR FA_SPEED_BAR OA_SPEED_BAR -VCNT : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID_END OBS_LEAD OBS_VALID_BEG OBS_VALID_END FCST_VAR FCST_UNITS FCST_LEV OBS_VAR OBS_UNITS OBS_LEV OBTYPE VX_MASK INTERP_MTHD INTERP_PNTS FCST_THRESH OBS_THRESH COV_THRESH ALPHA LINE_TYPE TOTAL FBAR FBAR_BCL FBAR_BCU OBAR OBAR_BCL OBAR_BCU FS_RMS FS_RMS_BCL FS_RMS_BCU OS_RMS OS_RMS_BCL OS_RMS_BCU MSVE MSVE_BCL MSVE_BCU RMSVE RMSVE_BCL RMSVE_BCU FSTDEV FSTDEV_BCL FSTDEV_BCU OSTDEV OSTDEV_BCL OSTDEV_BCU FDIR FDIR_BCL FDIR_BCU ODIR ODIR_BCL ODIR_BCU FBAR_SPEED FBAR_SPEED_BCL FBAR_SPEED_BCU OBAR_SPEED OBAR_SPEED_BCL OBAR_SPEED_BCU VDIFF_SPEED VDIFF_SPEED_BCL VDIFF_SPEED_BCU VDIFF_DIR VDIFF_DIR_BCL VDIFF_DIR_BCU SPEED_ERR SPEED_ERR_BCL SPEED_ERR_BCU SPEED_ABSERR SPEED_ABSERR_BCL SPEED_ABSERR_BCU DIR_ERR DIR_ERR_BCL DIR_ERR_BCU DIR_ABSERR DIR_ABSERR_BCL DIR_ABSERR_BCU ANOM_CORR ANOM_CORR_NCL ANOM_CORR_NCU ANOM_CORR_BCL ANOM_CORR_BCU ANOM_CORR_UNCNTR ANOM_CORR_UNCNTR_BCL ANOM_CORR_UNCNTR_BCU +VL1L2 : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID_END OBS_LEAD OBS_VALID_BEG OBS_VALID_END FCST_VAR FCST_UNITS FCST_LEV OBS_VAR OBS_UNITS OBS_LEV OBTYPE VX_MASK INTERP_MTHD INTERP_PNTS FCST_THRESH OBS_THRESH COV_THRESH ALPHA LINE_TYPE TOTAL UFBAR VFBAR UOBAR VOBAR UVFOBAR UVFFBAR UVOOBAR F_SPEED_BAR O_SPEED_BAR DIR_ME DIR_MAE DIR_MSE +VAL1L2 : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID_END OBS_LEAD OBS_VALID_BEG OBS_VALID_END FCST_VAR FCST_UNITS FCST_LEV OBS_VAR OBS_UNITS OBS_LEV OBTYPE VX_MASK INTERP_MTHD INTERP_PNTS FCST_THRESH OBS_THRESH COV_THRESH ALPHA LINE_TYPE TOTAL UFABAR VFABAR UOABAR VOABAR UVFOABAR UVFFABAR UVOOABAR FA_SPEED_BAR OA_SPEED_BAR DIRA_ME DIRA_MAE DIRA_MSE +VCNT : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID_END OBS_LEAD OBS_VALID_BEG OBS_VALID_END FCST_VAR FCST_UNITS FCST_LEV OBS_VAR OBS_UNITS OBS_LEV OBTYPE VX_MASK INTERP_MTHD INTERP_PNTS FCST_THRESH OBS_THRESH COV_THRESH ALPHA LINE_TYPE TOTAL FBAR FBAR_BCL FBAR_BCU OBAR OBAR_BCL OBAR_BCU FS_RMS FS_RMS_BCL FS_RMS_BCU OS_RMS OS_RMS_BCL OS_RMS_BCU MSVE MSVE_BCL MSVE_BCU RMSVE RMSVE_BCL RMSVE_BCU FSTDEV FSTDEV_BCL FSTDEV_BCU OSTDEV OSTDEV_BCL OSTDEV_BCU FDIR FDIR_BCL FDIR_BCU ODIR ODIR_BCL ODIR_BCU FBAR_SPEED FBAR_SPEED_BCL FBAR_SPEED_BCU OBAR_SPEED OBAR_SPEED_BCL OBAR_SPEED_BCU VDIFF_SPEED VDIFF_SPEED_BCL VDIFF_SPEED_BCU VDIFF_DIR VDIFF_DIR_BCL VDIFF_DIR_BCU SPEED_ERR SPEED_ERR_BCL SPEED_ERR_BCU SPEED_ABSERR SPEED_ABSERR_BCL SPEED_ABSERR_BCU DIR_ERR DIR_ERR_BCL DIR_ERR_BCU DIR_ABSERR DIR_ABSERR_BCL DIR_ABSERR_BCU ANOM_CORR ANOM_CORR_NCL ANOM_CORR_NCU ANOM_CORR_BCL ANOM_CORR_BCU ANOM_CORR_UNCNTR ANOM_CORR_UNCNTR_BCL ANOM_CORR_UNCNTR_BCU DIR_ME DIR_ME_BCL DIR_ME_BCU DIR_MAE DIR_MAE_BCL DIR_MAE_BCU DIR_MSE DIR_MSE_BCL DIR_MSE_BCU DIR_RMSE DIR_RMSE_BCL DIR_RMSE_BCU GENMPR : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID_END OBS_LEAD OBS_VALID_BEG OBS_VALID_END FCST_VAR FCST_UNITS FCST_LEV OBS_VAR OBS_UNITS OBS_LEV OBTYPE VX_MASK INTERP_MTHD INTERP_PNTS FCST_THRESH OBS_THRESH COV_THRESH ALPHA LINE_TYPE TOTAL INDEX STORM_ID PROB_LEAD PROB_VAL AGEN_INIT AGEN_FHR AGEN_LAT AGEN_LON AGEN_DLAND BGEN_LAT BGEN_LON BGEN_DLAND GEN_DIST GEN_TDIFF INIT_TDIFF DEV_CAT OPS_CAT SSIDX : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID_END OBS_LEAD OBS_VALID_BEG OBS_VALID_END FCST_VAR FCST_UNITS FCST_LEV OBS_VAR OBS_UNITS OBS_LEV OBTYPE VX_MASK INTERP_MTHD INTERP_PNTS FCST_THRESH OBS_THRESH COV_THRESH ALPHA LINE_TYPE FCST_MODEL REF_MODEL N_INIT N_TERM N_VLD SS_INDEX MODE_SOA : VERSION MODEL DESC FCST_LEAD FCST_VALID_BEG FCST_VALID_END OBS_LEAD OBS_VALID_BEG OBS_VALID_END FCST_VAR FCST_UNITS FCST_LEV OBS_VAR OBS_UNITS OBS_LEV OBTYPE VX_MASK INTERP_MTHD INTERP_PNTS FCST_THRESH OBS_THRESH COV_THRESH ALPHA LINE_TYPE N_VALID GRID_RES OBJECT_ID OBJECT_CAT CENTROID_X CENTROID_Y CENTROID_LAT CENTROID_LON AXIS_ANG LENGTH WIDTH AREA AREA_THRESH CURVATURE CURVATURE_X CURVATURE_Y COMPLEXITY INTENSITY_10 INTENSITY_25 INTENSITY_50 INTENSITY_75 INTENSITY_90 INTENSITY_50 INTENSITY_SUM diff --git a/src/basic/vx_util/stat_column_defs.h b/src/basic/vx_util/stat_column_defs.h index f77e2200cb..909441b5ba 100644 --- a/src/basic/vx_util/stat_column_defs.h +++ b/src/basic/vx_util/stat_column_defs.h @@ -124,14 +124,16 @@ static const char * vl1l2_columns [] = { "TOTAL", "UFBAR", "VFBAR", "UOBAR", "VOBAR", "UVFOBAR", "UVFFBAR", "UVOOBAR", "F_SPEED_BAR", - "O_SPEED_BAR" + "O_SPEED_BAR", "DIR_ME", "DIR_MAE", + "DIR_MSE" }; static const char * val1l2_columns [] = { - "TOTAL", "UFABAR", "VFABAR", - "UOABAR", "VOABAR", "UVFOABAR", - "UVFFABAR", "UVOOABAR", "FA_SPEED_BAR", - "OA_SPEED_BAR" + "TOTAL", "UFABAR", "VFABAR", + "UOABAR", "VOABAR", "UVFOABAR", + "UVFFABAR", "UVOOABAR", "FA_SPEED_BAR", + "OA_SPEED_BAR", "DIRA_ME", "DIRA_MAE", + "DIRA_MSE" }; @@ -158,6 +160,10 @@ static const char * vcnt_columns [] = { "ANOM_CORR", "ANOM_CORR_NCL", "ANOM_CORR_NCU", "ANOM_CORR_BCL", "ANOM_CORR_BCU", "ANOM_CORR_UNCNTR", "ANOM_CORR_UNCNTR_BCL", "ANOM_CORR_UNCNTR_BCU", + "DIR_ME", "DIR_ME_BCL", "DIR_ME_BCU", + "DIR_MAE", "DIR_MAE_BCL", "DIR_MAE_BCU", + "DIR_MSE", "DIR_MSE_BCL", "DIR_MSE_BCU", + "DIR_RMSE", "DIR_RMSE_BCL", "DIR_RMSE_BCU" }; static const char * pct_columns [] = { diff --git a/src/libcode/vx_stat_out/stat_columns.cc b/src/libcode/vx_stat_out/stat_columns.cc index bd1dd46218..034c3c1961 100644 --- a/src/libcode/vx_stat_out/stat_columns.cc +++ b/src/libcode/vx_stat_out/stat_columns.cc @@ -2901,7 +2901,8 @@ void write_sl1l2_cols(const SL1L2Info &sl1l2_info, // Scalar L1L2 Line Type (SL1L2) // Dump out the SL1L2 line: // TOTAL, FBAR, OBAR, - // FOBAR, FFBAR, OOBAR + // FOBAR, FFBAR, OOBAR, + // MAE // at.set_entry(r, c+0, // Total Count sl1l2_info.scount); @@ -2974,7 +2975,8 @@ void write_vl1l2_cols(const VL1L2Info &vl1l2_info, // TOTAL, UFBAR, VFBAR, // UOBAR, VOBAR, UVFOBAR, // UVFFBAR, UVOOBAR F_SPEED_BAR, - // O_SPEED_BAR, + // O_SPEED_BAR, DIR_ME, DIR_MAE, + // DIR_MSE // at.set_entry(r, c+0, // Total Count @@ -3007,6 +3009,15 @@ void write_vl1l2_cols(const VL1L2Info &vl1l2_info, at.set_entry(r, c+9, // O_SPEED_BAR vl1l2_info.o_speed_bar); + at.set_entry(r, c+10, // DIR_ME + vl1l2_info.dir_bar); + + at.set_entry(r, c+11, // DIR_MAE + vl1l2_info.absdir_bar); + + at.set_entry(r, c+12, // DIR_MSE + vl1l2_info.dir2_bar); + return; } @@ -3018,10 +3029,11 @@ void write_val1l2_cols(const VL1L2Info &vl1l2_info, // // Vector Anomaly L1L2 Line Type (VAL1L2) // Dump out the VAL1L2 line: - // TOTAL, UFABAR, VFABAR, - // UOABAR, VOABAR, UVFOABAR, - // UVFFABAR, UVOOABAR, FA_SPEED_BAR, - // OA_SPEED_BAR + // TOTAL, UFABAR, VFABAR, + // UOABAR, VOABAR, UVFOABAR, + // UVFFABAR, UVOOABAR, FA_SPEED_BAR, + // OA_SPEED_BAR, DIRA_ME, DIRA_MAE, + // DIRA_MSE // at.set_entry(r, c+0, // Total Anomaly Count @@ -3054,6 +3066,15 @@ void write_val1l2_cols(const VL1L2Info &vl1l2_info, at.set_entry(r, c+9, // OA_SPEED_BAR vl1l2_info.oa_speed_bar); + at.set_entry(r, c+10, // DIRA_ME + vl1l2_info.dira_bar); + + at.set_entry(r, c+11, // DIRA_MAE + vl1l2_info.absdira_bar); + + at.set_entry(r, c+12, // DIRA_MSE + vl1l2_info.dira2_bar); + return; } @@ -3084,10 +3105,17 @@ void write_vcnt_cols(const VL1L2Info &vcnt_info, int i, // SPD_ABSERR, SPD_ABSERR_BCL, SPD_ABSERR_BCU, // DIR_ERR, DIR_ERR_BCL, DIR_ERR_BCU, // DIR_ABSERR, DIR_ABSERR_BCL, DIR_ABSERR_BCU, - // ANOM_CORR, ANOM_CORR_NCL, ANOM_CORR_NCU, ANOM_CORR_BCL, ANOM_CORR_BCU - // ANOM_CORR_UNCNTR, ANOM_CORR_UNCNTR_BCL, ANOM_CORR_UNCNTR_BCU + // ANOM_CORR, ANOM_CORR_NCL, ANOM_CORR_NCU, + // ANOM_CORR_BCL, ANOM_CORR_BCU + // ANOM_CORR_UNCNTR, ANOM_CORR_UNCNTR_BCL, ANOM_CORR_UNCNTR_BCU, + // DIR_ME, DIR_ME_BCL, DIR_ME_BCU, + // DIR_MAE, DIR_MAE_BCL, DIR_MAE_BCU, + // DIR_MSE, DIR_MSE_BCL, DIR_MSE_BCU, + // DIR_RMSE, DIR_RMSE_BCL, DIR_RMSE_BCU // + // TODO: MET #963 Compute the VCNT bootstrap CI's + at.set_entry(r, c++, max(vcnt_info.vcount, // TOTAL vcnt_info.vacount)); @@ -3173,6 +3201,22 @@ void write_vcnt_cols(const VL1L2Info &vcnt_info, int i, at.set_entry(r, c++, (string)na_str); // ANOM_CORR_UNCNTR_BCL at.set_entry(r, c++, (string)na_str); // ANOM_CORR_UNCNTR_BCU + at.set_entry(r, c++, vcnt_info.DIR_ME.v); // DIR_ME + at.set_entry(r, c++, (string)na_str); // DIR_ME_BCL + at.set_entry(r, c++, (string)na_str); // DIR_ME_BCU + + at.set_entry(r, c++, vcnt_info.DIR_MAE.v); // DIR_MAE + at.set_entry(r, c++, (string)na_str); // DIR_MAE_BCL + at.set_entry(r, c++, (string)na_str); // DIR_MAE_BCU + + at.set_entry(r, c++, vcnt_info.DIR_MSE.v); // DIR_MSE + at.set_entry(r, c++, (string)na_str); // DIR_MSE_BCL + at.set_entry(r, c++, (string)na_str); // DIR_MSE_BCU + + at.set_entry(r, c++, vcnt_info.DIR_RMSE.v); // DIR_RMSE + at.set_entry(r, c++, (string)na_str); // DIR_RMSE_BCL + at.set_entry(r, c++, (string)na_str); // DIR_RMSE_BCU + return; } diff --git a/src/libcode/vx_statistics/met_stats.cc b/src/libcode/vx_statistics/met_stats.cc index fd50117173..a33f1adc73 100644 --- a/src/libcode/vx_statistics/met_stats.cc +++ b/src/libcode/vx_statistics/met_stats.cc @@ -1362,7 +1362,7 @@ VL1L2Info & VL1L2Info::operator+=(const VL1L2Info &c) { v_info.allocate_n_alpha(n_alpha); for(int i=0; i 0) { v_info.uf_bar = (uf_bar*vcount + c.uf_bar*c.vcount) /v_info.vcount; @@ -1374,20 +1374,26 @@ VL1L2Info & VL1L2Info::operator+=(const VL1L2Info &c) { v_info.uvoo_bar = (uvoo_bar*vcount + c.uvoo_bar*c.vcount) /v_info.vcount; v_info.f_speed_bar = (f_speed_bar*vcount + c.f_speed_bar*c.vcount)/v_info.vcount; v_info.o_speed_bar = (o_speed_bar*vcount + c.o_speed_bar*c.vcount)/v_info.vcount; + v_info.dir_bar = (dir_bar*vcount + c.dir_bar*c.vcount) /v_info.vcount; + v_info.absdir_bar = (absdir_bar*vcount + c.absdir_bar*c.vcount) /v_info.vcount; + v_info.dir2_bar = (dir2_bar*vcount + c.dir2_bar*c.vcount) /v_info.vcount; } - v_info.vacount = vacount + c.vacount; + v_info.vacount = vacount + c.vacount; if(v_info.vacount > 0) { - v_info.ufa_bar = (ufa_bar*vacount + c.ufa_bar*c.vacount) /v_info.vacount; - v_info.vfa_bar = (vfa_bar*vacount + c.vfa_bar*c.vacount) /v_info.vacount; - v_info.uoa_bar = (uoa_bar*vacount + c.uoa_bar*c.vacount) /v_info.vacount; - v_info.voa_bar = (voa_bar*vacount + c.voa_bar*c.vacount) /v_info.vacount; - v_info.uvfoa_bar = (uvfoa_bar*vacount + c.uvfoa_bar*c.vacount)/v_info.vacount; - v_info.uvffa_bar = (uvffa_bar*vacount + c.uvffa_bar*c.vacount)/v_info.vacount; - v_info.uvooa_bar = (uvooa_bar*vacount + c.uvooa_bar*c.vacount)/v_info.vacount; + v_info.ufa_bar = (ufa_bar*vacount + c.ufa_bar*c.vacount) /v_info.vacount; + v_info.vfa_bar = (vfa_bar*vacount + c.vfa_bar*c.vacount) /v_info.vacount; + v_info.uoa_bar = (uoa_bar*vacount + c.uoa_bar*c.vacount) /v_info.vacount; + v_info.voa_bar = (voa_bar*vacount + c.voa_bar*c.vacount) /v_info.vacount; + v_info.uvfoa_bar = (uvfoa_bar*vacount + c.uvfoa_bar*c.vacount) /v_info.vacount; + v_info.uvffa_bar = (uvffa_bar*vacount + c.uvffa_bar*c.vacount) /v_info.vacount; + v_info.uvooa_bar = (uvooa_bar*vacount + c.uvooa_bar*c.vacount) /v_info.vacount; v_info.fa_speed_bar = (fa_speed_bar*vacount + c.fa_speed_bar*c.vacount)/v_info.vacount; v_info.oa_speed_bar = (oa_speed_bar*vacount + c.oa_speed_bar*c.vacount)/v_info.vacount; + v_info.dira_bar = (dira_bar*vacount + c.dira_bar*c.vacount) /v_info.vacount; + v_info.absdira_bar = (absdira_bar*vacount + c.absdira_bar*c.vacount) /v_info.vacount; + v_info.dira2_bar = (dira2_bar*vacount + c.dira2_bar*c.vacount) /v_info.vacount; } v_info.compute_stats(); @@ -1416,24 +1422,20 @@ void VL1L2Info::zero_out() { // VL1L2 Quantities // - uf_bar = 0.0; - vf_bar = 0.0; - uo_bar = 0.0; - vo_bar = 0.0; - uvfo_bar = 0.0; - uvff_bar = 0.0; - uvoo_bar = 0.0; - f_speed_bar = 0.0; - o_speed_bar = 0.0; - - f_bar = 0.0; - o_bar = 0.0; - me = 0.0; - mse = 0.0; - rmse = 0.0; - speed_bias = 0.0; - - vcount = 0; + uf_bar = 0.0; + vf_bar = 0.0; + uo_bar = 0.0; + vo_bar = 0.0; + uvfo_bar = 0.0; + uvff_bar = 0.0; + uvoo_bar = 0.0; + f_speed_bar = 0.0; + o_speed_bar = 0.0; + dir_bar = 0.0; + absdir_bar = 0.0; + dir2_bar = 0.0; + + vcount = 0; // // VAL1L2 Quantities @@ -1448,6 +1450,9 @@ void VL1L2Info::zero_out() { uvooa_bar = 0.0; fa_speed_bar = 0.0; oa_speed_bar = 0.0; + dira_bar = 0.0; + absdira_bar = 0.0; + dira2_bar = 0.0; vacount = 0; @@ -1459,6 +1464,8 @@ void VL1L2Info::zero_out() { void VL1L2Info::clear() { n = 0; + n_dir_undef = 0; + n_dira_undef = 0; n_alpha = 0; if(alpha) { delete [] alpha; alpha = (double *) 0; } @@ -1486,6 +1493,10 @@ void VL1L2Info::clear() { DIR_ABSERR.clear(); ANOM_CORR.clear(); ANOM_CORR_UNCNTR.clear(); + DIR_ME.clear(); + DIR_MAE.clear(); + DIR_MSE.clear(); + DIR_RMSE.clear(); zero_out(); @@ -1504,27 +1515,26 @@ void VL1L2Info::assign(const VL1L2Info &c) { logic = c.logic; n = c.n; + n_dir_undef = c.n_dir_undef; + n_dira_undef = c.n_dira_undef; allocate_n_alpha(c.n_alpha); for(i=0; i 0) { + dir_bar /= dir_wgt_sum; + absdir_bar /= dir_wgt_sum; + dir2_bar /= dir_wgt_sum; + } + + // Normalize anomalous wind direction differences + if(dira_wgt_sum > 0) { + dira_bar /= dira_wgt_sum; + absdira_bar /= dira_wgt_sum; + dira2_bar /= dira_wgt_sum; + } + if(vcount > 0) compute_stats(); - // Check for 0 points + // Check for zero points if(vcount == 0) { uf_bar = bad_data_double; @@ -1681,11 +1735,9 @@ void VL1L2Info::set(const PairDataPoint &pd_u_all, uvoo_bar = bad_data_double; f_speed_bar = bad_data_double; o_speed_bar = bad_data_double; - - me = bad_data_double; - mse = bad_data_double; - rmse = bad_data_double; - speed_bias = bad_data_double; + dir_bar = bad_data_double; + absdir_bar = bad_data_double; + dir2_bar = bad_data_double; FBAR.v = bad_data_double; OBAR.v = bad_data_double; @@ -1716,9 +1768,11 @@ void VL1L2Info::set(const PairDataPoint &pd_u_all, ANOM_CORR.v = bad_data_double; ANOM_CORR_UNCNTR.v = bad_data_double; - } - else { - rmse = sqrt(mse); + + DIR_ME.v = bad_data_double; + DIR_MAE.v = bad_data_double; + DIR_MSE.v = bad_data_double; + DIR_RMSE.v = bad_data_double; } if(vacount == 0) { @@ -1731,6 +1785,9 @@ void VL1L2Info::set(const PairDataPoint &pd_u_all, uvooa_bar = bad_data_double; fa_speed_bar = bad_data_double; oa_speed_bar = bad_data_double; + dira_bar = bad_data_double; + absdira_bar = bad_data_double; + dira2_bar = bad_data_double; } return; @@ -1772,6 +1829,10 @@ void VL1L2Info::allocate_n_alpha(int i) { DIR_ABSERR.allocate_n_alpha(n_alpha); ANOM_CORR.allocate_n_alpha(n_alpha); ANOM_CORR_UNCNTR.allocate_n_alpha(n_alpha); + DIR_ME.allocate_n_alpha(n_alpha); + DIR_MAE.allocate_n_alpha(n_alpha); + DIR_MSE.allocate_n_alpha(n_alpha); + DIR_RMSE.allocate_n_alpha(n_alpha); } return; @@ -1820,6 +1881,20 @@ void VL1L2Info::compute_stats() { uf_bar*uo_bar + vf_bar*vo_bar); DIR_ABSERR.v = fabs(DIR_ERR.v); + + // Print undefined wind direction warning message + if(n_dir_undef > 0) { + mlog << Warning << "\nVL1L2Info::compute_stats() -> " + << "Skipping " << n_dir_undef << " of " << vcount + << " vector pairs for which the direction difference is undefined.\n" + << "Set the \"wind_thresh\" and \"wind_logic\" configuration options " + << "to exclude zero vectors.\n\n"; + } + + DIR_ME.v = dir_bar; + DIR_MAE.v = absdir_bar; + DIR_MSE.v = dir2_bar; + DIR_RMSE.v = sqrt(dir2_bar); } if(vacount > 0) { @@ -1837,6 +1912,15 @@ void VL1L2Info::compute_stats() { } ANOM_CORR_UNCNTR.v = compute_anom_corr_uncntr(uvffa_bar, uvooa_bar, uvfoa_bar); + + // Print undefined wind direction warning message + if(n_dira_undef > 0) { + mlog << Warning << "\nVL1L2Info::compute_stats() -> " + << "Skipping " << n_dira_undef << " of " << vacount + << " anomaly vector pairs for which the direction difference is undefined.\n" + << "Set the \"wind_thresh\" and \"wind_logic\" configuration options " + << "to exclude zero vectors.\n\n"; + } } // Compute parametric confidence intervals @@ -1932,6 +2016,10 @@ double VL1L2Info::get_stat(const char *stat_name) { else if(strcmp(stat_name, "DIR_ABSERR" ) == 0) v = DIR_ABSERR.v; else if(strcmp(stat_name, "ANOM_CORR" ) == 0) v = ANOM_CORR.v; else if(strcmp(stat_name, "ANOM_CORR_UNCNTR") == 0) v = ANOM_CORR_UNCNTR.v; + else if(strcmp(stat_name, "DIR_ME" ) == 0) v = DIR_ME.v; + else if(strcmp(stat_name, "DIR_MAE" ) == 0) v = DIR_MAE.v; + else if(strcmp(stat_name, "DIR_MSE" ) == 0) v = DIR_MSE.v; + else if(strcmp(stat_name, "DIR_RMSE" ) == 0) v = DIR_RMSE.v; else { mlog << Error << "\nVL1L2Info::get_stat() -> " << "unknown continuous statistic name \"" << stat_name diff --git a/src/libcode/vx_statistics/met_stats.h b/src/libcode/vx_statistics/met_stats.h index f17a0c867a..f0715d45b3 100644 --- a/src/libcode/vx_statistics/met_stats.h +++ b/src/libcode/vx_statistics/met_stats.h @@ -276,6 +276,10 @@ class VL1L2Info { // Number of points int n; + + // Number of points for which the wind direction difference is undefined + int n_dir_undef; + int n_dira_undef; // VL1L2 Quantities @@ -291,6 +295,10 @@ class VL1L2Info { double f_speed_bar; double o_speed_bar; + double dir_bar; // Average direction difference in (-180, +180] + double absdir_bar; // Average absolute direction difference + double dir2_bar; // Average squared direction difference + // Vector continuous statistics derived from VL1L2 and VAL1L2 partial sums CIInfo FBAR; @@ -322,21 +330,11 @@ class VL1L2Info { CIInfo ANOM_CORR; CIInfo ANOM_CORR_UNCNTR; - - // - // Extra VL1L2 quantities - // - - double f_bar; // fcst wind speed - double o_bar; // obs wind speed - - double me; // mean error - - double mse; // mean squared error - - double rmse; // root mean squared error - - double speed_bias; + + CIInfo DIR_ME; + CIInfo DIR_MAE; + CIInfo DIR_MSE; + CIInfo DIR_RMSE; int vcount; @@ -353,6 +351,10 @@ class VL1L2Info { double fa_speed_bar; double oa_speed_bar; + double dira_bar; // Average anomalous direction difference in (-180, +180] + double absdira_bar; // Average anomalous absolute direction difference + double dira2_bar; // Average anomalous squared direction difference + int vacount; // Compute sums diff --git a/src/tools/core/grid_stat/grid_stat.cc b/src/tools/core/grid_stat/grid_stat.cc index d2f137ff0c..c65ca49109 100644 --- a/src/tools/core/grid_stat/grid_stat.cc +++ b/src/tools/core/grid_stat/grid_stat.cc @@ -2253,6 +2253,9 @@ void do_vl1l2(VL1L2Info *&v_info, int i_vx, const PairDataPoint *pd_v_ptr) { int i, j; + mlog << Debug(2) + << "Computing Vector Partial Sums and Continuous Vector Statistics.\n"; + // Check that the number of pairs are the same if(pd_u_ptr->n_obs != pd_v_ptr->n_obs) { mlog << Error << "\ndo_vl1l2() -> " diff --git a/src/tools/core/point_stat/point_stat.cc b/src/tools/core/point_stat/point_stat.cc index 474fdde6ec..6c50ea880c 100644 --- a/src/tools/core/point_stat/point_stat.cc +++ b/src/tools/core/point_stat/point_stat.cc @@ -1632,6 +1632,9 @@ void do_vl1l2(VL1L2Info *&v_info, int i_vx, const PairDataPoint *pd_u_ptr, const PairDataPoint *pd_v_ptr) { int i, j; + mlog << Debug(2) + << "Computing Vector Partial Sums and Continuous Vector Statistics.\n"; + // // Check that the number of pairs are the same // diff --git a/src/tools/core/stat_analysis/aggr_stat_line.cc b/src/tools/core/stat_analysis/aggr_stat_line.cc index 5edf0a5025..99b5906429 100644 --- a/src/tools/core/stat_analysis/aggr_stat_line.cc +++ b/src/tools/core/stat_analysis/aggr_stat_line.cc @@ -37,6 +37,8 @@ // -out_thresh and -out_line_type options. // 017 11/10/22 Halley Gotway MET #2339 Add SEEPS and SEEPS_MPR // line types. +// 018 02/13/24 Halley Gotway MET #2395 Add wind direction stats +// to VL1L2, VAL1L2, and VCNT. // //////////////////////////////////////////////////////////////////////// @@ -2139,6 +2141,21 @@ void aggr_mpr_wind_lines(LineDataFile &f, STATAnalysisJob &job, it->second.pd_v.f_na[i]*it->second.pd_v.f_na[i]); v_info.o_speed_bar = sqrt(it->second.pd_u.o_na[i]*it->second.pd_u.o_na[i] + it->second.pd_v.o_na[i]*it->second.pd_v.o_na[i]); + + double d_diff = angle_difference( + it->second.pd_u.f_na[i], it->second.pd_v.f_na[i], + it->second.pd_u.o_na[i], it->second.pd_v.o_na[i]); + + if(is_bad_data(d_diff)) { + v_info.n_dir_undef = 1; + } + else { + v_info.n_dir_undef = 0; + v_info.dir_bar = d_diff; + v_info.absdir_bar = abs(d_diff); + v_info.dir2_bar = d_diff*d_diff; + } + aggr.vl1l2_info += v_info; // diff --git a/src/tools/core/stat_analysis/parse_stat_line.cc b/src/tools/core/stat_analysis/parse_stat_line.cc index 77758a91bd..57bc92eb46 100644 --- a/src/tools/core/stat_analysis/parse_stat_line.cc +++ b/src/tools/core/stat_analysis/parse_stat_line.cc @@ -31,6 +31,8 @@ // 011 01/24/20 Halley Gotway Add RPS line type. // 012 11/10/22 Halley Gotway MET #2339 Add SEEPS and SEEPS_MPR // line types. +// 013 02/13/24 Halley Gotway MET #2395 Add wind direction stats +// to VL1L2, VAL1L2, and VCNT. // //////////////////////////////////////////////////////////////////////// @@ -234,6 +236,9 @@ void parse_vl1l2_line(STATLine &l, VL1L2Info &v_info) { v_info.uvoo_bar = atof(l.get_item("UVOOBAR")); v_info.f_speed_bar = atof(l.get_item("F_SPEED_BAR")); v_info.o_speed_bar = atof(l.get_item("O_SPEED_BAR")); + v_info.dir_bar = atof(l.get_item("DIR_ME")); + v_info.absdir_bar = atof(l.get_item("DIR_MAE")); + v_info.dir2_bar = atof(l.get_item("DIR_MSE")); v_info.compute_stats(); @@ -256,6 +261,9 @@ void parse_val1l2_line(STATLine &l, VL1L2Info &v_info) { v_info.uvooa_bar = atof(l.get_item("UVOOABAR")); v_info.fa_speed_bar = atof(l.get_item("FA_SPEED_BAR")); v_info.oa_speed_bar = atof(l.get_item("OA_SPEED_BAR")); + v_info.dira_bar = atof(l.get_item("DIRA_ME")); + v_info.absdira_bar = atof(l.get_item("DIRA_MAE")); + v_info.dira2_bar = atof(l.get_item("DIRA_MSE")); v_info.compute_stats();