Merge branch 'omaha_16.2.1' into omaha_16.2.1-lx
Conflicts: cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/dialogs/TextEditorDialog.java Former-commit-id: 50282f22b76f6d393c1918652a9e0da8696847f0
This commit is contained in:
commit
bbd0a34445
23 changed files with 600 additions and 285 deletions
|
@ -54,7 +54,7 @@ def start(queue, append, sites, climateDir):
|
|||
#mythread.start()
|
||||
|
||||
# Process Data button
|
||||
def process(queue, stnPickle):
|
||||
def process(queue, stnPickle, append, sites, climateDir):
|
||||
import ClimateDataUpdate
|
||||
import cPickle as pickle
|
||||
o = pickle.loads(stnPickle)
|
||||
|
|
|
@ -112,6 +112,8 @@ import com.vividsolutions.jts.geom.LineString;
|
|||
* 09-09-2014 RM #657 Qinglu Lin handle StormTrackState.trackType is null.
|
||||
* 09-25-2014 ASM #16773 D. Friedman Fix NPE.
|
||||
* 10-10-2014 ASM #16844 D. Friedman Prevent some errors when moving track.
|
||||
* 02-09-2016 ASM #18421 D. Friedman Don't call ToolsDataManager.setStormTrackData
|
||||
* if there is no storm motion.
|
||||
* </pre>
|
||||
*
|
||||
* @author mschenke
|
||||
|
@ -1454,6 +1456,9 @@ public class StormTrackDisplay implements IRenderable {
|
|||
}
|
||||
|
||||
private void postData(StormTrackState state) {
|
||||
if (!(state.speed > 0)) {
|
||||
return;
|
||||
}
|
||||
StormTrackData data = new StormTrackData();
|
||||
Coordinate[] coords = new Coordinate[state.timePoints.length];
|
||||
for (int i = 0; i < coords.length; ++i) {
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
# support, and with no warranty, express or implied, as to its usefulness for
|
||||
# any purpose.
|
||||
#
|
||||
# CoastalThreat
|
||||
# StormSurgeThreat
|
||||
#
|
||||
# Author: Tom LeFebvre/Pablo Santos
|
||||
# April 20, 2012 - To use gridded MSL TO NAVD and MSL to MLLW
|
||||
|
@ -19,13 +19,13 @@
|
|||
# Sept 18, 2014: Added code to pull grids from NHC via ISC if PHISH not
|
||||
# Available on time. Left inactive (commented out) for the moment until that can be fully tested later
|
||||
# in 2014 or in 2015.
|
||||
# May 22, 2015 (LEFebvre/Santos): Added option to create null grids and manual grids when
|
||||
# PSURGE not available. Added checks for current guidance for PHISH and ISC options.
|
||||
#
|
||||
# Last Modified: LeFebvre/Santos, July 27, 2015: Expanded Manual options to include Replace and Add options.
|
||||
# This allows sites to specify manually different threat levels across different edit areas and time ranges.
|
||||
# See 2015HTIUserGuide for details.
|
||||
#
|
||||
# Feb 11, 2016 LeFebvre (16.1.2): Added code to create zero grids and manual grids when
|
||||
# PSURGE not available. Added checks for current guidance for PHISH and ISC options.
|
||||
# ----------------------------------------------------------------------------
|
||||
# The MenuItems list defines the GFE menu item(s) under which the
|
||||
# Procedure is to appear.
|
||||
|
@ -179,12 +179,16 @@ class Procedure (SmartScript.SmartScript):
|
|||
|
||||
weName = "Surge" + pctStr + "Pctincr"
|
||||
#print "Attempting to retrieve: ", weName, level
|
||||
trList = self.getWEInventory(dbName, weName, level)
|
||||
|
||||
if len(trList) == 0:
|
||||
self.statusBarMsg("No grids available for model:" + dbName, "S")
|
||||
return None
|
||||
# get the StormSurgeProb inventory
|
||||
surgeTRList = self.getWEInventory(dbName, weName, level)
|
||||
if len(surgeTRList) == 0:
|
||||
self.statusBarMsg("No PHISH grid found.", "U")
|
||||
return
|
||||
|
||||
# Make timeRanges for all 13 grids. Start with the beginning of the first Phish grid
|
||||
baseTime = int(surgeTRList[0].startTime().unixTime() / (6 * 3600)) * (6 * 3600) #snap to 6 hour period
|
||||
trList = self.makeTimingTRs(baseTime)
|
||||
|
||||
n = 1
|
||||
for tr in trList:
|
||||
start = tr.startTime().unixTime() - 6*3600
|
||||
|
@ -197,7 +201,13 @@ class Procedure (SmartScript.SmartScript):
|
|||
end = tr.startTime().unixTime()
|
||||
tr6 = TimeRange.TimeRange(AbsTime.AbsTime(start),
|
||||
AbsTime.AbsTime(end))
|
||||
phishGrid = self.getGrids(dbName, weName, level, tr)
|
||||
|
||||
surgeTR = TimeRange.TimeRange(tr.startTime(), AbsTime.AbsTime(tr.startTime().unixTime() + 3600))
|
||||
if surgeTR in surgeTRList:
|
||||
phishGrid = self.getGrids(dbName, weName, level, surgeTR)
|
||||
else:
|
||||
phishGrid = np.zeros(self.getGridShape(), 'f')
|
||||
|
||||
#
|
||||
# For consistency we need to add smoothing here too as we do in execute.
|
||||
#
|
||||
|
@ -208,7 +218,7 @@ class Procedure (SmartScript.SmartScript):
|
|||
if smoothThreatGrid is "Yes":
|
||||
phishGrid = np.where(np.greater(phishGrid, 0.0), self.smoothGrid(phishGrid,3), phishGrid)
|
||||
|
||||
grid = np.where(phishGrid>-100,phishGrid*3.28, np.float32(-80.0))
|
||||
grid = np.where(phishGrid>-100, phishGrid*3.28, np.float32(-80.0)) # Convert units from meters to feet
|
||||
self.createGrid(mutableID, "InundationTiming", "SCALAR", grid, tr6, precision=1)
|
||||
|
||||
return
|
||||
|
@ -600,7 +610,7 @@ class Procedure (SmartScript.SmartScript):
|
|||
print "Timing grid not found at:", trList[i]
|
||||
|
||||
if (start - baseTime) / 3600 >= inunStartHour and (end - baseTime) / 3600 <= inunEndHour:
|
||||
timingGrids[i][modifyMask] = inundationHeight # populate where needed
|
||||
timingGrids[i][modifyMask] = inundationHeight # populate only where needed
|
||||
|
||||
self.createGrid(mutableID, "InundationTiming", "SCALAR", timingGrids[i], trList[i])
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
# TCV_Dictionary
|
||||
# TCV_Dictionary file
|
||||
# Author: GFE Installation Script
|
||||
# Last Modified: Feb 13, 2015
|
||||
# Last Modified: Jan 26, 2016
|
||||
# ----------------------------------------------------------------------------
|
||||
# Needed to prevent an error from the SmartTool module
|
||||
WeatherElementEdited = None
|
||||
|
@ -16,7 +16,7 @@ ThreatStatements = {
|
|||
"check plans": {
|
||||
"planning": "Emergency planning should include a reasonable threat for major hurricane force wind greater than 110 MPH of equivalent Category 3 intensity or higher.",
|
||||
"preparation": "To be safe, aggressively prepare for the potential of devastating to catastrophic wind impacts. Efforts should now be underway to secure all properties.",
|
||||
"action": "Extremely Dangerous and life threatening wind is possible. Failure to adequately shelter may result in serious injury, loss of life, or immense human suffering.",
|
||||
"action": "Extremely dangerous and life threatening wind is possible. Failure to adequately shelter may result in serious injury, loss of life, or immense human suffering.",
|
||||
},
|
||||
"complete preparations": {
|
||||
"planning": "Emergency plans should include a reasonable threat for major hurricane force wind greater than 110 MPH of equivalent Category 3 intensity or higher.",
|
||||
|
|
|
@ -79,6 +79,7 @@ import com.raytheon.viz.ui.dialogs.ICloseCallback;
|
|||
* 29 June 2015 14630 xwei Fixed : Not able to import basins.dat with apostrophe and incorrect data posted
|
||||
* 30 June 2015 17360 xwei Fixed : basins.dat import failed if the first line does not have Lat Lon
|
||||
* Dec 18, 2015 5217 mduff Changes to fix importing geo files.
|
||||
* Feb 15, 2016 5217 mduff convert longitude back to hydro's "View value" of being positive
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -835,7 +836,8 @@ public class ArealDefinitionsDlg extends CaveSWTDialog {
|
|||
geoData.setBoundaryType(HydroConstants.GEOAREA_DATANAMES[listCbo
|
||||
.getSelectionIndex()]);
|
||||
geoData.setInteriorLat(intLat);
|
||||
geoData.setInteriorLon(intLon);
|
||||
// Convert back to hydro format of positive longitude values
|
||||
geoData.setInteriorLon(intLon * -1);
|
||||
geoData.setLon(lonPoints);
|
||||
geoData.setLat(latPoints);
|
||||
geoData.setNumberPoints(nPts);
|
||||
|
|
|
@ -96,8 +96,6 @@ import com.vividsolutions.jts.geom.GeometryFactory;
|
|||
* Feb 14, 2013 1616 bsteffen Add option for interpolation of colormap
|
||||
* parameters, disable colormap interpolation
|
||||
* by default.
|
||||
* Nov 19, 2015 18105 lbousaidi Removed time and PrecipField legend on the right
|
||||
* side of cave to give space to basin info.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -899,8 +897,16 @@ public class MPELegendResource extends
|
|||
} else if (rsc.getStatus() != ResourceStatus.INITIALIZED) {
|
||||
continue;
|
||||
} else {
|
||||
legend.label="";
|
||||
legend.label = rsc.getName();
|
||||
legend.resource = resourcePair;
|
||||
if (rsc.isTimeAgnostic() == false) {
|
||||
DataTime date = frameInfo.getTimeForResource(rsc);
|
||||
String time = " No Data Available";
|
||||
if (date != null) {
|
||||
time = " - " + date.getLegendString();
|
||||
}
|
||||
legend.label += time;
|
||||
}
|
||||
}
|
||||
|
||||
if (!vis) {
|
||||
|
|
|
@ -30,7 +30,8 @@ import com.raytheon.uf.common.status.UFStatus.Priority;
|
|||
import com.raytheon.viz.mpe.util.DailyQcUtils.Station;
|
||||
|
||||
/**
|
||||
* TODO Add Description
|
||||
* This routine will estimate 6 hourly periods when 24 hour rain exists. Based on:
|
||||
* ohd/pproc_lib/src/GageQCEngine/TEXT/estimate_daily_stations.c in AWIPS I.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
|
@ -38,6 +39,8 @@ import com.raytheon.viz.mpe.util.DailyQcUtils.Station;
|
|||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Mar 10, 2009 snaples Initial creation
|
||||
* Jan 11, 2016 5173 bkowal Do not estimate a station that has been forced
|
||||
* good. Eliminated warnings.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -55,8 +58,8 @@ public class EstDailyStations {
|
|||
public void estimate_daily_stations(int j,
|
||||
ArrayList<Station> precip_stations, int numPstations) {
|
||||
|
||||
int dqc_neig = dqc.mpe_dqc_max_precip_neighbors;
|
||||
int isom = dqc.isom;
|
||||
int dqc_neig = DailyQcUtils.mpe_dqc_max_precip_neighbors;
|
||||
int isom = DailyQcUtils.isom;
|
||||
int isohyets_used = dqc.isohyets_used;
|
||||
int method = dqc.method;
|
||||
int m, k, i, l, ii;
|
||||
|
@ -83,18 +86,18 @@ public class EstDailyStations {
|
|||
int details = dqc.mpe_td_details_set;
|
||||
int mpe_td_new_algorithm_set = dqc.mpe_td_new_algorithm_set;
|
||||
|
||||
if (dqc.pdata[j].data_time == null) {
|
||||
if (DailyQcUtils.pdata[j].data_time == null) {
|
||||
return;
|
||||
}
|
||||
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
|
||||
cal.setTime(dqc.pdata[j].data_time);
|
||||
cal.setTime(DailyQcUtils.pdata[j].data_time);
|
||||
|
||||
/* this routine will estimate 6 hourly periods when 24 hour rain exists */
|
||||
|
||||
for (m = 0; m < max_stations; m++) {
|
||||
/* dont estimate missing 24 hour stations */
|
||||
if (dqc.pdata[j].stn[m].frain[4].data < 0
|
||||
|| dqc.pdata[j].stn[m].frain[4].qual == 4) {
|
||||
if (DailyQcUtils.pdata[j].stn[m].frain[4].data < 0
|
||||
|| DailyQcUtils.pdata[j].stn[m].frain[4].qual == 4) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -102,17 +105,17 @@ public class EstDailyStations {
|
|||
|
||||
for (k = 0; k < 4; k++) {
|
||||
|
||||
if (dqc.pdata[j].stn[m].frain[k].data >= 0
|
||||
&& dqc.pdata[j].stn[m].frain[k].qual == 2) {
|
||||
if (DailyQcUtils.pdata[j].stn[m].frain[k].data >= 0
|
||||
&& DailyQcUtils.pdata[j].stn[m].frain[k].qual == 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (dqc.pdata[j].stn[m].frain[k].qual == 1) {
|
||||
if (DailyQcUtils.pdata[j].stn[m].frain[k].qual == 1) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (dqc.pdata[j].stn[m].rrain[k].data < 0
|
||||
&& dqc.pdata[j].stn[m].frain[k].qual != 2) {
|
||||
if (DailyQcUtils.pdata[j].stn[m].rrain[k].data < 0
|
||||
&& DailyQcUtils.pdata[j].stn[m].frain[k].qual != 2) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -124,8 +127,9 @@ public class EstDailyStations {
|
|||
|
||||
/* dont estimate stations forced good, bad or estimated */
|
||||
|
||||
if (dqc.pdata[j].stn[m].frain[4].qual == 1
|
||||
|| dqc.pdata[j].stn[m].frain[4].qual == 5) {
|
||||
if (DailyQcUtils.pdata[j].stn[m].frain[4].qual == 0
|
||||
|| DailyQcUtils.pdata[j].stn[m].frain[4].qual == 1
|
||||
|| DailyQcUtils.pdata[j].stn[m].frain[4].qual == 5) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -154,16 +158,16 @@ public class EstDailyStations {
|
|||
|
||||
/* dont estimate unless good or forced good */
|
||||
|
||||
if (dqc.pdata[j].stn[i].frain[k].qual != 0
|
||||
&& dqc.pdata[j].stn[i].frain[k].qual != 8
|
||||
&& dqc.pdata[j].stn[i].frain[k].qual != 3
|
||||
&& dqc.pdata[j].stn[i].frain[k].qual != 2) {
|
||||
if (DailyQcUtils.pdata[j].stn[i].frain[k].qual != 0
|
||||
&& DailyQcUtils.pdata[j].stn[i].frain[k].qual != 8
|
||||
&& DailyQcUtils.pdata[j].stn[i].frain[k].qual != 3
|
||||
&& DailyQcUtils.pdata[j].stn[i].frain[k].qual != 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* dont use missing stations */
|
||||
|
||||
if (dqc.pdata[j].stn[i].frain[k].data < 0) {
|
||||
if (DailyQcUtils.pdata[j].stn[i].frain[k].data < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -186,10 +190,10 @@ public class EstDailyStations {
|
|||
testdist = 1 / testdist;
|
||||
|
||||
if (method == 2 && isoh > 0 && isoh1 > 0) {
|
||||
padj = dqc.pdata[j].stn[i].frain[k].data
|
||||
padj = DailyQcUtils.pdata[j].stn[i].frain[k].data
|
||||
* isoh1 / isoh;
|
||||
} else {
|
||||
padj = dqc.pdata[j].stn[i].frain[k].data;
|
||||
padj = DailyQcUtils.pdata[j].stn[i].frain[k].data;
|
||||
}
|
||||
|
||||
fdist = testdist + fdist;
|
||||
|
@ -229,14 +233,14 @@ public class EstDailyStations {
|
|||
continue;
|
||||
}
|
||||
|
||||
if (dqc.pdata[j].stn[i].frain[k].qual != 0
|
||||
&& dqc.pdata[j].stn[i].frain[k].qual != 8
|
||||
&& dqc.pdata[j].stn[i].frain[k].qual != 3
|
||||
&& dqc.pdata[j].stn[i].frain[k].qual != 2) {
|
||||
if (DailyQcUtils.pdata[j].stn[i].frain[k].qual != 0
|
||||
&& DailyQcUtils.pdata[j].stn[i].frain[k].qual != 8
|
||||
&& DailyQcUtils.pdata[j].stn[i].frain[k].qual != 3
|
||||
&& DailyQcUtils.pdata[j].stn[i].frain[k].qual != 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (dqc.pdata[j].stn[i].frain[k].data < 0) {
|
||||
if (DailyQcUtils.pdata[j].stn[i].frain[k].data < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -257,10 +261,10 @@ public class EstDailyStations {
|
|||
testdist = 1 / testdist;
|
||||
|
||||
if (method == 2 && isoh > 0 && isoh1 > 0) {
|
||||
padj = dqc.pdata[j].stn[i].frain[k].data
|
||||
padj = DailyQcUtils.pdata[j].stn[i].frain[k].data
|
||||
* isoh1 / isoh;
|
||||
} else {
|
||||
padj = dqc.pdata[j].stn[i].frain[k].data;
|
||||
padj = DailyQcUtils.pdata[j].stn[i].frain[k].data;
|
||||
}
|
||||
|
||||
fdist = testdist + fdist;
|
||||
|
@ -293,27 +297,26 @@ public class EstDailyStations {
|
|||
if (i == m) {
|
||||
continue;
|
||||
}
|
||||
if (dqc.pdata[j].stn[i].frain[k].qual != 0
|
||||
&& dqc.pdata[j].stn[i].frain[k].qual != 8
|
||||
&& dqc.pdata[j].stn[i].frain[k].qual != 3
|
||||
&& dqc.pdata[j].stn[i].frain[k].qual != 2) {
|
||||
if (DailyQcUtils.pdata[j].stn[i].frain[k].qual != 0
|
||||
&& DailyQcUtils.pdata[j].stn[i].frain[k].qual != 8
|
||||
&& DailyQcUtils.pdata[j].stn[i].frain[k].qual != 3
|
||||
&& DailyQcUtils.pdata[j].stn[i].frain[k].qual != 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (dqc.pdata[j].stn[i].frain[k].data < 0) {
|
||||
if (DailyQcUtils.pdata[j].stn[i].frain[k].data < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
buf = String
|
||||
.format(" %s(%f,%f)",
|
||||
precip_stations.get(i).hb5,
|
||||
dqc.pdata[j].stn[i].frain[k].data,
|
||||
DailyQcUtils.pdata[j].stn[i].frain[k].data,
|
||||
precip_stations.get(i).isoh[isom]);
|
||||
|
||||
dqc.td_fpwr.write(buf);
|
||||
dqc.td_fpwr.newLine();
|
||||
}
|
||||
// fvalue[k] = fdata / fdist;
|
||||
|
||||
} catch (IOException e) {
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
|
@ -340,8 +343,8 @@ public class EstDailyStations {
|
|||
dqc.td_fpwr.write(buf);
|
||||
dqc.td_fpwr.newLine();
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
e.getLocalizedMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -352,14 +355,14 @@ public class EstDailyStations {
|
|||
continue;
|
||||
}
|
||||
|
||||
if (dqc.pdata[j].stn[i].frain[k].qual != 0
|
||||
&& dqc.pdata[j].stn[i].frain[k].qual != 8
|
||||
&& dqc.pdata[j].stn[i].frain[k].qual != 3
|
||||
&& dqc.pdata[j].stn[i].frain[k].qual != 2) {
|
||||
if (DailyQcUtils.pdata[j].stn[i].frain[k].qual != 0
|
||||
&& DailyQcUtils.pdata[j].stn[i].frain[k].qual != 8
|
||||
&& DailyQcUtils.pdata[j].stn[i].frain[k].qual != 3
|
||||
&& DailyQcUtils.pdata[j].stn[i].frain[k].qual != 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (dqc.pdata[j].stn[i].frain[k].data < 0) {
|
||||
if (DailyQcUtils.pdata[j].stn[i].frain[k].data < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -385,7 +388,7 @@ public class EstDailyStations {
|
|||
.format(" %s(%f,%f)",
|
||||
precip_stations
|
||||
.get(closest_good_gage_index).hb5,
|
||||
dqc.pdata[j].stn[closest_good_gage_index].frain[k].data,
|
||||
DailyQcUtils.pdata[j].stn[closest_good_gage_index].frain[k].data,
|
||||
precip_stations
|
||||
.get(closest_good_gage_index).isoh[isom]);
|
||||
|
||||
|
@ -393,8 +396,8 @@ public class EstDailyStations {
|
|||
dqc.td_fpwr.write(buf);
|
||||
dqc.td_fpwr.newLine();
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
e.getLocalizedMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -405,7 +408,7 @@ public class EstDailyStations {
|
|||
fvalue[k] = -9999;
|
||||
} else {
|
||||
if (closest_good_gage_index != -9999) {
|
||||
fvalue[k] = dqc.pdata[j].stn[closest_good_gage_index].frain[k].data;
|
||||
fvalue[k] = DailyQcUtils.pdata[j].stn[closest_good_gage_index].frain[k].data;
|
||||
} else {
|
||||
fvalue[k] = -9999;
|
||||
}
|
||||
|
@ -418,8 +421,8 @@ public class EstDailyStations {
|
|||
|
||||
for (k = 0; k < 4; k++) {
|
||||
|
||||
dqc.pdata[j].stn[m].frain[k].qual = 6;
|
||||
dqc.pdata[j].stn[m].frain[k].data = dqc.pdata[j].stn[m].frain[4].data / 4;
|
||||
DailyQcUtils.pdata[j].stn[m].frain[k].qual = 6;
|
||||
DailyQcUtils.pdata[j].stn[m].frain[k].data = DailyQcUtils.pdata[j].stn[m].frain[4].data / 4;
|
||||
|
||||
}
|
||||
|
||||
|
@ -433,10 +436,10 @@ public class EstDailyStations {
|
|||
|
||||
for (k = 0; k < 4; k++) {
|
||||
|
||||
if ((dqc.pdata[j].stn[m].rrain[k].data >= 0 && dqc.pdata[j].stn[m].frain[k].qual != 1)
|
||||
|| (dqc.pdata[j].stn[m].frain[k].qual == 2)) {
|
||||
if ((DailyQcUtils.pdata[j].stn[m].rrain[k].data >= 0 && DailyQcUtils.pdata[j].stn[m].frain[k].qual != 1)
|
||||
|| (DailyQcUtils.pdata[j].stn[m].frain[k].qual == 2)) {
|
||||
stotal = stotal
|
||||
+ dqc.pdata[j].stn[m].frain[k].data;
|
||||
+ DailyQcUtils.pdata[j].stn[m].frain[k].data;
|
||||
} else {
|
||||
|
||||
num_missing++;
|
||||
|
@ -447,7 +450,7 @@ public class EstDailyStations {
|
|||
|
||||
}
|
||||
|
||||
stotal = dqc.pdata[j].stn[m].frain[4].data - stotal;
|
||||
stotal = DailyQcUtils.pdata[j].stn[m].frain[4].data - stotal;
|
||||
|
||||
if (stotal < 0) {
|
||||
stotal = 0;
|
||||
|
@ -461,22 +464,22 @@ public class EstDailyStations {
|
|||
|
||||
for (k = 0; k < 4; k++) {
|
||||
|
||||
if ((dqc.pdata[j].stn[m].rrain[k].data >= 0 && dqc.pdata[j].stn[m].frain[k].qual != 1)
|
||||
|| (dqc.pdata[j].stn[m].frain[k].qual == 2)) {
|
||||
if ((DailyQcUtils.pdata[j].stn[m].rrain[k].data >= 0 && DailyQcUtils.pdata[j].stn[m].frain[k].qual != 1)
|
||||
|| (DailyQcUtils.pdata[j].stn[m].frain[k].qual == 2)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ftotal != 0) {
|
||||
|
||||
dqc.pdata[j].stn[m].frain[k].data = (float) (fvalue[k] * fmult);
|
||||
dqc.pdata[j].stn[m].frain[k].qual = 6;
|
||||
DailyQcUtils.pdata[j].stn[m].frain[k].data = (float) (fvalue[k] * fmult);
|
||||
DailyQcUtils.pdata[j].stn[m].frain[k].qual = 6;
|
||||
|
||||
}
|
||||
|
||||
else {
|
||||
|
||||
dqc.pdata[j].stn[m].frain[k].data = (float) (stotal / num_missing);
|
||||
dqc.pdata[j].stn[m].frain[k].qual = 6;
|
||||
DailyQcUtils.pdata[j].stn[m].frain[k].data = (float) (stotal / num_missing);
|
||||
DailyQcUtils.pdata[j].stn[m].frain[k].qual = 6;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@ import java.io.FileReader;
|
|||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
@ -45,6 +46,7 @@ import java.util.Timer;
|
|||
import java.util.TimerTask;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.regex.PatternSyntaxException;
|
||||
|
||||
import javax.xml.bind.JAXB;
|
||||
import javax.xml.bind.JAXBException;
|
||||
|
@ -135,6 +137,7 @@ import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel
|
|||
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType;
|
||||
import com.raytheon.uf.common.localization.LocalizationFile;
|
||||
import com.raytheon.uf.common.localization.PathManagerFactory;
|
||||
import com.raytheon.uf.common.localization.exception.LocalizationException;
|
||||
import com.raytheon.uf.common.serialization.JAXBManager;
|
||||
import com.raytheon.uf.common.serialization.comm.IServerRequest;
|
||||
import com.raytheon.uf.common.site.SiteMap;
|
||||
|
@ -361,7 +364,8 @@ import com.raytheon.viz.ui.simulatedtime.SimulatedTimeOperations;
|
|||
* 19Nov2015 5141 randerso Replace commas with ellipses if product not enabled for
|
||||
* mixed case transmission
|
||||
* 10Dec2015 5206 randerso Replace commas with ellipses only in WarnGen products
|
||||
* 11Dec2015 RM14752 mgamazaychikov Fix problems with wrapping in the impact section.
|
||||
* 11Dec2015 RM14752 mgamazaychikov Fix problems with wrapping in the impact section, generalized
|
||||
* the approach to padding paragraphs.
|
||||
* 06Jan2016 RM18452 mgamazaychikov Fix NPE for null product in enterEditor
|
||||
* 06Jan2016 5225 randerso Fix problem with mixed case not getting converted to upper case
|
||||
* when multiple text editors are open on the same product.
|
||||
|
@ -503,16 +507,6 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener,
|
|||
*/
|
||||
private static final String PARAGRAPH_DELIMITERS = "*$.-/^#";
|
||||
|
||||
/**
|
||||
* String to delimit padded paragraphs.
|
||||
*/
|
||||
private static final String PADDED_PARAGRAPH_DELIMITERS = "*";
|
||||
|
||||
/**
|
||||
* Expression for start of an obs.
|
||||
*/
|
||||
private static final String METAR_PARAGRAPH = "(METAR|SPECI)\\b.*";
|
||||
|
||||
// Pattern no long used but keeping it here for just in case not using
|
||||
// it breaks being compatialbe with A1.
|
||||
|
||||
|
@ -1419,6 +1413,10 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener,
|
|||
/** Highlight background color. */
|
||||
private Color highlightBackgroundClr;
|
||||
|
||||
private static List<Pattern> paddingPatternList = new ArrayList<Pattern>();
|
||||
|
||||
private static final String PARAGRAPH_PADDING_PATTERN_FILENAME = "textws/gui/ParagraphPaddingPattern.txt";
|
||||
|
||||
/**
|
||||
* Constructor with additional cave style rules
|
||||
*
|
||||
|
@ -8004,7 +8002,6 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener,
|
|||
private void rewrapInternal(int lineNumber) {
|
||||
boolean inLocations = false;
|
||||
boolean inPathcast = false;
|
||||
String padding = "";
|
||||
// get contents of line
|
||||
String line = textEditor.getLine(lineNumber);
|
||||
// check for special paragraph cases
|
||||
|
@ -8028,21 +8025,8 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener,
|
|||
inPathcast = true;
|
||||
}
|
||||
|
||||
// is this the impact paragraph?
|
||||
if (paragraphStart.startsWith(" IMPACT...")
|
||||
|| paragraphStart.startsWith(" HAZARD...")
|
||||
|| paragraphStart.startsWith(" SOURCE...")) {
|
||||
padding = " ";
|
||||
}
|
||||
|
||||
if (paragraphStart.matches(METAR_PARAGRAPH)) {
|
||||
padding = " ";
|
||||
} else if (checkParagraphPadding(paragraphStart)) {
|
||||
// do we need to add or remove padding when we manipulate lines (
|
||||
// two
|
||||
// spaces )
|
||||
padding = " ";
|
||||
}
|
||||
// get the padding for the paragraph
|
||||
String padding = getParagraphPadding(paragraphStart);
|
||||
|
||||
if ((inLocations || inPathcast)
|
||||
&& paragraphStartLineNumber == lineNumber) {
|
||||
|
@ -8388,23 +8372,6 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener,
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* checks if the paragraph starting at the line passed in uses two space
|
||||
* padding for subsequent lines
|
||||
*
|
||||
* @param firstLine
|
||||
* @return
|
||||
*/
|
||||
private boolean checkParagraphPadding(String firstLine) {
|
||||
boolean rval = false;
|
||||
if (firstLine.length() > 0
|
||||
&& PADDED_PARAGRAPH_DELIMITERS.contains(firstLine.substring(0,
|
||||
1))) {
|
||||
rval = true;
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
|
||||
/**
|
||||
* find and return the line number that is the start of the paragraph
|
||||
* containing the line number passed in
|
||||
|
@ -8830,4 +8797,75 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener,
|
|||
public void timechanged() {
|
||||
validateTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the contents of PARAGRAPH_PADDING_PATTERN_FILENAME into
|
||||
* paddingPatternList.
|
||||
*/
|
||||
private void loadPaddingPattern() {
|
||||
IPathManager pathMgr = PathManagerFactory.getPathManager();
|
||||
LocalizationFile lf = pathMgr.getStaticLocalizationFile(
|
||||
LocalizationType.CAVE_STATIC,
|
||||
PARAGRAPH_PADDING_PATTERN_FILENAME);
|
||||
if ((lf != null) && lf.exists()) {
|
||||
try (BufferedReader br = new BufferedReader(new InputStreamReader(
|
||||
lf.openInputStream()))) {
|
||||
String line = null;
|
||||
List<Pattern> patternList = new ArrayList<Pattern>();
|
||||
while ((line = br.readLine()) != null) {
|
||||
if (!line.startsWith("#")) {
|
||||
try {
|
||||
Pattern ptrn = Pattern.compile(line);
|
||||
patternList.add(ptrn);
|
||||
} catch (PatternSyntaxException e) {
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
"Could not compile regex for line " + line
|
||||
+ " from Padding Pattern file "
|
||||
+ lf.toString(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
paddingPatternList = patternList;
|
||||
} catch (IOException e) {
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
"Could not read Padding Pattern file "
|
||||
+ PARAGRAPH_PADDING_PATTERN_FILENAME, e);
|
||||
} catch (LocalizationException e) {
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
"Could not find Padding Pattern file "
|
||||
+ PARAGRAPH_PADDING_PATTERN_FILENAME, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the padding:
|
||||
* - according to padding pattern
|
||||
* - to empty string
|
||||
*
|
||||
* @param paragraphStart
|
||||
*/
|
||||
private String getParagraphPadding(String paragraphStart) {
|
||||
String defaultParagraphPadding = "";
|
||||
for (Pattern paddingPtrn : getPaddingPatternList()) {
|
||||
Matcher m = paddingPtrn.matcher(paragraphStart);
|
||||
if (m.matches()) {
|
||||
int paragraphOffset = m.group(1).toString().length();
|
||||
StringBuilder sb = new StringBuilder(paragraphOffset);
|
||||
for (int i = 0; i < paragraphOffset; i++) {
|
||||
sb.append(" ");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
return defaultParagraphPadding;
|
||||
}
|
||||
|
||||
private List<Pattern> getPaddingPatternList() {
|
||||
// load padding pattern file
|
||||
if (paddingPatternList.isEmpty()){
|
||||
loadPaddingPattern();
|
||||
}
|
||||
return paddingPatternList;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
#
|
||||
# This file contains the regex for paragraphs in text product
|
||||
# that requires special padding. The padding for impact paragraphs
|
||||
# is set in WarnGen templates. Whenever it is changed there, the
|
||||
# change needs to be reflected in this file as well. The regex must match the
|
||||
# entire line and must include parentheses to capture the desired prefix that
|
||||
# will define the indentation level of the paragraph.
|
||||
#
|
||||
# Software History.
|
||||
#
|
||||
# Date Ticket Engineer Description
|
||||
# ------------ ---------- ---------- --------------------------
|
||||
# 31Jan2016 RM18503 mgamazaychikov Created.
|
||||
#
|
||||
# Paragraph that starts with spaces followed by one of
|
||||
#
|
||||
# "IMPACT..."
|
||||
# "HAZARD..."
|
||||
# "SOURCE..."
|
||||
#
|
||||
(\s*IMPACT\.\.\.).*
|
||||
(\s*HAZARD\.\.\.).*
|
||||
(\s*SOURCE\.\.\.).*
|
||||
#
|
||||
# Paragraph that starts with one of:
|
||||
#
|
||||
# "METAR"
|
||||
# "SPECI"
|
||||
#
|
||||
(METAR).*
|
||||
(SPECI).*
|
||||
#
|
||||
# Paragraph that start with
|
||||
#
|
||||
# "* "
|
||||
#
|
||||
(\*\s+).*
|
|
@ -50,4 +50,14 @@
|
|||
<contribute xsi:type="menuItem" menuText="24hr 95th Percentile Total Precipitation" key="TP95pct24hr" indentText="false" />
|
||||
</contribute>
|
||||
|
||||
<contribute xsi:type="toolbarSubMenu" menuText="72hr">
|
||||
<contribute xsi:type="menuItem" menuText="72hr 5th Percentile Total Precipitation" key="TP5pct72hr" indentText="false" />
|
||||
<contribute xsi:type="menuItem" menuText="72hr 10th Percentile Total Precipitation" key="TP10pct72hr" indentText="false" />
|
||||
<contribute xsi:type="menuItem" menuText="72hr 25th Percentile Total Precipitation" key="TP25pct72hr" indentText="false" />
|
||||
<contribute xsi:type="menuItem" menuText="72hr 50th Percentile Total Precipitation" key="TP50pct72hr" indentText="false" />
|
||||
<contribute xsi:type="menuItem" menuText="72hr 75th Percentile Total Precipitation" key="TP75pct72hr" indentText="false" />
|
||||
<contribute xsi:type="menuItem" menuText="72hr 90th Percentile Total Precipitation" key="TP90pct72hr" indentText="false" />
|
||||
<contribute xsi:type="menuItem" menuText="72hr 95th Percentile Total Precipitation" key="TP95pct72hr" indentText="false" />
|
||||
</contribute>
|
||||
|
||||
</menuTemplate>
|
|
@ -255,6 +255,7 @@ import com.vividsolutions.jts.simplify.TopologyPreservingSimplifier;
|
|||
* 12/21/2015 DCS 17942 D. Friedman Support "extension area": polygon can extend past normal features into WFO's marine/land areas.
|
||||
* Show preview of redrawn polygon when developer mode property is set.
|
||||
* 01/06/2016 ASM #18453 D. Friedman Cache extension areas so they are not regenerated on Restart or (limited) template changes.
|
||||
* 02/23/2016 ASM #18669 D. Friedman Improve speed and reduce memory usage of extension area generation.
|
||||
* </pre>
|
||||
*
|
||||
* @author mschenke
|
||||
|
@ -1016,30 +1017,83 @@ public class WarngenLayer extends AbstractStormTrackResource {
|
|||
}
|
||||
|
||||
private Geometry createExtensionArea() throws Exception {
|
||||
long t0 = System.currentTimeMillis();
|
||||
GeospatialData[] features = primaryGDA.geoData.getFeatures(false); // Never uses cwaStretch feactures.
|
||||
Geometry[] g = new Geometry[features.length];
|
||||
for (int i = 0; i < g.length; ++i) {
|
||||
/*
|
||||
* Pre-simplify as an optmization. Makes it possible to
|
||||
* change the static extension distance in real time.
|
||||
*/
|
||||
g[i] = extensionSimplify(
|
||||
convertGeom(features[i].geometry, primaryGDA.geoData.latLonToLocal),
|
||||
options.getSimplificationTolerance()).
|
||||
buffer(options.getDistance());
|
||||
// Pre-simplify and extend each feature.
|
||||
g[i] = simplifyAndExtendFeature(
|
||||
convertGeom(features[i].geometry,
|
||||
primaryGDA.geoData.latLonToLocal),
|
||||
options.getSimplificationTolerance(),
|
||||
options.getDistance());
|
||||
}
|
||||
Geometry r = GeometryUtil.union(g);
|
||||
r = createExtensionAreaFromLocal(r);
|
||||
Geometry vis = extensionGDA.buildArea(r, false);
|
||||
perfLog.logDuration("Extension area", System.currentTimeMillis() - t0);
|
||||
extensionAreaManager.cacheArea(primaryGDA, extensionGDA, options, r, vis);
|
||||
extensionAreaVis = vis;
|
||||
issueRefresh();
|
||||
return r;
|
||||
}
|
||||
|
||||
private Geometry simplifyAndExtendFeature(Geometry geom, double tolerance, double dist) {
|
||||
ArrayList<Geometry> parts = new ArrayList<Geometry>();
|
||||
GeometryUtil.buildGeometryList(parts, geom);
|
||||
ArrayList<Geometry> outParts = new ArrayList<Geometry>(parts.size());
|
||||
for (Geometry g : parts) {
|
||||
g = extensionSimplify(g, tolerance);
|
||||
if (dist > 0) {
|
||||
g = g.buffer(dist);
|
||||
}
|
||||
outParts.add(g);
|
||||
}
|
||||
GeometryFactory gf = new GeometryFactory();
|
||||
/*
|
||||
* All parts should be Polygons and this should return a
|
||||
* MultiPolygon or single Polygon.
|
||||
*/
|
||||
return gf.buildGeometry(outParts);
|
||||
}
|
||||
|
||||
private static final int BUFFER_GEOMETRY_BATCH_SIZE = 100;
|
||||
|
||||
/*
|
||||
* Geometry.buffer() can run the VM out of memory if the geometry is too
|
||||
* complicated (e.g., a MultiPolygon with thousands of component
|
||||
* Polygons.) The following code limits the number of components that
|
||||
* are buffered at one time.
|
||||
*/
|
||||
private Geometry createExtensionAreaFromLocal(Geometry geom) {
|
||||
// geom should be simlified so that the following ops are not painful.
|
||||
Geometry r = geom;
|
||||
if (r.getNumGeometries() > BUFFER_GEOMETRY_BATCH_SIZE) {
|
||||
GeometryFactory gf = new GeometryFactory();
|
||||
Geometry[] ga = new Geometry[BUFFER_GEOMETRY_BATCH_SIZE];
|
||||
while (r.getNumGeometries() > BUFFER_GEOMETRY_BATCH_SIZE) {
|
||||
Geometry[] batches = new Geometry[
|
||||
(r.getNumGeometries() + (BUFFER_GEOMETRY_BATCH_SIZE - 1))
|
||||
/ BUFFER_GEOMETRY_BATCH_SIZE];
|
||||
int si = 0;
|
||||
int bi = 0;
|
||||
while (si < r.getNumGeometries()) {
|
||||
int gai = 0;
|
||||
while (si < r.getNumGeometries() && gai < ga.length) {
|
||||
ga[gai++] = r.getGeometryN(si++);
|
||||
}
|
||||
/* Note that ga is being reused every pass so the
|
||||
* GeometryCollection created here must not continue
|
||||
* to be referenced.
|
||||
*/
|
||||
Geometry batch = gf.createGeometryCollection(
|
||||
gai == BUFFER_GEOMETRY_BATCH_SIZE ?
|
||||
ga : Arrays.copyOf(ga, gai));
|
||||
batch = batch.buffer(0);
|
||||
batches[bi++] = batch;
|
||||
}
|
||||
r = gf.createGeometryCollection(batches);
|
||||
}
|
||||
}
|
||||
r = r.buffer(0);
|
||||
r = extensionSimplify(r, options.getSimplificationTolerance());
|
||||
r = convertGeom(r, primaryGDA.geoData.localToLatLon);
|
||||
|
|
|
@ -152,6 +152,7 @@ import com.vividsolutions.jts.io.WKTReader;
|
|||
* May 29, 2015 4440 randerso Fix resource leak (file not closed)
|
||||
* Jul 15, 2015 DR17716 mgamazaychikov Change to Geometry class in total intersection calculations.
|
||||
* Oct 21, 2105 5021 randerso Fix issue with CORs for mixed case
|
||||
* Feb 9, 2016 DR18421 D. Friedman Don't call ToolsDataManager.setStormTrackData if there is no storm motion.
|
||||
* </pre>
|
||||
*
|
||||
* @author njensen
|
||||
|
@ -555,10 +556,12 @@ public class TemplateRunner {
|
|||
stormLocs[i].y);
|
||||
}
|
||||
context.put("eventLocation", coords);
|
||||
t0 = System.currentTimeMillis();
|
||||
ToolsDataManager.getInstance().setStormTrackData(std);
|
||||
perfLog.logDuration("Save storm track data",
|
||||
System.currentTimeMillis() - t0);
|
||||
if (std.getMotionSpeed() > 0) {
|
||||
t0 = System.currentTimeMillis();
|
||||
ToolsDataManager.getInstance().setStormTrackData(std);
|
||||
perfLog.logDuration("Save storm track data",
|
||||
System.currentTimeMillis() - t0);
|
||||
}
|
||||
} else {
|
||||
// Retrieve the old Warning
|
||||
// Example: s[0-5] = T.CON-KLWX.SV.W.0123
|
||||
|
@ -612,10 +615,12 @@ public class TemplateRunner {
|
|||
std.setDate(simulatedTime);
|
||||
std.setMotionDirection(motionDirection);
|
||||
std.setMotionSpeed(oldWarn.getMotspd());
|
||||
t0 = System.currentTimeMillis();
|
||||
ToolsDataManager.getInstance().setStormTrackData(std);
|
||||
perfLog.logDuration("Save storm track data",
|
||||
System.currentTimeMillis() - t0);
|
||||
if (std.getMotionSpeed() > 0) {
|
||||
t0 = System.currentTimeMillis();
|
||||
ToolsDataManager.getInstance().setStormTrackData(std);
|
||||
perfLog.logDuration("Save storm track data",
|
||||
System.currentTimeMillis() - t0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -122,6 +122,7 @@ import com.raytheon.uf.edex.database.DataAccessLayerException;
|
|||
* 06/29/2015 #4537 rferrel Allow for durations less then 1 hour.
|
||||
* 07/13/2015 #4537 randerso Additional changes to allow D2DParms with sub-hourly durations/intervals
|
||||
* 12/03/2015 #5168 randerso Added flag to use database time range if valid
|
||||
* 01/27/2016 #5290 randerso Do not put null time ranges in the grid inventory.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -653,7 +654,9 @@ public class D2DGridDatabase extends VGridDatabase {
|
|||
+ dataTime.getFcstTime());
|
||||
}
|
||||
}
|
||||
invSet.add(tr);
|
||||
if (tr != null) {
|
||||
invSet.add(tr);
|
||||
}
|
||||
}
|
||||
inventory = new ArrayList<TimeRange>(invSet);
|
||||
} else {
|
||||
|
|
|
@ -301,12 +301,13 @@ rfc.groupName = 'ISC'
|
|||
|
||||
# NHA ISC area
|
||||
domain = ShapeTable('nhadomain')
|
||||
#segment.name = "AllCWA"
|
||||
domain.name = "TropicalISC"
|
||||
domain.groupName = "ISC"
|
||||
domain.editAreaName = "ISC_NHA"
|
||||
|
||||
# Storm Surge Watch/Warning Area
|
||||
stormsurgeww = ShapeTable('stormsurgeww')
|
||||
stormsurgeww.name = "StormSurgeWW"
|
||||
stormsurgeww.groupName = "SurgeCollab"
|
||||
stormsurgeww.editAreaName = "StormSurgeWW_EditArea"
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Version 2015.8.27-0
|
||||
# Version 2016.02.24-0
|
||||
|
||||
import GenericHazards
|
||||
import string, time, os, re, types, copy, LogStream, collections
|
||||
|
@ -549,21 +549,16 @@ class TextProduct(HLSTCV_Common.TextProduct):
|
|||
productDict['stormInformation'] = stormInfoDict
|
||||
|
||||
def _situationOverview(self, productDict, productSegmentGroup, productSegment):
|
||||
overviewSectionTitle = ".Situation Overview...\n"
|
||||
|
||||
# Get the WRKHLS product that has the situation overview we want
|
||||
wrkhlsProduct = self.getPreviousProduct("WRKHLS")
|
||||
|
||||
# Try finding the situation overview
|
||||
overviewSearch = re.search("(?ism).*^%s(.+?)^\." % (overviewSectionTitle), wrkhlsProduct)
|
||||
# Use generic text for the situation overview
|
||||
productDict['situationOverview'] = self._frame("Succinctly describe the expected evolution of the event for the cwa; which hazards are of greater (or lesser) concern, forecast focus, etc.")
|
||||
|
||||
# Get the WRKHLS product minus header that has the situation overview we want
|
||||
wrkhlsProduct = self.getPreviousProduct("WRKHLS")[40:]
|
||||
|
||||
# If we found the overview
|
||||
if overviewSearch is not None:
|
||||
# Clean it up
|
||||
productDict['situationOverview'] = self._cleanText(overviewSearch.group(1).strip())
|
||||
else:
|
||||
# Use generic text for the situation overview
|
||||
productDict['situationOverview'] = self._frame("Succinctly describe the expected evolution of the event for the cwa; which hazards are of greater (or lesser) concern, forecast focus, etc.")
|
||||
if len(wrkhlsProduct) > 0:
|
||||
# Clean and frame the imported overview and use it instead of the generic text
|
||||
productDict['situationOverview'] = self._frame(self._cleanText(wrkhlsProduct.strip()))
|
||||
|
||||
def _windSection(self, productDict, productSegmentGroup, productSegment):
|
||||
sectionDict = dict()
|
||||
|
@ -2101,7 +2096,7 @@ class TextProduct(HLSTCV_Common.TextProduct):
|
|||
for label, latLon in refList:
|
||||
lat, lon = latLon
|
||||
localRef = self._calcReference(lat0, lon0, lat, lon)
|
||||
localRef = localRef + " OF " + label
|
||||
localRef = localRef + " of " + label
|
||||
localRef = localRef.replace(",","")
|
||||
localRefs.append(localRef)
|
||||
return localRefs
|
||||
|
@ -2592,7 +2587,7 @@ class LegacyFormatter():
|
|||
else:
|
||||
text = ""
|
||||
for headline in headlinesList:
|
||||
text += self._textProduct.indentText("**" + headline + "**\n",
|
||||
text += self._textProduct.indentText("**" + headline + "** ",
|
||||
maxWidth=self._textProduct._lineLength)
|
||||
|
||||
text = self._textProduct._frame(text) + "\n\n"
|
||||
|
@ -2678,7 +2673,7 @@ class LegacyFormatter():
|
|||
title = "Situation Overview"
|
||||
text = title + "\n" + "-"*len(title) + "\n\n"
|
||||
|
||||
text += self._textProduct.indentText(overviewText, maxWidth=self._textProduct._lineLength)
|
||||
text += self._textProduct.endline(overviewText, linelength=self._textProduct._lineLength)
|
||||
text += "\n"
|
||||
|
||||
return text
|
||||
|
@ -2754,4 +2749,3 @@ class LegacyFormatter():
|
|||
self._textProduct.debug_print("subpart newtext = '%s'" % (self._pp.pformat(newtext)))
|
||||
text += newtext
|
||||
return text
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Version 2015.11.19-0
|
||||
# Version 2016.02.24-0
|
||||
|
||||
import GenericHazards
|
||||
import JsonSupport
|
||||
|
@ -469,14 +469,14 @@ class TextProduct(HLSTCV_Common.TextProduct):
|
|||
if len(self._segmentList) == 0:
|
||||
return "No hazards to report"
|
||||
|
||||
# Determine time ranges
|
||||
self._determineTimeRanges(argDict)
|
||||
|
||||
# Make sure we have all of the necessary grids before continuing
|
||||
error = self._performGridChecks(argDict)
|
||||
if error is not None:
|
||||
return error
|
||||
|
||||
# Determine time ranges
|
||||
self._determineTimeRanges(argDict)
|
||||
|
||||
# Sample the data
|
||||
self._sampleData(argDict)
|
||||
|
||||
|
@ -513,14 +513,14 @@ class TextProduct(HLSTCV_Common.TextProduct):
|
|||
gridChecks += [(self._isCorrectNumGrids, "WindThreat", 1, argDict),
|
||||
(self._isContinuousDuration, "Wind", 120, argDict),
|
||||
(self._isContinuousDuration, "WindGust", 120, argDict),
|
||||
(self._isContinuousDuration, "pws34int", 120, argDict),
|
||||
(self._isContinuousDuration, "pws64int", 120, argDict),
|
||||
(self._isCombinedContinuousDuration, "pwsD34", "pwsN34", 96, argDict),
|
||||
(self._isCombinedContinuousDuration, "pwsD64", "pwsN64", 96, argDict),]
|
||||
(self._isContinuousDuration, "pws34int", 114, argDict),
|
||||
(self._isContinuousDuration, "pws64int", 114, argDict),
|
||||
(self._isCombinedContinuousDuration, "pwsD34", "pwsN34", 102, argDict),
|
||||
(self._isCombinedContinuousDuration, "pwsD64", "pwsN64", 102, argDict),]
|
||||
|
||||
if self._PopulateSurge and len(self._coastalAreas()) != 0:
|
||||
gridChecks += [(self._isCorrectNumGrids, "InundationMax", 1, argDict),
|
||||
(self._isCorrectNumGrids, "InundationTiming", 13, argDict),]
|
||||
(self._isCorrectNumGrids, "InundationTiming", 12, argDict),]
|
||||
|
||||
missingGridErrors = []
|
||||
for gridCheck in gridChecks:
|
||||
|
@ -530,9 +530,9 @@ class TextProduct(HLSTCV_Common.TextProduct):
|
|||
error = ""
|
||||
if gridCheck[0] == self._isCorrectNumGrids:
|
||||
if gridCheck[2] == 1:
|
||||
error = "%s needs exactly 1 grid" % (gridCheck[1])
|
||||
error = "%s needs at least 1 grid" % (gridCheck[1])
|
||||
else:
|
||||
error = "%s needs exactly %s grids" % (gridCheck[1], gridCheck[2])
|
||||
error = "%s needs at least %s grids" % (gridCheck[1], gridCheck[2])
|
||||
elif gridCheck[0] == self._isContinuousDuration:
|
||||
error = "%s needs at least %s continuous hours worth of data" % (gridCheck[1], gridCheck[2])
|
||||
else:
|
||||
|
@ -556,13 +556,28 @@ class TextProduct(HLSTCV_Common.TextProduct):
|
|||
ifpClient = argDict["ifpClient"]
|
||||
dbId = argDict["databaseID"]
|
||||
parmId = ParmID(weatherElement, dbId)
|
||||
gridTimes = ifpClient.getGridInventory(parmId)
|
||||
times = ifpClient.getGridInventory(parmId)
|
||||
|
||||
self.debug_print("Element being tested: %s" % (self._pp.pformat(weatherElement)), 1)
|
||||
self.debug_print("Expected number of grids: %s" % (self._pp.pformat(expectedNumGrids)), 1)
|
||||
self.debug_print("Length of grid times: %s" % (self._pp.pformat(len(gridTimes))), 1)
|
||||
|
||||
return len(gridTimes) == expectedNumGrids
|
||||
gridTimes = []
|
||||
for index in range(len(times)):
|
||||
gridTime = TimeRange.TimeRange(times[index])
|
||||
|
||||
if (gridTime.endTime() <= self._timeRange.startTime() or
|
||||
gridTime.startTime() >= self._timeRange.endTime()):
|
||||
|
||||
prettyStartTime = self._pp.pformat(str(gridTime.startTime()))
|
||||
prettyEndTime = self._pp.pformat(str(gridTime.endTime()))
|
||||
self.debug_print("skipping grid %s (%s - %s): outside of time range"
|
||||
% (index, prettyStartTime, prettyEndTime), 1)
|
||||
else:
|
||||
gridTimes.append(gridTime)
|
||||
|
||||
self.debug_print("Actual number of grids: %s" % (self._pp.pformat(len(gridTimes))), 1)
|
||||
|
||||
return len(gridTimes) >= expectedNumGrids
|
||||
|
||||
def _isContinuousDuration(self, weatherElement, minimumNumHours, argDict):
|
||||
return self._checkContinuousDuration([weatherElement], minimumNumHours, argDict)
|
||||
|
@ -592,11 +607,28 @@ class TextProduct(HLSTCV_Common.TextProduct):
|
|||
gridTimes = sorted(gridTimes, key= lambda gridTime: gridTime.startTime())
|
||||
|
||||
totalHours = 0
|
||||
previousEndTime = gridTimes[0].startTime()
|
||||
previousEndTime = None
|
||||
for gridTime in gridTimes:
|
||||
self.debug_print("previous end time: %s" % (self._pp.pformat(str(previousEndTime))), 1)
|
||||
self.debug_print("current start time: %s" % (self._pp.pformat(str(gridTime.startTime()))), 1)
|
||||
|
||||
if gridTime.endTime() <= self._timeRange.startTime():
|
||||
prettyEndTime = self._pp.pformat(str(gridTime.endTime()))
|
||||
prettyStartTime = self._pp.pformat(str(self._timeRange.startTime()))
|
||||
self.debug_print("skipping: grid end time (%s) before time range start time (%s)"
|
||||
% (prettyEndTime, prettyStartTime), 1)
|
||||
continue
|
||||
|
||||
if gridTime.startTime() >= self._timeRange.endTime():
|
||||
prettyStartTime = self._pp.pformat(str(gridTime.startTime()))
|
||||
prettyEndTime = self._pp.pformat(str(self._timeRange.endTime()))
|
||||
self.debug_print("done: grid start time (%s) after time range end time (%s)"
|
||||
% (prettyStartTime, prettyEndTime), 1)
|
||||
break
|
||||
|
||||
if previousEndTime is None:
|
||||
previousEndTime = gridTime.startTime()
|
||||
|
||||
if previousEndTime != gridTime.startTime():
|
||||
# Not continuous
|
||||
return False
|
||||
|
@ -674,10 +706,6 @@ class TextProduct(HLSTCV_Common.TextProduct):
|
|||
|
||||
self.debug_print("vtecRecord = %s" % (self._pp.pformat(vtecRecord)), 1)
|
||||
|
||||
if vtecRecord["phen"] == "SS":
|
||||
# Temporary? Change the vtec mode for SS hazards to be experimental
|
||||
vstr = vstr[0] + 'X' + vstr[2:]
|
||||
|
||||
self.debug_print("final vstr = %s" % vstr, 1)
|
||||
records.append(vstr)
|
||||
segmentDict['vtecRecords'] = records
|
||||
|
@ -1066,13 +1094,15 @@ class TextProduct(HLSTCV_Common.TextProduct):
|
|||
def _initializeSegmentZoneData(self, segment):
|
||||
# The current advisory will be populated when getting a section's stats
|
||||
self._currentAdvisory['ZoneData'][segment] = {
|
||||
"WindThreat": None,
|
||||
"WindForecast": None,
|
||||
"StormSurgeThreat": None,
|
||||
"StormSurgeForecast": None,
|
||||
"FloodingRainThreat": None,
|
||||
"FloodingRainForecast": None,
|
||||
"TornadoThreat": None,
|
||||
"WindThreat": None,
|
||||
"WindForecast": None,
|
||||
"WindHighestPhaseReached": None,
|
||||
"StormSurgeThreat": None,
|
||||
"StormSurgeForecast": None,
|
||||
"StormSurgeHighestPhaseReached": None,
|
||||
"FloodingRainThreat": None,
|
||||
"FloodingRainForecast": None,
|
||||
"TornadoThreat": None,
|
||||
}
|
||||
|
||||
def _getPreviousAdvisories(self):
|
||||
|
@ -1299,6 +1329,11 @@ class SectionCommon():
|
|||
|
||||
def _isThreatNoneForEntireStorm(self, threatName):
|
||||
previousAdvisories = self._textProduct._getPreviousAdvisories()
|
||||
|
||||
# For the first advisory, this needs to be false otherwise
|
||||
# potential impacts could be wrong
|
||||
if len(previousAdvisories) == 0:
|
||||
return False
|
||||
|
||||
for advisory in previousAdvisories:
|
||||
if advisory["ZoneData"][self._segment][threatName] != "None":
|
||||
|
@ -1385,7 +1420,8 @@ class SectionCommon():
|
|||
elif self._isThreatIncreasing(shorterTermTrendDifference, longerTermTrendDifference):
|
||||
self._textProduct.debug_print("threat is increasing", 1)
|
||||
threatTrendValue = "INCREASING"
|
||||
elif currentThreat == "Extreme" and \
|
||||
# NOTE: Modified so more threat levels can be classified as increasing when forecast has increased
|
||||
elif currentThreat in ["Mod", "High", "Extreme"] and \
|
||||
self._isMagnitudeIncreasing(forecastKey, magnitudeIncreaseThreshold):
|
||||
self._textProduct.debug_print("Increasing based on magnitude", 1)
|
||||
threatTrendValue = "INCREASING"
|
||||
|
@ -1480,20 +1516,27 @@ class SectionCommon():
|
|||
elif (onsetHour <= 6) and (endHour is not None) and (endHour > 0):
|
||||
tr = "hunker down"
|
||||
|
||||
self._textProduct.debug_print("tr is currently -> '%s'" % (tr), 1)
|
||||
self._textProduct.debug_print("Before default section. %s tr is currently -> %s for %s" % (section, tr, self._segment), 1)
|
||||
|
||||
# Will need to redo this logic when SS hazards are used
|
||||
if section == "Wind":
|
||||
threatGrid = "WindThreat"
|
||||
elif section == "Surge":
|
||||
threatGrid = "StormSurgeThreat"
|
||||
|
||||
if tr == "default":
|
||||
records = self._textProduct._getVtecRecords(self._segment)
|
||||
for record in records:
|
||||
if record["phen"] in ["HU", "TR"] and record["sig"] == "W":
|
||||
if record["act"] == "CAN":
|
||||
if self._textProduct._currentAdvisory['ZoneData'][self._segment][threatGrid] in \
|
||||
["Elevated", "Mod", "High", "Extreme"]:
|
||||
tr = "hunker down"
|
||||
break
|
||||
if self._textProduct._currentAdvisory['ZoneData'][self._segment][threatGrid] not in \
|
||||
["Elevated", "Mod", "High", "Extreme"]:
|
||||
if section == "Wind":
|
||||
tr = "recovery"
|
||||
break
|
||||
# This is just for 2015
|
||||
elif record["act"] == "CON" and \
|
||||
section == "Surge" and \
|
||||
self._textProduct._currentAdvisory['ZoneData'][self._segment]["StormSurgeThreat"] == "None" and \
|
||||
self._pastSurgeThreatsNotNone():
|
||||
elif section == "Surge" and self._pastSurgeThreatsNotNone():
|
||||
tr = "recovery"
|
||||
break
|
||||
|
||||
|
@ -1501,7 +1544,45 @@ class SectionCommon():
|
|||
section == "Wind" and \
|
||||
self._pastWindHazardWasCAN():
|
||||
tr = "recovery"
|
||||
|
||||
self._textProduct.debug_print("After default section. %s tr is -> %s for %s" % (section, tr, self._segment), 1)
|
||||
|
||||
# ---------------------------------------------------------------------
|
||||
# Don't allow the event to regress to an earlier phase for this section
|
||||
|
||||
# "default" isn't ordered because it can occur at multiple points before the recovery phase
|
||||
phaseOrder = [None, "check plans", "complete preparations", "hunker down", "recovery"]
|
||||
|
||||
if self._sectionHeaderName == "Storm Surge":
|
||||
highestPhaseReachedField = "StormSurgeHighestPhaseReached"
|
||||
else: # Flooding Rain and Tornado are tied to Wind so that's why they use Wind's phase
|
||||
highestPhaseReachedField = "WindHighestPhaseReached"
|
||||
|
||||
previousHighestPhaseReached = self._textProduct._previousAdvisory['ZoneData'][self._segment][highestPhaseReachedField]
|
||||
currentHighestPhaseReached = self._textProduct._currentAdvisory['ZoneData'][self._segment][highestPhaseReachedField]
|
||||
if phaseOrder.index(currentHighestPhaseReached) >= phaseOrder.index(previousHighestPhaseReached):
|
||||
highestPhaseReached = currentHighestPhaseReached
|
||||
else:
|
||||
highestPhaseReached = previousHighestPhaseReached
|
||||
|
||||
if tr == "default":
|
||||
if highestPhaseReached == "recovery":
|
||||
tr = "recovery"
|
||||
else:
|
||||
highestPhaseIndex = phaseOrder.index(highestPhaseReached)
|
||||
|
||||
self._textProduct.debug_print("highestPhaseReached so far for %s is -> '%s' for '%s" \
|
||||
% (self._sectionHeaderName, highestPhaseReached, self._segment), 1)
|
||||
|
||||
currentPhaseIndex = phaseOrder.index(tr)
|
||||
if currentPhaseIndex < highestPhaseIndex:
|
||||
tr = highestPhaseReached
|
||||
elif currentPhaseIndex > highestPhaseIndex:
|
||||
self._textProduct._currentAdvisory['ZoneData'][self._segment][highestPhaseReachedField] = tr
|
||||
|
||||
|
||||
self._textProduct.debug_print("End of method. %s tr is -> %s for %s" % (section, tr, self._segment), 1)
|
||||
|
||||
return tr
|
||||
|
||||
def _pastWindHazardWasCAN(self):
|
||||
|
@ -1524,6 +1605,8 @@ class SectionCommon():
|
|||
return False
|
||||
|
||||
def _pastSurgeThreatsNotNone(self):
|
||||
|
||||
# Will need to modify this to be both Wind and Surge once SS codes are added
|
||||
previousAdvisories = self._textProduct._getPreviousAdvisories()
|
||||
|
||||
# If there are NOT any advisories to process - no need to continue
|
||||
|
@ -1563,7 +1646,7 @@ class SectionCommon():
|
|||
with open("/awips2/cave/etc/gfe/userPython/utilities/TCVDictionary.py", 'r') as pythonFile:
|
||||
fileContents = pythonFile.read()
|
||||
exec(fileContents)
|
||||
|
||||
|
||||
# ThreatStatements comes from TCVDictionary.py when it is exec'ed
|
||||
threatStatements = ThreatStatements
|
||||
|
||||
|
@ -1587,7 +1670,7 @@ class SectionCommon():
|
|||
self._setProductPartValue(segmentDict, 'potentialImpactsSummary', summary)
|
||||
|
||||
def _getPotentialImpactsSummaryText(self, maxThreat):
|
||||
if not self.isThreatNoneForEntireStorm:
|
||||
if self.isThreatNoneForEntireStorm:
|
||||
return "Potential Impacts: Little to None"
|
||||
if self._tr is not None and self._sectionHeaderName in ["Wind", "Storm Surge"]:
|
||||
if self._tr == "hunker down":
|
||||
|
@ -1855,11 +1938,11 @@ class WindSection(SectionCommon):
|
|||
# Dictionary representing wind thresholds in kts
|
||||
# for category 1, 2, 3, 4 or 5 hurricanes.
|
||||
return {
|
||||
'CAT 5 Hurricane': (157, 999),
|
||||
'CAT 4 Hurricane': (130, 157),
|
||||
'CAT 3 Hurricane': (111, 130),
|
||||
'CAT 2 Hurricane': ( 96, 111),
|
||||
'CAT 1 Hurricane': ( 74, 96),
|
||||
'Cat 5 Hurricane': (157, 999),
|
||||
'Cat 4 Hurricane': (130, 157),
|
||||
'Cat 3 Hurricane': (111, 130),
|
||||
'Cat 2 Hurricane': ( 96, 111),
|
||||
'Cat 1 Hurricane': ( 74, 96),
|
||||
'Strong Tropical Storm': ( 58, 73),
|
||||
'Tropical Storm': ( 39, 58),
|
||||
}
|
||||
|
@ -2108,7 +2191,7 @@ class FloodingRainSection(SectionCommon):
|
|||
words = self._rainRange(int(self._stats._sumAccum + 0.5))
|
||||
|
||||
# If we have previous rainfall
|
||||
if self._stats._prevAccum not in [0.0, None]:
|
||||
if self._stats._prevAccum not in [0.0, None] and (int(self._stats._sumAccum + 0.5)) != 0:
|
||||
words = "Additional " + words
|
||||
self._setProductPartValue(segmentDict, 'peakRain', "Peak Rainfall Amounts: " + words)
|
||||
|
||||
|
@ -2116,7 +2199,9 @@ class FloodingRainSection(SectionCommon):
|
|||
minAccum = 0
|
||||
maxAccum = 0
|
||||
|
||||
if sumAccum == 0:
|
||||
if sumAccum == 0 and self._stats._prevAccum not in [0.0, None]:
|
||||
return "No additional significant rainfall forecast"
|
||||
elif sumAccum == 0 and self._stats._prevAccum in [0.0, None]:
|
||||
return "No significant rainfall forecast"
|
||||
elif sumAccum == 1:
|
||||
return "around 1 inch"
|
||||
|
@ -2187,14 +2272,6 @@ class FloodingRainSection(SectionCommon):
|
|||
if len(subsectionDict) > 0:
|
||||
self._setProductPartValue(segmentDict, 'impactsSubsection', subsectionDict)
|
||||
|
||||
def _specialImpactsStatements(self):
|
||||
return {"hunker down": ["Potential impacts from flooding rain are still unfolding.",
|
||||
"The extent of realized impacts will depend on actual rainfall amounts as received at particular locations.",
|
||||
],
|
||||
"recovery": ["For additional information on impacts being caused by flooding rain, refer to the local hazardous weather outlook or hurricane local statement.",
|
||||
],
|
||||
}
|
||||
|
||||
def _potentialImpactsSummary(self, segmentDict, productSegmentGroup, productSegment):
|
||||
if not self._textProduct._WSPGridsAvailable:
|
||||
self._setProductPartValue(segmentDict, 'potentialImpactsSummary',
|
||||
|
@ -2315,14 +2392,6 @@ class TornadoSection(SectionCommon):
|
|||
if len(subsectionDict) > 0:
|
||||
self._setProductPartValue(segmentDict, 'impactsSubsection', subsectionDict)
|
||||
|
||||
def _specialImpactsStatements(self):
|
||||
return {"hunker down": ["Potential impacts from tropical tornadoes are still unfolding.",
|
||||
"The extent of realized impacts will depend on the severity of actual tornado occurrence as experienced at particular locations.",
|
||||
],
|
||||
"recovery": ["For additional information on impacts being caused by tropical tornadoes, refer to the local hazardous weather outlook or hurricane local statement.",
|
||||
],
|
||||
}
|
||||
|
||||
def _potentialImpactsSummary(self, segmentDict, productSegmentGroup, productSegment):
|
||||
if not self._textProduct._WSPGridsAvailable:
|
||||
self._setProductPartValue(segmentDict, 'potentialImpactsSummary',
|
||||
|
@ -2825,18 +2894,16 @@ class StormSurgeSectionStats(SectionCommonStats):
|
|||
self._setStats(intersectStatList, timeRangeList)
|
||||
|
||||
def _setStats(self, statList, timeRangeList):
|
||||
windows = []
|
||||
phishStartTime = None
|
||||
phishEndTime = None
|
||||
possibleStop = 0
|
||||
possibleStart = 0
|
||||
|
||||
# If this is an inland area, just move on
|
||||
if statList == "InlandArea":
|
||||
return
|
||||
|
||||
self._textProduct.debug_print("*"*100, 1)
|
||||
self._textProduct.debug_print("phishStartTime = %s phishEndTime = %s possibleStop = %d possibleStart = %d" %
|
||||
(str(phishStartTime), str(phishEndTime), possibleStop, possibleStart), 1)
|
||||
self._textProduct.debug_print("Setting Surge Section stats for %s" % self._segment, 1)
|
||||
|
||||
statDict = statList[0]
|
||||
self._inundationMax = self._textProduct._getStatValue(statDict, "InundationMax", "Max")
|
||||
|
@ -2844,55 +2911,107 @@ class StormSurgeSectionStats(SectionCommonStats):
|
|||
self._inundationMax = round(self._inundationMax)
|
||||
self._textProduct.debug_print("self._inundationMax = %s" % (self._inundationMax), 1)
|
||||
|
||||
self._textProduct.debug_print("%s" % (self._textProduct._pp.pformat(statList)), 1)
|
||||
self._textProduct.debug_print("length of statList = %s" % (len(statList)), 1)
|
||||
for period in range(len(statList)):
|
||||
tr, _ = timeRangeList[period]
|
||||
statDict = statList[period]
|
||||
self._textProduct.debug_print("-"*50, 1)
|
||||
self._textProduct.debug_print("tr = %s" % (self._textProduct._pp.pformat(tr)), 1)
|
||||
self._textProduct.debug_print("statDict = %s" % (self._textProduct._pp.pformat(statDict)), 1)
|
||||
|
||||
|
||||
curPhish = self._textProduct._getStatValue(statDict, "InundationTiming", "Max")
|
||||
self._textProduct.debug_print("tr = %s" % (self._textProduct._pp.pformat(tr)), 1)
|
||||
self._textProduct.debug_print("curPhish = '%s' possibleStop = %d possibleStart = %d" %
|
||||
(str(curPhish), possibleStop, possibleStart), 1)
|
||||
self._textProduct.debug_print("phishStartTime = %s phishEndTime = %s" %
|
||||
self._textProduct.debug_print("curPhish = '%s'" % (str(curPhish)), 1)
|
||||
self._textProduct.debug_print("phishStartTime = %s phishEndTime = %s" %
|
||||
(str(phishStartTime), str(phishEndTime)), 1)
|
||||
|
||||
if (curPhish is None) or (curPhish == 'None'):
|
||||
self._textProduct.debug_print("Done: Reached end of grids (curPhish was None)", 1)
|
||||
break
|
||||
|
||||
if self._inundationMax >= 3:
|
||||
if curPhish >= 1:
|
||||
if possibleStop != 0:
|
||||
possibleStop = 0
|
||||
possibleStart += 1
|
||||
if phishStartTime is None:
|
||||
phishStartTime = tr.startTime()
|
||||
elif curPhish < 1 and possibleStart < 2:
|
||||
possibleStart = 0
|
||||
phishStartTime = None
|
||||
elif phishStartTime is not None and curPhish is not None: # Only checking if valid grid
|
||||
possibleStop += 1
|
||||
if possibleStop < 2:
|
||||
phishEndTime = tr.startTime()
|
||||
else: # possibleStop == 2
|
||||
break
|
||||
else: # curPhish is None so out of grids
|
||||
break
|
||||
|
||||
# For start time:
|
||||
# If inundationMax >= 3:
|
||||
# Looking for 2 consecutive grids with a surge height >= 1
|
||||
# Start will be the start time of the FIRST of the 2 consecutive grids
|
||||
# If 1 <= inundationMax < 3:
|
||||
# Looking for 1 grid with a surge height >= 1
|
||||
# Start will be the start time of this grid
|
||||
#
|
||||
# For end time:
|
||||
# Looking for 2 consecutive grids with a surge height < 1
|
||||
# End will be the start time of the FIRST of the 2 consecutive grids
|
||||
|
||||
# If we have another period after this one, we may need to look at the two
|
||||
# consecutive periods for start and end time conditions
|
||||
isLastPeriod = True
|
||||
if period < len(statList) - 1:
|
||||
isLastPeriod = False
|
||||
nextTr, _ = timeRangeList[period+1]
|
||||
nextStatDict = statList[period+1]
|
||||
nextPhish = self._textProduct._getStatValue(nextStatDict, "InundationTiming", "Max")
|
||||
|
||||
self._textProduct.debug_print("nextTr = %s" % (self._textProduct._pp.pformat(nextTr)), 1)
|
||||
self._textProduct.debug_print("nextStatDict = %s" % (self._textProduct._pp.pformat(nextStatDict)), 1)
|
||||
self._textProduct.debug_print("nextPhish = '%s'" % (str(nextPhish)), 1)
|
||||
|
||||
# Set what the condition is for determining the start time
|
||||
if (self._inundationMax >= 3) and (not isLastPeriod):
|
||||
startCondition = (curPhish >= 1) and (nextPhish >= 1)
|
||||
self._textProduct.debug_print("startCondition looking at 2 periods", 1)
|
||||
elif 1 <= self._inundationMax < 3:
|
||||
if curPhish >= 1:
|
||||
if possibleStop != 0:
|
||||
possibleStop = 0
|
||||
if phishStartTime is None:
|
||||
phishStartTime = tr.startTime()
|
||||
elif phishStartTime is not None and curPhish is not None: # Only checking if valid grid
|
||||
possibleStop += 1
|
||||
if possibleStop < 2:
|
||||
phishEndTime = tr.startTime()
|
||||
else: # possibleStop == 2
|
||||
break
|
||||
else: # curPhish is None so out of grids
|
||||
break
|
||||
startCondition = curPhish >= 1
|
||||
self._textProduct.debug_print("startCondition looking at 1 period", 1)
|
||||
else:
|
||||
startCondition = False
|
||||
self._textProduct.debug_print("no startCondition, done", 1)
|
||||
break
|
||||
|
||||
# Set what the condition is for determining the end time
|
||||
if not isLastPeriod:
|
||||
endCondition = (curPhish < 1) and (nextPhish < 1)
|
||||
self._textProduct.debug_print("endCondition looking at 2 periods", 1)
|
||||
else:
|
||||
endCondition = False
|
||||
self._textProduct.debug_print("this is the last period, no endCondition possible", 1)
|
||||
|
||||
if startCondition and (phishStartTime is None):
|
||||
phishStartTime = tr.startTime()
|
||||
elif endCondition and (phishStartTime is not None) and (phishEndTime is None):
|
||||
phishEndTime = tr.startTime()
|
||||
|
||||
# We found a new window, save it, reset and look for any additional windows
|
||||
self._textProduct.debug_print("Found a new window:", 1)
|
||||
self._textProduct.debug_print("window phishStartTime = %s window phishEndTime = %s" %
|
||||
(str(phishStartTime), str(phishEndTime)), 1)
|
||||
|
||||
windows.append((phishStartTime, phishEndTime))
|
||||
phishStartTime = None
|
||||
phishEndTime = None
|
||||
|
||||
self._textProduct.debug_print("Looking for additional windows", 1)
|
||||
|
||||
self._textProduct.debug_print("new phishStartTime = %s new phishEndTime = %s" %
|
||||
(str(phishStartTime), str(phishEndTime)), 1)
|
||||
|
||||
# Check for the case where a window doesn't end
|
||||
if (phishStartTime is not None) and (phishEndTime is None):
|
||||
self._textProduct.debug_print("Found a never-ending window:", 1)
|
||||
self._textProduct.debug_print("window phishStartTime = %s window phishEndTime = %s" %
|
||||
(str(phishStartTime), str(phishEndTime)), 1)
|
||||
windows.append((phishStartTime, None))
|
||||
|
||||
# Create the final window
|
||||
if len(windows) == 0:
|
||||
phishStartTime = None
|
||||
phishEndTime = None
|
||||
else:
|
||||
phishStartTime = windows[0][0] # Start time of first window
|
||||
phishEndTime = windows[-1][1] # End time of last window
|
||||
|
||||
self._textProduct.debug_print("Constructed the final window:", 1)
|
||||
self._textProduct.debug_print("final phishStartTime = %s final phishEndTime = %s" %
|
||||
(str(phishStartTime), str(phishEndTime)), 1)
|
||||
|
||||
self._windowSurge = "Window of concern: "
|
||||
|
||||
|
@ -2907,7 +3026,7 @@ class StormSurgeSectionStats(SectionCommonStats):
|
|||
|
||||
self._textProduct.debug_print("surge startTime = %s self._onsetSurgeHour = %s " %
|
||||
(self._textProduct._pp.pformat(startTime), self._onsetSurgeHour), 1)
|
||||
if phishEndTime is not None and possibleStop >= 2:
|
||||
if phishEndTime is not None:
|
||||
self._endSurgeHour = self._calculateHourOffset(phishEndTime)
|
||||
endTime = AbsTime(self._textProduct._issueTime_secs + self._endSurgeHour*60*60)
|
||||
windowPeriod = self._textProduct.makeTimeRange(startTime, endTime)
|
||||
|
@ -2917,18 +3036,12 @@ class StormSurgeSectionStats(SectionCommonStats):
|
|||
|
||||
startTimeDescriptor = self._textProduct._formatPeriod(windowPeriod)
|
||||
|
||||
# Modified to handle case where last grid is zero but did not have two grids
|
||||
if phishEndTime is None or possibleStop == 1:
|
||||
if phishEndTime is None:
|
||||
self._windowSurge += "Begins " + startTimeDescriptor
|
||||
elif phishStartTime == phishEndTime:
|
||||
self._windowSurge += startTimeDescriptor
|
||||
else:
|
||||
endTimeDescriptor = self._textProduct._formatPeriod(windowPeriod, useEndTime = True)
|
||||
|
||||
if self._onsetSurgeHour > 12:
|
||||
# self._windowSurge += startTimeDescriptor +\
|
||||
# " through " +\
|
||||
# endTimeDescriptor
|
||||
self._windowSurge += startTimeDescriptor +\
|
||||
" until " +\
|
||||
endTimeDescriptor
|
||||
|
@ -2936,17 +3049,22 @@ class StormSurgeSectionStats(SectionCommonStats):
|
|||
self._windowSurge += "through " + endTimeDescriptor
|
||||
|
||||
if self._inundationMax is not None:
|
||||
# Round so we don't store values like 1.600000023841858
|
||||
# inundationMax is already rounded but should be stored as an int and not a float
|
||||
self._currentAdvisory["StormSurgeForecast"] = int(self._inundationMax)
|
||||
|
||||
self._textProduct.debug_print("+"*60, 1)
|
||||
self._textProduct.debug_print("In StormSurgeSectionStats._setStats", 1)
|
||||
self._textProduct.debug_print("Done in StormSurgeSectionStats._setStats:", 1)
|
||||
self._textProduct.debug_print("self._inundationMax = '%s'" %
|
||||
(self._inundationMax), 1)
|
||||
self._textProduct.debug_print("self._onsetSurgeHour = '%s'" %
|
||||
(self._onsetSurgeHour), 1)
|
||||
self._textProduct.debug_print("self._endSurgeHour = '%s'" %
|
||||
(self._endSurgeHour), 1)
|
||||
self._textProduct.debug_print("self._windowSurge = '%s'" %
|
||||
(self._windowSurge), 1)
|
||||
self._textProduct.debug_print("self._maxThreat = '%s'" %
|
||||
(self._maxThreat), 1)
|
||||
self._textProduct.debug_print("+"*60, 1)
|
||||
|
||||
|
||||
class FloodingRainSectionStats(SectionCommonStats):
|
||||
|
|
|
@ -56,6 +56,8 @@ import com.raytheon.uf.edex.decodertools.core.DecoderTools;
|
|||
* Jan 30, 2010 15779 lbousaidi added 4 letter to station id for ACR
|
||||
* Aug 08, 2013 16408 wkwock Use different metar.cfg file and options
|
||||
* May 14, 2014 2536 bclement moved WMO Header to common, removed TimeTools usage
|
||||
* Feb 12, 2016 18665 snaples/bkowal Update MetarToShef transformer to use options from token or config file.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author jkorman
|
||||
|
@ -457,28 +459,34 @@ public class MetarToShefTransformer extends
|
|||
throws TransformerException {
|
||||
ObsToSHEFOptions tmpOptions = null;
|
||||
MetarToShefRun mtsr = mtsrList.get(report.getId());
|
||||
String optionsToUse = null;
|
||||
if (mtsr == null) {
|
||||
tmpOptions = defaultOptions;
|
||||
optionsToUse = this.metar2ShefOptions;
|
||||
} else {
|
||||
optionsToUse = (mtsr.getMetarToShefOptions() == null) ? this.metar2ShefOptions
|
||||
: mtsr.getMetarToShefOptions();
|
||||
tmpOptions = optionsList.get(mtsr.getConfigFileName()
|
||||
+ mtsr.getMetarToShefOptions());
|
||||
+ optionsToUse);
|
||||
if (tmpOptions == null) {
|
||||
// just to prevent t memory leak
|
||||
if (optionsList.size() > MAX_LIST) {
|
||||
optionsList.clear();
|
||||
}
|
||||
|
||||
tmpOptions = new ObsToSHEFOptions(mtsr.getConfigFileName(),
|
||||
mtsr.getMetarToShefOptions(), true);
|
||||
optionsToUse, true);
|
||||
|
||||
optionsList
|
||||
.put(mtsr.getConfigFileName()
|
||||
+ mtsr.getMetarToShefOptions(), tmpOptions);
|
||||
+ optionsToUse, tmpOptions);
|
||||
}
|
||||
mtsrList.remove(report.getId());
|
||||
}
|
||||
options = tmpOptions;
|
||||
logger.info("Metar to SHEF for " + report.getStationId()
|
||||
+ " use config file: " + options.getCfgFileName()
|
||||
+ " with options:" + mtsr.getMetarToShefOptions());
|
||||
+ " with options:" + optionsToUse);
|
||||
configureArchiveDir();
|
||||
|
||||
return transformReport(report, headers);
|
||||
|
@ -496,4 +504,4 @@ public class MetarToShefTransformer extends
|
|||
|
||||
mtsrList.putAll(matchLst);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -83,7 +83,13 @@
|
|||
<parameter>TP75pct24hr</parameter>
|
||||
<parameter>TP90pct24hr</parameter>
|
||||
<parameter>TP95pct24hr</parameter>
|
||||
|
||||
<parameter>TP5pct72hr</parameter>
|
||||
<parameter>TP10pct72hr</parameter>
|
||||
<parameter>TP25pct72hr</parameter>
|
||||
<parameter>TP50pct72hr</parameter>
|
||||
<parameter>TP75pct72hr</parameter>
|
||||
<parameter>TP90pct72hr</parameter>
|
||||
<parameter>TP95pct72hr</parameter>
|
||||
</paramLevelMatches>
|
||||
<contourStyle>
|
||||
<displayUnits>in</displayUnits>
|
||||
|
|
|
@ -88,6 +88,13 @@
|
|||
<parameter>TP75pct24hr</parameter>
|
||||
<parameter>TP90pct24hr</parameter>
|
||||
<parameter>TP95pct24hr</parameter>
|
||||
<parameter>TP5pct72hr</parameter>
|
||||
<parameter>TP10pct72hr</parameter>
|
||||
<parameter>TP25pct72hr</parameter>
|
||||
<parameter>TP50pct72hr</parameter>
|
||||
<parameter>TP75pct72hr</parameter>
|
||||
<parameter>TP90pct72hr</parameter>
|
||||
<parameter>TP95pct72hr</parameter>
|
||||
|
||||
</paramLevelMatches>
|
||||
<imageStyle>
|
||||
|
|
|
@ -139,7 +139,7 @@ Must be paired with proper vm code (also commented out in flashFloodWarning.vm)!
|
|||
<bullet bulletName="rain3" bulletText="Three inches so far" bulletGroup="rainAmt" parseString="THREE INCHES OF RAIN HAVE ALREADY FALLEN"/>
|
||||
<bullet bulletName="rainEdit" bulletText="User defined amount" bulletGroup="rainAmt" parseString="INCHES OF RAIN HAVE FALLEN"/>
|
||||
<bullet bulletText="*********** ADDITIONAL INFO ***********" bulletType="title"/>
|
||||
<bullet bulletName="listofcities" bulletDefault="true" bulletText="Select for a list of cities" bulletGroup="pcast" parseSting=""LOCATIONS","INCLUDE...""/>
|
||||
<bullet bulletName="listofcities" bulletDefault="true" bulletText="Select for a list of cities" bulletGroup="pcast" parseString=""LOCATIONS","INCLUDE...""/>
|
||||
<!-- <bullet bulletName="pathcast" bulletText="Generate Pathcast " bulletGroup="pcast" parseString="THE FOLLOWING LOCATIONS..."/>
|
||||
-->
|
||||
<bullet bulletName="addRainfall" bulletText="Additional rainfall of XX inches expected" parseString="ADDITIONAL RAINFALL"/>
|
||||
|
|
9
edexOsgi/com.raytheon.uf.common.dataplugin.warning/utility/common_static/base/warngen/specialWeatherStatement.xml
Executable file → Normal file
9
edexOsgi/com.raytheon.uf.common.dataplugin.warning/utility/common_static/base/warngen/specialWeatherStatement.xml
Executable file → Normal file
|
@ -5,6 +5,7 @@
|
|||
Mike Dangelo 1/23/2014 added blankStatement bullet
|
||||
Mike Rega 5/23/14 DR 17380 svr wx watch logic OB14.3.1
|
||||
Mike Dangelo 6/24/2014 removed unnecessary example bullets
|
||||
Evan Bookbinder 6/21/2015 fixed bad parse strings (thunderstorms) on two winter weather CTAs.
|
||||
Phil Kurimski 10-20-2015 added campers CTA
|
||||
-->
|
||||
<warngenConfig>
|
||||
|
@ -117,8 +118,8 @@ turned on unless the corresponding .vm file is turned on in a given template's .
|
|||
<bullet bulletName="includeTorWatches" bulletText="Include Tornado Watches" parseString=""/>
|
||||
<bullet bulletName="includeSvrWatches" bulletText="Include Severe Thunderstorm Watches" parseString=""/>
|
||||
<bullet bulletText="******** WINTER WX CALLS TO ACTION (CHOOSE 1 OR MORE) *********" bulletType="title"/>
|
||||
<bullet bulletName="advisoryCTA" bulletText="Advisory may be required" bulletGroup="toggle3" parseString="STORMS MAY INTENSIFY...MONITOR TV"/>
|
||||
<bullet bulletName="advisoryEffectCTA" bulletText="Advisory in effect" bulletGroup="toggle3" parseString="FREQUENT CLOUD TO GROUND LIGHTNING IS OCCURRING"/>
|
||||
<bullet bulletName="advisoryCTA" bulletText="Advisory may be required" bulletGroup="toggle3" parseString="WINTER WEATHER ADVISORY MAY BECOME NECESSARY"/>
|
||||
<bullet bulletName="advisoryEffectCTA" bulletText="Advisory in effect" bulletGroup="toggle3" parseString="WINTER WEATHER ADVISORY IS IN EFFECT"/>
|
||||
<bullet bulletName="snowSquallCTA" bulletText="Snow Squall" parseString="TORRENTIAL RAINFALL IS ALSO OCCURRING"/>
|
||||
<bullet bulletName="freezingDrizzleCTA" bulletText="Freezing Drizzle/Rain" parseString="CONTACT YOUR NEAREST LAW ENFORCEMENT"/>
|
||||
<bullet bulletName="flashFreezeCTA" bulletText="Flash Freeze" parseString="RAPID DROP IN TEMPERATURES"/>
|
||||
|
@ -169,8 +170,8 @@ turned on unless the corresponding .vm file is turned on in a given template's .
|
|||
<bullet bulletName="includeTorWatches" bulletText="Include Tornado Watches" parseString=""/>
|
||||
<bullet bulletName="includeSvrWatches" bulletText="Include Severe Thunderstorm Watches" parseString=""/>
|
||||
<bullet bulletText="******** WINTER WX CALLS TO ACTION (CHOOSE 1 OR MORE) *********" bulletType="title"/>
|
||||
<bullet bulletName="advisoryCTA" bulletText="Advisory may be required" bulletGroup="toggle3" parseString="STORMS MAY INTENSIFY...MONITOR TV"/>
|
||||
<bullet bulletName="advisoryEffectCTA" bulletText="Advisory in effect" bulletGroup="toggle3" parseString="FREQUENT CLOUD TO GROUND LIGHTNING IS OCCURRING"/>
|
||||
<bullet bulletName="advisoryCTA" bulletText="Advisory may be required" bulletGroup="toggle3" parseString="WINTER WEATHER ADVISORY MAY BECOME NECESSARY"/>
|
||||
<bullet bulletName="advisoryEffectCTA" bulletText="Advisory in effect" bulletGroup="toggle3" parseString="WINTER WEATHER ADVISORY IS IN EFFECT"/>
|
||||
<bullet bulletName="snowSquallCTA" bulletText="Snow Squall" parseString="TORRENTIAL RAINFALL IS ALSO OCCURRING"/>
|
||||
<bullet bulletName="freezingDrizzleCTA" bulletText="Freezing Drizzle/Rain" parseString="CONTACT YOUR NEAREST LAW ENFORCEMENT"/>
|
||||
<bullet bulletName="flashFreezeCTA" bulletText="Flash Freeze" parseString="RAPID DROP IN TEMPERATURES"/>
|
||||
|
|
9
edexOsgi/com.raytheon.uf.common.dataplugin.warning/utility/common_static/base/warngen/tornadoWarning.xml
Executable file → Normal file
9
edexOsgi/com.raytheon.uf.common.dataplugin.warning/utility/common_static/base/warngen/tornadoWarning.xml
Executable file → Normal file
|
@ -13,6 +13,7 @@
|
|||
Richard Barnhill 10-28-2013 Changed/added torEMER bulletGroup to keep it locked on followups
|
||||
Mike Dangelo 1-23-2014 Changed parseStrings for default safety rules CTAs and law enf CTA
|
||||
Evan Bookbinder 9-5-2014 Fixed law enf CTA parse strings to match
|
||||
Evan Bookbinder 6-15-15 Fixed incorrect softball and grapefruit hail sizes
|
||||
Evan Bookbinder 12-7-2015 Added TOR EMER CTA back into cta1 bullet group (undid 1/23/2014 change)
|
||||
-->
|
||||
|
||||
|
@ -109,8 +110,8 @@ turned on unless the corresponding .vm file is turned on in a given template's .
|
|||
<bullet bulletName="tennisBallHail" bulletText="Tennis ball hail (2 1/2")" bulletGroup="hailThreat" parseString="TENNIS BALL SIZE"/>
|
||||
<bullet bulletName="baseballHail" bulletText="Baseball size hail (2 3/4")" bulletGroup="hailThreat" parseString="BASEBALL SIZE"/>
|
||||
<bullet bulletName="threeinchHail" bulletText="Three inch hail (3")" bulletGroup="hailThreat" parseString="THREE INCHES IN DIAMETER"/>
|
||||
<bullet bulletName="grapefruitHail" bulletText="Grapefruit size hail (4")" bulletGroup="hailThreat" parseString="GRAPEFRUIT SIZE"/>
|
||||
<bullet bulletName="softballHail" bulletText="Softball size hail (4 1/4")" bulletGroup="hailThreat" parseString="SOFTBALL SIZE"/>
|
||||
<bullet bulletName="softballHail" bulletText="Softball size hail (4")" bulletGroup="hailThreat" parseString="SOFTBALL SIZE"/>
|
||||
<bullet bulletName="grapefruitHail" bulletText="Grapefruit size hail (4 1/2")" bulletGroup="hailThreat" parseString="GRAPEFRUIT SIZE"/>
|
||||
-->
|
||||
<bullet bulletText="" bulletType="title"/>
|
||||
<bullet bulletText="****** ADDITIONAL REPORTS *******" bulletType="title"/>
|
||||
|
@ -173,8 +174,8 @@ turned on unless the corresponding .vm file is turned on in a given template's .
|
|||
<bullet bulletName="tennisBallHail" bulletText="Tennis ball hail (2 1/2")" bulletGroup="hailThreat" parseString="TENNIS BALL SIZE"/>
|
||||
<bullet bulletName="baseballHail" bulletText="Baseball size hail (2 3/4")" bulletGroup="hailThreat" parseString="BASEBALL SIZE"/>
|
||||
<bullet bulletName="threeinchHail" bulletText="Three inch hail (3")" bulletGroup="hailThreat" parseString="THREE INCHES IN DIAMETER"/>
|
||||
<bullet bulletName="grapefruitHail" bulletText="Grapefruit size hail (4")" bulletGroup="hailThreat" parseString="GRAPEFRUIT SIZE"/>
|
||||
<bullet bulletName="softballHail" bulletText="Softball size hail (4 1/4")" bulletGroup="hailThreat" parseString="SOFTBALL SIZE"/>
|
||||
<bullet bulletName="softballHail" bulletText="Softball size hail (4")" bulletGroup="hailThreat" parseString="SOFTBALL SIZE"/>
|
||||
<bullet bulletName="grapefruitHail" bulletText="Grapefruit size hail (4 1/2")" bulletGroup="hailThreat" parseString="GRAPEFRUIT SIZE"/>
|
||||
-->
|
||||
<bullet bulletText="" bulletType="title"/>
|
||||
<bullet bulletText="****** ADDITIONAL REPORTS *******" bulletType="title"/>
|
||||
|
|
|
@ -73,6 +73,9 @@ HDS ^(YEI.[89]8) KWNH (..)(..)(..)[^!]*!(grib|grib2)/ncep/([^/]*)/#([^/]*)/([0-9
|
|||
# ZETA98 KWNE 311200 /mRFC_QPE !grib/ncep/RFC_QPE/#240/201101311200/F006/APCP/sfc/
|
||||
HDS ^(ZETA98) (K[NW][EN][ES]) (..)(..)(..)([^!]*)!(grib|grib2)/[^/]*/([^/]*)/#([^/]*)/([0-9]{8})([0-9]{4})/([^/]*)/([^/]*)
|
||||
FILE -overwrite -log -close -edex /data_store/\7/(\3:yyyy)(\3:mm)\3/\4/\8/GRID\9/\(11)Z_\(12)_\(13)-\1_\2_\3\4\5_(seq).\7.%Y%m%d%H
|
||||
# DR 18644 - Pattern to account for change to grib2
|
||||
ANY ^(ZETA98) (K[NW][EN][ES]) (..)(..)(..)([^!]*)!(grib|grib2)/[^/]*/([^/]*)/#([^/]*)/([0-9]{8})([0-9]{4})(F[0-9]{3})/([^/]*)
|
||||
FILE -overwrite -log -close -edex /data_store/\7/(\3:yyyy)(\3:mm)\3/\4/\8/GRID\9/\(11)Z_\(12)_\(13)-\1_\2_\3\4\5_(seq).\7.%Y%m%d%H
|
||||
|
||||
# AWIPS 1 GRID ^ZEGA98.*KNES /img/SBN/Raw
|
||||
#
|
||||
|
@ -887,7 +890,10 @@ ANY ^(FEAK[45][7-9]|FOAK5[7-9]|FECN[35]0|FOCN30|FEPA[45]0|FOPA50|FEUS5[1-6]|F[EO
|
|||
EXP (.*ecmwf_mos_decrypted.*)
|
||||
FILE -overwrite -log -close -edex \1
|
||||
|
||||
# DR 18637: PQPF data
|
||||
NGRID ^(HEN[A-KXY][0-9][0-9]) (KWNH) (..)(..)(..)[^!]*!(grib|grib2)/[^/]*/([^/]*)/#([^/]*)/([0-9]{8})([0-9]{4})(F[0-9]{3})/([^/]*)
|
||||
FILE -overwrite -log -close -edex /data_store/\6/(\3:yyyy)(\3:mm)\3/\4/\7/GRID\8/\(10)Z_\(11)-\1_\2_\3\4\5_(seq).\6.%Y%m%d%H
|
||||
|
||||
|
||||
|
||||
|
||||
# This separate pattern necessary because some pqpf data cause ldm grib2 errors and it doesn't parse entire grib record
|
||||
NGRID ^(HEN[A-KXY][0-9][0-9]) (KWNH) (..)(..)(..)[^!]*!(grib|grib2)/[^/]*/([^/]*)/#([^/]*)/FHRS/([^/]*)
|
||||
FILE -overwrite -log -close -edex /data_store/\6/(\3:yyyy)(\3:mm)\3/\4/\7/GRID\8/\1_\2_\3\4\5_(seq).\6.%Y%m%d%H
|
||||
|
|
Loading…
Add table
Reference in a new issue