diff --git a/docs/Users_Guide/tc-pairs.rst b/docs/Users_Guide/tc-pairs.rst index dbacd34839..556f7358c2 100644 --- a/docs/Users_Guide/tc-pairs.rst +++ b/docs/Users_Guide/tc-pairs.rst @@ -421,35 +421,38 @@ TC-Pairs produces output in TCST format. The default output file name can be ove - BMODEL - User provided text string designating model name * - 4 + - DESC + - User provided description text string + * - 5 - STORM_ID - BBCCYYYY designation of storm - * - 5 + * - 6 - BASIN - Basin (BB in STORM_ID) - * - 6 + * - 7 - CYCLONE - Cyclone number (CC in STORM_ID) - * - 7 + * - 8 - STORM_NAME - Name of Storm - * - 8 + * - 9 - INIT - Initialization time of forecast in YYYYMMDD_HHMMSS format. - * - 9 + * - 10 - LEAD - Forecast lead time in HHMMSS format. - * - 10 + * - 11 - VALID - Forecast valid time in YYYYMMDD_HHMMSS format. - * - 11 + * - 12 - INIT_MASK - Initialization time masking grid applied - * - 12 + * - 13 - VALID_MASK - Valid time masking grid applied - * - 13 + * - 14 - LINE_TYPE - - Output line type (TCMPR or PROBRIRW) + - Output line types described below .. _TCMPR Line Type: @@ -463,151 +466,151 @@ TC-Pairs produces output in TCST format. The default output file name can be ove * - Column Number - Header Column Name - Description - * - 13 + * - 14 - TCMPR - Tropical Cyclone Matched Pair line type - * - 14 + * - 15 - TOTAL - Total number of pairs in track - * - 15 + * - 16 - INDEX - Index of the current track pair - * - 16 + * - 17 - LEVEL - Level of storm classification - * - 17 + * - 18 - WATCH_WARN - HU or TS watch or warning in effect - * - 18 + * - 19 - INITIALS - Forecaster initials - * - 19 + * - 20 - ALAT - Latitude position of adeck model - * - 20 + * - 21 - ALON - Longitude position of adeck model - * - 21 + * - 22 - BLAT - Latitude position of bdeck model - * - 22 + * - 23 - BLON - Longitude position of bdeck model - * - 23 + * - 24 - TK_ERR - Track error of adeck relative to bdeck (nm) - * - 24 + * - 25 - X_ERR - X component position error (nm) - * - 25 + * - 26 - Y_ERR - Y component position error (nm) - * - 26 + * - 27 - ALTK_ERR - Along track error (nm) - * - 27 + * - 28 - CRTK_ERR - Cross track error (nm) - * - 28 + * - 29 - ADLAND - adeck distance to land (nm) - * - 29 + * - 30 - BDLAND - bdeck distance to land (nm) - * - 30 + * - 31 - AMSLP - adeck mean sea level pressure - * - 31 + * - 32 - BMSLP - bdeck mean sea level pressure - * - 32 + * - 33 - AMAX_WIND - adeck maximum wind speed - * - 33 + * - 34 - BMAX_WIND - bdeck maximum wind speed - * - 34, 35 + * - 35, 36 - A/BAL_WIND_34 - a/bdeck 34-knot radius winds in full circle - * - 36, 37 + * - 37, 38 - A/BNE_WIND_34 - a/bdeck 34-knot radius winds in NE quadrant - * - 38, 39 + * - 39, 40 - A/BSE_WIND_34 - a/bdeck 34-knot radius winds in SE quadrant - * - 40, 41 + * - 41, 42 - A/BSW_WIND_34 - a/bdeck 34-knot radius winds in SW quadrant - * - 42, 43 + * - 43, 44 - A/BNW_WIND_34 - a/bdeck 34-knot radius winds in NW quadrant - * - 44, 45 + * - 45, 46 - A/BAL_WIND_50 - a/bdeck 50-knot radius winds in full circle - * - 46, 47 + * - 47, 48 - A/BNE_WIND_50 - a/bdeck 50-knot radius winds in NE quadrant - * - 48, 49 + * - 49, 50 - A/BSE_WIND_50 - a/bdeck 50-knot radius winds in SE quadrant - * - 50, 51 + * - 51, 52 - A/BSW_WIND_50 - a/bdeck 50-knot radius winds in SW quadrant - * - 52, 53 + * - 53, 54 - A/BNW_WIND_50 - a/bdeck 50-knot radius winds in NW quadrant - * - 54, 55 + * - 55, 56 - A/BAL_WIND_64 - a/bdeck 64-knot radius winds in full circle - * - 56, 57 + * - 57, 58 - A/BNE_WIND_64 - a/bdeck 64-knot radius winds in NE quadrant - * - 58, 59 + * - 59, 60 - A/BSE_WIND_64 - a/bdeck 64-knot radius winds in SE quadrant - * - 60, 61 + * - 61, 62 - A/BSW_WIND_64 - a/bdeck 64-knot radius winds in SW quadrant - * - 62, 63 + * - 63, 64 - A/BNW_WIND_64 - a/bdeck 64-knot radius winds in NW quadrant - * - 64, 65 + * - 65, 66 - A/BRADP - pressure in millibars of the last closed isobar, 900 - 1050 mb - * - 66, 67 + * - 67, 68 - A/BRRP - radius of the last closed isobar in nm, 0 - 9999 nm - * - 68, 69 + * - 69, 70 - A/BMRD - radius of max winds, 0 - 999 nm - * - 70, 71 + * - 71, 72 - A/BGUSTS - gusts, 0 through 995 kts - * - 72, 73 + * - 73, 74 - A/BEYE - eye diameter, 0 through 999 nm - * - 74, 75 + * - 75, 76 - A/BDIR - storm direction in compass coordinates, 0 - 359 degrees - * - 76, 77 + * - 77, 78 - A/BSPEED - storm speed, 0 - 999 kts - * - 78, 79 + * - 79, 80 - A/BDEPTH - system depth, D-deep, M-medium, S-shallow, X-unknown - * - 80 + * - 81 - NUM_MEMBERS - consensus variable: number of models (or ensemble members) that were used to build the consensus track - * - 81 + * - 82 - TRACK_SPREAD - consensus variable: the mean of the distances from the member location to the consensus track location (nm) - * - 82 + * - 83 - TRACK_STDEV - consensus variable: the standard deviation of the distances from the member locations to the consensus track location (nm) - * - 83 + * - 84 - MSLP_STDEV - consensus variable: the standard deviation of the member's mean sea level pressure values - * - 84 + * - 85 - MAX_WIND_STDEV - consensus variable: the standard deviation of the member's maximum wind speed values @@ -623,31 +626,31 @@ TC-Pairs produces output in TCST format. The default output file name can be ove * - Column Number - Header Column Name - Description - * - 13 + * - 14 - TCDIAG - Tropical Cyclone Diagnostics line type - * - 14 + * - 15 - TOTAL - Total number of pairs in track - * - 15 + * - 16 - INDEX - Index of the current track pair - * - 16 + * - 17 - DIAG_SOURCE - Diagnostics data source indicated by the `-diag` command line option - * - 17 + * - 18 - TRACK_SOURCE - ATCF ID of the track data used to define the diagnostics - * - 18 + * - 19 - FIELD_SOURCE - Description of gridded field data source used to define the diagnostics - * - 19 + * - 20 - N_DIAG - Number of storm diagnostic name and value columns to follow - * - 20 + * - 21 - DIAG_i - Name of the of the ith storm diagnostic (repeated) - * - 21 + * - 22 - VALUE_i - Value of the ith storm diagnostic (repeated) @@ -663,75 +666,75 @@ TC-Pairs produces output in TCST format. The default output file name can be ove * - Column Number - Header Column Name - Description - * - 13 + * - 14 - PROBRIRW - Probability of Rapid Intensification/Weakening line type - * - 14 + * - 15 - ALAT - Latitude position of edeck model - * - 15 + * - 16 - ALON - Longitude position of edeck model - * - 16 + * - 17 - BLAT - Latitude position of bdeck model - * - 17 + * - 18 - BLON - Longitude position of bdeck model - * - 18 + * - 19 - INITIALS - Forecaster initials - * - 19 + * - 20 - TK_ERR - Track error of adeck relative to bdeck (nm) - * - 20 + * - 21 - X_ERR - X component position error (nm) - * - 21 + * - 22 - Y_ERR - Y component position error (nm) - * - 22 + * - 23 - ADLAND - adeck distance to land (nm) - * - 23 + * - 24 - BDLAND - bdeck distance to land (nm) - * - 24 + * - 25 - RI_BEG - Start of RI time window in HH format - * - 25 + * - 26 - RI_END - End of RI time window in HH format - * - 26 + * - 27 - RI_WINDOW - Width of RI time window in HH format - * - 27 + * - 28 - AWIND_END - Forecast maximum wind speed at RI end - * - 28 + * - 29 - BWIND_BEG - Best track maximum wind speed at RI begin - * - 29 + * - 30 - BWIND_END - Best track maximum wind speed at RI end - * - 30 + * - 31 - BDELTA - Exact Best track wind speed change in RI window - * - 31 + * - 32 - BDELTA_MAX - Maximum Best track wind speed change in RI window - * - 32 + * - 33 - BLEVEL_BEG - Best track storm classification at RI begin - * - 33 + * - 34 - BLEVEL_END - Best track storm classification at RI end - * - 34 + * - 35 - N_THRESH - Number of probability thresholds - * - 35 + * - 36 - THRESH_i - The ith probability threshold value (repeated) - * - 36 + * - 37 - PROB_i - The ith probability value (repeated) diff --git a/docs/Users_Guide/tc-stat.rst b/docs/Users_Guide/tc-stat.rst index 1902330f8b..0d9e824837 100644 --- a/docs/Users_Guide/tc-stat.rst +++ b/docs/Users_Guide/tc-stat.rst @@ -59,6 +59,8 @@ The TC-Stat tool can be used to read TCMPR lines and compare the occurrence of r Users may specify several job command options to configure the behavior of this job. Using these configurable options, the TC-Stat tool analyzes paired tracks and for each track point (i.e. each TCMPR line) determines whether rapid intensification or weakening occurred. For each point in time, it uses the forecast and BEST track event occurrence to populate a 2x2 contingency table. The job may be configured to require that forecast and BEST track events occur at exactly the same time to be considered a hit. Alternatively, the job may be configured to define a hit as long as the forecast and BEST track events occurred within a configurable time window. Using this relaxed matching criteria false alarms may be considered hits and misses may be considered correct negatives as long as the adeck and bdeck events were close enough in time. Each rirw job applies a single intensity change threshold. Therefore, assessing a model's performance with rapid intensification and weakening requires that two separate jobs be run. +The RIRW job supports the **-out_stat** option to write the contingency table counts and statistics to a STAT output file. + Probability of Rapid Intensification ------------------------------------ @@ -383,6 +385,7 @@ _________________________ e.g.: -job filter -line_type TCMPR -amodel HWFI -dump_row ./tc_filter_job.tcst -job summary -line_type TCMPR -column TK_ERR -dump_row ./tc_summary_job.tcst -job rirw -line_type TCMPR -rirw_time 24 -rirw_exact false -rirw_thresh ge20 + -job rirw -line_type TCMPR -rirw_time 24 -rirw_exact false -rirw_thresh ge20 -out_stat ./tc_rirw.stat -job probrirw -line_type PROBRIRW -column_thresh RI_WINDOW ==24 \ -probrirw_thresh 30 -probrirw_prob_thresh ==0.25 @@ -470,6 +473,8 @@ The RIRW job produces contingency table counts and statistics defined by identif Users may also specify the **-out_alpha** option to define the alpha value for the confidence intervals in the CTS output line type. In addition, the **-by column_name** option is a convenient way of running the same job across multiple stratifications of data. For example, **-by AMODEL** runs the same job for each unique AMODEL name in the data. +Users may also specify the **-out_stat** option to write the contingency table counts and statistics (for the CTC and CTS output line types) to an output STAT file. Information about the RIRW timing information and filtering criteria are written to the STAT header columns while the contingency table counts and/or statistics are written to the CTC and/or CTS output columns. + **Job: PROBRIRW** The PROBRIRW job produces probabilistic contingency table counts and statistics defined by placing forecast probabilities and BEST track rapid intensification events into an Nx2 contingency table. Users may specify several job command options to configure the behavior of this job: diff --git a/internal/test_unit/config/TCStatConfig_ALAL2010 b/internal/test_unit/config/TCStatConfig_ALAL2010 index 02360bf454..05bf63a7a1 100644 --- a/internal/test_unit/config/TCStatConfig_ALAL2010 +++ b/internal/test_unit/config/TCStatConfig_ALAL2010 @@ -211,7 +211,8 @@ jobs = [ "-job filter -amodel AHWI -rirw_track BDECK -rirw_thresh >=30 -rirw_exact FALSE -dump_row ${MET_TEST_OUTPUT}/tc_stat/ALAL2010_AHWI_ri.tcst", "-job filter -amodel AHWI -rirw_track BDECK -rirw_thresh <=-30 -rirw_exact TRUE -dump_row ${MET_TEST_OUTPUT}/tc_stat/ALAL2010_AHWI_rw.tcst", "-job rirw -rirw_window 00 -rirw_thresh <=-15 -out_line_type CTC,CTS,MPR", - "-job rirw -rirw_window 12 -rirw_thresh <=-15 -out_line_type CTC,CTS,MPR" + "-job rirw -rirw_window 12 -rirw_thresh <=-15 -out_line_type CTC,CTS,MPR", + "-job rirw -rirw_window 12 -rirw_thresh <=-15 -out_line_type CTC,CTS -out_stat ${MET_TEST_OUTPUT}/tc_stat/ALAL2010_rirw.stat" ]; // diff --git a/src/basic/vx_log/string_array.cc b/src/basic/vx_log/string_array.cc index 91e84f573b..5723348a93 100644 --- a/src/basic/vx_log/string_array.cc +++ b/src/basic/vx_log/string_array.cc @@ -267,6 +267,30 @@ return; //////////////////////////////////////////////////////////////////////// +void StringArray::add_uniq(const std::string text) + +{ + + // + // Only store unique strings + // + +if(!has(text)) { + + s.push_back(text); + + Sorted = false; + +} + +return; + +} + + +//////////////////////////////////////////////////////////////////////// + + void StringArray::add(const StringArray & a) { @@ -285,6 +309,35 @@ return; //////////////////////////////////////////////////////////////////////// +void StringArray::add_uniq(const StringArray & a) + +{ + +if ( a.n() == 0 ) return; + + // + // Only store unique strings + // + +for(int i=0; i 0 && !Desc.has(line.desc())) { keep = false; n.RejDesc++; } else if(StormId.n() > 0 && - !has_storm_id(StormId, (string)line.basin(), (string)line.cyclone(), line.init())) + !has_storm_id(StormId, (string)line.basin(), (string)line.cyclone(), line.init())) { keep = false; n.RejStormId++; } else if(Basin.n() > 0 && !Basin.has(line.basin())) { keep = false; n.RejBasin++; } @@ -1169,6 +1170,8 @@ void TCStatJob::open_stat_file() { close_stat_file(); + stat_row = 0; + if(StatFile.empty()) return; StatOut = new ofstream; @@ -1431,7 +1434,7 @@ ConcatString TCStatJob::serialize() const { if(DumpFile.length() > 0) s << "-dump_row " << DumpFile << " "; if(StatFile.length() > 0) - s << "-stat_row " << StatFile << " "; + s << "-out_stat " << StatFile << " "; return(s); } @@ -2964,6 +2967,8 @@ void TCStatJobRIRW::clear() { for(i=0; i<4; i++) DumpFileCTC[i].clear(); close_dump_file(); + close_stat_file(); + // Set to default values OutAlpha = default_tc_alpha; OutLineType.clear(); @@ -3163,9 +3168,17 @@ void TCStatJobRIRW::do_job(const StringArray &file_list, close_dump_file(); // Process the RI/RW job output - if(JobOut) do_output(*JobOut); - else do_output(cout); - + if(StatOut) + do_stat_output(*StatOut); + else if(JobOut) + do_output(*JobOut); + else + do_output(cout); + + // Close the stat file + if(StatOut) + close_stat_file(); + return; } @@ -3300,7 +3313,21 @@ void TCStatJobRIRW::process_pair(TrackPairInfo &pair) { << bprv << sep << bcur << sep << bdlt << sep << (is_bad_data(b) ? na_str : bool_to_string(b)) << sep << cat; + + // Track unique header column strings + cur_map[key].AModel.add_uniq(pair.tcmpr_line(i)->amodel()); + cur_map[key].BModel.add_uniq(pair.tcmpr_line(i)->bmodel()); + cur_map[key].Desc.add_uniq(pair.tcmpr_line(i)->desc()); + cur_map[key].Basin.add_uniq(pair.tcmpr_line(i)->basin()); + cur_map[key].InitMask.add_uniq(pair.tcmpr_line(i)->init_mask()); + cur_map[key].ValidMask.add_uniq(pair.tcmpr_line(i)->valid_mask()); + + // Track timing information cur_map[key].Hdr.add(cur); + cur_map[key].Init.add(pair.tcmpr_line(i)->init()); + cur_map[key].Lead.add(pair.tcmpr_line(i)->lead()); + cur_map[key].Valid.add(pair.tcmpr_line(i)->valid()); + } // end for i // Add the current map @@ -3355,7 +3382,17 @@ void TCStatJobRIRW::add_map(map&m) { RIRWMap[it->first].Info.cts.set_fn_on( RIRWMap[it->first].Info.cts.fn_on() + it->second.Info.cts.fn_on()); - RIRWMap[it->first].Hdr.add(it->second.Hdr); + + RIRWMap[it->first].Hdr.add_uniq(it->second.Hdr); + RIRWMap[it->first].AModel.add_uniq(it->second.AModel); + RIRWMap[it->first].BModel.add_uniq(it->second.BModel); + RIRWMap[it->first].Desc.add_uniq(it->second.Desc); + RIRWMap[it->first].Basin.add_uniq(it->second.Basin); + RIRWMap[it->first].InitMask.add_uniq(it->second.InitMask); + RIRWMap[it->first].ValidMask.add_uniq(it->second.ValidMask); + RIRWMap[it->first].Init.add(it->second.Init); + RIRWMap[it->first].Lead.add(it->second.Lead); + RIRWMap[it->first].Valid.add(it->second.Valid); } } // end for it @@ -3459,7 +3496,7 @@ void TCStatJobRIRW::do_cts_output(ostream &out) { StringArray sa; int i, r, c; AsciiTable out_at; - + // Format the output table out_at.set_size((int) RIRWMap.size() + 1, 9 + ByColumn.n() + n_cts_columns); @@ -3634,6 +3671,271 @@ void TCStatJobRIRW::do_mpr_output(ostream &out) { return; } +//////////////////////////////////////////////////////////////////////// + +void TCStatJobRIRW::setup_stat_file(int n_row) { + STATLineType cur_lt, out_lt; + StringArray out_sa; + int i, c, n_col; + + // + // Nothing to do if no output STAT file stream is defined + // + if(!StatOut) return; + + // + // Check for a single output line type + // + out_sa = (OutLineType.n() > 0 ? + OutLineType : LineType); + + out_lt = (out_sa.n() == 1 ? + string_to_statlinetype(out_sa[0].c_str()) : no_stat_line_type); + + // + // Loop through the output line types and determine the number of + // output columns + // + for(i=0, c=0, n_col=0; i " + << "unexpected stat line type \"" << statlinetype_to_string(cur_lt) + << "\"!\n" + << "The line type \"" << statlinetype_to_string(cur_lt) + << "\" is not supported when -out_stat is requested.\n\n"; + exit(1); + } + if(c > n_col) n_col = c; + } + + // + // Add the header columns + // + n_col += n_header_columns; + + // + // Create table from scratch + // + if(stat_row == 0) { + + // + // Multiply the number of rows by the number of + // output line types to avoid resizing later + // + n_row *= max(1, out_sa.n()); + + // + // Setup the STAT table + // + stat_at.set_size(n_row, n_col); + justify_stat_cols(stat_at); + stat_at.set_precision(Precision); + stat_at.set_bad_data_value(bad_data_double); + stat_at.set_bad_data_str(na_str); + stat_at.set_delete_trailing_blank_rows(1); + + // + // Write the STAT header row + // + switch(out_lt) { + case stat_ctc: + write_header_row(ctc_columns, n_ctc_columns, 1, stat_at, 0, 0); + break; + + case stat_cts: + write_header_row(cts_columns, n_cts_columns, 1, stat_at, 0, 0); + break; + + // Write only header columns for unspecified line type + case no_stat_line_type: + write_header_row((const char **) 0, 0, 1, stat_at, 0, 0); + break; + + default: + mlog << Error << "\nSTATAnalysisJob::setup_stat_file() -> " + << "unexpected stat line type \"" << statlinetype_to_string(out_lt) + << "\"!\n\n"; + exit(1); + } + // + // Increment row counter + // + stat_row++; + } + // + // Expand the table, if needed + // + else { + + // + // Determine the required dimensions + // + int need_rows = max(stat_at.nrows(), stat_row + n_row); + int need_cols = max(stat_at.ncols(), n_col); + + if(need_rows > stat_at.nrows() || need_cols > stat_at.ncols()) { + // + // Resize the STAT table + // + stat_at.expand(need_rows, need_cols); + justify_stat_cols(stat_at); + stat_at.set_precision(Precision); + stat_at.set_bad_data_value(bad_data_double); + stat_at.set_bad_data_str(na_str); + stat_at.set_delete_trailing_blank_rows(1); + } + } + + return; +} + +//////////////////////////////////////////////////////////////////////// + +void TCStatJobRIRW::do_stat_output(ostream &out) { + map::iterator it; + StatHdrColumns shc; + StringArray sa; + ConcatString cs; + TimeArray Valid; + unixtime valid_beg, valid_end; + int lead_time; + int i, j, r, c; + + // Setup -out_stat file + setup_stat_file(1 + (int) RIRWMap.size()); + + // + // Setup stat header columns + // + + // Set the output FCST_VAR column + cs << cs_erase << "RIRW_" << sec_to_timestring(RIRWTimeADeck) + << (!RIRWExactADeck ? "_MAX" : ""); + shc.set_fcst_var(cs); + + // Set the output OBS_VAR column + cs << cs_erase << "RIRW_" << sec_to_timestring(RIRWTimeBDeck) + << (!RIRWExactBDeck ? "_MAX" : ""); + shc.set_obs_var(cs); + + // Set the output FCST_THRESH and OBS_THRESH columns + shc.set_fcst_thresh(RIRWThreshADeck); + shc.set_obs_thresh(RIRWThreshBDeck); + + mlog << Debug(2) << "Computing output for " + << (int) RIRWMap.size() << " case(s).\n"; + + // + // Loop through the map + // + for(it = RIRWMap.begin(), r=1; it != RIRWMap.end(); it++) { + + // Set the output MODEL column + shc.set_model(write_css(it->second.AModel).c_str()); + + // Set the output OBTYPE column + shc.set_obtype(write_css(it->second.BModel).c_str()); + + // Set the output VX_MASK column + cs << cs_erase; + + // Add -out_init_mask name, if specified + if(OutInitMaskName.nonempty()) { + cs << OutInitMaskName; + } + // Add -out_valid_mask name, if specified + if(OutValidMaskName.nonempty()) { + if(cs.nonempty()) cs << ","; + cs << OutValidMaskName; + } + // If neither are specified, use input mask and/or basin names + if(cs.empty()) { + StringArray sa; + sa.add_uniq(it->second.InitMask); + sa.add_uniq(it->second.ValidMask); + + // Use the basin names instead + if(sa.n() == 1 && sa[0] == na_str) { + sa.clear(); + sa.add_uniq(it->second.Basin); + } + cs = write_css(sa); + } + + // Set shc mask name + shc.set_mask(cs.c_str()); + + // Set shc lead-time and valid-time variables + lead_time = it->second.Lead.max(); + valid_beg = it->second.Valid.min(); + valid_end = it->second.Valid.max(); + + shc.set_fcst_lead_sec(lead_time); + shc.set_fcst_valid_beg(valid_beg); + shc.set_fcst_valid_end(valid_end); + shc.set_obs_lead_sec(bad_data_int); + shc.set_obs_valid_beg(valid_beg); + shc.set_obs_valid_end(valid_end); + + // + // Write the output STAT header columns + // + + // + // Initialize + // + c = 0; + + // + // CTC output line + // + if(OutLineType.has(stat_ctc_str)) { + shc.set_alpha(bad_data_double); + shc.set_line_type(stat_ctc_str); + write_header_cols(shc, stat_at, stat_row); + write_ctc_cols(it->second.Info, stat_at, stat_row++, n_header_columns); + } + + // + // CTS output line + // + if(OutLineType.has(stat_cts_str)) { + + // + // Store the alpha information in the CTSInfo object + // + it->second.Info.allocate_n_alpha(1); + it->second.Info.alpha[0] = OutAlpha; + shc.set_alpha(OutAlpha); + + // + // Compute the stats and confidence intervals for this + // CTSInfo object + // + + it->second.Info.compute_stats(); + it->second.Info.compute_ci(); + + // + // Write the data line + // + shc.set_line_type(stat_cts_str); + write_header_cols(shc, stat_at, stat_row); + write_cts_cols(it->second.Info, 0, stat_at, stat_row++, n_header_columns); + } + } // end for it + + // Write the table + out << stat_at << "\n" << flush; + + return; +} + + //////////////////////////////////////////////////////////////////////// // // Code for class TCStatJobProbRIRW diff --git a/src/tools/tc_utils/tc_stat/tc_stat_job.h b/src/tools/tc_utils/tc_stat/tc_stat_job.h index cb4b250a47..0a0db927de 100644 --- a/src/tools/tc_utils/tc_stat/tc_stat_job.h +++ b/src/tools/tc_utils/tc_stat/tc_stat_job.h @@ -74,6 +74,15 @@ struct SummaryMapData { struct RIRWMapData { CTSInfo Info; StringArray Hdr; + StringArray AModel; + StringArray BModel; + StringArray Desc; + StringArray Basin; + StringArray InitMask; + StringArray ValidMask; + TimeArray Init; + NumArray Lead; + TimeArray Valid; }; //////////////////////////////////////////////////////////////////////// @@ -317,6 +326,8 @@ class TCStatJob { // Derived output statistics ConcatString StatFile; // File name for output statistics std::ofstream *StatOut; // Output statistics file stream + AsciiTable stat_at; // AsciiTable for buffering output STAT data + int stat_row; // Counter for the current stat row // Polyline masking regions ConcatString OutInitMaskFile; @@ -486,11 +497,14 @@ class TCStatJobRIRW : public TCStatJob { void add_map(std::map&); - void do_output (std::ostream &); - void do_ctc_output(std::ostream &); - void do_cts_output(std::ostream &); - void do_mpr_output(std::ostream &); - + void setup_stat_file(int n_row); + + void do_output (std::ostream &); + void do_ctc_output (std::ostream &); + void do_cts_output (std::ostream &); + void do_mpr_output (std::ostream &); + void do_stat_output(std::ostream &); + // Store the case information StringArray ByColumn;