Merge remote-tracking branch 'vlab/tcv_16.1.2' into master_16.1.2
Former-commit-id: 77fef70f5b79331f3c57cb580f0204acc1d9b64d
This commit is contained in:
commit
6070484233
3 changed files with 106 additions and 35 deletions
|
@ -3,7 +3,7 @@
|
||||||
# support, and with no warranty, express or implied, as to its usefulness for
|
# support, and with no warranty, express or implied, as to its usefulness for
|
||||||
# any purpose.
|
# any purpose.
|
||||||
#
|
#
|
||||||
# CoastalThreat
|
# StormSurgeThreat
|
||||||
#
|
#
|
||||||
# Author: Tom LeFebvre/Pablo Santos
|
# Author: Tom LeFebvre/Pablo Santos
|
||||||
# April 20, 2012 - To use gridded MSL TO NAVD and MSL to MLLW
|
# 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
|
# 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
|
# Available on time. Left inactive (commented out) for the moment until that can be fully tested later
|
||||||
# in 2014 or in 2015.
|
# 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.
|
# 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.
|
# This allows sites to specify manually different threat levels across different edit areas and time ranges.
|
||||||
# See 2015HTIUserGuide for details.
|
# 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
|
# The MenuItems list defines the GFE menu item(s) under which the
|
||||||
# Procedure is to appear.
|
# Procedure is to appear.
|
||||||
|
@ -185,12 +185,16 @@ class Procedure (SmartScript.SmartScript):
|
||||||
|
|
||||||
weName = "Surge" + pctStr + "Pctincr"
|
weName = "Surge" + pctStr + "Pctincr"
|
||||||
#print "Attempting to retrieve: ", weName, level
|
#print "Attempting to retrieve: ", weName, level
|
||||||
trList = self.getWEInventory(dbName, weName, level)
|
# get the StormSurgeProb inventory
|
||||||
|
surgeTRList = self.getWEInventory(dbName, weName, level)
|
||||||
if len(trList) == 0:
|
if len(surgeTRList) == 0:
|
||||||
self.statusBarMsg("No grids available for model:" + dbName, "S")
|
self.statusBarMsg("No PHISH grid found.", "U")
|
||||||
return None
|
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
|
n = 1
|
||||||
for tr in trList:
|
for tr in trList:
|
||||||
start = tr.startTime().unixTime() - 6*3600
|
start = tr.startTime().unixTime() - 6*3600
|
||||||
|
@ -203,7 +207,13 @@ class Procedure (SmartScript.SmartScript):
|
||||||
end = tr.startTime().unixTime()
|
end = tr.startTime().unixTime()
|
||||||
tr6 = TimeRange.TimeRange(AbsTime.AbsTime(start),
|
tr6 = TimeRange.TimeRange(AbsTime.AbsTime(start),
|
||||||
AbsTime.AbsTime(end))
|
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.
|
# For consistency we need to add smoothing here too as we do in execute.
|
||||||
#
|
#
|
||||||
|
@ -214,7 +224,7 @@ class Procedure (SmartScript.SmartScript):
|
||||||
if smoothThreatGrid is "Yes":
|
if smoothThreatGrid is "Yes":
|
||||||
phishGrid = np.where(np.greater(phishGrid, 0.0), self.smoothGrid(phishGrid,3), phishGrid)
|
phishGrid = np.where(np.greater(phishGrid, 0.0), self.smoothGrid(phishGrid,3), phishGrid)
|
||||||
|
|
||||||
grid = np.where(phishGrid>-100,phishGrid*3.28, -80.0)
|
grid = np.where(phishGrid>-100, phishGrid*3.28, -80.0) # Convert units from meters to feet
|
||||||
self.createGrid(mutableID, "InundationTiming", "SCALAR", grid, tr6, precision=1)
|
self.createGrid(mutableID, "InundationTiming", "SCALAR", grid, tr6, precision=1)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
@ -610,7 +620,7 @@ class Procedure (SmartScript.SmartScript):
|
||||||
print "Timing grid not found at:", trList[i]
|
print "Timing grid not found at:", trList[i]
|
||||||
|
|
||||||
if (start - baseTime) / 3600 >= inunStartHour and (end - baseTime) / 3600 <= inunEndHour:
|
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])
|
self.createGrid(mutableID, "InundationTiming", "SCALAR", timingGrids[i], trList[i])
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Version 2016.01.26-0
|
# Version 2016.02.09-0
|
||||||
|
|
||||||
import GenericHazards
|
import GenericHazards
|
||||||
import string, time, os, re, types, copy, LogStream, collections
|
import string, time, os, re, types, copy, LogStream, collections
|
||||||
|
@ -2096,7 +2096,7 @@ class TextProduct(HLSTCV_Common.TextProduct):
|
||||||
for label, latLon in refList:
|
for label, latLon in refList:
|
||||||
lat, lon = latLon
|
lat, lon = latLon
|
||||||
localRef = self._calcReference(lat0, lon0, lat, lon)
|
localRef = self._calcReference(lat0, lon0, lat, lon)
|
||||||
localRef = localRef + " OF " + label
|
localRef = localRef + " of " + label
|
||||||
localRef = localRef.replace(",","")
|
localRef = localRef.replace(",","")
|
||||||
localRefs.append(localRef)
|
localRefs.append(localRef)
|
||||||
return localRefs
|
return localRefs
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Version 2016.01.26-0
|
# Version 2016.02.09-0
|
||||||
|
|
||||||
import GenericHazards
|
import GenericHazards
|
||||||
import JsonSupport
|
import JsonSupport
|
||||||
|
@ -513,14 +513,14 @@ class TextProduct(HLSTCV_Common.TextProduct):
|
||||||
gridChecks += [(self._isCorrectNumGrids, "WindThreat", 1, argDict),
|
gridChecks += [(self._isCorrectNumGrids, "WindThreat", 1, argDict),
|
||||||
(self._isContinuousDuration, "Wind", 120, argDict),
|
(self._isContinuousDuration, "Wind", 120, argDict),
|
||||||
(self._isContinuousDuration, "WindGust", 120, argDict),
|
(self._isContinuousDuration, "WindGust", 120, argDict),
|
||||||
(self._isContinuousDuration, "pws34int", 120, argDict),
|
(self._isContinuousDuration, "pws34int", 114, argDict),
|
||||||
(self._isContinuousDuration, "pws64int", 120, argDict),
|
(self._isContinuousDuration, "pws64int", 114, argDict),
|
||||||
(self._isCombinedContinuousDuration, "pwsD34", "pwsN34", 96, argDict),
|
(self._isCombinedContinuousDuration, "pwsD34", "pwsN34", 102, argDict),
|
||||||
(self._isCombinedContinuousDuration, "pwsD64", "pwsN64", 96, argDict),]
|
(self._isCombinedContinuousDuration, "pwsD64", "pwsN64", 102, argDict),]
|
||||||
|
|
||||||
if self._PopulateSurge and len(self._coastalAreas()) != 0:
|
if self._PopulateSurge and len(self._coastalAreas()) != 0:
|
||||||
gridChecks += [(self._isCorrectNumGrids, "InundationMax", 1, argDict),
|
gridChecks += [(self._isCorrectNumGrids, "InundationMax", 1, argDict),
|
||||||
(self._isCorrectNumGrids, "InundationTiming", 13, argDict),]
|
(self._isCorrectNumGrids, "InundationTiming", 12, argDict),]
|
||||||
|
|
||||||
missingGridErrors = []
|
missingGridErrors = []
|
||||||
for gridCheck in gridChecks:
|
for gridCheck in gridChecks:
|
||||||
|
@ -530,9 +530,9 @@ class TextProduct(HLSTCV_Common.TextProduct):
|
||||||
error = ""
|
error = ""
|
||||||
if gridCheck[0] == self._isCorrectNumGrids:
|
if gridCheck[0] == self._isCorrectNumGrids:
|
||||||
if gridCheck[2] == 1:
|
if gridCheck[2] == 1:
|
||||||
error = "%s needs exactly 1 grid" % (gridCheck[1])
|
error = "%s needs at least 1 grid" % (gridCheck[1])
|
||||||
else:
|
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:
|
elif gridCheck[0] == self._isContinuousDuration:
|
||||||
error = "%s needs at least %s continuous hours worth of data" % (gridCheck[1], gridCheck[2])
|
error = "%s needs at least %s continuous hours worth of data" % (gridCheck[1], gridCheck[2])
|
||||||
else:
|
else:
|
||||||
|
@ -575,9 +575,9 @@ class TextProduct(HLSTCV_Common.TextProduct):
|
||||||
else:
|
else:
|
||||||
gridTimes.append(gridTime)
|
gridTimes.append(gridTime)
|
||||||
|
|
||||||
self.debug_print("Length of grid times: %s" % (self._pp.pformat(len(gridTimes))), 1)
|
self.debug_print("Actual number of grids: %s" % (self._pp.pformat(len(gridTimes))), 1)
|
||||||
|
|
||||||
return len(gridTimes) == expectedNumGrids
|
return len(gridTimes) >= expectedNumGrids
|
||||||
|
|
||||||
def _isContinuousDuration(self, weatherElement, minimumNumHours, argDict):
|
def _isContinuousDuration(self, weatherElement, minimumNumHours, argDict):
|
||||||
return self._checkContinuousDuration([weatherElement], minimumNumHours, argDict)
|
return self._checkContinuousDuration([weatherElement], minimumNumHours, argDict)
|
||||||
|
@ -1094,13 +1094,15 @@ class TextProduct(HLSTCV_Common.TextProduct):
|
||||||
def _initializeSegmentZoneData(self, segment):
|
def _initializeSegmentZoneData(self, segment):
|
||||||
# The current advisory will be populated when getting a section's stats
|
# The current advisory will be populated when getting a section's stats
|
||||||
self._currentAdvisory['ZoneData'][segment] = {
|
self._currentAdvisory['ZoneData'][segment] = {
|
||||||
"WindThreat": None,
|
"WindThreat": None,
|
||||||
"WindForecast": None,
|
"WindForecast": None,
|
||||||
"StormSurgeThreat": None,
|
"WindHighestPhaseReached": None,
|
||||||
"StormSurgeForecast": None,
|
"StormSurgeThreat": None,
|
||||||
"FloodingRainThreat": None,
|
"StormSurgeForecast": None,
|
||||||
"FloodingRainForecast": None,
|
"StormSurgeHighestPhaseReached": None,
|
||||||
"TornadoThreat": None,
|
"FloodingRainThreat": None,
|
||||||
|
"FloodingRainForecast": None,
|
||||||
|
"TornadoThreat": None,
|
||||||
}
|
}
|
||||||
|
|
||||||
def _getPreviousAdvisories(self):
|
def _getPreviousAdvisories(self):
|
||||||
|
@ -1327,6 +1329,11 @@ class SectionCommon():
|
||||||
|
|
||||||
def _isThreatNoneForEntireStorm(self, threatName):
|
def _isThreatNoneForEntireStorm(self, threatName):
|
||||||
previousAdvisories = self._textProduct._getPreviousAdvisories()
|
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:
|
for advisory in previousAdvisories:
|
||||||
if advisory["ZoneData"][self._segment][threatName] != "None":
|
if advisory["ZoneData"][self._segment][threatName] != "None":
|
||||||
|
@ -1514,6 +1521,9 @@ class SectionCommon():
|
||||||
if tr == "default":
|
if tr == "default":
|
||||||
records = self._textProduct._getVtecRecords(self._segment)
|
records = self._textProduct._getVtecRecords(self._segment)
|
||||||
for record in records:
|
for record in records:
|
||||||
|
if self._textProduct._currentAdvisory['ZoneData'][self._segment]["WindThreat"] != "None":
|
||||||
|
tr = "hunker down"
|
||||||
|
break
|
||||||
if record["phen"] in ["HU", "TR"] and record["sig"] == "W":
|
if record["phen"] in ["HU", "TR"] and record["sig"] == "W":
|
||||||
if record["act"] == "CAN":
|
if record["act"] == "CAN":
|
||||||
tr = "recovery"
|
tr = "recovery"
|
||||||
|
@ -1530,6 +1540,30 @@ class SectionCommon():
|
||||||
section == "Wind" and \
|
section == "Wind" and \
|
||||||
self._pastWindHazardWasCAN():
|
self._pastWindHazardWasCAN():
|
||||||
tr = "recovery"
|
tr = "recovery"
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------
|
||||||
|
# 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"
|
||||||
|
|
||||||
|
if tr == "default":
|
||||||
|
if self._textProduct._currentAdvisory['ZoneData'][self._segment][highestPhaseReachedField] == "recovery":
|
||||||
|
tr = "recovery"
|
||||||
|
else:
|
||||||
|
highestPhaseIndex = \
|
||||||
|
phaseOrder.index(self._textProduct._currentAdvisory['ZoneData'][self._segment][highestPhaseReachedField])
|
||||||
|
currentPhaseIndex = phaseOrder.index(tr)
|
||||||
|
|
||||||
|
if currentPhaseIndex < highestPhaseIndex:
|
||||||
|
tr = self._textProduct._currentAdvisory['ZoneData'][self._segment][highestPhaseReachedField]
|
||||||
|
elif currentPhaseIndex > highestPhaseIndex:
|
||||||
|
self._textProduct._currentAdvisory['ZoneData'][self._segment][highestPhaseReachedField] = tr
|
||||||
|
|
||||||
return tr
|
return tr
|
||||||
|
|
||||||
|
@ -1592,7 +1626,7 @@ class SectionCommon():
|
||||||
with open("/awips2/cave/etc/gfe/userPython/utilities/TCVDictionary.py", 'r') as pythonFile:
|
with open("/awips2/cave/etc/gfe/userPython/utilities/TCVDictionary.py", 'r') as pythonFile:
|
||||||
fileContents = pythonFile.read()
|
fileContents = pythonFile.read()
|
||||||
exec(fileContents)
|
exec(fileContents)
|
||||||
|
|
||||||
# ThreatStatements comes from TCVDictionary.py when it is exec'ed
|
# ThreatStatements comes from TCVDictionary.py when it is exec'ed
|
||||||
threatStatements = ThreatStatements
|
threatStatements = ThreatStatements
|
||||||
|
|
||||||
|
@ -2840,6 +2874,7 @@ class StormSurgeSectionStats(SectionCommonStats):
|
||||||
self._setStats(intersectStatList, timeRangeList)
|
self._setStats(intersectStatList, timeRangeList)
|
||||||
|
|
||||||
def _setStats(self, statList, timeRangeList):
|
def _setStats(self, statList, timeRangeList):
|
||||||
|
windows = []
|
||||||
phishStartTime = None
|
phishStartTime = None
|
||||||
phishEndTime = None
|
phishEndTime = None
|
||||||
|
|
||||||
|
@ -2867,7 +2902,7 @@ class StormSurgeSectionStats(SectionCommonStats):
|
||||||
|
|
||||||
curPhish = self._textProduct._getStatValue(statDict, "InundationTiming", "Max")
|
curPhish = self._textProduct._getStatValue(statDict, "InundationTiming", "Max")
|
||||||
self._textProduct.debug_print("curPhish = '%s'" % (str(curPhish)), 1)
|
self._textProduct.debug_print("curPhish = '%s'" % (str(curPhish)), 1)
|
||||||
self._textProduct.debug_print("phishStartTime = %s phishEndTime = %s" %
|
self._textProduct.debug_print("phishStartTime = %s phishEndTime = %s" %
|
||||||
(str(phishStartTime), str(phishEndTime)), 1)
|
(str(phishStartTime), str(phishEndTime)), 1)
|
||||||
|
|
||||||
if (curPhish is None) or (curPhish == 'None'):
|
if (curPhish is None) or (curPhish == 'None'):
|
||||||
|
@ -2924,13 +2959,39 @@ class StormSurgeSectionStats(SectionCommonStats):
|
||||||
phishStartTime = tr.startTime()
|
phishStartTime = tr.startTime()
|
||||||
elif endCondition and (phishStartTime is not None) and (phishEndTime is None):
|
elif endCondition and (phishStartTime is not None) and (phishEndTime is None):
|
||||||
phishEndTime = tr.startTime()
|
phishEndTime = tr.startTime()
|
||||||
self._textProduct.debug_print("final phishStartTime = %s final phishEndTime = %s" %
|
|
||||||
|
# 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)
|
(str(phishStartTime), str(phishEndTime)), 1)
|
||||||
break
|
|
||||||
|
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" %
|
self._textProduct.debug_print("new phishStartTime = %s new phishEndTime = %s" %
|
||||||
(str(phishStartTime), str(phishEndTime)), 1)
|
(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: "
|
self._windowSurge = "Window of concern: "
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue