Merge tag 'OB_16.1.2-19' into asm_16.1.2
16.1.2-19 Former-commit-id: a8f3d08e25a0de6957a18c138103886798a0d301
This commit is contained in:
commit
5dc39c363d
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
|
||||
# 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.
|
||||
|
@ -185,12 +185,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
|
||||
|
@ -203,7 +207,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.
|
||||
#
|
||||
|
@ -214,7 +224,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, -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)
|
||||
|
||||
return
|
||||
|
@ -610,7 +620,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])
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Version 2016.01.26-0
|
||||
# Version 2016.02.09-0
|
||||
|
||||
import GenericHazards
|
||||
import string, time, os, re, types, copy, LogStream, collections
|
||||
|
@ -2096,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
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Version 2016.01.26-0
|
||||
# Version 2016.02.09-0
|
||||
|
||||
import GenericHazards
|
||||
import JsonSupport
|
||||
|
@ -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:
|
||||
|
@ -575,9 +575,9 @@ class TextProduct(HLSTCV_Common.TextProduct):
|
|||
else:
|
||||
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):
|
||||
return self._checkContinuousDuration([weatherElement], minimumNumHours, argDict)
|
||||
|
@ -1094,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):
|
||||
|
@ -1327,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":
|
||||
|
@ -1514,6 +1521,9 @@ class SectionCommon():
|
|||
if tr == "default":
|
||||
records = self._textProduct._getVtecRecords(self._segment)
|
||||
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["act"] == "CAN":
|
||||
tr = "recovery"
|
||||
|
@ -1530,6 +1540,30 @@ class SectionCommon():
|
|||
section == "Wind" and \
|
||||
self._pastWindHazardWasCAN():
|
||||
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
|
||||
|
||||
|
@ -1592,7 +1626,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
|
||||
|
||||
|
@ -2840,6 +2874,7 @@ class StormSurgeSectionStats(SectionCommonStats):
|
|||
self._setStats(intersectStatList, timeRangeList)
|
||||
|
||||
def _setStats(self, statList, timeRangeList):
|
||||
windows = []
|
||||
phishStartTime = None
|
||||
phishEndTime = None
|
||||
|
||||
|
@ -2867,7 +2902,7 @@ class StormSurgeSectionStats(SectionCommonStats):
|
|||
|
||||
curPhish = self._textProduct._getStatValue(statDict, "InundationTiming", "Max")
|
||||
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)
|
||||
|
||||
if (curPhish is None) or (curPhish == 'None'):
|
||||
|
@ -2924,13 +2959,39 @@ class StormSurgeSectionStats(SectionCommonStats):
|
|||
phishStartTime = tr.startTime()
|
||||
elif endCondition and (phishStartTime is not None) and (phishEndTime is None):
|
||||
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)
|
||||
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)
|
||||
|
||||
# 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: "
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue