Merge branch 'master_13.5.2' (13.5.2-2) into omaha_13.5.2
Conflicts: msi/VizLauncher/VizLauncher.suo msi/VizLauncher/VizLauncher/com/raytheon/viz/launcher/process/AbstractProcessLauncher.cs msi/build/A2Staging/VisualStudio/VizLauncher.exe Former-commit-id:b6df6f2aaa
[formerly4a0604f28c
] [formerly866885e3eb
] [formerlyb6df6f2aaa
[formerly4a0604f28c
] [formerly866885e3eb
] [formerly347d1eaef4
[formerly866885e3eb
[formerly c3a0913f289df802c65015686f877ca9c5e42bf5]]]] Former-commit-id:347d1eaef4
Former-commit-id:b800b32b9e
[formerly539b51afc9
] [formerly 3fd03f9ee6b9805b2ebcb1741513edfb88c0e02f [formerly9a6a2561fc
]] Former-commit-id: 787b21002c060468c496b24a83315fa2608c04a8 [formerly29e2e0a01c
] Former-commit-id:db663043c7
This commit is contained in:
commit
d4ac47d817
5 changed files with 1686 additions and 703 deletions
|
@ -47,697 +47,123 @@ import com.raytheon.viz.mpe.util.DailyQcUtils.Station;
|
|||
|
||||
public class RenderPcp {
|
||||
|
||||
private static boolean first = true;
|
||||
|
||||
Pcp pcp = DailyQcUtils.pcp;
|
||||
|
||||
/*
|
||||
* QC codes
|
||||
*/
|
||||
private static final int MISSING = -1;
|
||||
|
||||
private static final int STANDARD = 0;
|
||||
|
||||
private static final int FAILED = 1;
|
||||
|
||||
private static final int MANUAL = 2;
|
||||
|
||||
private static final int QUESTIONABLE = 3;
|
||||
|
||||
private static final int PARTIAL = 4;
|
||||
|
||||
private static final int ESTIMATED = 5;
|
||||
|
||||
private static final int TIMEDISTRIBUTED = 6;
|
||||
|
||||
private static final int VERIFIED = 8;
|
||||
|
||||
/**
|
||||
* Converts point precipitation data in struct pdata to hrap grid. The 20
|
||||
* closest stations are precalculated for each grid point - this speeds
|
||||
* computations for data sets with many precipitation points. If there are
|
||||
* no good precipitation points for a grid point, then a recalculation is
|
||||
* made using all precipitation points. 1/R**2 interpolation is used. If
|
||||
* requested, the final interpolation is scaled using seasonal isohyets. The
|
||||
* grid is saved as a disk file and used later for a raster or vector (HRAP)
|
||||
* plot.
|
||||
*
|
||||
* @param m
|
||||
* @param k
|
||||
* @param mk
|
||||
* @param numPstations
|
||||
* @param precip_stations
|
||||
* @param hrap_grid
|
||||
* @param pdata
|
||||
* @param pcp_in_use
|
||||
*/
|
||||
public void render_pcp(int pcpn_day, int pcpn_time, int pcpn_time_step,
|
||||
int numPstations, ArrayList<Station> precip_stations,
|
||||
Hrap_Grid hrap_grid, Pdata[] pdata, int[] pcp_in_use) {
|
||||
|
||||
int isom = DailyQcUtils.isom;
|
||||
int method = DailyQcUtils.method;
|
||||
int mpe_dqc_max_precip_neighbors = DailyQcUtils.mpe_dqc_max_precip_neighbors;
|
||||
int i, j, h, hh, time_pos, htotal;
|
||||
double distance, dist1, dist2, dist, value;
|
||||
double temp;
|
||||
int totals[] = new int[5];
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
totals[i] = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* pcpn_time_step is a function parameter. It specifies whether to
|
||||
* interpolate 6hr or 24hr HRAP grid
|
||||
*/
|
||||
/*
|
||||
* pcpn_time is a function parameter. It specifies which 6hr HRAP grid
|
||||
* to generate. It takes 0,1,2,or 3 to represent different 6hr period of
|
||||
* a day.
|
||||
*/
|
||||
/*
|
||||
* time_pos is assigned a value of 0,1,2,or 3 (for 6hr data) or 4 (for
|
||||
* 24hr data). This value is used in
|
||||
* pdata[pcpn_day].stn[hh].frain[time_pos].data to control whether to
|
||||
* retrieve 6hr data or 24hr data.
|
||||
*/
|
||||
if (pcpn_time_step == 0) {
|
||||
time_pos = pcpn_time; // for 6 hour data: 0,1,2,3.
|
||||
} else {
|
||||
time_pos = 4; // for 24 hour data
|
||||
|
||||
/*
|
||||
* in case the 24hr grid rendering is required, we check
|
||||
* 24hr_grid_gen_method_token() to determine how to generate the
|
||||
* grid. New Post OB9.2
|
||||
*/
|
||||
|
||||
if (getTokenValue24hrGridGenMeth() == 1) {
|
||||
render24hrPcpUsingFour6hr(pcpn_day, pcpn_time, numPstations,
|
||||
precip_stations, hrap_grid, pdata, pcp_in_use);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* begin to interpolate value for each bin in the HRAP grid */
|
||||
/*
|
||||
* to interpolate, two quantities are needed first: value and distance.
|
||||
* They are calculated by using the neighboring stations.
|
||||
*/
|
||||
for (i = 0; i < hrap_grid.maxi; i++) {
|
||||
for (j = 0; j < hrap_grid.maxj; j++) {
|
||||
/*
|
||||
* Check if the grid cell is covered by an HSA. If not, then do
|
||||
* not estimate precipitation for it.
|
||||
*/
|
||||
if (hrap_grid.owner[i][j] == -1) {
|
||||
pcp.value[i][j] = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
value = 0.0;
|
||||
distance = 0.0;
|
||||
htotal = 0;
|
||||
|
||||
/*
|
||||
* the following for loop is to calculate two quantities: value
|
||||
* and distance, which later on, are used to interpret the HRAP
|
||||
* grid.
|
||||
*/
|
||||
/*
|
||||
* It uses neighbor stations of a HRAP grid bin to calculate
|
||||
* value and distance.
|
||||
*/
|
||||
/* for each neighbor station of the grid bin, do the following */
|
||||
|
||||
/* For each of the closest stations. */
|
||||
for (h = 0; h < mpe_dqc_max_precip_neighbors; h++) {
|
||||
hh = hrap_grid.gage[i][j].index[h];
|
||||
// hh is index of stations
|
||||
if (pdata[pcpn_day].stn[hh].frain[time_pos].data < 0) {
|
||||
/* No precip data. */
|
||||
continue;
|
||||
} // frain refers to level 2 data; rrain refers to level 1
|
||||
|
||||
if (method == 2 && precip_stations.get(hh).isoh[isom] <= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pdata[pcpn_day].stn[hh].frain[time_pos].qual != 0
|
||||
&& pdata[pcpn_day].stn[hh].frain[time_pos].qual != 8
|
||||
&& pdata[pcpn_day].stn[hh].frain[time_pos].qual != 6
|
||||
&& pdata[pcpn_day].stn[hh].frain[time_pos].qual != 3
|
||||
&& pdata[pcpn_day].stn[hh].frain[time_pos].qual != 4
|
||||
&& pdata[pcpn_day].stn[hh].frain[time_pos].qual != 2) {
|
||||
/* The station has a bad qc flag. Do not use it. */
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert the coordinates of the grid and station in
|
||||
* lat/lon into distance.
|
||||
*/
|
||||
dist1 = (i + (hrap_grid.hrap_minx - precip_stations.get(hh).hrap_x));
|
||||
dist2 = (j + (hrap_grid.hrap_miny - precip_stations.get(hh).hrap_y));
|
||||
|
||||
dist = Math.pow(dist1, 2) + Math.pow(dist2, 2);
|
||||
|
||||
if (dist < .00001) {
|
||||
dist = .00001;
|
||||
}
|
||||
|
||||
dist = 1 / dist;
|
||||
|
||||
temp = pdata[pcpn_day].stn[hh].frain[time_pos].data * dist;
|
||||
|
||||
if (method == 2 && precip_stations.get(hh).isoh[isom] > 0) {
|
||||
temp = temp * hrap_grid.isoh[isom][i][j]
|
||||
/ (precip_stations.get(hh).isoh[isom] * 25.4);
|
||||
}
|
||||
|
||||
value = value + temp;
|
||||
|
||||
distance = distance + dist;
|
||||
|
||||
htotal++;
|
||||
|
||||
if (htotal == 10) {
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* end for loop (h = 0; h < mpe_dqc_max_precip_neighbors;h++)
|
||||
* the above for loop is for each neighbor station.
|
||||
*/
|
||||
/*
|
||||
* the above for loop is to calculate value and distance, which
|
||||
* later on, are used to interpret the HRAP grid
|
||||
*/
|
||||
|
||||
/*
|
||||
* the resulting htotal is the valid number of neighbor stations
|
||||
* that are used to calculate value and distance, which later
|
||||
* on, are used to interpret the HRAP grid
|
||||
*/
|
||||
|
||||
/*
|
||||
* if there is not enough valid neighbor station, such as htotal
|
||||
* <4, the code below handle this situation. Basically, the code
|
||||
* recalculate the value and distance using all the stations --
|
||||
* see the for (h = 0; h < max_stations; h++) loop below.
|
||||
*/
|
||||
if (htotal < 4) {
|
||||
|
||||
value = 0.0;
|
||||
distance = 0.0;
|
||||
htotal = 0;
|
||||
|
||||
for (h = 0; h < numPstations; h++) {
|
||||
if (pdata[pcpn_day].stn[h].frain[time_pos].data < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pdata[pcpn_day].stn[h].frain[time_pos].qual != 0
|
||||
&& pdata[pcpn_day].stn[h].frain[time_pos].qual != 8
|
||||
&& pdata[pcpn_day].stn[h].frain[time_pos].qual != 6
|
||||
&& pdata[pcpn_day].stn[h].frain[time_pos].qual != 3
|
||||
&& pdata[pcpn_day].stn[h].frain[time_pos].qual != 4
|
||||
&& pdata[pcpn_day].stn[h].frain[time_pos].qual != 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (method == 2
|
||||
&& precip_stations.get(h).isoh[isom] <= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
dist1 = (i + (hrap_grid.hrap_minx - precip_stations
|
||||
.get(h).hrap_x));
|
||||
dist2 = (j + (hrap_grid.hrap_miny - precip_stations
|
||||
.get(h).hrap_y));
|
||||
|
||||
dist = Math.pow(dist1, 2) + Math.pow(dist2, 2);
|
||||
|
||||
/*
|
||||
* if distance from grid box to station is >
|
||||
* mpe_dqc_grid_max_distbins,
|
||||
*/
|
||||
/* then do not use station */
|
||||
if (dist < .00001) {
|
||||
dist = .00001;
|
||||
}
|
||||
|
||||
else if (Math.sqrt(dist) > DailyQcUtils.mpe_dqc_grid_max_dist) {
|
||||
continue;
|
||||
}
|
||||
dist = 1 / dist;
|
||||
|
||||
temp = pdata[pcpn_day].stn[h].frain[time_pos].data
|
||||
* dist;
|
||||
|
||||
if (method == 2
|
||||
&& precip_stations.get(h).isoh[isom] > 0) {
|
||||
temp = temp
|
||||
* hrap_grid.isoh[isom][i][j]
|
||||
/ (precip_stations.get(h).isoh[isom] * 25.4);
|
||||
}
|
||||
|
||||
value = value + temp;
|
||||
|
||||
distance = distance + dist;
|
||||
|
||||
htotal++;
|
||||
|
||||
}
|
||||
|
||||
}/* end the handling of special case : if (htotal < 4), */
|
||||
/* which means there is no enough neighboring stations */
|
||||
|
||||
if (htotal == 0) {
|
||||
pcp.value[i][j] = 0;
|
||||
} else {
|
||||
pcp.value[i][j] = (int) (value / distance * 100.0);
|
||||
}
|
||||
// if (htotal != 0) {
|
||||
// pcp.value[i][j] += (int) (value / distance * 100);
|
||||
// }
|
||||
if (pcp.value[i][j] < .01) {
|
||||
pcp.value[i][j] = 0;
|
||||
}
|
||||
}
|
||||
} // end of the ( k = 0; k<4; k++) loop, which interpolates 4 6hr HRAP
|
||||
// grid.
|
||||
|
||||
/* final adjustment of the pcp->value */
|
||||
// for (i = 0; i < hrap_grid.maxi; i++) {
|
||||
// hrap_grid comes from the function parameter
|
||||
// for (j = 0; j < hrap_grid.maxj; j++) {
|
||||
//
|
||||
// if (pcp.value[i][j] < .01) {
|
||||
// pcp.value[i][j] = 0;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
if (pcpn_time_step == 0) {
|
||||
time_pos = pcpn_day * 4 + 3 - pcpn_time;
|
||||
} else {
|
||||
time_pos = 40 + pcpn_day;
|
||||
}
|
||||
// notice that time_pos is a variable defined inside the function, and
|
||||
// its value do not need to be limited as 0,1,2,3,or 4. Here it is
|
||||
// assigned with bigger numbers.
|
||||
// time_pos = 40 + pcpn_day;
|
||||
|
||||
// pcp_in_use[i] = 1 -- grids rendered via Render button OR Save Level2
|
||||
// option
|
||||
// = -1 --grids for this time period not rendered (initialization value)
|
||||
pcp_in_use[time_pos] = 1;
|
||||
|
||||
ReadQPFGrids rqp = new ReadQPFGrids();
|
||||
rqp.write_file("pcp", time_pos, pcp);
|
||||
}
|
||||
|
||||
/*
|
||||
* get the token value of token mpe_24hr_grid_gen_method. This token will
|
||||
* determine how we generate the 24hr grid. We can either use the 24hr gage
|
||||
* values, which is the old way, or we can use four 6hr gage values and add
|
||||
* them together.
|
||||
*/
|
||||
/* there is some problem with the static */
|
||||
|
||||
/**
|
||||
* @param pcpn_day
|
||||
* @param pcpn_time
|
||||
* @param numPstations
|
||||
* @param precip_stations
|
||||
* @param hrap_grid
|
||||
* @param pdata
|
||||
* @param pcp_in_use
|
||||
*/
|
||||
private void render24hrPcpUsingFour6hr(int pcpn_day, int pcpn_time,
|
||||
int numPstations, ArrayList<Station> precip_stations,
|
||||
Hrap_Grid hrap_grid, Pdata[] pdata, int[] pcp_in_use) {
|
||||
|
||||
int i, j, k, h, hh, time_pos, htotal;
|
||||
double distance, dist1, dist2, dist, value;
|
||||
double temp;
|
||||
int isom = DailyQcUtils.isom;
|
||||
int method = DailyQcUtils.method;
|
||||
int totals[] = new int[5];
|
||||
int all_total = 0;
|
||||
int neighbor_total = 0;
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
totals[i] = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* pcpn_time_step is function parameter. It specifies whether to
|
||||
* interpolate 6hr or 24hr HRAP grid
|
||||
*/
|
||||
/*
|
||||
* pcpn_time is a function parameter. It specifies which 6hr HRAP grid
|
||||
* to generate. It takes 0,1,2,or 3 to represent different 6hr period of
|
||||
* a day.
|
||||
*/
|
||||
/*
|
||||
* time_pos is assigned a value of 0,1,2,or 3 (for 6hr data) or 4 (for
|
||||
* 24hr data). This value is used in
|
||||
* pdata[pcpn_day].stn[hh].frain[time_pos].data to control whether to
|
||||
* retrieve 6hr data or 24hr data.
|
||||
*/
|
||||
|
||||
/* initialization of the pcp->value */
|
||||
for (i = 0; i < hrap_grid.maxi; i++) { /*
|
||||
* hrap_grid comes from the
|
||||
* function parameter
|
||||
*/
|
||||
for (j = 0; j < hrap_grid.maxj; j++) {
|
||||
pcp.value[i][j] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* begin to interpolate 4 6hr grids. At the end of each iteration, the
|
||||
* calculated interpolation value is added to pcp->value[i][j].
|
||||
*/
|
||||
/*
|
||||
* time_pos is assigned a value of 0,1,2,or 3 (for four 6hr data). This
|
||||
* value is used in pdata[pcpn_day].stn[hh].frain[time_pos].data to
|
||||
* retrieve 6hr data.
|
||||
*/
|
||||
for (k = 0; k < 4; k++) {
|
||||
time_pos = k; /* for 6 hour data: 0, 1,2,3. */
|
||||
|
||||
/* begin to interpolate value for each bin in the HRAP grid */
|
||||
/*
|
||||
* to interpolate, two quantities are needed first: value and
|
||||
* distance. They are calculated by using the neighboring stations.
|
||||
*/
|
||||
|
||||
for (i = 0; i < hrap_grid.maxi; i++) { /*
|
||||
* hrap_grid comes from the
|
||||
* function parameter
|
||||
*/
|
||||
for (j = 0; j < hrap_grid.maxj; j++) {
|
||||
/*
|
||||
* Check if the grid cell is covered by an HSA. If not, then
|
||||
* do not estimate precipitation for it.
|
||||
*/
|
||||
if (hrap_grid.owner[i][j] == -1) {
|
||||
pcp.value[i][j] = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
value = 0.0;
|
||||
distance = 0.0;
|
||||
htotal = 0;
|
||||
|
||||
/*
|
||||
* the following for loop is to calculate two quantities:
|
||||
* value and distance, which later on, are used to interpret
|
||||
* the HRAP grid.
|
||||
*/
|
||||
/*
|
||||
* It uses neighbor stations of a HRAP grid bin to calculate
|
||||
* value and distance.
|
||||
*/
|
||||
/*
|
||||
* for each neighbor station of the grid bin, do the
|
||||
* following
|
||||
*/
|
||||
int mpe_dqc_max_precip_neighbors = DailyQcUtils.mpe_dqc_max_precip_neighbors;
|
||||
|
||||
for (h = 0; h < mpe_dqc_max_precip_neighbors; h++) {
|
||||
hh = hrap_grid.gage[i][j].index[h];/*
|
||||
* hh is index of
|
||||
* stations
|
||||
*/
|
||||
|
||||
if (pdata[pcpn_day].stn[hh].frain[time_pos].data < 0) {
|
||||
/* No precip data. */
|
||||
continue;
|
||||
} /*
|
||||
* frain refers to level 2 data; rain refers to level
|
||||
* 1
|
||||
*/
|
||||
|
||||
/*
|
||||
* generate something for output later on if in debug
|
||||
* mode
|
||||
*/
|
||||
// if (debug_level >= 1) {
|
||||
// if (pdata[pcpn_day].stn[hh].frain[time_pos].qual
|
||||
// == MISSING)
|
||||
// {
|
||||
// missing_total++;
|
||||
// }
|
||||
//
|
||||
// if (pdata[pcpn_day].stn[hh].frain[time_pos].qual
|
||||
// == ESTIMATED)
|
||||
// {
|
||||
// estimated_total++;
|
||||
// }
|
||||
//
|
||||
// if (pdata[pcpn_day].stn[hh].frain[time_pos].qual
|
||||
// == FAILED)
|
||||
// {
|
||||
// failed_total++;
|
||||
// }
|
||||
//
|
||||
// if (method == 2 && station[hh].isoh[isom] <= 0)
|
||||
// {
|
||||
// climo_total++;
|
||||
// }
|
||||
// } /* end if (debug_level >= 1) */
|
||||
|
||||
if (DailyQcUtils.method == 2
|
||||
&& precip_stations.get(hh).isoh[isom] <= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pdata[pcpn_day].stn[hh].frain[time_pos].qual != 0
|
||||
&& pdata[pcpn_day].stn[hh].frain[time_pos].qual != 8
|
||||
&& pdata[pcpn_day].stn[hh].frain[time_pos].qual != 6
|
||||
&& pdata[pcpn_day].stn[hh].frain[time_pos].qual != 3
|
||||
&& pdata[pcpn_day].stn[hh].frain[time_pos].qual != 4
|
||||
&& pdata[pcpn_day].stn[hh].frain[time_pos].qual != 2) {
|
||||
/* The station has a bad qc flag. Do not use it. */
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert the coordinates of the grid and station in
|
||||
* lat/lon into distance.
|
||||
*/
|
||||
dist1 = (i + hrap_grid.hrap_minx - precip_stations
|
||||
.get(hh).hrap_x);
|
||||
dist2 = (j + hrap_grid.hrap_miny - precip_stations
|
||||
.get(hh).hrap_y);
|
||||
|
||||
dist = Math.pow(dist1, 2) + Math.pow(dist2, 2);
|
||||
|
||||
if (dist < .00001) {
|
||||
dist = .00001;
|
||||
}
|
||||
|
||||
dist = 1 / dist;
|
||||
|
||||
temp = pdata[pcpn_day].stn[hh].frain[time_pos].data
|
||||
* dist;
|
||||
|
||||
if (method == 2
|
||||
&& precip_stations.get(hh).isoh[isom] > 0) {
|
||||
temp = temp
|
||||
* hrap_grid.isoh[isom][i][j]
|
||||
/ (precip_stations.get(hh).isoh[isom] * 25.4);
|
||||
}
|
||||
|
||||
value = value + temp;
|
||||
|
||||
distance = distance + dist;
|
||||
|
||||
htotal++;
|
||||
|
||||
if (htotal == 10) {
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* end for loop (h = 0; h <
|
||||
* mpe_dqc_max_precip_neighbors;h++)
|
||||
*/
|
||||
/* the above for loop is for each neighbor station. */
|
||||
/*
|
||||
* the above for loop is to calculate value and distance,
|
||||
* which later on, are used to interpret the HRAP grid
|
||||
*/
|
||||
|
||||
/*
|
||||
* the resulting htotal is the valid number of neighbor
|
||||
* stations that are used to calculate value and distance,
|
||||
* which later on, are used to interpret the HRAP grid
|
||||
*/
|
||||
|
||||
/*
|
||||
* if there is not enough valid neighbor station, such as
|
||||
* htotal <4, the code below handle this situation.
|
||||
* Basically, the code recalculate the value and distance
|
||||
* using all the stations -- see the for (h = 0; h <
|
||||
* max_stations; h++) loop below.
|
||||
*/
|
||||
if (htotal < 4) {
|
||||
|
||||
value = 0.0;
|
||||
distance = 0.0;
|
||||
htotal = 0;
|
||||
|
||||
for (h = 0; h < numPstations; h++) {
|
||||
if (pdata[pcpn_day].stn[h].frain[time_pos].data < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pdata[pcpn_day].stn[h].frain[time_pos].qual != 0
|
||||
&& pdata[pcpn_day].stn[h].frain[time_pos].qual != 8
|
||||
&& pdata[pcpn_day].stn[h].frain[time_pos].qual != 6
|
||||
&& pdata[pcpn_day].stn[h].frain[time_pos].qual != 3
|
||||
&& pdata[pcpn_day].stn[h].frain[time_pos].qual != 4
|
||||
&& pdata[pcpn_day].stn[h].frain[time_pos].qual != 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (method == 2
|
||||
&& precip_stations.get(h).isoh[isom] <= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
dist1 = (i + hrap_grid.hrap_minx - precip_stations
|
||||
.get(h).hrap_x);
|
||||
dist2 = (j + hrap_grid.hrap_miny - precip_stations
|
||||
.get(h).hrap_y);
|
||||
|
||||
dist = Math.pow(dist1, 2) + Math.pow(dist2, 2);
|
||||
|
||||
if (dist < .00001) {
|
||||
dist = .00001;
|
||||
}
|
||||
|
||||
dist = 1 / dist;
|
||||
|
||||
temp = pdata[pcpn_day].stn[h].frain[time_pos].data
|
||||
* dist;
|
||||
|
||||
if (method == 2
|
||||
&& precip_stations.get(h).isoh[isom] > 0) {
|
||||
temp = temp
|
||||
* hrap_grid.isoh[isom][i][j]
|
||||
/ (precip_stations.get(h).isoh[isom] * 25.4);
|
||||
}
|
||||
|
||||
value = value + temp;
|
||||
|
||||
distance = distance + dist;
|
||||
|
||||
htotal++;
|
||||
|
||||
}
|
||||
neighbor_total++;
|
||||
} /* end the handling of special case : if (htotal < 4), */
|
||||
/* which means there is no enough neighboring stations */
|
||||
|
||||
/*
|
||||
* add the interpreted value for the bin of the HRAP_grid
|
||||
*/
|
||||
/*
|
||||
* if (htotal == 0) { pcp->value[i][j] += 0; } else {
|
||||
* pcp->value[i][j] += (int) (value / distance * 100); }
|
||||
*/
|
||||
if (htotal != 0) {
|
||||
pcp.value[i][j] += (int) (value / distance * 100);
|
||||
}
|
||||
|
||||
/*
|
||||
* if (pcp->value[i][j] < .01) { pcp->value[i][j] = 0; }
|
||||
*/
|
||||
all_total++;
|
||||
|
||||
} /* end of for loop (j = 0; j < hrap_grid->maxj; j++) */
|
||||
} /* end of for loop (i = 0; i < hrap_grid->maxi; i++) */
|
||||
/* At this moment, the interpretation of HRAP grid is done */
|
||||
|
||||
}/*
|
||||
* end of the ( k = 0; k<4; k++) loop, which interpolates 4 6hr HRAP
|
||||
* grid.
|
||||
*/
|
||||
|
||||
/* final adjustment of the pcp->value */
|
||||
for (i = 0; i < hrap_grid.maxi; i++) { /*
|
||||
* hrap_grid comes from the
|
||||
* function parameter
|
||||
*/
|
||||
for (j = 0; j < hrap_grid.maxj; j++) {
|
||||
|
||||
if (pcp.value[i][j] < .01) {
|
||||
pcp.value[i][j] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* time_pos = pcpn_day * 4 + 3 - pcpn_time; */
|
||||
time_pos = 40 + pcpn_day;
|
||||
|
||||
/*
|
||||
* pcp_in_use[i] = 1 -- grids rendered via Render button OR Save Level2
|
||||
* option = -1 --grids for this time period not rendered (initialization
|
||||
* value)
|
||||
*/
|
||||
pcp_in_use[time_pos] = 1;
|
||||
|
||||
/*
|
||||
* results of grid rendering routines (render_t, render_t6, render_pcp,
|
||||
* render_z) are written to scratch files using the write_file routine.
|
||||
* scratch file is stored in the scratch directory.
|
||||
*/
|
||||
ReadQPFGrids rqp = new ReadQPFGrids();
|
||||
rqp.write_file("pcp", time_pos, pcp);
|
||||
|
||||
}
|
||||
|
||||
int getTokenValue24hrGridGenMeth() {
|
||||
|
||||
int token_of_24hr_grid_gen_method = 0;
|
||||
|
||||
/* int token_of_24hr_grid_gen_method = 0; */
|
||||
|
||||
if (first == true) {
|
||||
String token_name_of_24hr_grid_gen_method_token = "mpe_dqc_24hr_precip_grid_meth";
|
||||
|
||||
/* char strTokenValue[50] = { '\0' }; */
|
||||
String DQC24hrPrecipMeth;
|
||||
|
||||
// char message[GAGEQC_MESSAGE_LEN] = { '\0' };
|
||||
|
||||
AppsDefaults appsDefaults = AppsDefaults.getInstance();
|
||||
DQC24hrPrecipMeth = appsDefaults
|
||||
.getToken(token_name_of_24hr_grid_gen_method_token);
|
||||
// sprintf(message, "\nSTATUS: token value of \"%s\" : %s\n",
|
||||
// token_name_of_24hr_grid_gen_method_token, strTokenValue);
|
||||
// logMessage(message);
|
||||
|
||||
if (DQC24hrPrecipMeth != null && DQC24hrPrecipMeth.length() > 0) {
|
||||
/* we use the token ACCUM_6HR and USE_24HR */
|
||||
if (DQC24hrPrecipMeth.equalsIgnoreCase("ACCUM_6HR")) {
|
||||
token_of_24hr_grid_gen_method = 1;
|
||||
}
|
||||
}
|
||||
|
||||
first = false;
|
||||
}
|
||||
|
||||
return token_of_24hr_grid_gen_method;
|
||||
}
|
||||
}
|
||||
private static boolean first = true;
|
||||
|
||||
Pcp pcp = DailyQcUtils.pcp;
|
||||
|
||||
/*
|
||||
* QC codes
|
||||
*/
|
||||
private static final int MISSING = -1;
|
||||
|
||||
private static final int STANDARD = 0;
|
||||
|
||||
private static final int SCREENED = 0;
|
||||
|
||||
private static final int FAILED = 1;
|
||||
|
||||
private static final int MANUAL = 2;
|
||||
|
||||
private static final int QUESTIONABLE = 3;
|
||||
|
||||
private static final int PARTIAL = 4;
|
||||
|
||||
private static final int ESTIMATED = 5;
|
||||
|
||||
private static final int TIMEDISTRIBUTED = 6;
|
||||
|
||||
private static final int VERIFIED = 8;
|
||||
|
||||
private static final String MPE_DQC_GRID_RENDERING_METHOD_TOKEN = "mpe_dqc_grid_render_method";
|
||||
|
||||
private static final int maxDistSquared = DailyQcUtils.mpe_dqc_grid_max_dist
|
||||
* DailyQcUtils.mpe_dqc_grid_max_dist;
|
||||
|
||||
/**
|
||||
* Converts point precipitation data in struct pdata to hrap grid. The 20
|
||||
* closest stations are precalculated for each grid point - this speeds
|
||||
* computations for data sets with many precipitation points. If there are
|
||||
* no good precipitation points for a grid point, then a recalculation is
|
||||
* made using all precipitation points. 1/R**2 interpolation is used. If
|
||||
* requested, the final interpolation is scaled using seasonal isohyets. The
|
||||
* grid is saved as a disk file and used later for a raster or vector (HRAP)
|
||||
* plot.
|
||||
*
|
||||
* @param m
|
||||
* @param k
|
||||
* @param mk
|
||||
* @param numPstations
|
||||
* @param
|
||||
* @param hrap_grid
|
||||
* @param pdata
|
||||
* @param pcp_in_use
|
||||
*/
|
||||
// mpe_dqc_grid_render_method
|
||||
|
||||
// ---------------------------------------------------------------------------------------
|
||||
|
||||
public void render_pcp(int pcpn_day, int pcpn_time, int pcpn_time_step,
|
||||
int numPstations, ArrayList<Station> precip_stations,
|
||||
Hrap_Grid hrap_grid, Pdata[] pdata, int[] pcp_in_use) {
|
||||
|
||||
String header = "RenderPcp.render_pcp(): ";
|
||||
|
||||
AppsDefaults appsDefaults = AppsDefaults.getInstance();
|
||||
|
||||
String tokenValue = appsDefaults
|
||||
.getToken(MPE_DQC_GRID_RENDERING_METHOD_TOKEN);
|
||||
|
||||
// System.out.println(header + "tokenValue = " + tokenValue);
|
||||
|
||||
// tokenValue = "BLOCKING";
|
||||
// tokenValue = "DISTANCE_SQUARED";
|
||||
|
||||
System.out.println(header + "now tokenValue = " + tokenValue);
|
||||
|
||||
if (tokenValue != null && tokenValue.equalsIgnoreCase("BLOCKING")) {
|
||||
RenderPcpBlocking renderer = new RenderPcpBlocking();
|
||||
|
||||
renderer.render_pcp(pcpn_day, pcpn_time, pcpn_time_step,
|
||||
numPstations, precip_stations, hrap_grid, pdata, pcp_in_use);
|
||||
}
|
||||
|
||||
else {
|
||||
RenderPcpStandard renderer = new RenderPcpStandard();
|
||||
|
||||
renderer.render_pcp(pcpn_day, pcpn_time, pcpn_time_step,
|
||||
numPstations, precip_stations, hrap_grid, pdata, pcp_in_use);
|
||||
|
||||
}
|
||||
|
||||
determineMaxPrecip(hrap_grid);
|
||||
|
||||
}
|
||||
|
||||
private int determineMaxPrecip(Hrap_Grid hrap_grid) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
String header = "RenderPcp.determineMaxPrecip(): ";
|
||||
|
||||
int value = 0;
|
||||
int maxValue = -1;
|
||||
|
||||
for (int col = 0; col < hrap_grid.maxi; col++) {
|
||||
for (int row = 0; row < hrap_grid.maxj; row++) {
|
||||
value = pcp.value[row][col];
|
||||
|
||||
if (value > maxValue) {
|
||||
maxValue = value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
System.out.println(header + "maxValue = " + maxValue);
|
||||
|
||||
return maxValue;
|
||||
|
||||
} // end determineMaxPrecip()
|
||||
|
||||
// ---------------------------------------------------------------------------------------
|
||||
} // end class RenderPcp
|
|
@ -0,0 +1,957 @@
|
|||
/**
|
||||
* This software was developed and / or modified by Raytheon Company,
|
||||
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
|
||||
*
|
||||
* U.S. EXPORT CONTROLLED TECHNICAL DATA
|
||||
* This software product contains export-restricted data whose
|
||||
* export/transfer/disclosure is restricted by U.S. law. Dissemination
|
||||
* to non-U.S. persons whether in the United States or abroad requires
|
||||
* an export license or other authorization.
|
||||
*
|
||||
* Contractor Name: Raytheon Company
|
||||
* Contractor Address: 6825 Pine Street, Suite 340
|
||||
* Mail Stop B8
|
||||
* Omaha, NE 68106
|
||||
* 402.291.0100
|
||||
*
|
||||
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
||||
* further licensing information.
|
||||
**/
|
||||
package com.raytheon.viz.mpe.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.raytheon.uf.common.ohd.AppsDefaults;
|
||||
import com.raytheon.viz.mpe.util.DailyQcUtils.Hrap_Grid;
|
||||
import com.raytheon.viz.mpe.util.DailyQcUtils.Pcp;
|
||||
import com.raytheon.viz.mpe.util.DailyQcUtils.Pdata;
|
||||
import com.raytheon.viz.mpe.util.DailyQcUtils.Station;
|
||||
|
||||
/**
|
||||
* DESCRIPTION: Maps precipitation station values to an HRAP grid. Produces the
|
||||
* DailyQC version of the GageOnly analysis.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Mar 11, 2009 snaples Initial creation
|
||||
* May 02, 2011 8962 snaples Added render24hrPcpUsingFour6hr() method
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author snaples
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class RenderPcpBlocking {
|
||||
|
||||
private static boolean first = true;
|
||||
|
||||
Pcp pcp = DailyQcUtils.pcp;
|
||||
|
||||
/*
|
||||
* QC codes
|
||||
*/
|
||||
private static final int MISSING = -1;
|
||||
private static final int STANDARD = 0;
|
||||
private static final int SCREENED = 0;
|
||||
private static final int FAILED = 1;
|
||||
private static final int MANUAL = 2;
|
||||
private static final int QUESTIONABLE = 3;
|
||||
private static final int PARTIAL = 4;
|
||||
private static final int ESTIMATED = 5;
|
||||
private static final int TIMEDISTRIBUTED = 6;
|
||||
private static final int VERIFIED = 8;
|
||||
|
||||
// private static final String MPE_DQC_GRID_RENDERING_METHOD_TOKEN =
|
||||
// "mpe_dqc_grid_render_method";
|
||||
|
||||
private static final int maxDistSquared = DailyQcUtils.mpe_dqc_grid_max_dist
|
||||
* DailyQcUtils.mpe_dqc_grid_max_dist;
|
||||
|
||||
// private static final int maxDistSquared = 400;
|
||||
|
||||
/**
|
||||
* Converts point precipitation data in struct pdata to hrap grid. The 20
|
||||
* closest stations are precalculated for each grid point - this speeds
|
||||
* computations for data sets with many precipitation points. If there are
|
||||
* no good precipitation points for a grid point, then a recalculation is
|
||||
* made using all precipitation points. 1/R**2 interpolation is used. If
|
||||
* requested, the final interpolation is scaled using seasonal isohyets. The
|
||||
* grid is saved as a disk file and used later for a raster or vector (HRAP)
|
||||
* plot.
|
||||
*
|
||||
* @param m
|
||||
* @param k
|
||||
* @param mk
|
||||
* @param numPstations
|
||||
* @param
|
||||
* @param hrap_grid
|
||||
* @param pdata
|
||||
* @param pcp_in_use
|
||||
*/
|
||||
// mpe_dqc_grid_render_method
|
||||
|
||||
private boolean usingSingleDirectionCloseOutMode = true;
|
||||
private static final int MIN_PREFERRED_USED_GRID_CELLS = 4;
|
||||
private static final int MIN_REQUIRED_USED_GRID_CELLS = 1;
|
||||
|
||||
private SearchDirection north = new SearchDirection();
|
||||
private SearchDirection south = new SearchDirection();
|
||||
private SearchDirection east = new SearchDirection();
|
||||
private SearchDirection west = new SearchDirection();
|
||||
|
||||
private int colMin;
|
||||
private int colMax;
|
||||
private int rowMin;
|
||||
private int rowMax;
|
||||
private int prevColMin;
|
||||
private int prevColMax;
|
||||
private int prevRowMin;
|
||||
private int prevRowMax;
|
||||
|
||||
// weighting variables
|
||||
private int usedGridCellCount = 0;
|
||||
private double totalWeightedValue = 0;
|
||||
private double totalDistanceWeight = 0;
|
||||
|
||||
// grid variables
|
||||
private int binStationCount[][];
|
||||
|
||||
private int usableStationCount = 0;
|
||||
|
||||
private double valueGrid[][];
|
||||
private double prismStationGrid[][];
|
||||
|
||||
private int isom = -1;
|
||||
|
||||
class SearchDirection {
|
||||
private boolean isOpen;
|
||||
private int level;
|
||||
|
||||
public SearchDirection() {
|
||||
reset();
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
setOpen(true);
|
||||
setLevel(0);
|
||||
}
|
||||
|
||||
public boolean isOpen() {
|
||||
return isOpen;
|
||||
}
|
||||
|
||||
public void setOpen(boolean isOpen) {
|
||||
this.isOpen = isOpen;
|
||||
}
|
||||
|
||||
public void close() {
|
||||
setOpen(false);
|
||||
}
|
||||
|
||||
void expandSearchIfAllowed() {
|
||||
if (isOpen()) {
|
||||
incrementLevel();
|
||||
|
||||
if (getLevel() > DailyQcUtils.mpe_dqc_grid_max_dist) {
|
||||
setLevel(DailyQcUtils.mpe_dqc_grid_max_dist);
|
||||
close();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void incrementLevel() {
|
||||
this.level++;
|
||||
}
|
||||
|
||||
private void setLevel(int level) {
|
||||
this.level = level;
|
||||
}
|
||||
|
||||
public int getLevel() {
|
||||
return level;
|
||||
}
|
||||
|
||||
} // end inner class SearchDirection
|
||||
|
||||
// ---------------------------------------------------------------------------------------
|
||||
|
||||
// ---------------------------------------------------------------------------------------
|
||||
int getTokenValue24hrGridGenMeth() {
|
||||
|
||||
int token_of_24hr_grid_gen_method = 0;
|
||||
|
||||
if (first == true) {
|
||||
String tokenName = "mpe_dqc_24hr_precip_grid_meth";
|
||||
|
||||
String dqc24hrPrecipMeth;
|
||||
|
||||
// char message[GAGEQC_MESSAGE_LEN] = { '\0' };
|
||||
|
||||
AppsDefaults appsDefaults = AppsDefaults.getInstance();
|
||||
dqc24hrPrecipMeth = appsDefaults.getToken(tokenName);
|
||||
|
||||
if (dqc24hrPrecipMeth != null) {
|
||||
/* allowed token values: (ACCUM_6HR, USE_24HR) */
|
||||
if (dqc24hrPrecipMeth.equalsIgnoreCase("ACCUM_6HR")) {
|
||||
token_of_24hr_grid_gen_method = 1;
|
||||
}
|
||||
}
|
||||
first = false;
|
||||
}
|
||||
|
||||
return token_of_24hr_grid_gen_method;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
public void render_pcp(int pcpn_day, int pcpn_time, int pcpn_time_step,
|
||||
int numPstations, ArrayList<Station> stationList,
|
||||
Hrap_Grid hrap_grid, Pdata[] pdata, int[] pcp_in_use) {
|
||||
|
||||
isom = DailyQcUtils.isom;
|
||||
|
||||
int time_pos;
|
||||
|
||||
if (pcpn_time_step == 0) {
|
||||
time_pos = pcpn_time; // for 6 hour data: 0,1,2,3.
|
||||
|
||||
boolean save_grids = true;
|
||||
boolean accumulate_grids = false;
|
||||
|
||||
render_pcp_internal(pcpn_day, pcpn_time, pcpn_time_step,
|
||||
numPstations, stationList, hrap_grid, pdata, pcp_in_use,
|
||||
save_grids, accumulate_grids);
|
||||
} else {
|
||||
time_pos = 4; // for 24 hour data
|
||||
|
||||
/*
|
||||
* in case the 24hr grid rendering is required, we check
|
||||
* 24hr_grid_gen_method_token() to determine how to generate the
|
||||
* grid. New Post OB9.2
|
||||
*/
|
||||
|
||||
// debug
|
||||
// first = true;
|
||||
|
||||
if (getTokenValue24hrGridGenMeth() == 1) {
|
||||
render24hrPcpUsingFour6hr(pcpn_day, pcpn_time, numPstations,
|
||||
stationList, hrap_grid, pdata, pcp_in_use);
|
||||
return;
|
||||
} else // calculate 24-hour grids the regular way
|
||||
{
|
||||
|
||||
boolean save_grids = true;
|
||||
boolean accumulate_grids = false;
|
||||
|
||||
render_pcp_internal(pcpn_day, pcpn_time, pcpn_time_step,
|
||||
numPstations, stationList, hrap_grid, pdata,
|
||||
pcp_in_use, save_grids, accumulate_grids);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void render_pcp_internal(int pcpn_day, int pcpn_time,
|
||||
int pcpn_time_step, int numPstations,
|
||||
ArrayList<Station> stationList, Hrap_Grid hrap_grid, Pdata[] pdata,
|
||||
int[] pcp_in_use, boolean save_grids, boolean should_accumulate) {
|
||||
// String header = "RenderPcpBlocking.render_pcp_internal(): ";
|
||||
|
||||
int isom = DailyQcUtils.isom;
|
||||
|
||||
double resultingPrecipValue = 0.0;
|
||||
|
||||
/*-----------------------------------------------------*/
|
||||
|
||||
allocateGrids(hrap_grid);
|
||||
|
||||
initializeGrids(hrap_grid, should_accumulate);
|
||||
|
||||
placeStationsInGrid(pcpn_day, pcpn_time, pcpn_time_step, numPstations,
|
||||
stationList, hrap_grid, pdata);
|
||||
|
||||
// for every grid location, determine its estimated value
|
||||
for (int col = 0; col < hrap_grid.maxi; col++) {
|
||||
for (int row = 0; row < hrap_grid.maxj; row++) {
|
||||
|
||||
/*
|
||||
* Check if the grid cell is covered by an HSA. If not, then do
|
||||
* not estimate precipitation for it.
|
||||
*/
|
||||
if (hrap_grid.owner[col][row] == -1) {
|
||||
pcp.value[row][col] = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (binStationCount[col][row] > 0) // if any station is in this
|
||||
// grid bin
|
||||
{
|
||||
resultingPrecipValue = valueGrid[col][row];
|
||||
|
||||
// adjust grid bin with actual gage by the prism factor
|
||||
if (prismStationGrid[col][row] > 0) {
|
||||
double prismStationValue = prismStationGrid[col][row] * 25.4;
|
||||
double prismGridValue = hrap_grid.isoh[isom][col][row];
|
||||
|
||||
double prismFactor = (double) prismGridValue
|
||||
/ prismStationValue;
|
||||
|
||||
resultingPrecipValue *= prismFactor;
|
||||
} else {
|
||||
resultingPrecipValue = 0.0;
|
||||
}
|
||||
|
||||
// pcp.value[row][col] is the value of grid,
|
||||
// so we don't need to estimate a value for [row][col]
|
||||
}
|
||||
|
||||
else // this grid location requires an estimate to be generated
|
||||
{
|
||||
resultingPrecipValue = estimateValue(isom, col, row,
|
||||
hrap_grid);
|
||||
}
|
||||
|
||||
if (resultingPrecipValue >= 0.0) {
|
||||
int precipInHundredthsOfMm = (int) Math
|
||||
.floor((resultingPrecipValue * 100.0));
|
||||
|
||||
if (should_accumulate) { // for case where we want to make
|
||||
// 24 = 4 6hr periods added
|
||||
// together
|
||||
pcp.value[col][row] += precipInHundredthsOfMm;
|
||||
} else {
|
||||
pcp.value[col][row] = precipInHundredthsOfMm;
|
||||
}
|
||||
}
|
||||
|
||||
} /* end for (col = 0 ... */
|
||||
|
||||
} /* end for (row = 0 ... */
|
||||
|
||||
// System.out.println(header + "maxPrecip in hundredths of mm = " +
|
||||
// maxPrecip);
|
||||
|
||||
int time_pos;
|
||||
/*
|
||||
* notice that time_pos is a variable defined inside the function, and
|
||||
* its value do not need to be limited as 0,1,2,3,or 4. Here it is
|
||||
* assigned with bigger numbers.
|
||||
*/
|
||||
if (pcpn_time_step == 0) // one of the 6-hr periods
|
||||
{
|
||||
time_pos = pcpn_day * 4 + 3 - pcpn_time;
|
||||
} else // 24 hr
|
||||
{
|
||||
time_pos = 40 + pcpn_day;
|
||||
}
|
||||
|
||||
if (save_grids) {
|
||||
/*
|
||||
* pcp_in_use[i] = 1 -- grids rendered via Render button OR Save
|
||||
* Level2 option = -1 --grids for this time period not rendered
|
||||
* (initialization value)
|
||||
*/
|
||||
pcp_in_use[time_pos] = 1;
|
||||
|
||||
/*
|
||||
* results of grid rendering routines (render_t, render_t6,
|
||||
* render_pcp, render_z) are written to scratch files using the
|
||||
* write_file routine. scratch file is stored in the scratch
|
||||
* directory.
|
||||
*/
|
||||
|
||||
ReadQPFGrids rqp = new ReadQPFGrids();
|
||||
rqp.write_file("pcp", time_pos, pcp);
|
||||
}
|
||||
|
||||
} // end render_pcp_internal()
|
||||
|
||||
private double estimateValue(int isom, int col, int row, Hrap_Grid hrap_grid) {
|
||||
|
||||
// String header = "RenderPcpBlocking.estimateValue(): ";
|
||||
int r;
|
||||
int c;
|
||||
|
||||
double estimatedPrecipValue = 0.0;
|
||||
|
||||
if (hrap_grid.isoh[isom][col][row] < 0.01) {
|
||||
estimatedPrecipValue = 0;
|
||||
return estimatedPrecipValue; // can't do anything more, quit
|
||||
}
|
||||
|
||||
// look through surrounding grid bins only for
|
||||
// values to be used in the distance-weighted interpolation
|
||||
|
||||
// set to open and level = 0
|
||||
north.reset();
|
||||
south.reset();
|
||||
east.reset();
|
||||
west.reset();
|
||||
|
||||
// initialize
|
||||
totalWeightedValue = 0.0;
|
||||
totalDistanceWeight = 0.0;
|
||||
usedGridCellCount = 0;
|
||||
|
||||
rowMax = row;
|
||||
rowMin = row;
|
||||
colMax = col;
|
||||
colMin = col;
|
||||
|
||||
prevRowMax = rowMax;
|
||||
prevRowMin = rowMin;
|
||||
prevColMax = colMax;
|
||||
prevColMin = colMin;
|
||||
|
||||
while (north.isOpen() || south.isOpen() || east.isOpen()
|
||||
|| west.isOpen()) {
|
||||
// expand search levels as appropriate
|
||||
// changes rowMin, rowMax, colMin, colMax
|
||||
expandGridSearch(col, row, hrap_grid);
|
||||
|
||||
if (rowMin < prevRowMin) // grew the top side
|
||||
{
|
||||
r = rowMin;
|
||||
for (c = colMin; c <= colMax; c++) {
|
||||
processGriddedStationValues(col, row, c, r, hrap_grid);
|
||||
}
|
||||
} else // didn't grow the top side
|
||||
{
|
||||
if (colMin < prevColMin) // still need to check top left corner
|
||||
{
|
||||
c = colMin;
|
||||
r = rowMin;
|
||||
processGriddedStationValues(col, row, c, r, hrap_grid);
|
||||
}
|
||||
|
||||
if (colMax > prevColMax) // still need to check top right corner
|
||||
{
|
||||
c = colMax;
|
||||
r = rowMin;
|
||||
processGriddedStationValues(col, row, c, r, hrap_grid);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (rowMax > prevRowMax) // grew the bottom side
|
||||
{
|
||||
r = rowMax;
|
||||
for (c = colMin; c <= colMax; c++) {
|
||||
processGriddedStationValues(col, row, c, r, hrap_grid);
|
||||
}
|
||||
} else // didn't grow the bottom side
|
||||
{
|
||||
if (colMin < prevColMin) // still need to check bottom left
|
||||
// corner
|
||||
{
|
||||
c = colMin;
|
||||
r = rowMax;
|
||||
processGriddedStationValues(col, row, c, r, hrap_grid);
|
||||
}
|
||||
if (colMax > prevColMax) // still need to check bottom right
|
||||
// corner
|
||||
{
|
||||
c = colMax;
|
||||
r = rowMax;
|
||||
processGriddedStationValues(col, row, c, r, hrap_grid);
|
||||
}
|
||||
}
|
||||
|
||||
if (colMin < prevColMin) // grew left side
|
||||
{
|
||||
c = colMin;
|
||||
for (r = rowMin + 1; r < rowMax; r++) {
|
||||
processGriddedStationValues(col, row, c, r, hrap_grid);
|
||||
}
|
||||
}
|
||||
|
||||
if (colMax > prevColMax) // grew right side
|
||||
{
|
||||
c = colMax;
|
||||
for (r = rowMin + 1; r < rowMax; r++) {
|
||||
processGriddedStationValues(col, row, c, r, hrap_grid);
|
||||
}
|
||||
}
|
||||
|
||||
if (usedGridCellCount >= MIN_PREFERRED_USED_GRID_CELLS) // have
|
||||
// enough
|
||||
// cells to
|
||||
// look at,
|
||||
// can quit
|
||||
// now
|
||||
{
|
||||
north.close();
|
||||
south.close();
|
||||
east.close();
|
||||
west.close();
|
||||
|
||||
// System.out.println(header +
|
||||
// "met minimum cell preference, resultingPrecipValue = " +
|
||||
// resultingPrecipValue);
|
||||
}
|
||||
|
||||
} /* end while (northLevelOpen ... */
|
||||
|
||||
// set weighted value to the cell or set value to 0.0 if there is not
|
||||
// enough data
|
||||
if (usedGridCellCount >= MIN_REQUIRED_USED_GRID_CELLS) {
|
||||
estimatedPrecipValue = totalWeightedValue / totalDistanceWeight;
|
||||
|
||||
// System.out.println(header +
|
||||
// "met minimum cell requirement, resultingPrecipValue = " +
|
||||
// resultingPrecipValue);
|
||||
} else // set to zero precip
|
||||
{
|
||||
estimatedPrecipValue = 0.0;
|
||||
}
|
||||
|
||||
return estimatedPrecipValue;
|
||||
|
||||
} // end estimateValue()
|
||||
|
||||
// *--------------------------------------------------------------------------
|
||||
|
||||
void processGriddedStationValues(int renderingCol, int renderingRow,
|
||||
int gridCol, int gridRow, Hrap_Grid hrap_grid) {
|
||||
|
||||
String header = "RenderPcpBlocking.processGriddedStationValues(): ";
|
||||
|
||||
int usedCells = 0;
|
||||
// sprintf(message,
|
||||
// "renderingCol = %d, renderingRow = %d, gridCol = %d, gridRow = %d \n",
|
||||
// renderingCol, renderingRow, gridCol, gridRow);
|
||||
|
||||
// logMessage(message);
|
||||
|
||||
if ((gridCol < 0) || (gridCol > hrap_grid.maxi) || (gridRow < 0)
|
||||
|| (gridRow > hrap_grid.maxj)) {
|
||||
System.out.println(header + "OUT OF RANGE gridCol = " + gridCol
|
||||
+ " gridRow = " + gridRow);
|
||||
}
|
||||
|
||||
double gageValue = valueGrid[gridCol][gridRow];
|
||||
|
||||
if (gageValue >= 0.0) // there is a gage
|
||||
// located at (gridCol,gridRow)
|
||||
// with a valid precip value
|
||||
{
|
||||
|
||||
usedCells = adjustWeights(gageValue, gridRow, gridCol,
|
||||
renderingRow, renderingCol, hrap_grid, isom,
|
||||
prismStationGrid);
|
||||
|
||||
usedGridCellCount += usedCells;
|
||||
// if data was found, close off a direction, usually 2 directions,
|
||||
// such as north and west
|
||||
|
||||
if (usedCells > 0) {
|
||||
determineDirectionFoundAndCloseOff(renderingCol, renderingRow,
|
||||
gridCol, gridRow);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
} // end processGriddedStationValues()
|
||||
|
||||
// *--------------------------------------------------------------------------
|
||||
|
||||
void expandGridSearch(int col, int row, Hrap_Grid hrap_grid) {
|
||||
// expand search levels as appropriate
|
||||
|
||||
north.expandSearchIfAllowed();
|
||||
south.expandSearchIfAllowed();
|
||||
east.expandSearchIfAllowed();
|
||||
west.expandSearchIfAllowed();
|
||||
|
||||
// save previous values of row and col min and max
|
||||
prevRowMax = rowMax;
|
||||
prevRowMin = rowMin;
|
||||
prevColMax = colMax;
|
||||
prevColMin = colMin;
|
||||
|
||||
// determine nested for loop ranges
|
||||
rowMax = row + north.getLevel();
|
||||
if (rowMax >= hrap_grid.maxj) {
|
||||
rowMax = hrap_grid.maxj - 1;
|
||||
north.close();
|
||||
}
|
||||
|
||||
rowMin = row - south.getLevel(); // row
|
||||
if (rowMin < 0) {
|
||||
rowMin = 0;
|
||||
south.close();
|
||||
}
|
||||
|
||||
colMin = col - west.getLevel();
|
||||
if (colMin < 0) {
|
||||
colMin = 0;
|
||||
west.close();
|
||||
}
|
||||
|
||||
colMax = col + east.getLevel();
|
||||
if (colMax >= hrap_grid.maxi) {
|
||||
colMax = hrap_grid.maxi - 1;
|
||||
east.close();
|
||||
}
|
||||
|
||||
return;
|
||||
} // end expandGridSearch()
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
void determineDirectionFoundAndCloseOffSimpleVersion(int renderingCol,
|
||||
int renderingRow, int stationCol, int stationRow) {
|
||||
if (stationRow < renderingRow) {
|
||||
south.close();
|
||||
} else if (stationRow > renderingRow) {
|
||||
north.close();
|
||||
}
|
||||
|
||||
if (stationCol < renderingCol) {
|
||||
west.close();
|
||||
} else if (stationCol > renderingCol) {
|
||||
east.close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
void determineDirectionFoundAndCloseOff(int renderingCol, int renderingRow,
|
||||
int stationCol, int stationRow) {
|
||||
|
||||
final int closeEnoughToBeEqual = 2;
|
||||
|
||||
// String header =
|
||||
// "RenderPcpBlocking.determineDirectionFoundAndCloseOff(): ";
|
||||
|
||||
// consider taking a diff and a point is considered in a straightline if
|
||||
// its difference is < 3 from the grid bin to render
|
||||
|
||||
int northSouthDifference = Math.abs(stationRow - renderingRow);
|
||||
int eastWestDifference = Math.abs(stationCol - renderingCol);
|
||||
|
||||
boolean isNorthOrSouth = false;
|
||||
boolean isEastOrWest = false;
|
||||
|
||||
if (northSouthDifference - eastWestDifference <= closeEnoughToBeEqual) {
|
||||
isNorthOrSouth = true;
|
||||
isEastOrWest = true;
|
||||
} else if (northSouthDifference > eastWestDifference) {
|
||||
isNorthOrSouth = true;
|
||||
} else {
|
||||
isEastOrWest = true;
|
||||
}
|
||||
|
||||
if (usingSingleDirectionCloseOutMode) {
|
||||
// System.out.println(header +
|
||||
// "Using usingSingleDirectionCloseOutMode difference-based close off.");
|
||||
|
||||
if (isNorthOrSouth) {
|
||||
// this point functions as the north-south representative, since
|
||||
// it is primarily north or south
|
||||
|
||||
if (stationRow < renderingRow) {
|
||||
south.close();
|
||||
} else if (stationRow > renderingRow) {
|
||||
north.close();
|
||||
}
|
||||
}
|
||||
|
||||
if (isEastOrWest) {
|
||||
if (stationCol < renderingCol) {
|
||||
west.close();
|
||||
} else if (stationCol > renderingCol) {
|
||||
east.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else // in mode in which points represent 2 directions (unless directly
|
||||
// North-south or east-west)
|
||||
{
|
||||
// System.out.println(header +
|
||||
// "Using traditional difference cutoff.");
|
||||
if (stationRow < renderingRow) {
|
||||
south.close();
|
||||
} else if (stationRow > renderingRow) {
|
||||
north.close();
|
||||
}
|
||||
|
||||
if (stationCol < renderingCol) {
|
||||
west.close();
|
||||
} else if (stationCol > renderingCol) {
|
||||
east.close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
} // determineDirectionFoundAndCloseOff()
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
void allocateGrids(Hrap_Grid hrap_grid) {
|
||||
|
||||
int maxI = hrap_grid.maxi;
|
||||
int maxJ = hrap_grid.maxj;
|
||||
|
||||
binStationCount = new int[maxI][maxJ];
|
||||
|
||||
valueGrid = new double[maxI][maxJ];
|
||||
|
||||
prismStationGrid = new double[maxI][maxJ];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
void initializeGrids(Hrap_Grid hrap_grid, boolean should_accumulate) {
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
|
||||
/* initialize grids */
|
||||
for (i = 0; i < hrap_grid.maxi; i++) {
|
||||
for (j = 0; j < hrap_grid.maxj; j++) {
|
||||
binStationCount[i][j] = 0;
|
||||
valueGrid[i][j] = DailyQcUtils.MOSAIC_DEFAULT; // precip in
|
||||
// inches
|
||||
prismStationGrid[i][j] = DailyQcUtils.MOSAIC_DEFAULT; // prism
|
||||
// station
|
||||
// value
|
||||
// mapped
|
||||
// to
|
||||
// grid
|
||||
// (this
|
||||
// algorithm
|
||||
// only)
|
||||
|
||||
if (!should_accumulate) {
|
||||
// in special 24hr = sum of 4 6hr periods mode,
|
||||
// we accumulate in this grid, so we don't reinit every time
|
||||
|
||||
pcp.value[i][j] = (int) DailyQcUtils.MOSAIC_DEFAULT; // final
|
||||
// precip
|
||||
// in
|
||||
// hundredths
|
||||
// of
|
||||
// mm
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
void placeStationsInGrid(int pcpn_day, int pcpn_time, int pcpn_time_step,
|
||||
int max_stations, ArrayList<Station> stationList,
|
||||
Hrap_Grid hrap_grid, Pdata pdata[]) {
|
||||
|
||||
int method = DailyQcUtils.method;
|
||||
String header = "RenderPcpBlocking.placeStationsInGrid(): ";
|
||||
|
||||
int time_pos;
|
||||
|
||||
if (pcpn_time_step == 0) {
|
||||
time_pos = pcpn_time; // for 6 hour data: 0,1,2,3.
|
||||
} else {
|
||||
time_pos = 4; // for 24 hour data
|
||||
}
|
||||
|
||||
int hx, hy;
|
||||
int h = 0;
|
||||
|
||||
int noPrismCount = 0;
|
||||
|
||||
// System.out.println("max_stations = " + max_stations);
|
||||
|
||||
int maxPrecip = 0;
|
||||
|
||||
for (h = 0; h < max_stations; h++) {
|
||||
Station station = stationList.get(h);
|
||||
|
||||
hx = (int) (station.hrap_x - hrap_grid.hrap_minx);
|
||||
hy = (int) (station.hrap_y - hrap_grid.hrap_miny);
|
||||
|
||||
/* check that station is within the site's area */
|
||||
if (hx >= hrap_grid.maxi || hy >= hrap_grid.maxj || (hx < 0)
|
||||
|| (hy < 0)) {
|
||||
// This station cannot be used, because its coordinates are out
|
||||
// of range
|
||||
continue;
|
||||
}
|
||||
|
||||
// debug only
|
||||
|
||||
int stationCount = binStationCount[hx][hy];
|
||||
|
||||
double precipValue = pdata[pcpn_day].stn[h].frain[time_pos].data;
|
||||
|
||||
short qualCode = pdata[pcpn_day].stn[h].frain[time_pos].qual;
|
||||
|
||||
// skip if not an acceptable quality code
|
||||
if (qualCode != SCREENED && qualCode != VERIFIED
|
||||
&& qualCode != TIMEDISTRIBUTED && qualCode != QUESTIONABLE
|
||||
&& qualCode != PARTIAL && qualCode != MANUAL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((method == 2) && (station.isoh[isom] <= 0)) // no prism data for
|
||||
// the station
|
||||
{
|
||||
noPrismCount++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* if station value is missing, ignore */
|
||||
if (precipValue >= 0.0) {
|
||||
|
||||
int precipIn_h_mm = (int) Math.floor(precipValue * 100.0);
|
||||
|
||||
if (precipIn_h_mm > maxPrecip) {
|
||||
maxPrecip = precipIn_h_mm;
|
||||
}
|
||||
|
||||
// we have data and no other station has been assigned to this
|
||||
// bin yet
|
||||
if (binStationCount[hx][hy] == 0) {
|
||||
binStationCount[hx][hy] = 1;
|
||||
valueGrid[hx][hy] = precipValue;
|
||||
prismStationGrid[hx][hy] = station.isoh[isom];
|
||||
|
||||
usableStationCount++;
|
||||
}
|
||||
|
||||
else if (stationCount > 0) // we have at least 1 value for this
|
||||
// grid location
|
||||
{
|
||||
|
||||
double valueGridTotalValue = (valueGrid[hx][hy] * stationCount)
|
||||
+ precipValue;
|
||||
double prismGridTotalValue = (prismStationGrid[hx][hy] * stationCount)
|
||||
+ station.isoh[isom];
|
||||
binStationCount[hx][hy]++;
|
||||
stationCount++;
|
||||
|
||||
double newGridAvgValue = valueGridTotalValue / stationCount;
|
||||
double newPrismAvgValue = prismGridTotalValue
|
||||
/ stationCount;
|
||||
|
||||
valueGrid[hx][hy] = newGridAvgValue;
|
||||
prismStationGrid[hx][hy] = newPrismAvgValue;
|
||||
|
||||
usableStationCount++;
|
||||
|
||||
} // end else
|
||||
} // end if
|
||||
|
||||
} // end for (h = 0; h < max_stations; h++)
|
||||
|
||||
System.out.println(header + " maxPrecip in hundredths of mm = "
|
||||
+ maxPrecip);
|
||||
|
||||
// System.out.println(header +
|
||||
// " number of stations missing PRISM data = " + noPrismCount);
|
||||
// System.out.println(header + " usableStationCount = " +
|
||||
// usableStationCount);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------
|
||||
/*
|
||||
* get the token value of token mpe_24hr_grid_gen_method. This token will
|
||||
* determine how we generate the 24hr grid. We can either use the 24hr gage
|
||||
* values, which is the old way, or we can use four 6hr gage values and add
|
||||
* them together.
|
||||
*/
|
||||
/* there is some problem with the static */
|
||||
|
||||
private void render24hrPcpUsingFour6hr(int pcpn_day, int pcpn_time,
|
||||
int numPstations, ArrayList<Station> stationList,
|
||||
Hrap_Grid hrap_grid, Pdata[] pdata, int[] pcp_in_use) {
|
||||
|
||||
/* initialization of the pcp.value */
|
||||
for (int i = 0; i < hrap_grid.maxi; i++) {
|
||||
for (int j = 0; j < hrap_grid.maxj; j++) {
|
||||
pcp.value[i][j] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
boolean save_grids = false;
|
||||
boolean should_accumulate = true;
|
||||
|
||||
for (int k = 0; k < 4; k++) {
|
||||
int pcpn_time_internal = k;
|
||||
|
||||
int pcpn_time_step = 0; // means it is one of the 6-hr periods
|
||||
|
||||
render_pcp_internal(pcpn_day, pcpn_time_internal, pcpn_time_step,
|
||||
numPstations, stationList, hrap_grid, pdata, pcp_in_use,
|
||||
save_grids, should_accumulate);
|
||||
|
||||
}
|
||||
|
||||
} // end render24hrPcpUsingFour6hr()
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
int adjustWeights(double originalValue, int otherRow, int otherColumn,
|
||||
int renderingRow, int renderingColumn, Hrap_Grid hrap_grid,
|
||||
int monthIndex, double[][] prismStationGrid) {
|
||||
|
||||
String header = "RenderPcpBlocking.adjustWeights(): ";
|
||||
|
||||
final double MIN_DISTANCE = 0.00001;
|
||||
int usedCount = 0;
|
||||
|
||||
double distanceWeight = 0.0;
|
||||
double weightedValue = 0.0;
|
||||
|
||||
int rowDiff = otherRow - renderingRow;
|
||||
int colDiff = otherColumn - renderingColumn;
|
||||
double distanceSquared = (rowDiff * rowDiff) + (colDiff * colDiff);
|
||||
|
||||
// int maxDistSquared = DailyQcUtils.mpe_dqc_grid_max_dist *
|
||||
// DailyQcUtils.mpe_dqc_grid_max_dist;
|
||||
|
||||
if (distanceSquared < MIN_DISTANCE) {
|
||||
distanceSquared = MIN_DISTANCE;
|
||||
}
|
||||
|
||||
/*
|
||||
* mpe_dqc_grid_max_dist = max distance of influence of a gage in units
|
||||
* of grid bins
|
||||
*/
|
||||
|
||||
if (distanceSquared <= maxDistSquared) {
|
||||
distanceWeight = 1.0 / distanceSquared;
|
||||
weightedValue = originalValue * distanceWeight;
|
||||
|
||||
// adjust by PRISM factor
|
||||
if (prismStationGrid[renderingColumn][renderingRow] > 0) {
|
||||
double prismFactor = (double) hrap_grid.isoh[monthIndex][renderingColumn][renderingRow]
|
||||
/ (prismStationGrid[renderingColumn][renderingRow] * 25.4);
|
||||
weightedValue *= prismFactor;
|
||||
|
||||
System.out.println(header + " prismFactor > 0 " + prismFactor);
|
||||
|
||||
}
|
||||
|
||||
totalWeightedValue += weightedValue;
|
||||
totalDistanceWeight += distanceWeight;
|
||||
|
||||
usedCount++;
|
||||
}
|
||||
|
||||
return usedCount;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------
|
||||
|
||||
}
|
|
@ -0,0 +1,603 @@
|
|||
/**
|
||||
* This software was developed and / or modified by Raytheon Company,
|
||||
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
|
||||
*
|
||||
* U.S. EXPORT CONTROLLED TECHNICAL DATA
|
||||
* This software product contains export-restricted data whose
|
||||
* export/transfer/disclosure is restricted by U.S. law. Dissemination
|
||||
* to non-U.S. persons whether in the United States or abroad requires
|
||||
* an export license or other authorization.
|
||||
*
|
||||
* Contractor Name: Raytheon Company
|
||||
* Contractor Address: 6825 Pine Street, Suite 340
|
||||
* Mail Stop B8
|
||||
* Omaha, NE 68106
|
||||
* 402.291.0100
|
||||
*
|
||||
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
||||
* further licensing information.
|
||||
**/
|
||||
package com.raytheon.viz.mpe.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.raytheon.uf.common.ohd.AppsDefaults;
|
||||
import com.raytheon.viz.mpe.util.DailyQcUtils.Hrap_Grid;
|
||||
import com.raytheon.viz.mpe.util.DailyQcUtils.Pcp;
|
||||
import com.raytheon.viz.mpe.util.DailyQcUtils.Pdata;
|
||||
import com.raytheon.viz.mpe.util.DailyQcUtils.Station;
|
||||
|
||||
/**
|
||||
* DESCRIPTION: Maps precipitation station values to an HRAP grid. Produces the
|
||||
* DailyQC version of the GageOnly analysis.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Mar 11, 2009 snaples Initial creation
|
||||
* May 02, 2011 8962 snaples Added render24hrPcpUsingFour6hr() method
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author snaples
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class RenderPcpStandard {
|
||||
|
||||
private static final int MINIMUM_NEAREST_NEIGHBOR_GAGES = 4;
|
||||
|
||||
private static final int SUFFICIENT_NEAREST_NEIGHBOR_GAGES = 10;
|
||||
|
||||
private static boolean first = true;
|
||||
|
||||
Pcp pcp = DailyQcUtils.pcp;
|
||||
|
||||
/*
|
||||
* QC codes
|
||||
*/
|
||||
private static final int MISSING = -1;
|
||||
|
||||
private static final int STANDARD = 0;
|
||||
|
||||
private static final int SCREENED = 0;
|
||||
|
||||
private static final int FAILED = 1;
|
||||
|
||||
private static final int MANUAL = 2;
|
||||
|
||||
private static final int QUESTIONABLE = 3;
|
||||
|
||||
private static final int PARTIAL = 4;
|
||||
|
||||
private static final int ESTIMATED = 5;
|
||||
|
||||
private static final int TIMEDISTRIBUTED = 6;
|
||||
|
||||
private static final int VERIFIED = 8;
|
||||
|
||||
private static final String MPE_DQC_GRID_RENDERING_METHOD_TOKEN = "mpe_dqc_grid_render_method";
|
||||
|
||||
private static final int maxDistSquared = DailyQcUtils.mpe_dqc_grid_max_dist
|
||||
* DailyQcUtils.mpe_dqc_grid_max_dist;
|
||||
|
||||
private static final double BOGUS_ESTIMATED_GRID_VALUE = -1.0;
|
||||
|
||||
// weighting variables
|
||||
|
||||
// consider making these members of a local variable of an inner class
|
||||
private double totalWeightedValue = 0;
|
||||
private double totalDistanceWeight = 0;
|
||||
|
||||
/**
|
||||
* Converts point precipitation data in struct pdata to hrap grid. The 20
|
||||
* closest stations are precalculated for each grid point - this speeds
|
||||
* computations for data sets with many precipitation points. If there are
|
||||
* no good precipitation points for a grid point, then a recalculation is
|
||||
* made using all precipitation points. 1/R**2 interpolation is used. If
|
||||
* requested, the final interpolation is scaled using seasonal isohyets. The
|
||||
* grid is saved as a disk file and used later for a raster or vector (HRAP)
|
||||
* plot.
|
||||
*
|
||||
* @param m
|
||||
* @param k
|
||||
* @param mk
|
||||
* @param numPstations
|
||||
* @param
|
||||
* @param hrap_grid
|
||||
* @param pdata
|
||||
* @param pcp_in_use
|
||||
*/
|
||||
|
||||
// ---------------------------------------------------------------------------------------
|
||||
|
||||
public void render_pcp(int pcpn_day, int pcpn_time, int pcpn_time_step,
|
||||
int numPstations, ArrayList<Station> precip_stations,
|
||||
Hrap_Grid hrap_grid, Pdata[] pdata, int[] pcp_in_use) {
|
||||
|
||||
// String header = "RenderPcpStandard.render_pcp_original(): ";
|
||||
|
||||
int isom = DailyQcUtils.isom;
|
||||
int method = DailyQcUtils.method;
|
||||
int mpe_dqc_max_precip_neighbors = DailyQcUtils.mpe_dqc_max_precip_neighbors;
|
||||
int i, j, h, hh, time_pos;
|
||||
|
||||
int usedStationCount = 0;
|
||||
int totals[] = new int[5];
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
totals[i] = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* pcpn_time_step is a function parameter. It specifies whether to
|
||||
* interpolate 6hr or 24hr HRAP grid
|
||||
*/
|
||||
/*
|
||||
* pcpn_time is a function parameter. It specifies which 6hr HRAP grid
|
||||
* to generate. It takes 0,1,2,or 3 to represent different 6hr period of
|
||||
* a day.
|
||||
*/
|
||||
/*
|
||||
* time_pos is assigned a value of 0,1,2,or 3 (for 6hr data) or 4 (for
|
||||
* 24hr data). This value is used in
|
||||
* pdata[pcpn_day].stn[hh].frain[time_pos].data to control whether to
|
||||
* retrieve 6hr data or 24hr data.
|
||||
*/
|
||||
if (pcpn_time_step == 0) {
|
||||
time_pos = pcpn_time; // for 6 hour data: 0,1,2,3.
|
||||
} else {
|
||||
time_pos = 4; // for 24 hour data
|
||||
|
||||
/*
|
||||
* in case the 24hr grid rendering is required, we check
|
||||
* 24hr_grid_gen_method_token() to determine how to generate the
|
||||
* grid. New Post OB9.2
|
||||
*/
|
||||
|
||||
if (getTokenValue24hrGridGenMeth() == 1) {
|
||||
render24hrPcpUsingFour6hr(pcpn_day, pcpn_time, numPstations,
|
||||
precip_stations, hrap_grid, pdata, pcp_in_use);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* begin to interpolate value for each bin in the HRAP grid */
|
||||
/*
|
||||
* to interpolate, two quantities are needed first: value and distance.
|
||||
* They are calculated by using the neighboring stations.
|
||||
*/
|
||||
for (i = 0; i < hrap_grid.maxi; i++) {
|
||||
for (j = 0; j < hrap_grid.maxj; j++) {
|
||||
/*
|
||||
* Check if the grid cell is covered by an HSA. If not, then do
|
||||
* not estimate precipitation for it.
|
||||
*/
|
||||
if (hrap_grid.owner[i][j] == -1) {
|
||||
pcp.value[i][j] = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
totalDistanceWeight = 0.0;
|
||||
totalWeightedValue = 0.0;
|
||||
usedStationCount = 0;
|
||||
boolean usedStation = false;
|
||||
/*
|
||||
* the following for loop is to calculate two quantities: value
|
||||
* and distance, which later on, are used to interpret the HRAP
|
||||
* grid.
|
||||
*/
|
||||
/*
|
||||
* It uses neighbor stations of a HRAP grid bin to calculate
|
||||
* value and distance.
|
||||
*/
|
||||
/* for each neighbor station of the grid bin, do the following */
|
||||
|
||||
/* For each of the closest stations. */
|
||||
for (h = 0; h < mpe_dqc_max_precip_neighbors; h++) {
|
||||
|
||||
// hh is index of stations
|
||||
|
||||
hh = hrap_grid.gage[i][j].index[h];
|
||||
|
||||
int gageIndex = hh;
|
||||
|
||||
usedStation = processStation(gageIndex, isom, i, j,
|
||||
pcpn_day, pcpn_time, time_pos, method,
|
||||
precip_stations, hrap_grid, pdata, pcp_in_use,
|
||||
false);
|
||||
|
||||
if (usedStation) {
|
||||
usedStationCount++;
|
||||
}
|
||||
|
||||
if (usedStationCount == SUFFICIENT_NEAREST_NEIGHBOR_GAGES) {
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* end for loop (h = 0; h < mpe_dqc_max_precip_neighbors;h++)
|
||||
* the above for loop is for each neighbor station.
|
||||
*/
|
||||
/*
|
||||
* the above for loop is to calculate value and distance, which
|
||||
* later on, are used to interpret the HRAP grid
|
||||
*/
|
||||
|
||||
/*
|
||||
* the resulting htotal is the valid number of neighbor stations
|
||||
* that are used to calculate value and distance, which later
|
||||
* on, are used to interpret the HRAP grid
|
||||
*/
|
||||
|
||||
/*
|
||||
* if there is not enough valid neighbor station, such as
|
||||
* usedStationCount < MINIMUM_NEAREST_NEIGHBOR_GAGES the code
|
||||
* below handle this situation. Basically, the code recalculate
|
||||
* the value and distance using all the stations -- see the for
|
||||
* (h = 0; h < max_stations; h++) loop below.
|
||||
*/
|
||||
|
||||
if (usedStationCount < MINIMUM_NEAREST_NEIGHBOR_GAGES) {
|
||||
|
||||
totalWeightedValue = 0.0;
|
||||
totalDistanceWeight = 0.0;
|
||||
usedStationCount = 0;
|
||||
|
||||
for (h = 0; h < numPstations; h++) {
|
||||
|
||||
int gageIndex = h;
|
||||
|
||||
usedStation = processStation(gageIndex, isom, i, j,
|
||||
pcpn_day, pcpn_time, time_pos, method,
|
||||
precip_stations, hrap_grid, pdata, pcp_in_use,
|
||||
true);
|
||||
|
||||
if (usedStation) {
|
||||
usedStationCount++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}/*
|
||||
* end the handling of special case : if (usedStationCount <
|
||||
* MINIMUM_NEAREST_NEIGHBOR_GAGES),
|
||||
*/
|
||||
/* which means there are not enough neighboring stations */
|
||||
|
||||
// found no usable gages
|
||||
if (usedStationCount == 0) {
|
||||
pcp.value[i][j] = 0;
|
||||
}
|
||||
|
||||
else {
|
||||
|
||||
pcp.value[i][j] = (int) (totalWeightedValue
|
||||
/ totalDistanceWeight * 100.0);
|
||||
}
|
||||
|
||||
if (pcp.value[i][j] < .01) {
|
||||
pcp.value[i][j] = 0;
|
||||
}
|
||||
|
||||
} // end for (j = 0; j < hrap_grid.maxj; j++) {
|
||||
} // end for (i = 0; i < hrap_grid.maxi; i++) {
|
||||
|
||||
if (pcpn_time_step == 0) {
|
||||
time_pos = pcpn_day * 4 + 3 - pcpn_time;
|
||||
} else {
|
||||
time_pos = 40 + pcpn_day;
|
||||
}
|
||||
// notice that time_pos is a variable defined inside the function, and
|
||||
// its value do not need to be limited as 0,1,2,3,or 4. Here it is
|
||||
// assigned with bigger numbers.
|
||||
// time_pos = 40 + pcpn_day;
|
||||
|
||||
// pcp_in_use[i] = 1 -- grids rendered via Render button OR Save Level2
|
||||
// option
|
||||
// = -1 --grids for this time period not rendered (initialization value)
|
||||
pcp_in_use[time_pos] = 1;
|
||||
|
||||
ReadQPFGrids rqp = new ReadQPFGrids();
|
||||
rqp.write_file("pcp", time_pos, pcp);
|
||||
}
|
||||
|
||||
private boolean processStation(int gageIndex, int isom, int col, int row,
|
||||
int pcpn_day, int pcpn_time, int time_pos, int method,
|
||||
ArrayList<Station> stationList, Hrap_Grid hrap_grid, Pdata[] pdata,
|
||||
int[] pcp_in_use, boolean checkDistance) {
|
||||
boolean usedStation = false;
|
||||
|
||||
Station station = stationList.get(gageIndex);
|
||||
|
||||
float value = pdata[pcpn_day].stn[gageIndex].frain[time_pos].data;
|
||||
|
||||
if (value < 0) {
|
||||
return usedStation;// false
|
||||
}
|
||||
|
||||
int qualityCode = pdata[pcpn_day].stn[gageIndex].frain[time_pos].qual;
|
||||
|
||||
if (qualityCode != 0 && qualityCode != 8 && qualityCode != 6
|
||||
&& qualityCode != 3 && qualityCode != 4 && qualityCode != 2) {
|
||||
return usedStation; // false
|
||||
}
|
||||
|
||||
if (method == 2 && station.isoh[isom] <= 0) {
|
||||
return usedStation; // false
|
||||
}
|
||||
|
||||
/*
|
||||
* determine distance between grid bin and the station in question of
|
||||
* the grid and station in question
|
||||
*/
|
||||
double distanceX = (col + (hrap_grid.hrap_minx - station.hrap_x));
|
||||
double distanceY = (row + (hrap_grid.hrap_miny - station.hrap_y));
|
||||
|
||||
double distanceSquared = (distanceX * distanceX)
|
||||
+ (distanceY * distanceY);
|
||||
|
||||
if (distanceSquared < .00001) {
|
||||
distanceSquared = .00001;
|
||||
}
|
||||
|
||||
if (checkDistance) {
|
||||
if (distanceSquared > maxDistSquared) // too far away, don't use the
|
||||
// station
|
||||
{
|
||||
return usedStation; // false, bail out, don't adjust weight with
|
||||
// this reading
|
||||
}
|
||||
}
|
||||
|
||||
double distanceWeight = 1 / distanceSquared;
|
||||
double weightedValue = value * distanceWeight;
|
||||
|
||||
float prismValue = station.isoh[isom];
|
||||
|
||||
if (method == 2 && prismValue > 0) {
|
||||
weightedValue = weightedValue * hrap_grid.isoh[isom][col][row]
|
||||
/ (prismValue * 25.4);
|
||||
}
|
||||
|
||||
totalWeightedValue += weightedValue;
|
||||
totalDistanceWeight += distanceWeight;
|
||||
|
||||
usedStation = true;
|
||||
return usedStation;
|
||||
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------
|
||||
/*
|
||||
* get the token value of token mpe_24hr_grid_gen_method. This token will
|
||||
* determine how we generate the 24hr grid. We can either use the 24hr gage
|
||||
* values, which is the old way, or we can use four 6hr gage values and add
|
||||
* them together.
|
||||
*/
|
||||
/* there is some problem with the static */
|
||||
|
||||
/**
|
||||
* @param pcpn_day
|
||||
* @param pcpn_time
|
||||
* @param numPstations
|
||||
* @param precip_stations
|
||||
* @param hrap_grid
|
||||
* @param pdata
|
||||
* @param pcp_in_use
|
||||
*/
|
||||
private void render24hrPcpUsingFour6hr(int pcpn_day, int pcpn_time,
|
||||
int numPstations, ArrayList<Station> precip_stations,
|
||||
Hrap_Grid hrap_grid, Pdata[] pdata, int[] pcp_in_use) {
|
||||
|
||||
int i, j, k, h, hh, time_pos;
|
||||
boolean usedStation = false;
|
||||
int isom = DailyQcUtils.isom;
|
||||
int method = DailyQcUtils.method;
|
||||
int totals[] = new int[5];
|
||||
int all_total = 0;
|
||||
int neighbor_total = 0;
|
||||
|
||||
int usedStationCount;
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
totals[i] = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* pcpn_time_step is function parameter. It specifies whether to
|
||||
* interpolate 6hr or 24hr HRAP grid
|
||||
*/
|
||||
/*
|
||||
* pcpn_time is a function parameter. It specifies which 6hr HRAP grid
|
||||
* to generate. It takes 0,1,2,or 3 to represent different 6hr period of
|
||||
* a day.
|
||||
*/
|
||||
/*
|
||||
* time_pos is assigned a value of 0,1,2,or 3 (for 6hr data) or 4 (for
|
||||
* 24hr data). This value is used in
|
||||
* pdata[pcpn_day].stn[hh].frain[time_pos].data to control whether to
|
||||
* retrieve 6hr data or 24hr data.
|
||||
*/
|
||||
|
||||
/* initialization of the pcp.value */
|
||||
for (i = 0; i < hrap_grid.maxi; i++) {
|
||||
for (j = 0; j < hrap_grid.maxj; j++) {
|
||||
pcp.value[i][j] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* begin to interpolate 4 6hr grids. At the end of each iteration, the
|
||||
* calculated interpolation value is added to pcp.value[i][j].
|
||||
*/
|
||||
/*
|
||||
* time_pos is assigned a value of 0,1,2,or 3 (for four 6hr data). This
|
||||
* value is used in pdata[pcpn_day].stn[hh].frain[time_pos].data to
|
||||
* retrieve 6hr data.
|
||||
*/
|
||||
for (k = 0; k < 4; k++) {
|
||||
time_pos = k; /* for 6 hour data: 0, 1,2,3. */
|
||||
|
||||
/* begin to interpolate value for each bin in the HRAP grid */
|
||||
/*
|
||||
* to interpolate, two quantities are needed first: value and
|
||||
* distance. They are calculated by using the neighboring stations.
|
||||
*/
|
||||
|
||||
for (i = 0; i < hrap_grid.maxi; i++) {
|
||||
for (j = 0; j < hrap_grid.maxj; j++) {
|
||||
/*
|
||||
* Check if the grid cell is covered by an HSA. If not, then
|
||||
* do not estimate precipitation for it.
|
||||
*/
|
||||
if (hrap_grid.owner[i][j] == -1) {
|
||||
pcp.value[i][j] = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
totalDistanceWeight = 0.0;
|
||||
totalWeightedValue = 0.0;
|
||||
usedStationCount = 0;
|
||||
|
||||
/*
|
||||
* for each neighbor station of the grid bin, do the
|
||||
* following
|
||||
*/
|
||||
int mpe_dqc_max_precip_neighbors = DailyQcUtils.mpe_dqc_max_precip_neighbors;
|
||||
|
||||
for (h = 0; h < mpe_dqc_max_precip_neighbors; h++) {
|
||||
hh = hrap_grid.gage[i][j].index[h];/*
|
||||
* hh is index of
|
||||
* stations
|
||||
*/
|
||||
int gageIndex = hh;
|
||||
|
||||
usedStation = processStation(gageIndex, isom, i, j,
|
||||
pcpn_day, pcpn_time, time_pos, method,
|
||||
precip_stations, hrap_grid, pdata, pcp_in_use,
|
||||
false);
|
||||
|
||||
if (usedStation) {
|
||||
usedStationCount++;
|
||||
}
|
||||
|
||||
if (usedStationCount == SUFFICIENT_NEAREST_NEIGHBOR_GAGES) {
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (usedStationCount < MINIMUM_NEAREST_NEIGHBOR_GAGES) {
|
||||
|
||||
// not enough gages, so extend search to all gages
|
||||
totalWeightedValue = 0.0;
|
||||
totalDistanceWeight = 0.0;
|
||||
usedStationCount = 0;
|
||||
|
||||
for (h = 0; h < numPstations; h++) {
|
||||
|
||||
int gageIndex = h;
|
||||
|
||||
usedStation = processStation(gageIndex, isom, i, j,
|
||||
pcpn_day, pcpn_time, time_pos, method,
|
||||
precip_stations, hrap_grid, pdata,
|
||||
pcp_in_use, false);
|
||||
|
||||
if (usedStation) {
|
||||
usedStationCount++;
|
||||
}
|
||||
|
||||
}
|
||||
neighbor_total++;
|
||||
}
|
||||
|
||||
if (usedStationCount != 0) {
|
||||
pcp.value[i][j] += (int) ((totalWeightedValue / totalDistanceWeight) * 100);
|
||||
}
|
||||
|
||||
/*
|
||||
* if (pcp.value[i][j] < .01) { pcp.value[i][j] = 0; }
|
||||
*/
|
||||
all_total++;
|
||||
|
||||
} /* end of for loop (j = 0; j < hrap_grid.maxj; j++) */
|
||||
} /* end of for loop (i = 0; i < hrap_grid.maxi; i++) */
|
||||
/* At this moment, the interpretation of HRAP grid is done */
|
||||
|
||||
}/*
|
||||
* end of the ( k = 0; k<4; k++) loop, which interpolates 4 6hr HRAP
|
||||
* grid.
|
||||
*/
|
||||
|
||||
/* final adjustment of the pcp.value */
|
||||
for (i = 0; i < hrap_grid.maxi; i++) {
|
||||
for (j = 0; j < hrap_grid.maxj; j++) {
|
||||
|
||||
if (pcp.value[i][j] < .01) { // this doesn't really make sense,
|
||||
// since this is an integer
|
||||
pcp.value[i][j] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* time_pos = pcpn_day * 4 + 3 - pcpn_time; */
|
||||
time_pos = 40 + pcpn_day;
|
||||
|
||||
/*
|
||||
* pcp_in_use[i] = 1 -- grids rendered via Render button OR Save Level2
|
||||
* option = -1 --grids for this time period not rendered (initialization
|
||||
* value)
|
||||
*/
|
||||
pcp_in_use[time_pos] = 1;
|
||||
|
||||
/*
|
||||
* results of grid rendering routines (render_t, render_t6, render_pcp,
|
||||
* render_z) are written to scratch files using the write_file routine.
|
||||
* scratch file is stored in the scratch directory.
|
||||
*/
|
||||
ReadQPFGrids rqp = new ReadQPFGrids();
|
||||
rqp.write_file("pcp", time_pos, pcp);
|
||||
|
||||
} // end render24hrPcpUsingFour6hr()
|
||||
|
||||
// ---------------------------------------------------------------------------------------
|
||||
int getTokenValue24hrGridGenMeth() {
|
||||
|
||||
int token_of_24hr_grid_gen_method = 0;
|
||||
|
||||
if (first == true) {
|
||||
String tokenName = "mpe_dqc_24hr_precip_grid_meth";
|
||||
|
||||
String dqc24hrPrecipMeth;
|
||||
|
||||
// char message[GAGEQC_MESSAGE_LEN] = { '\0' };
|
||||
|
||||
AppsDefaults appsDefaults = AppsDefaults.getInstance();
|
||||
dqc24hrPrecipMeth = appsDefaults.getToken(tokenName);
|
||||
|
||||
if (dqc24hrPrecipMeth != null) {
|
||||
/* allowed token values: (ACCUM_6HR, USE_24HR) */
|
||||
if (dqc24hrPrecipMeth.equalsIgnoreCase("ACCUM_6HR")) {
|
||||
token_of_24hr_grid_gen_method = 1;
|
||||
}
|
||||
}
|
||||
first = false;
|
||||
}
|
||||
|
||||
return token_of_24hr_grid_gen_method;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------
|
||||
|
||||
}
|
|
@ -24,7 +24,6 @@ Export-Package: gov.noaa.nws.ncep.viz.common,
|
|||
gov.noaa.nws.ncep.viz.common.customprojection,
|
||||
gov.noaa.nws.ncep.viz.common.dbQuery,
|
||||
gov.noaa.nws.ncep.viz.common.display,
|
||||
gov.noaa.nws.ncep.viz.common.gpdQuery,
|
||||
gov.noaa.nws.ncep.viz.common.graphicUtil,
|
||||
gov.noaa.nws.ncep.viz.common.preferences,
|
||||
gov.noaa.nws.ncep.viz.common.soundingQuery,
|
||||
|
@ -35,7 +34,5 @@ Import-Package: com.raytheon.uf.common.comm,
|
|||
com.raytheon.uf.common.parameter,
|
||||
com.raytheon.viz.pointdata,
|
||||
com.vividsolutions.jts.geom,
|
||||
gov.noaa.nws.ncep.common.dataplugin.gpd.product,
|
||||
gov.noaa.nws.ncep.common.dataplugin.gpd.query,
|
||||
javax.measure.unit
|
||||
|
||||
|
|
|
@ -348,7 +348,7 @@ fi
|
|||
|
||||
if [ "${1}" = "-viz" ]; then
|
||||
buildRPM "awips2"
|
||||
# buildRPM "awips2-common-base"
|
||||
buildRPM "awips2-common-base"
|
||||
# buildRPM "awips2-rcm"
|
||||
# buildRPM "awips2-hydroapps-shared"
|
||||
# buildRPM "awips2-notification"
|
||||
|
@ -366,11 +366,11 @@ if [ "${1}" = "-edex" ]; then
|
|||
#buildRPM "awips2-common-base"
|
||||
# buildRPM "awips2-adapt-native"
|
||||
#buildRPM "awips2-python-qpid"
|
||||
buildRPM "awips2-cli"
|
||||
# buildRPM "awips2-gfesuite-client"
|
||||
# buildRPM "awips2-gfesuite-server"
|
||||
buildRPM "awips2-ncep-database"
|
||||
buildRPM "awips2-python-dynamicserialize"
|
||||
# buildRPM "awips2-cli"
|
||||
buildRPM "awips2-gfesuite-client"
|
||||
buildRPM "awips2-gfesuite-server"
|
||||
# buildRPM "awips2-ncep-database"
|
||||
# buildRPM "awips2-python-dynamicserialize"
|
||||
buildEDEX
|
||||
if [ $? -ne 0 ]; then
|
||||
exit 1
|
||||
|
|
Loading…
Add table
Reference in a new issue