From a8e6ca8270f6385dd98904a291c6d75f1977956d Mon Sep 17 00:00:00 2001 From: John Halley Gotway Date: Fri, 29 Oct 2021 16:36:03 -0600 Subject: [PATCH] Per #1905, keep track of which ensemble member is the control and exclude it from the spread and variance computations. --- .../vx_statistics/pair_data_ensemble.cc | 57 ++++++++++++++----- .../vx_statistics/pair_data_ensemble.h | 4 ++ 2 files changed, 46 insertions(+), 15 deletions(-) diff --git a/met/src/libcode/vx_statistics/pair_data_ensemble.cc b/met/src/libcode/vx_statistics/pair_data_ensemble.cc index 5782cf6a0d..77b66536b3 100644 --- a/met/src/libcode/vx_statistics/pair_data_ensemble.cc +++ b/met/src/libcode/vx_statistics/pair_data_ensemble.cc @@ -108,6 +108,7 @@ void PairDataEnsemble::clear() { n_ens = 0; n_pair = 0; + ctrl_index = bad_data_int; skip_const = false; skip_ba.clear(); @@ -121,6 +122,7 @@ void PairDataEnsemble::clear() { esum_na.clear(); esumsq_na.clear(); + esumn_na.clear(); mn_na.clear(); mn_oerr_na.clear(); @@ -170,6 +172,7 @@ void PairDataEnsemble::extend(int n) { var_plus_oerr_na.extend (n); esum_na.extend (n); esumsq_na.extend (n); + esumn_na.extend (n); mn_na.extend (n); mn_oerr_na.extend (n); @@ -222,6 +225,7 @@ void PairDataEnsemble::assign(const PairDataEnsemble &pd) { ign_na = pd.ign_na; pit_na = pd.pit_na; n_pair = pd.n_pair; + ctrl_index = pd.ctrl_index; skip_const = pd.skip_const; skip_ba = pd.skip_ba; @@ -231,6 +235,7 @@ void PairDataEnsemble::assign(const PairDataEnsemble &pd) { esum_na = pd.esum_na; esumsq_na = pd.esumsq_na; + esumn_na = pd.esumn_na; mn_na = pd.mn_na; mn_oerr_na = pd.mn_oerr_na; @@ -290,12 +295,14 @@ void PairDataEnsemble::add_ens_var_sums(int i_obs, double v) { if(i_obs >= esum_na.n()) { esum_na.add(0.0); esumsq_na.add(0.0); + esumn_na.add(0.0); } // Track sums of the raw ensemble member values if(!is_bad_data(v)) { esum_na.inc(i_obs, v); esumsq_na.inc(i_obs, v*v); + esumn_na.inc(i_obs, 1); } return; @@ -416,17 +423,17 @@ void PairDataEnsemble::compute_pair_vals(const gsl_rng *rng_ptr) { else { // Compute the variance of the unperturbed ensemble members - var_unperturbed = compute_variance(esum_na[i], esumsq_na[i], v_na[i]); + var_unperturbed = compute_variance(esum_na[i], esumsq_na[i], esumn_na[i]); var_na.add(var_unperturbed); // Process the observation error information. ObsErrorEntry * e = (has_obs_error() ? obs_error_entry[i] : 0); if(e) { - // Compute perturbed ensemble mean and variance - cur_ens.compute_mean_variance(mean, var_perturbed); - mn_oerr_na.add(mean); - var_oerr_na.add(var_perturbed); + // Compute perturbed ensemble mean and variance + // Exclude the control member from the variance + mn_oerr_na.add(cur_ens.mean()); + var_oerr_na.add(cur_ens.variance(ctrl_index)); // JHG // Compute the variance plus observation error variance. var_plus_oerr_na.add(var_unperturbed + @@ -467,8 +474,12 @@ void PairDataEnsemble::compute_pair_vals(const gsl_rng *rng_ptr) { crps_emp_na.add(compute_crps_emp(o_na[i], cur_ens)); crpscl_emp_na.add(compute_crps_emp(o_na[i], cur_clm)); + // Ensemble mean and standard deviation + // Exclude the control member from the standard deviation + mean = cur_ens.mean(); + stdev = cur_ens.stdev(ctrl_index); // JHG + // Store Gaussian CRPS stats - cur_ens.compute_mean_stdev(mean, stdev); crps_gaus_na.add(compute_crps_gaus(o_na[i], mean, stdev)); crpscl_gaus_na.add(compute_crps_gaus(o_na[i], cmn_na[i], csd_na[i])); ign_na.add(compute_ens_ign(o_na[i], mean, stdev)); @@ -613,7 +624,7 @@ struct ssvar_bin_comp { void PairDataEnsemble::compute_ssvar() { int i, j; - double mn, var; + double var; ssvar_bin_map bins; NumArray cur; @@ -641,24 +652,22 @@ void PairDataEnsemble::compute_ssvar() { for(i=0; iflag) { @@ -1781,6 +1793,21 @@ void VxPairDataEnsemble::calc_obs_summary() { //////////////////////////////////////////////////////////////////////// +void VxPairDataEnsemble::set_ctrl_index(int index) { + + for(int i=0; i < n_msg_typ; i++){ + for(int j=0; j < n_mask; j++){ + for(int k=0; k < n_interp; k++){ + pd[i][j][k].ctrl_index = index; + } + } + } + + return; +} + +//////////////////////////////////////////////////////////////////////// + void VxPairDataEnsemble::set_skip_const(bool tf) { for(int i=0; i < n_msg_typ; i++){ diff --git a/met/src/libcode/vx_statistics/pair_data_ensemble.h b/met/src/libcode/vx_statistics/pair_data_ensemble.h index e9c2417e49..bee6b11838 100644 --- a/met/src/libcode/vx_statistics/pair_data_ensemble.h +++ b/met/src/libcode/vx_statistics/pair_data_ensemble.h @@ -90,6 +90,7 @@ class PairDataEnsemble : public PairBase { int n_ens; // Number of ensemble members int n_pair; // Number of valid pairs, n_obs - sum(skip_ba) + int ctrl_index; // Index of the control member bool skip_const; // Skip cases where the observation and // all ensemble members are constant BoolArray skip_ba; // Flag for each observation [n_obs] @@ -106,6 +107,7 @@ class PairDataEnsemble : public PairBase { NumArray esum_na; // Sum of unperturbed ensemble values [n_obs] NumArray esumsq_na; // Sum of unperturbed ensemble squared values [n_obs] + NumArray esumn_na; // Count of ensemble values [n_obs] NumArray mn_na; // Ensemble mean value [n_obs] NumArray mn_oerr_na; // Mean of perturbed members [n_obs] @@ -293,6 +295,8 @@ class VxPairDataEnsemble { void calc_obs_summary(); + void set_ctrl_index(int); + void set_skip_const(bool); };