Merge branch 'tcv_14.3.2' of ssh://vlab.ncep.noaa.gov:29418/AWIPS2_Dev_Baseline into master_14.3.2

Former-commit-id: d193ca5eb6 [formerly f0c6dcb30718baede5c31bcb267d3b4524252ab8]
Former-commit-id: 50ab069dbc
This commit is contained in:
Fay.Liang 2015-01-12 14:55:55 -05:00
commit e95f66b7f7
10 changed files with 491 additions and 374 deletions

View file

@ -1,4 +1,4 @@
# Version 2014.12.12-0 # Version 2014.12.17-0
import GenericHazards import GenericHazards
import JsonSupport import JsonSupport
@ -6,6 +6,7 @@ import LocalizationSupport
import string, time, os, errno, re, types, copy, collections import string, time, os, errno, re, types, copy, collections
import LogStream, ModuleAccessor, SampleAnalysis, EditAreaUtils import LogStream, ModuleAccessor, SampleAnalysis, EditAreaUtils
import math import math
import pprint
from AbsTime import * from AbsTime import *
from StartupDialog import IFPDialog as Dialog from StartupDialog import IFPDialog as Dialog
@ -17,6 +18,8 @@ class TextProduct(GenericHazards.TextProduct):
def __init__(self): def __init__(self):
GenericHazards.TextProduct.__init__(self) GenericHazards.TextProduct.__init__(self)
self._pp = pprint.PrettyPrinter()
############################################################### ###############################################################
### Hazards and Additional Hazards ### Hazards and Additional Hazards
@ -242,7 +245,8 @@ class TextProduct(GenericHazards.TextProduct):
removedParts.append(part) removedParts.append(part)
for part in removedParts: for part in removedParts:
self.debug_print("SARAH: Removing part = %s" % (part), 1) self.debug_print("in _processProductParts - " +
"Removing product part = %s" % (part), 1)
partsList.remove(part) partsList.remove(part)
################# Product Parts Helper Methods ################# Product Parts Helper Methods
@ -502,15 +506,16 @@ class TextProduct(GenericHazards.TextProduct):
for area in hazard['id']: for area in hazard['id']:
hazDict.setdefault((hdln, phen, sig), []).append(area) hazDict.setdefault((hdln, phen, sig), []).append(area)
#self.debug_print("hazDict", hazDict self.debug_print("hazDict = %s" % (self._pp.pformat(hazDict)), 1)
hazardHdlns=[] hazardHdlns=[]
huAreas = [] huAreas = []
# self.debug_print("\nAdditional Hazard Headlines" self.debug_print("Additional Hazard Headlines", 1)
for key in hazDict.keys(): for key in hazDict.keys():
hdln, phen, sig = key hdln, phen, sig = key
huAreas = huAreas + hazDict[key] huAreas = huAreas + hazDict[key]
hazardHdln = ((hdln, "NEW", phen,sig), hazDict[key], [],[],[]) hazardHdln = ((hdln, "NEW", phen,sig), hazDict[key], [],[],[])
#self.debug_print(" ", hazardHdln, hazDict[key] self.debug_print(" %s" % (self._pp.pformat(hazardHdln)), 1)
self.debug_print(" %s" % (self._pp.pformat(hazDict[key])), 1)
hazardHdlns.append(hazardHdln) hazardHdlns.append(hazardHdln)
return hazardHdlns, huAreas return hazardHdlns, huAreas
@ -533,14 +538,12 @@ class TextProduct(GenericHazards.TextProduct):
# Otherwise, they are ignored. # Otherwise, they are ignored.
# #
# E.g. hdlnList = self._checkHazard(hazardHdlns, [("FA","W")], returnList=True) # E.g. hdlnList = self._checkHazard(hazardHdlns, [("FA","W")], returnList=True)
self.debug_print("_checkHazard hazardHdlns is %s" % (hazardHdlns), 1) self.debug_print("_checkHazard hazardHdlns is %s" % (self._pp.pformat(hazardHdlns)), 1)
self.debug_print("_checkHazard phenSigList is %s" % (phenSigList), 1) self.debug_print("_checkHazard phenSigList is %s" % (self._pp.pformat(phenSigList)), 1)
chosen = [] chosen = []
for key, landList, marineList, coastalList, inlandList in hazardHdlns: for key, landList, marineList, coastalList, inlandList in hazardHdlns:
# self.debug_print("what is mode? %s" % mode, 1)
# SARAH - we do not want to consider marine hazards in this product # We do not want to consider marine hazards in this product
# hazAreas = landList+marineList
hazAreas = landList hazAreas = landList
hazValue = (key, hazAreas) hazValue = (key, hazAreas)
self.debug_print("hazValue is %s" % (repr(hazValue)), 1) self.debug_print("hazValue is %s" % (repr(hazValue)), 1)
@ -555,10 +558,9 @@ class TextProduct(GenericHazards.TextProduct):
# Check for land, marine, etc. # Check for land, marine, etc.
for checkAreaType in checkAreaTypes: for checkAreaType in checkAreaTypes:
exec "testList = " + checkAreaType + "List" exec "testList = " + checkAreaType + "List"
# self.debug_print("testList is %s" % testList, 1) self.debug_print("testList is %s" % (testList), 1)
if testList != []: if testList != []:
chosen.append(hazValue) chosen.append(hazValue)
# self.debug_print("chosen is %s" % chosen, 1)
elif checkAreas is not None: elif checkAreas is not None:
acceptedAreas=[] acceptedAreas=[]
for hazArea in hazAreas: for hazArea in hazAreas:
@ -570,7 +572,8 @@ class TextProduct(GenericHazards.TextProduct):
chosen.append(hazValue) chosen.append(hazValue)
if not returnList and chosen!=[]: break if not returnList and chosen!=[]: break
self.debug_print("MATT _checkHazard chosen = %s" % (repr(chosen)), 1) self.debug_print("In _checkHazard chosen = %s" %
(self._pp.pformat(chosen)), 1)
if not returnList: if not returnList:
return chosen!=[] return chosen!=[]
return chosen return chosen
@ -609,7 +612,8 @@ class TextProduct(GenericHazards.TextProduct):
trList = [] trList = []
self._periodList = [] self._periodList = []
for index, tr in enumerate(subRanges): for index, tr in enumerate(subRanges):
# self.debug_print(tr) self.debug_print("In _determineTimeRanges -> tr = %s" %
(self._pp.pformat(tr)), 1)
trList.append((tr, "Label")) trList.append((tr, "Label"))
if index == 0: if index == 0:
@ -633,10 +637,13 @@ class TextProduct(GenericHazards.TextProduct):
period = self.makeTimeRange(startTime, startTime+periodLength*3600) period = self.makeTimeRange(startTime, startTime+periodLength*3600)
self._periodList.append(period) self._periodList.append(period)
for i in range(1,10): for i in range(1,10):
startTime = period.endTime() # Start where the last period leaves off startTime = period.endTime() # Start where the last period leaves off
period = self.makeTimeRange(startTime, startTime+12*3600) period = self.makeTimeRange(startTime, startTime+12*3600)
self._periodList.append(period) self._periodList.append(period)
self.debug_print("final periodList =\n\n%s\n" %
(self._pp.pformat(self._periodList)), 1)
self._timeRangeList = trList self._timeRangeList = trList
def _calculateStartTime(self, localCreationTime): def _calculateStartTime(self, localCreationTime):
@ -645,21 +652,21 @@ class TextProduct(GenericHazards.TextProduct):
day = localCreationTime[2] day = localCreationTime[2]
hour = localCreationTime[3] hour = localCreationTime[3]
# If we are more than halfway though a 3 hr period # Define a variable to control which resolution we want
if hour % 3 > 1: resolution = self._resolution() # 6 is also a valid option
adjust = 3 # move on to the next 3 hr block
# If we are more than halfway though a block we would want
if hour % resolution > resolution / 2:
adjust = resolution # move on to the next block
else: else:
adjust = 0 adjust = 0
# if hour % 6 > 3: self.debug_print("In _calculateStartTime %d adjust = %d" %
# adjust = 6 # move on to the next 6 hr block (hour % resolution, adjust), 1)
# else:
# adjust = 0
# self.debug_print("MATT: _calculateStartTime %d adjust = %d" % (hour % 6, adjust)
# Now "truncate" to a 3-hourly boundary and compute startTime in local Time. # Now "truncate" to a block boundary and compute startTime in local time.
# hour = int( (hour/6) * 6) + adjust # hour = int( (hour/3) * 3) + adjust
hour = int( (hour/3) * 3) + adjust hour = int( (hour/resolution) * resolution) + adjust
if hour > 23: if hour > 23:
hour -= 24 hour -= 24
elif hour < 0: elif hour < 0:
@ -678,7 +685,7 @@ class TextProduct(GenericHazards.TextProduct):
# DAY + MORNING / AFTERNOON / EVENING / OVERNIGHT. # DAY + MORNING / AFTERNOON / EVENING / OVERNIGHT.
# If wholePeriod, format FROM ... TO... # If wholePeriod, format FROM ... TO...
self.debug_print("MATT Format period wholePeriod = %s, period = %s, useEndTime =%s" % self.debug_print("Format period wholePeriod = %s, period = %s, useEndTime =%s" %
(str(wholePeriod), str(period), str(useEndTime)), 1) (str(wholePeriod), str(period), str(useEndTime)), 1)
if period is None: if period is None:
return "" return ""
@ -687,10 +694,10 @@ class TextProduct(GenericHazards.TextProduct):
else: else:
startTime = period.startTime() startTime = period.startTime()
result = self._getTimeDesc(startTime, resolution, shiftToLocal) result = self._getTimeDesc(startTime, resolution, shiftToLocal)
self.debug_print("MATT result = '%s'" % (result), 1) self.debug_print("_getTimeDesc result = '%s'" % (result), 1)
if wholePeriod: if wholePeriod:
endResult = self._getTimeDesc(period.endTime(), resolution, shiftToLocal) endResult = self._getTimeDesc(period.endTime(), resolution, shiftToLocal)
self.debug_print("MATT endResult = '%s'" % (endResult), 1) self.debug_print("_getTimeDesc endResult = '%s'" % (endResult), 1)
if result != endResult: if result != endResult:
result=result + " TO "+ endResult result=result + " TO "+ endResult
return result return result
@ -1020,6 +1027,7 @@ FORECASTER STEWART"""
self._loadLastTwoAdvisories() self._loadLastTwoAdvisories()
def _synchronizeAdvisories(self): def _synchronizeAdvisories(self):
# Retrieving a directory causes synching to occur # Retrieving a directory causes synching to occur
file = LocalizationSupport.getLocalizationFile(LocalizationSupport.CAVE_STATIC, file = LocalizationSupport.getLocalizationFile(LocalizationSupport.CAVE_STATIC,
LocalizationSupport.SITE, self._site, LocalizationSupport.SITE, self._site,
@ -1044,12 +1052,12 @@ FORECASTER STEWART"""
filenames = os.listdir(advisoryDirectoryPath) filenames = os.listdir(advisoryDirectoryPath)
allAdvisories = filter(lambda filename: filename[-5:] == ".json", filenames) allAdvisories = filter(lambda filename: filename[-5:] == ".json", filenames)
self.debug_print("allAdvisories = %s" % (repr(allAdvisories))) self.debug_print("allAdvisories = %s" % (self._pp.pformat(allAdvisories)))
stormAdvisories = filter(lambda filename: self._getStormNameFromTCP() in filename, stormAdvisories = filter(lambda filename: self._getStormNameFromTCP() in filename,
allAdvisories) allAdvisories)
stormAdvisories = map(lambda filename: filename[:-5], stormAdvisories) stormAdvisories = map(lambda filename: filename[:-5], stormAdvisories)
self.debug_print("stormAdvisories = %s" % (repr(stormAdvisories))) self.debug_print("stormAdvisories = %s" % (self._pp.pformat(stormAdvisories)))
return stormAdvisories return stormAdvisories
@ -1074,8 +1082,8 @@ FORECASTER STEWART"""
else: # Must be the HLS else: # Must be the HLS
lastTwoAdvisories = stormAdvisories[:2] lastTwoAdvisories = stormAdvisories[:2]
self.debug_print("MATT DEBUG: last two advisories = %s" % self.debug_print("DEBUG: last two advisories = %s" %
(repr(lastTwoAdvisories)), 1) (self._pp.pformat(lastTwoAdvisories)), 1)
self._previousAdvisory = None self._previousAdvisory = None
if len(lastTwoAdvisories) >= 1: if len(lastTwoAdvisories) >= 1:
self._previousAdvisory = self._loadAdvisory(lastTwoAdvisories[0]) self._previousAdvisory = self._loadAdvisory(lastTwoAdvisories[0])
@ -1093,8 +1101,8 @@ FORECASTER STEWART"""
self._site, self._site,
fileName) fileName)
self.debug_print("SARAH: File contents for %s:" % (fileName), 1) self.debug_print("File contents for %s:" % (fileName), 1)
self.debug_print(repr(pythonDict), 1) self.debug_print(self._pp.pformat(pythonDict), 1)
# Only use transmitted advisories # Only use transmitted advisories
if pythonDict["Transmitted"] == False and advisoryName != "pending": if pythonDict["Transmitted"] == False and advisoryName != "pending":
@ -1102,8 +1110,7 @@ FORECASTER STEWART"""
else: else:
return pythonDict return pythonDict
except Exception, e: except Exception, e:
self.debug_print("SARAH Load Exception for %s : %s" % self.debug_print("Load Exception for %s : %s" % (fileName, e), 1)
(fileName, e), 1)
return None return None
def _getAdvisoryPath(self): def _getAdvisoryPath(self):
@ -1170,6 +1177,7 @@ class Common_Dialog(Dialog):
self._varDict = {} # all end results must be saved here self._varDict = {} # all end results must be saved here
self._infoDict = infoDict self._infoDict = infoDict
self._parent = parent self._parent = parent
self._pp = pprint.PrettyPrinter()
Dialog.__init__(self, parent=None, title=title) Dialog.__init__(self, parent=None, title=title)
def getVarDict(self): def getVarDict(self):

View file

@ -630,7 +630,7 @@ PotentialImpactStatements = {
}, },
} }
EvacuationStatements = ["For those under evacuation orders, leave as soon as practical with a destination in mind. Gas up your vehicle well ahead of time. Be sure that you take essential materiasl from your Emergency Supplies Kit. Let others know where you are going and when you intend to arrive.", EvacuationStatements = ["For those under evacuation orders, leave as soon as practical with a destination in mind. Gas up your vehicle well ahead of time. Be sure that you take essential materials from your Emergency Supplies Kit. Let others know where you are going and when you intend to arrive.",
"If evacuating the area, stick to prescribed evacuation routes. Look for additional traffic information on roadway smart signs and listen to select radio channels for further travel instructions. Do not use your cell phone while driving." "If evacuating the area, stick to prescribed evacuation routes. Look for additional traffic information on roadway smart signs and listen to select radio channels for further travel instructions. Do not use your cell phone while driving."
"For those not under evacuation orders, understand that there are inherent risks to evacuation (such as traffic congestion, accidents, and driving in bad weather), so evacuate only if necessary. Help keep roadways open for those that are under evacuation orders."] "For those not under evacuation orders, understand that there are inherent risks to evacuation (such as traffic congestion, accidents, and driving in bad weather), so evacuate only if necessary. Help keep roadways open for those that are under evacuation orders."]
@ -678,7 +678,6 @@ OtherPreparednessActions = {
"Problems with sewer backups can contaminate standing flood waters. Keep children away. Also, listen for boil water alerts relative to communities whose tap water may have become temporarily non-potable."], "Problems with sewer backups can contaminate standing flood waters. Keep children away. Also, listen for boil water alerts relative to communities whose tap water may have become temporarily non-potable."],
} }
AdditionalSources = ["- For information on appropriate preparations see ready.gov/louisiana", AdditionalSources = ["- For information on appropriate preparations see ready.gov",
"- For information on local evacuation shelters see www.emergency.louisana.gov/disaster_evaluation_guide.html",
"- For information on creating an emergency plan see getagameplan.org", "- For information on creating an emergency plan see getagameplan.org",
"- For additional disaster preparedness information see redcross.org"] "- For additional disaster preparedness information see redcross.org"]

View file

@ -192,48 +192,47 @@ public final class TPCWatchSrv extends AbstractWatchNotifierSrv {
// if it's a TCV // if it's a TCV
if ("TCV".equals(pil)) { if ("TCV".equals(pil)) {
super.handleWatch(warningRecs); super.handleWatch(warningRecs);
}
// if we are not in practice mode // if we are not in practice mode
if (!practiceMode) { if (!practiceMode) {
// if xxxId ends with a digit (i.e. its a national TCV) // if xxxId ends with a digit (i.e. its a national TCV)
String xxxId = record.getXxxid(); String xxxId = record.getXxxid();
if (Character.isDigit(xxxId.charAt(xxxId.length() - 1))) { if (Character.isDigit(xxxId.charAt(xxxId.length() - 1))) {
// build the full 9-letter PIL // build the full 9-letter PIL
String fullPil = SiteMap.getInstance().mapICAOToCCC( String fullPil = SiteMap.getInstance().mapICAOToCCC(
issuingOffice) issuingOffice)
+ pil + xxxId; + pil + xxxId;
// build the command line for the NWRWAVES script // build the command line for the NWRWAVES script
final String command = NWRWAVES_SCRIPT + fullPil; final String command = NWRWAVES_SCRIPT + fullPil;
// Create a separate thread to run the script // Create a separate thread to run the script
Thread thread = new Thread(new Runnable() { Thread thread = new Thread(new Runnable() {
@Override @Override
public void run() { public void run() {
RunProcess proc; RunProcess proc;
try { try {
proc = RunProcess.getRunProcess().exec(command); proc = RunProcess.getRunProcess().exec(command);
} catch (IOException e) { } catch (IOException e) {
statusHandler.error("Error executing " statusHandler
+ command, e); .error("Error executing " + command, e);
return; return;
}
int exitCode = proc.waitFor();
if (exitCode != 0) {
statusHandler
.error(command
+ " terminated abnormally with exit code: "
+ exitCode);
}
} }
});
thread.start(); int exitCode = proc.waitFor();
} if (exitCode != 0) {
statusHandler.error(command
+ " terminated abnormally with exit code: "
+ exitCode);
}
}
});
thread.start();
} }
} }
@ -296,7 +295,11 @@ public final class TPCWatchSrv extends AbstractWatchNotifierSrv {
statusHandler.error("Unable to delete " + pendingFile, e); statusHandler.error("Unable to delete " + pendingFile, e);
} }
sendTCVFiles(siteId); // if not practice mode
if (!practiceMode) {
// send TCV files to VTEC partner sites
sendTCVFiles(siteId);
}
} }
} }

View file

@ -516,24 +516,39 @@ class TextProduct(TextRules.TextRules, SampleAnalysis.SampleAnalysis,
nwsIntroUsed = 1 nwsIntroUsed = 1
if phraseCount == 0: if phraseCount == 0:
phraseCount = 1 phraseCount = 1
hazardBodyPhrase = hazardBodyPhrase + " HAS ISSUED " + \ if eachHazard['phen'] in ['HU', 'TR', 'TY']:
hazNameA + forPhrase + \ hazardBodyPhrase = hazardBodyPhrase + " HAS ISSUED " + \
"...WHICH IS IN EFFECT" + endTimePhrase + ". " hazNameA + ". "
else:
hazardBodyPhrase = hazardBodyPhrase + " HAS ISSUED " + \
hazNameA + forPhrase + \
"...WHICH IS IN EFFECT" + endTimePhrase + ". "
elif phraseCount == 1: elif phraseCount == 1:
phraseCount = 2 phraseCount = 2
if hdln != lastHdln: if hdln != lastHdln:
hazardBodyPhrase = hazardBodyPhrase + hazNameA + \ if eachHazard['phen'] in ['HU', 'TR', 'TY']:
" HAS ALSO BEEN ISSUED. THIS " + hazName + forPhrase + \ hazardBodyPhrase = hazardBodyPhrase + hazNameA + \
" IS IN EFFECT" + endTimePhrase + ". " " HAS ALSO BEEN ISSUED."
else:
hazardBodyPhrase = hazardBodyPhrase + hazNameA + \
" HAS ALSO BEEN ISSUED. THIS " + hazName + forPhrase + \
" IS IN EFFECT" + endTimePhrase + ". "
else: else:
hazardBodyPhrase = hazardBodyPhrase + hazNameA + \ if eachHazard['phen'] in ['HU', 'TR', 'TY']:
" HAS ALSO BEEN ISSUED" + endTimePhrase + ". " hazardBodyPhrase = hazardBodyPhrase + hazNameA + \
" HAS ALSO BEEN ISSUED."
else:
hazardBodyPhrase = hazardBodyPhrase + hazNameA + forPhrase + \
" HAS ALSO BEEN ISSUED" + endTimePhrase + ". "
else: else:
hazardBodyPhrase = hazardBodyPhrase + "IN ADDITION..." + \ if eachHazard['phen'] in ['HU', 'TR', 'TY']:
hazNameA + forPhrase + " HAS BEEN ISSUED. THIS " + hazName + \ hazardBodyPhrase = hazardBodyPhrase + "IN ADDITION..." + \
" IS IN EFFECT" + endTimePhrase + ". " hazNameA + " HAS BEEN ISSUED."
else:
hazardBodyPhrase = hazardBodyPhrase + "IN ADDITION..." + \
hazNameA + forPhrase + " HAS BEEN ISSUED. THIS " + hazName + \
" IS IN EFFECT" + endTimePhrase + ". "
lastHdln = hdln lastHdln = hdln
# #
# This is for the can hazards # This is for the can hazards
# #

View file

@ -1,4 +1,4 @@
# Version 2014.12.12-0 # Version 2015.1.6-0
import GenericHazards import GenericHazards
import string, time, os, re, types, copy, LogStream, collections import string, time, os, re, types, copy, LogStream, collections
@ -358,7 +358,7 @@ class TextProduct(HLSTCV_Common.TextProduct):
if self._ImpactsAnticipated: if self._ImpactsAnticipated:
includedImpacts = sorted(self._IncludedImpacts, key=self._impactsKeyFunction) includedImpacts = sorted(self._IncludedImpacts, key=self._impactsKeyFunction)
for ((_, sectionName), _) in includedImpacts: for ((_, sectionName), _) in includedImpacts:
self.debug_print("SARAH: adding section = '%s'" % (sectionName), 1) self.debug_print("adding section = '%s'" % (sectionName), 1)
partsList.append(sectionName) partsList.append(sectionName)
partsList.append('preparednessSection') partsList.append('preparednessSection')
@ -371,7 +371,7 @@ class TextProduct(HLSTCV_Common.TextProduct):
partsList.append('nextUpdate') partsList.append('nextUpdate')
partsList.append('endProduct') partsList.append('endProduct')
self.debug_print("Product Parts partsList = %s" % partsList, 1) self.debug_print("Product Parts partsList =\n\n%s\n" % (self._pp.pformat(partsList)), 1)
return { return {
'partsList': partsList 'partsList': partsList
@ -466,7 +466,7 @@ class TextProduct(HLSTCV_Common.TextProduct):
self._initializeHeadlines() self._initializeHeadlines()
self._ugcs = self._allAreas() self._ugcs = sorted(self._allAreas())
return None return None
@ -660,15 +660,17 @@ class TextProduct(HLSTCV_Common.TextProduct):
elif len(impactParts) == 1: elif len(impactParts) == 1:
impactRangeRest = impactParts[0] impactRangeRest = impactParts[0]
self.debug_print("MATT DEBUG: impactRange = '%s' impactMax = '%s' impactMin = '%s'" % (impactRange, impactMax, impactMin), 1) self.debug_print("DEBUG: impactRange = '%s' impactMax = '%s' impactMin = '%s'" %
(impactRange, impactMax, impactMin), 1)
# If there are additional life-threatening surge areas # If there are additional life-threatening surge areas
if impactRange != impactMax and impactRange != impactMin: if impactRange != impactMax and impactRange != impactMin:
curPhrase = "Brace for %s%s damage across %s." % \ curPhrase = "Brace for %s%s damage across %s." % \
(lifeThreatening, impactRange, self._frame("ENTER AREA DESCRIPTION")) (lifeThreatening, impactRange, self._frame("ENTER AREA DESCRIPTION"))
self.debug_print("MATT DEBUG: curPhrase = '%s'" % (curPhrase), 1) self.debug_print("DEBUG: curPhrase = '%s'" % (curPhrase), 1)
self.debug_print("MATT DEBUG: sectionDict['additionalImpactRange'] = '%s'" % (repr(sectionDict['additionalImpactRange'])), 1) self.debug_print("DEBUG: sectionDict['additionalImpactRange'] = \n'%s'" %
(sectionDict['additionalImpactRange']), 1)
# If this phrase is not already part of the additional impacts # If this phrase is not already part of the additional impacts
if curPhrase not in sectionDict['additionalImpactRange']: if curPhrase not in sectionDict['additionalImpactRange']:
@ -699,7 +701,8 @@ class TextProduct(HLSTCV_Common.TextProduct):
# Add it now # Add it now
sectionDict['additionalImpactRange'].append(curPhrase) sectionDict['additionalImpactRange'].append(curPhrase)
self.debug_print("Final Surge sectionDict['additionalImpactRange'] = '%s'" % (sectionDict['additionalImpactRange']), 1) self.debug_print("Final Surge sectionDict['additionalImpactRange'] = '%s'" %
(sectionDict['additionalImpactRange']), 1)
productDict['surgeSection'] = sectionDict productDict['surgeSection'] = sectionDict
def _floodingRainSection(self, productDict, productSegmentGroup, productSegment): def _floodingRainSection(self, productDict, productSegmentGroup, productSegment):
@ -716,7 +719,7 @@ class TextProduct(HLSTCV_Common.TextProduct):
inputThreatDominant = self._samplingDict['FloodingRainThreat']['inputThreatDominant'] inputThreatDominant = self._samplingDict['FloodingRainThreat']['inputThreatDominant']
self.debug_print("In _floodingRainSection", 1) self.debug_print("In _floodingRainSection", 1)
self.debug_print("_samplingDict = %s" % (repr(self._samplingDict['FloodingRainThreat'])), 1) self.debug_print("_samplingDict = \n\n%s\n" % (self._pp.pformat(self._samplingDict['FloodingRainThreat'])), 1)
# Test the simplest case first # Test the simplest case first
if impactMin == "none" and impactMax == "none": if impactMin == "none" and impactMax == "none":
@ -935,10 +938,10 @@ class TextProduct(HLSTCV_Common.TextProduct):
for key in keys: for key in keys:
self.debug_print("%s : %s" % (key, self._previousAdvisory[key]), 1) self.debug_print("%s : %s" % (key, self._previousAdvisory[key]), 1)
for hazard in self._previousAdvisory["HazardsForHLS"]: for hazard in self._previousAdvisory["HazardsForHLS"]:
self.debug_print("SARAH DEBUG Hazard: %s" % (repr(hazard)), 1) self.debug_print("DEBUG Hazard: %s" % (self._pp.pformat(hazard)), 1)
if hazard['act'] != 'CON': if hazard['act'] != 'CON':
self._changesHazardsList.append(hazard) self._changesHazardsList.append(hazard)
if hazard['act'] != 'CAN': if hazard['act'] not in ['CAN', "UPG"]:
self._currentHazardsList.append(hazard) self._currentHazardsList.append(hazard)
self.debug_print("-"*80, 1) self.debug_print("-"*80, 1)
@ -963,7 +966,7 @@ class TextProduct(HLSTCV_Common.TextProduct):
self.debug_print("=" * 100, 1) self.debug_print("=" * 100, 1)
self.debug_print("In _sampleHLSData for period %s (%s)" % \ self.debug_print("In _sampleHLSData for period %s (%s)" % \
(period, repr(self._timeRangeList[period][0])), 1) (period, self._timeRangeList[period][0]), 1)
statDict = statList[period] statDict = statList[period]
for threatName in ['WindThreat', 'FloodingRainThreat', 'TornadoThreat']: for threatName in ['WindThreat', 'FloodingRainThreat', 'TornadoThreat']:
@ -975,9 +978,9 @@ class TextProduct(HLSTCV_Common.TextProduct):
if decidingField is None or qpfToFfgRatio > decidingField: if decidingField is None or qpfToFfgRatio > decidingField:
self._samplingDict['FloodingRainThreat']['decidingField'] = qpfToFfgRatio self._samplingDict['FloodingRainThreat']['decidingField'] = qpfToFfgRatio
self.debug_print("SARAH: WindThreat = %s" % (self._samplingDict['WindThreat']['inputThreatDominant']), 1) self.debug_print("WindThreat = %s" % (self._samplingDict['WindThreat']['inputThreatDominant']), 1)
self.debug_print("SARAH: FloodingRainThreat = %s" % (self._samplingDict['FloodingRainThreat']['inputThreatDominant']), 1) self.debug_print("FloodingRainThreat = %s" % (self._samplingDict['FloodingRainThreat']['inputThreatDominant']), 1)
self.debug_print("SARAH: TornadoThreat = %s" % (self._samplingDict['TornadoThreat']['inputThreatDominant']), 1) self.debug_print("TornadoThreat = %s" % (self._samplingDict['TornadoThreat']['inputThreatDominant']), 1)
@ -1020,10 +1023,10 @@ class TextProduct(HLSTCV_Common.TextProduct):
if decidingField is None or inundationMax > decidingField: if decidingField is None or inundationMax > decidingField:
self._samplingDict['StormSurgeThreat']['decidingField'] = inundationMax self._samplingDict['StormSurgeThreat']['decidingField'] = inundationMax
self.debug_print("SARAH: StormSurgeThreat = %s" % (self._samplingDict['StormSurgeThreat']['inputThreatDominant']), 1) self.debug_print("StormSurgeThreat = %s" % (self._samplingDict['StormSurgeThreat']['inputThreatDominant']), 1)
def _sampleTCVAdvisory(self, advisory): def _sampleTCVAdvisory(self, advisory):
self.debug_print("SARAH: sampling TCV advisory!", 1) self.debug_print("sampling TCV advisory!", 1)
for zone in advisory["ZoneData"]: for zone in advisory["ZoneData"]:
self.debug_print("-" * 60, 1) self.debug_print("-" * 60, 1)
self.debug_print("Looking at zone %s" % (zone), 1) self.debug_print("Looking at zone %s" % (zone), 1)
@ -1055,46 +1058,46 @@ class TextProduct(HLSTCV_Common.TextProduct):
self._samplingDict[key]['inputThreatLow'] = lowThreat self._samplingDict[key]['inputThreatLow'] = lowThreat
self._samplingDict[key]['inputThreatHigh'] = highThreat self._samplingDict[key]['inputThreatHigh'] = highThreat
self.debug_print("Sampling dict = %s" % (repr(self._samplingDict)), 1) self.debug_print("Sampling dict =\n\n%s\n" % (self._pp.pformat(self._samplingDict)), 1)
def _sampleRankedDiscreteValue(self, threatName, statDict): def _sampleRankedDiscreteValue(self, threatName, statDict):
self.debug_print("-" * 60, 1) self.debug_print("-" * 60, 1)
self.debug_print("_sampleRankedDiscreteValue statDict = %s" % (repr(statDict)), 1) self.debug_print("_sampleRankedDiscreteValue statDict =\n\n%s\n" % (self._pp.pformat(statDict)), 1)
rankedThreatLevels = self.getStats(statDict, threatName + "__rankedDiscreteValue") rankedThreatLevels = self.getStats(statDict, threatName + "__rankedDiscreteValue")
self.debug_print("SARAH: sampling %s" % (threatName), 1) self.debug_print("sampling %s" % (threatName), 1)
self.debug_print("SARAH: sampleData: rankedThreatLevels = %s" % (repr(rankedThreatLevels)), 1) self.debug_print("sampleData: rankedThreatLevels =\n\n%s\n" % (self._pp.pformat(rankedThreatLevels)), 1)
if rankedThreatLevels is not None: if rankedThreatLevels is not None:
dominantThreatLevel = self._getDominantThreatLevel(threatName, rankedThreatLevels) dominantThreatLevel = self._getDominantThreatLevel(threatName, rankedThreatLevels)
self.debug_print("SARAH: dominantThreatLevel = %s" % (dominantThreatLevel), 1) self.debug_print("dominantThreatLevel = %s" % (dominantThreatLevel), 1)
currentDominantThreatLevel = self._samplingDict[threatName]['inputThreatDominant'] currentDominantThreatLevel = self._samplingDict[threatName]['inputThreatDominant']
self.debug_print("SARAH: currentDominantThreatLevel = %s" % (currentDominantThreatLevel), 1) self.debug_print("currentDominantThreatLevel = %s" % (currentDominantThreatLevel), 1)
self._samplingDict[threatName]['inputThreatDominant'] = self._getHighestThreat(threatName, self._samplingDict[threatName]['inputThreatDominant'] = self._getHighestThreat(threatName,
dominantThreatLevel, dominantThreatLevel,
currentDominantThreatLevel) currentDominantThreatLevel)
self.debug_print("SARAH: new dominant = %s" % (self._samplingDict[threatName]['inputThreatDominant']), 1) self.debug_print("new dominant = %s" % (self._samplingDict[threatName]['inputThreatDominant']), 1)
def _sampleMostSignificantDiscreteValue(self, threatName, statDict): def _sampleMostSignificantDiscreteValue(self, threatName, statDict):
self.debug_print("SARAH: _sampleMostSignificantDiscreteValue for %s" % (threatName), 1) self.debug_print("_sampleMostSignificantDiscreteValue for %s" % (threatName), 1)
threatLevel = self.getStats(statDict, threatName + "__mostSignificantDiscreteValue") threatLevel = self.getStats(statDict, threatName + "__mostSignificantDiscreteValue")
self.debug_print("SARAH: threatLevel = %s" % (threatLevel), 1) self.debug_print("threatLevel = %s" % (threatLevel), 1)
if threatLevel is not None: if threatLevel is not None:
inputThreatLow = self._samplingDict[threatName]['inputThreatLow'] inputThreatLow = self._samplingDict[threatName]['inputThreatLow']
self.debug_print("SARAH: current inputThreatLow = %s" % (inputThreatLow), 1) self.debug_print("current inputThreatLow = %s" % (inputThreatLow), 1)
if inputThreatLow is None: if inputThreatLow is None:
self._samplingDict[threatName]['inputThreatLow'] = threatLevel self._samplingDict[threatName]['inputThreatLow'] = threatLevel
else: else:
self._samplingDict[threatName]['inputThreatLow'] = self._getLowestThreat(threatName, self._samplingDict[threatName]['inputThreatLow'] = self._getLowestThreat(threatName,
threatLevel, threatLevel,
inputThreatLow) inputThreatLow)
self.debug_print("SARAH: new inputThreatLow = %s" % (self._samplingDict[threatName]['inputThreatLow']), 1) self.debug_print("new inputThreatLow = %s" % (self._samplingDict[threatName]['inputThreatLow']), 1)
inputThreatHigh = self._samplingDict[threatName]['inputThreatHigh'] inputThreatHigh = self._samplingDict[threatName]['inputThreatHigh']
self.debug_print("SARAH: current inputThreatHigh = %s" % (inputThreatHigh), 1) self.debug_print("current inputThreatHigh = %s" % (inputThreatHigh), 1)
self._samplingDict[threatName]['inputThreatHigh'] = self._getHighestThreat(threatName, self._samplingDict[threatName]['inputThreatHigh'] = self._getHighestThreat(threatName,
threatLevel, threatLevel,
inputThreatHigh) inputThreatHigh)
self.debug_print("SARAH: new inputThreatHigh = %s" % (self._samplingDict[threatName]['inputThreatHigh']), 1) self.debug_print("new inputThreatHigh = %s" % (self._samplingDict[threatName]['inputThreatHigh']), 1)
def _getDominantThreatLevel(self, threatName, rankedThreatLevels): def _getDominantThreatLevel(self, threatName, rankedThreatLevels):
dominantLevelWithHighestRank = None dominantLevelWithHighestRank = None
@ -1147,7 +1150,7 @@ class TextProduct(HLSTCV_Common.TextProduct):
catastrophicThreshold = self._samplingDict[threatName]['catastrophicThreshold'] catastrophicThreshold = self._samplingDict[threatName]['catastrophicThreshold']
self.debug_print("-" * 60, 1) self.debug_print("-" * 60, 1)
self.debug_print("MATT DEBUG: _setHazardImpactCategories for %s" % (threatName), 1) self.debug_print("DEBUG: _setHazardImpactCategories for %s" % (threatName), 1)
impactMin = None impactMin = None
impactMax = None impactMax = None
@ -1191,7 +1194,7 @@ class TextProduct(HLSTCV_Common.TextProduct):
impactRangeMax = "none" impactRangeMax = "none"
self.debug_print( self.debug_print(
"MATT DEBUG: impactMin = '%s' impactMax = '%s' impactRangeMax = '%s'" % \ "DEBUG: impactMin = '%s' impactMax = '%s' impactRangeMax = '%s'" % \
(impactMin, impactMax, impactRangeMax), 1) (impactMin, impactMax, impactRangeMax), 1)
# Determine dominant impact category for rest of CWA - No impact # Determine dominant impact category for rest of CWA - No impact
@ -1240,7 +1243,7 @@ class TextProduct(HLSTCV_Common.TextProduct):
segment_vtecRecords_tuples = [] segment_vtecRecords_tuples = []
for segment in segments: for segment in segments:
vtecRecords = self._getVtecRecords(segment) vtecRecords = self._getVtecRecords(segment)
self.debug_print("SARAH: vtecRecords = %s" % (repr(vtecRecords))) self.debug_print("vtecRecords =\n\n%s\n" % (self._pp.pformat(vtecRecords)))
segment_vtecRecords_tuples.append((segment, vtecRecords)) segment_vtecRecords_tuples.append((segment, vtecRecords))
productSegmentGroup = { productSegmentGroup = {
@ -1281,7 +1284,7 @@ class TextProduct(HLSTCV_Common.TextProduct):
else: else:
hazardDict[key] = hazardDict[key]+segment hazardDict[key] = hazardDict[key]+segment
#self.debug_print("hazardList = %s" % (repr(hazardList)), 1) self.debug_print("hazardList =\n\n%s\n" % (self._pp.pformat(hazardList)), 1)
return hazardList return hazardList
@ -1417,7 +1420,7 @@ class TextProduct(HLSTCV_Common.TextProduct):
# Storm intensity in mph and the stated intensity trend. # Storm intensity in mph and the stated intensity trend.
self._stormIntensityTrend = "Storm Intensity " + stormDict.get("StormIntensity","") self._stormIntensityTrend = "Storm Intensity " + stormDict.get("StormIntensity","")
self.debug_print("SARAH: BEGIN STORM INFORMATION", 1) self.debug_print("BEGIN STORM INFORMATION", 1)
self.debug_print("storm dict = %s" % (stormDict), 1) self.debug_print("storm dict = %s" % (stormDict), 1)
self.debug_print("storm name = %s" % (self._stormName), 1) self.debug_print("storm name = %s" % (self._stormName), 1)
self.debug_print("type = %s" % (self._stormType), 1) self.debug_print("type = %s" % (self._stormType), 1)
@ -1430,7 +1433,7 @@ class TextProduct(HLSTCV_Common.TextProduct):
self.debug_print("references = %s" % (self._stormLocalReferences), 1) self.debug_print("references = %s" % (self._stormLocalReferences), 1)
self.debug_print("movement trend = %s" % (self._stormMovementTrend), 1) self.debug_print("movement trend = %s" % (self._stormMovementTrend), 1)
self.debug_print("intensity trend = %s" % (self._stormIntensityTrend), 1) self.debug_print("intensity trend = %s" % (self._stormIntensityTrend), 1)
self.debug_print("SARAH: END STORM INFORMATION", 1) self.debug_print("END STORM INFORMATION", 1)
def _grabStormInfo(self, tcp): def _grabStormInfo(self, tcp):
# Get the storm information from the selected TCP # Get the storm information from the selected TCP
@ -1555,7 +1558,7 @@ class TextProduct(HLSTCV_Common.TextProduct):
# Assume we only have one NHC reference point by default # Assume we only have one NHC reference point by default
nhcReference = dict["StormReference"] nhcReference = dict["StormReference"]
## self.debug_print("referenceIndex = %s" % (referenceIndex), 1) self.debug_print("referenceIndex = %s" % (referenceIndex), 1)
# If we have more than one NHC reference point # If we have more than one NHC reference point
if referenceIndex != -1: if referenceIndex != -1:
@ -1603,13 +1606,15 @@ class TextProduct(HLSTCV_Common.TextProduct):
# Display some debug info - if flag is set # Display some debug info - if flag is set
self.debug_print("storminfoSearch = '%s'" % (stormInfoSearch)) self.debug_print("storminfoSearch = '%s'" % (stormInfoSearch))
## self.debug_print(repr(stormInfoSearch.groups()), 1) if stormInfoSearch is not None:
self.debug_print("\n\n%s\n" %
(self._pp.pformat(stormInfoSearch.groups())), 1)
# If we found the storm info section of the product # If we found the storm info section of the product
if stormInfoSearch is not None: if stormInfoSearch is not None:
# for group in stormInfoSearch.groups(): for group in stormInfoSearch.groups():
# self.debug_print('-'*50, 1) self.debug_print('-'*50, 1)
# self.debug_print("%s\n" % (group), 1) self.debug_print("%s\n" % (group), 1)
# Clean this section up a bit. Keep each paragraph separate # Clean this section up a bit. Keep each paragraph separate
# by a single <CR>, but remove all others as well as extra # by a single <CR>, but remove all others as well as extra
@ -1641,7 +1646,7 @@ class TextProduct(HLSTCV_Common.TextProduct):
# If we cannot find the summary, try to find a "repeating" section # If we cannot find the summary, try to find a "repeating" section
if repeatInfo is None: if repeatInfo is None:
repeatInfo = re.search("(?is)(REPEATING.+?\.)\n *\n", tcp) repeatInfo = re.search("(?is)(REPEATING.+?\.)\n *\n", tcp)
## self.debug_print(repr(repeatInfo), 1) self.debug_print(self._pp.pformat(repeatInfo), 1)
# If we found the repeated storm information summary # If we found the repeated storm information summary
if repeatInfo is not None: if repeatInfo is not None:
@ -1661,7 +1666,8 @@ class TextProduct(HLSTCV_Common.TextProduct):
# Display some debug info - if flag is set # Display some debug info - if flag is set
self.debug_print("locationSearch = '%s'" % (locationSearch), 1) self.debug_print("locationSearch = '%s'" % (locationSearch), 1)
## self.debug_print(repr(locationSearch.groups()), 1) if locationSearch is not None:
self.debug_print("\n\n%s\n" % (self._pp.pformat(locationSearch.groups())), 1)
# If we found the storm location section of the product # If we found the storm location section of the product
if locationSearch is not None: if locationSearch is not None:
@ -1720,18 +1726,18 @@ class TextProduct(HLSTCV_Common.TextProduct):
#======================================================================== #========================================================================
# Display final decoded information from TCP # Display final decoded information from TCP
## self.debug_print("*" *80, 1) self.debug_print("*" *80, 1)
## self.debug_print("Final TCP Info...\n", 1) self.debug_print("Final TCP Info...\n", 1)
## self.debug_print('dict["StormType"] = %s' % (dict["StormType"]), 1) self.debug_print('dict["StormType"] = %s' % (dict["StormType"]), 1)
## self.debug_print('dict["StormName"] = %s' % (dict["StormName"]), 1) self.debug_print('dict["StormName"] = %s' % (dict["StormName"]), 1)
## self.debug_print('dict["StormTime"] = %s' % (dict["StormTime"]), 1) self.debug_print('dict["StormTime"] = %s' % (dict["StormTime"]), 1)
## self.debug_print('dict["StormLat"] = %s' % (dict["StormLat"]), 1) self.debug_print('dict["StormLat"] = %s' % (dict["StormLat"]), 1)
## self.debug_print('dict["StormLon"] = %s' % (dict["StormLon"]), 1) self.debug_print('dict["StormLon"] = %s' % (dict["StormLon"]), 1)
## self.debug_print('dict["StormReference"] = %s' % (dict["StormReference"]), 1) self.debug_print('dict["StormReference"] = %s' % (dict["StormReference"]), 1)
## self.debug_print('dict["StormIntensity"] = %s' % (dict["StormIntensity"]), 1) self.debug_print('dict["StormIntensity"] = %s' % (dict["StormIntensity"]), 1)
## self.debug_print('dict["StormMotion"] = %s' % (dict["StormMotion"]), 1) self.debug_print('dict["StormMotion"] = %s' % (dict["StormMotion"]), 1)
## self.debug_print('dict["StormInfo"] = %s' % (dict["StormInfo"]), 1) self.debug_print('dict["StormInfo"] = %s' % (dict["StormInfo"]), 1)
## self.debug_print('dict["StormCenter"] = %s' % (dict["StormCenter"]), 1) self.debug_print('dict["StormCenter"] = %s' % (dict["StormCenter"]), 1)
# Return the dictionary will all the information we found in the TCP # Return the dictionary will all the information we found in the TCP
return dict return dict
@ -1744,7 +1750,7 @@ class TextProduct(HLSTCV_Common.TextProduct):
self._stormReference = "" self._stormReference = ""
self._stormLocalReferences = "" self._stormLocalReferences = ""
para = stormDict.get("StormCenter", "") para = stormDict.get("StormCenter", "")
# self.debug_print("para %d %s" % (len(para), para), 1) self.debug_print("para %d %s" % (len(para), para), 1)
if len(para)<= 0: if len(para)<= 0:
return return
@ -1768,13 +1774,15 @@ class TextProduct(HLSTCV_Common.TextProduct):
# Try to find these patterns in the text # Try to find these patterns in the text
coordPtnMatch = coordPtn.search(para) coordPtnMatch = coordPtn.search(para)
## self.debug_print("+" * 90, 1) self.debug_print("+" * 90, 1)
## self.debug_print("coordinate search...", 1) self.debug_print("coordinate search...", 1)
## self.debug_print(coordPtnMatch.groups(), 1) if coordPtnMatch is not None:
self.debug_print("\n\n%s|n" % (self._pp.pformat(coordPtnMatch.groups())), 1)
refPtnMatch = refPtn.search(para) refPtnMatch = refPtn.search(para)
## self.debug_print("reference search...", 1) self.debug_print("reference search...", 1)
## self.debug_print(refPtnMatch.groups(), 1) if refPtnMatch is not None:
self.debug_print("\n\n%s|n" % (self._pp.pformat(refPtnMatch.groups())), 1)
# If we found the coordinates we were after # If we found the coordinates we were after
if coordPtnMatch is not None: if coordPtnMatch is not None:
@ -1818,12 +1826,12 @@ class TextProduct(HLSTCV_Common.TextProduct):
self._stormLocalReferences = self._calcLocalReferences( self._stormLocalReferences = self._calcLocalReferences(
self._stormLat, self._stormLon) self._stormLat, self._stormLon)
## self.debug_print("stormLocalRefs = %s" % (self._stormLocalReferences), 1) self.debug_print("stormLocalRefs = %s" % (self._stormLocalReferences), 1)
# Compare the NHC reference to the local references # Compare the NHC reference to the local references
for localRef in self._stormLocalReferences: for localRef in self._stormLocalReferences:
## self.debug_print("self._stormReference = '%s', localRef = '%s'" % (self._stormReference, localRef), 1) self.debug_print("self._stormReference = '%s', localRef = '%s'" % (self._stormReference, localRef), 1)
# Get the locations from these statements # Get the locations from these statements
nhcRef = re.search('(?i)(north|south|east|west) of (.+)', nhcRef = re.search('(?i)(north|south|east|west) of (.+)',
@ -1831,7 +1839,11 @@ class TextProduct(HLSTCV_Common.TextProduct):
testRef = re.search('(?i)(north|south|east|west) of (.+)', testRef = re.search('(?i)(north|south|east|west) of (.+)',
localRef) localRef)
## self.debug_print("nhcRef = '%s'\ttestRef = '%s'" % (nhcRef.group(2), testRef.group(2)), 1) if nhcRef is not None:
self.debug_print("nhcRef = '%s'" % (nhcRef.group(2)), 1)
if testRef is not None:
self.debug_print("testRef = '%s'" % (testRef.group(2)), 1)
# If we have a local reference that matches the national # If we have a local reference that matches the national
# center reference # center reference
@ -1870,7 +1882,7 @@ class TextProduct(HLSTCV_Common.TextProduct):
# Remove references to KM e.g. # Remove references to KM e.g.
# 420 KM... 100 KM/HR... # 420 KM... 100 KM/HR...
# self.debug_print("words = '%s'" % (words), 1) self.debug_print("words = '%s'" % (words), 1)
kmSearch = re.compile("\.\.\. *[0-9]+ +(KM|KM/HR?) *\.?\.?\.?") kmSearch = re.compile("\.\.\. *[0-9]+ +(KM|KM/HR?) *\.?\.?\.?")
@ -1883,7 +1895,7 @@ class TextProduct(HLSTCV_Common.TextProduct):
for doubleSpace in doubleSpaces: for doubleSpace in doubleSpaces:
words = re.sub(doubleSpace, ' ', words) words = re.sub(doubleSpace, ' ', words)
# self.debug_print("\tfinal words = '%s'" % (words), 1) self.debug_print("\tfinal words = '%s'" % (words), 1)
return words return words
def _cleanText(self, text=''): def _cleanText(self, text=''):
@ -1934,7 +1946,7 @@ class TextProduct(HLSTCV_Common.TextProduct):
direction = self._bearing(lat1, lon1, lat0, lon0) direction = self._bearing(lat1, lon1, lat0, lon0)
direction = self._dirInEnglish(direction) direction = self._dirInEnglish(direction)
localRef ="ABOUT "+distMph_str+" MILES "+direction localRef ="ABOUT "+distMph_str+" MILES "+direction
# self.debug_print("localRef = %s" % (localRef), 1) self.debug_print("localRef = %s" % (localRef), 1)
return localRef return localRef
# Returns the distance from lat0, lon0 to lat1, lon1 in kilometers # Returns the distance from lat0, lon0 to lat1, lon1 in kilometers
@ -2199,7 +2211,7 @@ class Overview_Dialog(HLSTCV_Common.Common_Dialog):
# pull the data from the tkObject_dict before they get toasted # pull the data from the tkObject_dict before they get toasted
tkObject_dict = self._tkObject_dict tkObject_dict = self._tkObject_dict
overviewList = self._parent._overview_list() overviewList = self._parent._overview_list()
print("SARAH: in okCB!") print("in okCB!")
for infoDict in overviewList: for infoDict in overviewList:
name = infoDict["name"] name = infoDict["name"]
label = infoDict["label"] label = infoDict["label"]
@ -2218,7 +2230,7 @@ class Overview_Dialog(HLSTCV_Common.Common_Dialog):
checkList.append((options[i], svar.get())) checkList.append((options[i], svar.get()))
else: else:
if ivarList[i].get(): if ivarList[i].get():
print("SARAH: adding option = %s" % (repr(options[i]))) print("adding option = %s" % (self._pp.pformat(options[i])))
checkList.append(options[i]) checkList.append(options[i])
value = checkList value = checkList
self._setVarDict(name, value) self._setVarDict(name, value)
@ -2255,8 +2267,8 @@ class LegacyFormatter():
@param productParts -- list of instances of the ProductPart class with information about how to format each product part @param productParts -- list of instances of the ProductPart class with information about how to format each product part
@return text -- product string @return text -- product string
''' '''
text = '' text = ""
print("SARAH: productParts = %s" % (productParts)) self._textProduct.debug_print("productParts = %s" % (productParts))
for part in productParts: for part in productParts:
valtype = type(part) valtype = type(part)
if valtype is str: if valtype is str:
@ -2264,15 +2276,15 @@ class LegacyFormatter():
elif valtype is tuple: elif valtype is tuple:
name = part[0] name = part[0]
infoDicts = part[1] infoDicts = part[1]
self.debug_print("SARAH: name = %s" % (str(name)), 1) self._textProduct.debug_print("name = %s" % (name), 1)
self.debug_print("SARAH: infoDicts = %s" % (repr(infoDicts)), 1) self._textProduct.debug_print("infoDicts =\n\n%s\n" % (self._pp.pformat(infoDicts)), 1)
newtext = self.processSubParts(productDict.get(name), infoDicts) newtext = self.processSubParts(productDict.get(name), infoDicts)
self.debug_print("SARAH: newtext type = %s" % (type(newtext)), 1) self._textProduct.debug_print("newtext type = %s" % (type(newtext)), 1)
self.debug_print("SARAH: newtext = %s" % (repr(newtext)), 1) self._textProduct.debug_print("newtext =\n\n%s\b" % (self._pp.pformat(newtext)), 1)
text += newtext text += newtext
continue continue
elif valtype is list: elif valtype is list:
self.debug_print('GOT HERE -- found list', 1) self._textProduct.debug_print('GOT HERE -- found list', 1)
self._tpc.flush() self._tpc.flush()
# TODO THIS SHOULD BE REMOVED AFTER THE REFACTOR OF HazardServicesProductGenerationHandler.JAVA # TODO THIS SHOULD BE REMOVED AFTER THE REFACTOR OF HazardServicesProductGenerationHandler.JAVA
tup = (part[0], part[1]) tup = (part[0], part[1])
@ -2356,8 +2368,8 @@ class LegacyFormatter():
text += '&&\n' text += '&&\n'
elif name not in self._noOpParts(): elif name not in self._noOpParts():
textStr = productDict.get(name) textStr = productDict.get(name)
self.debug_print("SARAH: name = %s" % (name), 1) self._textProduct.debug_print("name = %s" % (name), 1)
self.debug_print("SARAH: textStr = '%s'" % (textStr), 1) self._textProduct.debug_print("textStr = '%s'" % (textStr), 1)
if textStr: if textStr:
text += textStr + '\n' text += textStr + '\n'
return text return text
@ -2431,14 +2443,17 @@ class LegacyFormatter():
if hazard['act'] == "CON": if hazard['act'] == "CON":
hazardText = "A " + hazard['hdln'] + " remains in effect for " + self._areaWords(hazard['id']) hazardText = "A " + hazard['hdln'] + " remains in effect for " + self._areaWords(hazard['id'])
elif hazard['act'] in ["NEW", "EXA"]: elif hazard['act'] in ["NEW", "EXA"]:
if hazard.has_key('upgradeFrom') and hazard['upgradeFrom'] is not None: if isChangesHazards and hazard.has_key('upgradeFrom') and hazard['upgradeFrom'] is not None:
import VTECTable import VTECTable
upgradeRecord = hazard['upgradeFrom'] upgradeRecord = hazard['upgradeFrom']
hazardText = "A " + VTECTable.VTECTable[upgradeRecord['phensig']]['hdln'] + \ hazardText = "A " + VTECTable.VTECTable[upgradeRecord['phensig']]['hdln'] + \
" has been upgraded to a " + hazard['hdln'] + \ " has been upgraded to a " + hazard['hdln'] + \
" for " + self._areaWords(hazard['id']) " for " + self._areaWords(hazard['id'])
else: else:
hazardText = "A " + hazard['hdln'] + " has been issued for " + self._areaWords(hazard['id']) if isChangesHazards:
hazardText = "A " + hazard['hdln'] + " has been issued for " + self._areaWords(hazard['id'])
else:
hazardText = "A " + hazard['hdln'] + " is in effect for " + self._areaWords(hazard['id'])
elif hazard['act'] == "CAN": elif hazard['act'] == "CAN":
hazardText = "The " + hazard['hdln'] + " for " + self._areaWords(hazard['id']) + " has been cancelled" hazardText = "The " + hazard['hdln'] + " for " + self._areaWords(hazard['id']) + " has been cancelled"
else: else:
@ -2523,11 +2538,11 @@ class LegacyFormatter():
curAdditionalImpactText = "" curAdditionalImpactText = ""
count = 1 count = 1
print("MATT DEBUG: %d sectionDict['additionalImpactRange'] = '%s'" % (len(sectionDict['additionalImpactRange']), sectionDict['additionalImpactRange'])) self._textProduct.debug_print("DEBUG: %d sectionDict['additionalImpactRange'] = '%s'" % (len(sectionDict['additionalImpactRange']), sectionDict['additionalImpactRange']))
for additionalImpact in sectionDict['additionalImpactRange']: for additionalImpact in sectionDict['additionalImpactRange']:
print("additionalImpact = '%s'" % (additionalImpact)) self._textProduct.debug_print("additionalImpact = '%s'" % (additionalImpact))
print("count = %d" % (count)) self._textProduct.debug_print("count = %d" % (count))
curAdditionalImpactText += \ curAdditionalImpactText += \
self._textProduct.indentText(additionalImpact, self._textProduct.indentText(additionalImpact,
@ -2537,7 +2552,7 @@ class LegacyFormatter():
len(curAdditionalImpactText) > 0: len(curAdditionalImpactText) > 0:
curAdditionalImpactText += "\n" curAdditionalImpactText += "\n"
print("MATT DEBUG: curAdditionalImpactText ='%s'" % (curAdditionalImpactText)) self._textProduct.debug_print("DEBUG: curAdditionalImpactText ='%s'" % (curAdditionalImpactText))
count += 1 count += 1
@ -2545,7 +2560,7 @@ class LegacyFormatter():
if additionalImpactRangeText.find(curAdditionalImpactText) == -1: if additionalImpactRangeText.find(curAdditionalImpactText) == -1:
# Add this additional impact text # Add this additional impact text
print("Adding current impact. '%s'" % (curAdditionalImpactText)) self._textProduct.debug_print("Adding current impact. '%s'" % (curAdditionalImpactText))
additionalImpactRangeText += curAdditionalImpactText additionalImpactRangeText += curAdditionalImpactText
text += additionalImpactRangeText text += additionalImpactRangeText
@ -2562,11 +2577,11 @@ class LegacyFormatter():
""" """
text = '' text = ''
for i in range(len(subParts)): for i in range(len(subParts)):
print("SARAH: subpart subParts[i] = %s" % (subParts[i])) self._textProduct.debug_print("subpart subParts[i] = %s" % (subParts[i]))
print("SARAH: subpart infoDicts[i] = %s" % (infoDicts[i])) self._textProduct.debug_print("subpart infoDicts[i] = %s" % (infoDicts[i]))
newtext = self._processProductParts(subParts[i], infoDicts[i].get('partsList')) newtext = self._processProductParts(subParts[i], infoDicts[i].get('partsList'))
print("SARAH: subpart newtext type = %s" % (type(newtext))) self._textProduct.debug_print("subpart newtext type = %s" % (type(newtext)))
print("SARAH: subpart newtext = '%s'" % (repr(newtext))) self._textProduct.debug_print("subpart newtext = '%s'" % (self._pp.pformat(newtext)))
text += newtext text += newtext
return text return text

View file

@ -1,4 +1,4 @@
# Version 2014.12.12-0 # Version 2015.1.6-0
import GenericHazards import GenericHazards
import JsonSupport import JsonSupport
@ -170,10 +170,10 @@ class TextProduct(HLSTCV_Common.TextProduct):
"_sectionHeader": 0, "_sectionHeader": 0,
"_lifePropertyThreatSummary": 0, "_lifePropertyThreatSummary": 0,
"_getThreatTrendSentence": 0, "_getThreatTrendSentence": 0,
"_getThreatTrendValue": 1, "_getThreatTrendValue": 0,
"_threatDifference": 1, "_threatDifference": 0,
"_isThreatDecreasing": 1, "_isThreatDecreasing": 0,
"_isThreatIncreasing": 1, "_isThreatIncreasing": 0,
"_advisoryHasValidKey": 0, "_advisoryHasValidKey": 0,
"_isMagnitudeIncreasing": 1, "_isMagnitudeIncreasing": 1,
"_calculateThreatStatementTr": 0, "_calculateThreatStatementTr": 0,
@ -188,7 +188,7 @@ class TextProduct(HLSTCV_Common.TextProduct):
#Unique to each section, but common method name #Unique to each section, but common method name
"sectionParts": 0, "sectionParts": 0,
"_forecastSubsection": 0, "_forecastSubsection": 0,
"_latestForecastSummary": 1, "_latestForecastSummary": 0,
"_threatSubsection": 0, "_threatSubsection": 0,
"_threatTrend": 0, "_threatTrend": 0,
"_threatStatements": 0, "_threatStatements": 0,
@ -262,7 +262,7 @@ class TextProduct(HLSTCV_Common.TextProduct):
"checkLastArrow": 0, "checkLastArrow": 0,
} }
# Definition["debug"] = 1 # turn on ALL debug messages # Definition["debug"] = 1 # turn on ALL debug messages
# Definition["debug"] = 0 # turn off ALL debug messages Definition["debug"] = 0 # turn off ALL debug messages
def __init__(self): def __init__(self):
@ -445,9 +445,7 @@ class TextProduct(HLSTCV_Common.TextProduct):
def generateForecast(self, argDict): def generateForecast(self, argDict):
# Generate Text Phrases for a list of edit areas # Generate Text Phrases for a list of edit areas
import pprint self.debug_print("argDict = %s" % (self._pp.pformat(argDict)), 1)
pp = pprint.PrettyPrinter()
self.debug_print("argDict = %s" % (pp.pformat(argDict)), 1)
error = self._initializeVariables(argDict) error = self._initializeVariables(argDict)
if error is not None: if error is not None:
@ -457,7 +455,7 @@ class TextProduct(HLSTCV_Common.TextProduct):
return "Could not determine the storm name" return "Could not determine the storm name"
self._segmentList = self._determineSegments() self._segmentList = self._determineSegments()
self.debug_print("Segment Information: %s" % (repr(self._segmentList)), 1) self.debug_print("Segment Information: %s" % (self._pp.pformat(self._segmentList)), 1)
if len(self._segmentList) == 0: if len(self._segmentList) == 0:
return "NO HAZARDS TO REPORT" return "NO HAZARDS TO REPORT"
@ -508,7 +506,7 @@ class TextProduct(HLSTCV_Common.TextProduct):
def _setup_segment(self, segmentDict, productSegmentGroup, productSegment): def _setup_segment(self, segmentDict, productSegmentGroup, productSegment):
segment, vtecRecords = productSegment segment, vtecRecords = productSegment
self.debug_print('setup_segment productSegment %s' % (repr(productSegment)), 1) self.debug_print('setup_segment productSegment %s' % (self._pp.pformat(productSegment)), 1)
# NOTE -- using _getVtecRecords to change to milliseconds # NOTE -- using _getVtecRecords to change to milliseconds
self._segmentVtecRecords = self._getVtecRecords(segment) self._segmentVtecRecords = self._getVtecRecords(segment)
@ -544,14 +542,14 @@ class TextProduct(HLSTCV_Common.TextProduct):
vstr = None vstr = None
vstr = vtecRecord["vtecstr"] vstr = vtecRecord["vtecstr"]
self.debug_print("vtecRecord = %s" % (repr(vtecRecord)), 1) self.debug_print("vtecRecord = %s" % (self._pp.pformat(vtecRecord)), 1)
# Post-process some VTEC codes which should not exist # Post-process some VTEC codes which should not exist
vstr = vstr.replace(".EXT.", ".CON.") vstr = vstr.replace(".EXT.", ".CON.")
vstr = vstr.replace(".EXB.", ".EXA.") vstr = vstr.replace(".EXB.", ".EXA.")
if vtecRecord["phen"] == "SS": if vtecRecord["phen"] == "SS":
# SARAH: Temporary? Change the vtec mode for SS hazards to be experimental # Temporary? Change the vtec mode for SS hazards to be experimental
vstr = vstr[0] + 'X' + vstr[2:] vstr = vstr[0] + 'X' + vstr[2:]
records.append(vstr) records.append(vstr)
segmentDict['vtecRecords'] = records segmentDict['vtecRecords'] = records
@ -604,7 +602,7 @@ class TextProduct(HLSTCV_Common.TextProduct):
segmentDict['locationsAffected'] += tcv_AreaDictionary[segment]["locationsAffected"] segmentDict['locationsAffected'] += tcv_AreaDictionary[segment]["locationsAffected"]
def _fcstConfidence(self, segmentDict, productSegmentGroup, productSegment): def _fcstConfidence(self, segmentDict, productSegmentGroup, productSegment):
# SARAH: TODO - Get this from the TCM product potentially? Not included until provided from NHC # TODO - Get this from the TCM product potentially? Not included until provided from NHC
return "" return ""
def _infoSection(self, segmentDict, productSegmentGroup, productSegment): def _infoSection(self, segmentDict, productSegmentGroup, productSegment):
@ -682,13 +680,11 @@ class TextProduct(HLSTCV_Common.TextProduct):
timeRangeList, timeRangeList,
editArea) editArea)
import pprint self.debug_print("*"*80, 1)
pp = pprint.PrettyPrinter()
self.debug_print("*"*80)
for index in range(len(timeRangeList)): for index in range(len(timeRangeList)):
self.debug_print("editArea =" + editArea, 1) self.debug_print("editArea =" + editArea, 1)
self.debug_print("timeRange = %s" % (pp.pformat(timeRangeList[index])), 1) self.debug_print("timeRangeList = %s" % (self._pp.pformat(timeRangeList[index])), 1)
self.debug_print("statList = %s" % (pp.pformat(statList[index])), 1) self.debug_print("statList = %s" % (self._pp.pformat(statList[index])), 1)
self.debug_print("-"*40, 1) self.debug_print("-"*40, 1)
# These stats are for handling the extra rainfall # These stats are for handling the extra rainfall
@ -721,21 +717,21 @@ class TextProduct(HLSTCV_Common.TextProduct):
# Get the segments based on hazards "overlaid" with combinations file # Get the segments based on hazards "overlaid" with combinations file
# Get the segments resulting from Hazards # Get the segments resulting from Hazards
#self.debug_print("\nRaw Analyzed %s" % (repr(self._hazardsTable.rawAnalyzedTable())), 1) self.debug_print("Raw Analyzed %s" % (self._pp.pformat(self._hazardsTable.rawAnalyzedTable())), 1)
hazSegments = self.organizeHazards(self._hazardsTable.rawAnalyzedTable()) hazSegments = self.organizeHazards(self._hazardsTable.rawAnalyzedTable())
#self.debug_print("\nSegments from HazardsTable organizeHazards %s" % (repr(hazSegments)), 1) self.debug_print("Segments from HazardsTable organizeHazards %s" % (self._pp.pformat(hazSegments)), 1)
# Get the forecaster entered combinations # Get the forecaster entered combinations
accessor = ModuleAccessor.ModuleAccessor() accessor = ModuleAccessor.ModuleAccessor()
# self.debug_print("self._defaultEditAreas = %s" % (repr(self._defaultEditAreas)), 1) self.debug_print("self._defaultEditAreas = %s" % (self._pp.pformat(self._defaultEditAreas)), 1)
combos = accessor.variable(self._defaultEditAreas, "Combinations") combos = accessor.variable(self._defaultEditAreas, "Combinations")
if combos is None: if combos is None:
LogStream.logVerbose("COMBINATION FILE NOT FOUND: " + self._defaultEditAreas) LogStream.logVerbose("COMBINATION FILE NOT FOUND: " + self._defaultEditAreas)
return [], None return [], None
#self.debug_print("\nSegments from Zone Combiner = %s" % (repr(combos)), 1) self.debug_print("Segments from Zone Combiner = %s" % (self._pp.pformat(combos)), 1)
# "Overlay" the forecaster-entered combinations onto the segments # "Overlay" the forecaster-entered combinations onto the segments
segmentList = self._refineSegments(hazSegments, combos) segmentList = self._refineSegments(hazSegments, combos)
#self.debug_print("\nNew segments = %s" % (repr(segmentList)), 1) self.debug_print("New segments = %s" % (self._pp.pformat(segmentList)), 1)
# Instead of a segment being a group of zones, it will be just a single zone. # Instead of a segment being a group of zones, it will be just a single zone.
# So collapse this list of lists down to a list of zones (aka. segments) # So collapse this list of lists down to a list of zones (aka. segments)
@ -763,9 +759,9 @@ class TextProduct(HLSTCV_Common.TextProduct):
# (We need to define self._segmentList for the mapping function # (We need to define self._segmentList for the mapping function
# to use) # to use)
self._segmentList = hazSegments self._segmentList = hazSegments
#self.debug_print("self._segmentList = %s" % (repr(self._segmentList)), 1) self.debug_print("self._segmentList = %s" % (self._pp.pformat(self._segmentList)), 1)
segmentMapping = map(self._findSegment, combo) segmentMapping = map(self._findSegment, combo)
#self.debug_print(" segmentMapping = %s" % (repr(segmentMapping)), 1) self.debug_print(" segmentMapping = %s" % (self._pp.pformat(segmentMapping)), 1)
# segmentDict keys will be the hazSegments and # segmentDict keys will be the hazSegments and
# we will gather all the areas of the combos that appear # we will gather all the areas of the combos that appear
@ -773,21 +769,21 @@ class TextProduct(HLSTCV_Common.TextProduct):
segmentDict = {} segmentDict = {}
keyList = [] keyList = []
for areaName in combo: for areaName in combo:
#self.debug_print(" Adding %s" % (areaName), 1) self.debug_print(" Adding %s" % (areaName), 1)
key = tuple(segmentMapping[combo.index(areaName)]) key = tuple(segmentMapping[combo.index(areaName)])
if key == (): # If no hazard for area, do not include if key == (): # If no hazard for area, do not include
continue continue
if key not in keyList: if key not in keyList:
keyList.append(key) keyList.append(key)
segmentDict.setdefault(key,[]).append(areaName) segmentDict.setdefault(key,[]).append(areaName)
#self.debug_print(" segmentDict = %s" % (repr(segmentDict)), 1) self.debug_print(" segmentDict = %s" % (self._pp.pformat(segmentDict)), 1)
# Keep track of the areas that we are including # Keep track of the areas that we are including
for key in keyList: for key in keyList:
segAreas = segmentDict[key] segAreas = segmentDict[key]
newAreas = newAreas + segAreas newAreas = newAreas + segAreas
newSegments.append(segAreas) newSegments.append(segAreas)
#self.debug_print(" newSegments = %s" % (repr(newSegments)), 1) self.debug_print(" newSegments = %s" % (self._pp.pformat(newSegments)), 1)
# Now add in the hazAreas that have not been accounted for # Now add in the hazAreas that have not been accounted for
# in the combinations # in the combinations
for hazSegment in hazSegments: for hazSegment in hazSegments:
@ -842,7 +838,7 @@ class TextProduct(HLSTCV_Common.TextProduct):
def _makeSegmentEditAreas(self, argDict): def _makeSegmentEditAreas(self, argDict):
areasList = self._allAreas() areasList = self._allAreas()
#self.debug_print("areaList = %s" % (repr(areasList)), 1) self.debug_print("areasList = %s" % (self._pp.pformat(areasList)), 1)
editAreas = [] editAreas = []
self._editAreaDict = {} self._editAreaDict = {}
for area in areasList: for area in areasList:
@ -872,15 +868,15 @@ class TextProduct(HLSTCV_Common.TextProduct):
hazSegments = self.organizeHazards(hazardTable.rawAnalyzedTable()) hazSegments = self.organizeHazards(hazardTable.rawAnalyzedTable())
self.debug_print("Segments from HazardsTable organizeHazards %s" % self.debug_print("Segments from HazardsTable organizeHazards %s" %
(repr(hazSegments)), 1) (self._pp.pformat(hazSegments)), 1)
combos = [([self._allAreas()], "AllAreas")] combos = [([self._allAreas()], "AllAreas")]
self.debug_print("Segments from Zone Combiner %s" % (repr(combos)), 1) self.debug_print("Segments from Zone Combiner %s" % (self._pp.pformat(combos)), 1)
# "Overlay" the forecaster-entered combinations onto the segments # "Overlay" the forecaster-entered combinations onto the segments
segmentList = self._refineSegments(hazSegments, combos) segmentList = self._refineSegments(hazSegments, combos)
self.debug_print("SegmentList from refineSegments = %s" % self.debug_print("SegmentList from refineSegments = %s" %
(repr(segmentList)), 1) (self._pp.pformat(segmentList)), 1)
allHazards = [] allHazards = []
for segment in segmentList: for segment in segmentList:
@ -970,11 +966,11 @@ class TextProduct(HLSTCV_Common.TextProduct):
fileName, fileName,
advisoryDict) advisoryDict)
self.debug_print("SARAH: Wrote file contents for: %s" % (fileName), 1) self.debug_print("Wrote file contents for: %s" % (fileName), 1)
self._synchronizeAdvisories() self._synchronizeAdvisories()
except Exception, e: except Exception, e:
self.debug_print("SARAH Save Exception for %s : %s" % (fileName, e), 1) self.debug_print("Save Exception for %s : %s" % (fileName, e), 1)
############################################################### ###############################################################
### GUI related methods ### GUI related methods
@ -1146,7 +1142,7 @@ class SectionCommon():
self._setProductPartValue(segmentDict, 'lifePropertyThreatSummary', self._setProductPartValue(segmentDict, 'lifePropertyThreatSummary',
"Threat to Life and Property: " + threatLevel) "Threat to Life and Property: " + threatLevel)
# SARAH - this new method will convert the single word threat trend into # This new method will convert the single word threat trend into
# an appropriate sentence # an appropriate sentence
def _getThreatTrendSentence(self, section, threatTrendValue): def _getThreatTrendSentence(self, section, threatTrendValue):
@ -1163,10 +1159,10 @@ class SectionCommon():
threatKey = elementName + "Threat" threatKey = elementName + "Threat"
forecastKey = elementName + "Forecast" forecastKey = elementName + "Forecast"
self._textProduct.debug_print("SARAH: THREAT DEBUG for %s" % elementName, 1) self._textProduct.debug_print("THREAT DEBUG for %s" % (elementName), 1)
self._textProduct.debug_print("SARAH: getThreatTrendValue _currentAdvisory =\n%s" % (repr(self._stats._currentAdvisory)), 1) self._textProduct.debug_print("getThreatTrendValue _currentAdvisory =\n%s" % (self._textProduct._pp.pformat(self._stats._currentAdvisory)), 1)
self._textProduct.debug_print("SARAH: getThreatTrendValue _previousAdvisory =\n%s" % (repr(self._stats._previousAdvisory)), 1) self._textProduct.debug_print("getThreatTrendValue _previousAdvisory =\n%s" % (self._textProduct._pp.pformat(self._stats._previousAdvisory)), 1)
if (self._stats._currentAdvisory is None) or (self._stats._previousAdvisory is None): if (self._stats._currentAdvisory is None) or (self._stats._previousAdvisory is None):
# Only compute a threat trend if we have 2 or more advisories # Only compute a threat trend if we have 2 or more advisories
@ -1176,26 +1172,26 @@ class SectionCommon():
previousThreat = self._stats._previousAdvisory[threatKey] previousThreat = self._stats._previousAdvisory[threatKey]
shorterTermTrendDifference = self._threatDifference(currentThreat, previousThreat) shorterTermTrendDifference = self._threatDifference(currentThreat, previousThreat)
self._textProduct.debug_print("SARAH: currentThreat = %s" % currentThreat, 1) self._textProduct.debug_print("currentThreat = %s" % (self._textProduct._pp.pformat(currentThreat)), 1)
self._textProduct.debug_print("SARAH: previousThreat = %s" % previousThreat, 1) self._textProduct.debug_print("previousThreat = %s" % (self._textProduct._pp.pformat(previousThreat)), 1)
self._textProduct.debug_print("SARAH: shorterTermTrendDifference = %s" % shorterTermTrendDifference, 1) self._textProduct.debug_print("shorterTermTrendDifference = %s" % (shorterTermTrendDifference), 1)
previousPreviousThreat = None previousPreviousThreat = None
longerTermTrendDifference = None longerTermTrendDifference = None
if self._stats._previousPreviousAdvisory is not None: if self._stats._previousPreviousAdvisory is not None:
self._textProduct.debug_print("SARAH: _previousPreviousAdvisory is not None", 1) self._textProduct.debug_print("_previousPreviousAdvisory is not None", 1)
previousPreviousThreat = self._stats._previousPreviousAdvisory[threatKey] previousPreviousThreat = self._stats._previousPreviousAdvisory[threatKey]
self._textProduct.debug_print("SARAH: previousPreviousThreat = %s" % previousPreviousThreat, 1) self._textProduct.debug_print("previousPreviousThreat = %s" % (self._textProduct._pp.pformat(previousPreviousThreat)), 1)
longerTermTrendDifference = self._threatDifference(currentThreat, previousPreviousThreat) longerTermTrendDifference = self._threatDifference(currentThreat, previousPreviousThreat)
self._textProduct.debug_print("SARAH: longerTermTrendDifference = %s" % longerTermTrendDifference, 1) self._textProduct.debug_print("longerTermTrendDifference = %s" % (longerTermTrendDifference), 1)
threatTrendValue = "NEARLY STEADY" threatTrendValue = "NEARLY STEADY"
self._textProduct.debug_print("magnitudeIncreaseThreshold = %s forecastKey = '%s'" % (magnitudeIncreaseThreshold, forecastKey), 1) self._textProduct.debug_print("magnitudeIncreaseThreshold = %s forecastKey = '%s'" % (magnitudeIncreaseThreshold, forecastKey), 1)
if self._isThreatDecreasing(shorterTermTrendDifference, longerTermTrendDifference): if self._isThreatDecreasing(shorterTermTrendDifference, longerTermTrendDifference):
self._textProduct.debug_print("SARAH: threat is decreasing", 1) self._textProduct.debug_print("threat is decreasing", 1)
threatTrendValue = "DECREASING" threatTrendValue = "DECREASING"
elif self._isThreatIncreasing(shorterTermTrendDifference, longerTermTrendDifference): elif self._isThreatIncreasing(shorterTermTrendDifference, longerTermTrendDifference):
self._textProduct.debug_print("SARAH: threat is increasing", 1) self._textProduct.debug_print("threat is increasing", 1)
threatTrendValue = "INCREASING" threatTrendValue = "INCREASING"
elif currentThreat == "Extreme" and \ elif currentThreat == "Extreme" and \
self._isMagnitudeIncreasing(forecastKey, magnitudeIncreaseThreshold): self._isMagnitudeIncreasing(forecastKey, magnitudeIncreaseThreshold):
@ -1206,8 +1202,8 @@ class SectionCommon():
def _threatDifference(self, threat1, threat2): def _threatDifference(self, threat1, threat2):
threatLevels = self._textProduct._threatKeyOrder() threatLevels = self._textProduct._threatKeyOrder()
self._textProduct.debug_print("SARAH: threat1 index = %s" % threatLevels.index(threat1), 1) self._textProduct.debug_print("threat1 index = %s" % (threatLevels.index(threat1)), 1)
self._textProduct.debug_print("SARAH: threat2 index = %s" % threatLevels.index(threat2), 1) self._textProduct.debug_print("threat2 index = %s" % (threatLevels.index(threat2)), 1)
return threatLevels.index(threat1) - threatLevels.index(threat2) return threatLevels.index(threat1) - threatLevels.index(threat2)
def _isThreatDecreasing(self, shorterTermTrendDifference, longerTermTrendDifference): def _isThreatDecreasing(self, shorterTermTrendDifference, longerTermTrendDifference):
@ -1215,14 +1211,14 @@ class SectionCommon():
if (shorterTermTrendDifference < 0 and \ if (shorterTermTrendDifference < 0 and \
longerTermTrendDifference is not None and \ longerTermTrendDifference is not None and \
longerTermTrendDifference < 0): longerTermTrendDifference < 0):
self._textProduct.debug_print("SARAH: the current threat is at least 1 category lower than both previous advisories", 1) self._textProduct.debug_print("the current threat is at least 1 category lower than both previous advisories", 1)
return True return True
#Or if the current threat decreased by more than 1 category #Or if the current threat decreased by more than 1 category
elif shorterTermTrendDifference < -1: elif shorterTermTrendDifference < -1:
self._textProduct.debug_print("SARAH: the current threat decreased by more than 1 category", 1) self._textProduct.debug_print("the current threat decreased by more than 1 category", 1)
return True return True
else: else:
self._textProduct.debug_print("SARAH: the current threat is not decreasing", 1) self._textProduct.debug_print("the current threat is not decreasing", 1)
return False return False
def _isThreatIncreasing(self, shorterTermTrendDifference, longerTermTrendDifference): def _isThreatIncreasing(self, shorterTermTrendDifference, longerTermTrendDifference):
@ -1230,14 +1226,14 @@ class SectionCommon():
if (shorterTermTrendDifference > 0 and \ if (shorterTermTrendDifference > 0 and \
longerTermTrendDifference is not None and \ longerTermTrendDifference is not None and \
longerTermTrendDifference > 0): longerTermTrendDifference > 0):
self._textProduct.debug_print("SARAH: the current threat is at least 1 category higher than both previous advisories", 1) self._textProduct.debug_print("the current threat is at least 1 category higher than both previous advisories", 1)
return True return True
#Or if the current threat increased by more than 1 category #Or if the current threat increased by more than 1 category
elif shorterTermTrendDifference > 1: elif shorterTermTrendDifference > 1:
self._textProduct.debug_print("SARAH: the current threat increased by more than 1 category", 1) self._textProduct.debug_print("the current threat increased by more than 1 category", 1)
return True return True
else: else:
self._textProduct.debug_print("SARAH: the current threat is not increasing", 1) self._textProduct.debug_print("the current threat is not increasing", 1)
return False return False
def _advisoryHasValidKey(self, advisory, key): def _advisoryHasValidKey(self, advisory, key):
@ -1247,43 +1243,43 @@ class SectionCommon():
def _isMagnitudeIncreasing(self, forecastKey, threshold): def _isMagnitudeIncreasing(self, forecastKey, threshold):
# currentValue, previousValue, previousPreviousValue # currentValue, previousValue, previousPreviousValue
self._textProduct.debug_print("SARAH: _isMagnitudeIncreasing", 1) self._textProduct.debug_print("_isMagnitudeIncreasing", 1)
self._textProduct.debug_print("SARAH: forecastKey = %s" % forecastKey, 1) self._textProduct.debug_print("forecastKey = %s" % (forecastKey), 1)
self._textProduct.debug_print("SARAH: threshold = %s" % threshold, 1) self._textProduct.debug_print("threshold = %s" % (threshold), 1)
if self._advisoryHasValidKey(self._stats._currentAdvisory, forecastKey) and \ if self._advisoryHasValidKey(self._stats._currentAdvisory, forecastKey) and \
self._advisoryHasValidKey(self._stats._previousAdvisory, forecastKey): self._advisoryHasValidKey(self._stats._previousAdvisory, forecastKey):
currentValue = self._stats._currentAdvisory[forecastKey] currentValue = self._stats._currentAdvisory[forecastKey]
previousValue = self._stats._previousAdvisory[forecastKey] previousValue = self._stats._previousAdvisory[forecastKey]
self._textProduct.debug_print("SARAH: currentValue = %s" % currentValue, 1) self._textProduct.debug_print("currentValue = %s" % (currentValue), 1)
self._textProduct.debug_print("SARAH: previousValue = %s" % previousValue, 1) self._textProduct.debug_print("previousValue = %s" % (previousValue), 1)
if (currentValue - previousValue) >= threshold: if (currentValue - previousValue) >= threshold:
self._textProduct.debug_print("SARAH: the current magnitude has increased by more than the threshold since the last advisory", 1) self._textProduct.debug_print("the current magnitude has increased by more than the threshold since the last advisory", 1)
return True return True
elif self._advisoryHasValidKey(self._stats._previousPreviousAdvisory, forecastKey): elif self._advisoryHasValidKey(self._stats._previousPreviousAdvisory, forecastKey):
previousPreviousValue = self._stats._previousPreviousAdvisory[forecastKey] previousPreviousValue = self._stats._previousPreviousAdvisory[forecastKey]
self._textProduct.debug_print("SARAH: previousPreviousValue = %s" % previousPreviousValue, 1) self._textProduct.debug_print("previousPreviousValue = %s" % (previousPreviousValue), 1)
if (currentValue - previousPreviousValue) >= threshold: if (currentValue - previousPreviousValue) >= threshold:
self._textProduct.debug_print("SARAH: the current magnitude has increased by more than the threshold since the previous previous advisory", 1) self._textProduct.debug_print("the current magnitude has increased by more than the threshold since the previous previous advisory", 1)
return True return True
else: else:
self._textProduct.debug_print("SARAH: the current magnitude does not meet the requirements to be considered increasing", 1) self._textProduct.debug_print("the current magnitude does not meet the requirements to be considered increasing", 1)
return False return False
else: else:
self._textProduct.debug_print("SARAH: the current magnitude did not increase past threshold and could not look at the previous previous advisory", 1) self._textProduct.debug_print("the current magnitude did not increase past threshold and could not look at the previous previous advisory", 1)
return False return False
else: else:
self._textProduct.debug_print("SARAH: the current advisory and/or previous advisory did not have key: %s" % forecastKey, 1) self._textProduct.debug_print("the current advisory and/or previous advisory did not have key: %s" % (forecastKey), 1)
return False return False
def _calculateThreatStatementTr(self, onsetHour, endHour, threatTrendValue): def _calculateThreatStatementTr(self, onsetHour, endHour, threatTrendValue):
tr = None tr = None
self._textProduct.debug_print("SARAH: onset hour = %s" % (onsetHour), 1) self._textProduct.debug_print("onset hour = %s" % (onsetHour), 1)
self._textProduct.debug_print("SARAH: end hour = %s" % (endHour), 1) self._textProduct.debug_print("end hour = %s" % (endHour), 1)
self._textProduct.debug_print("SHANNON: threatTrendValue = %s" % self._textProduct.debug_print("threatTrendValue = %s" %
(threatTrendValue), 1) (threatTrendValue), 1)
if (onsetHour is not None) and \ if (onsetHour is not None) and \
@ -1304,8 +1300,8 @@ class SectionCommon():
def _setThreatStatementsProductParts(self, segmentDict, productSegment, tr): def _setThreatStatementsProductParts(self, segmentDict, productSegment, tr):
self._textProduct.debug_print("SHANNON: tr = %s %s" % self._textProduct.debug_print("tr = %s %s" %
(repr(tr), self._sectionHeaderName), 1) (self._textProduct._pp.pformat(tr), self._sectionHeaderName), 1)
# if tr is not None and self._stats._maxThreat is not None: # if tr is not None and self._stats._maxThreat is not None:
if tr is not None: if tr is not None:
(planning, action, preparation) = self._getThreatStatements(productSegment, (planning, action, preparation) = self._getThreatStatements(productSegment,
@ -1316,7 +1312,7 @@ class SectionCommon():
self._setProductPartValue(segmentDict, 'threatStatements', self._setProductPartValue(segmentDict, 'threatStatements',
[planning, action, preparation]) [planning, action, preparation])
else: else:
self._textProduct.debug_print("SHANNON messed up", 1) self._textProduct.debug_print("this is not a valid time range", 1)
return return
def _getThreatStatements(self, productSegment, sectionName, maxThreat, tr): def _getThreatStatements(self, productSegment, sectionName, maxThreat, tr):
@ -1332,7 +1328,7 @@ class SectionCommon():
self._textProduct.debug_print(40*"-", 1) self._textProduct.debug_print(40*"-", 1)
self._textProduct.debug_print("sectionName = %s, maxThreat = %s, tr = %s" % self._textProduct.debug_print("sectionName = %s, maxThreat = %s, tr = %s" %
(sectionName, maxThreat, repr(tr)), 1) (sectionName, maxThreat, self._textProduct._pp.pformat(tr)), 1)
# if maxThreat is None: # if maxThreat is None:
# maxThreat = "None" # maxThreat = "None"
@ -1364,7 +1360,7 @@ class SectionCommon():
return "Potential Impacts: " + impactLevel return "Potential Impacts: " + impactLevel
def _potentialImpactsStatements(self, segmentDict, productSegmentGroup, productSegment): def _potentialImpactsStatements(self, segmentDict, productSegmentGroup, productSegment):
self._textProduct.debug_print("SHANNON: segment = %s, elementName = %s, maxThreat = %s" % self._textProduct.debug_print("segment = %s, elementName = %s, maxThreat = %s" %
(productSegment[0], self._sectionHeaderName, self._stats._maxThreat), 1) (productSegment[0], self._sectionHeaderName, self._stats._maxThreat), 1)
if self._stats._maxThreat is not None: if self._stats._maxThreat is not None:
statements = self._getPotentialImpactsStatements(productSegment, self._sectionHeaderName, self._stats._maxThreat) statements = self._getPotentialImpactsStatements(productSegment, self._sectionHeaderName, self._stats._maxThreat)
@ -1381,7 +1377,7 @@ class SectionCommon():
segment, vtecRecords = productSegment segment, vtecRecords = productSegment
self._textProduct.debug_print("SHANNON: zone number = %s, elementName = %s, maxThreat = %s" % self._textProduct.debug_print("zone number = %s, elementName = %s, maxThreat = %s" %
(segment, elementName, maxThreat), 1) (segment, elementName, maxThreat), 1)
if segment in tcv_AreaDictionary: if segment in tcv_AreaDictionary:
@ -1492,7 +1488,7 @@ class WindSection(SectionCommon):
if self._stats._maxGust is not None: if self._stats._maxGust is not None:
moderatedMaxWindGust = self._ktToMph(self._stats._maxGust, "WindGust") moderatedMaxWindGust = self._ktToMph(self._stats._maxGust, "WindGust")
# # SARAH - we want to round the wind gust to the nearest 5 kt # # We want to round the wind gust to the nearest 5 kt
# moderatedMaxWindGust = \ # moderatedMaxWindGust = \
# self._textProduct.round(moderatedMaxWindGust, "Nearest", 5) # self._textProduct.round(moderatedMaxWindGust, "Nearest", 5)
@ -1533,7 +1529,8 @@ class WindSection(SectionCommon):
windTr = self._calculateThreatStatementTr(self._stats._onset34Hour, windTr = self._calculateThreatStatementTr(self._stats._onset34Hour,
self._stats._end34Hour, self._stats._end34Hour,
self._threatTrendValue) self._threatTrendValue)
# self._textProduct.debug_print("MATT: in _threatStatements tr = %s" % (repr(windTr)) self._textProduct.debug_print("in _threatStatements tr = %s" %
(self._textProduct._pp.pformat(windTr)), 1)
if not hasattr(self._textProduct, "_windThreatStatementsTr"): if not hasattr(self._textProduct, "_windThreatStatementsTr"):
self._textProduct._windThreatStatementsTr = dict() self._textProduct._windThreatStatementsTr = dict()
@ -1550,7 +1547,7 @@ class WindSection(SectionCommon):
# if len(subsectionDict) > 0: # if len(subsectionDict) > 0:
# self._setProductPartValue(segmentDict, 'impactsSubsection', subsectionDict) # self._setProductPartValue(segmentDict, 'impactsSubsection', subsectionDict)
# SARAH - modified to not include wind impacts during the "recovery" and # Modified to not include wind impacts during the "recovery" and
# "nothing to see here" phases of the tropical cyclone event # "nothing to see here" phases of the tropical cyclone event
def _impactsSubsection(self, segmentDict, productSegmentGroup, productSegment): def _impactsSubsection(self, segmentDict, productSegmentGroup, productSegment):
@ -1664,7 +1661,7 @@ class StormSurgeSection(SectionCommon):
words = str(int(max - maxRange)) + "-" + str(int(max)) + " feet above ground" words = str(int(max - maxRange)) + "-" + str(int(max)) + " feet above ground"
elif max > 0: elif max > 0:
# SARAH - we were getting really weird values of peak surge # We were getting really weird values of peak surge
# (e.g. "UP TO 1.70000004768 FEET"). This fix will round up # (e.g. "UP TO 1.70000004768 FEET"). This fix will round up
# to the nearest integer value # to the nearest integer value
# words = "Up to " + str(max) + " feet above ground" # words = "Up to " + str(max) + " feet above ground"
@ -1711,7 +1708,7 @@ class StormSurgeSection(SectionCommon):
threatTrendSentence) threatTrendSentence)
def _threatStatements(self, segmentDict, productSegmentGroup, productSegment): def _threatStatements(self, segmentDict, productSegmentGroup, productSegment):
self._textProduct.debug_print("SARAH: Surge Threat Statements", 1) self._textProduct.debug_print("Surge Threat Statements", 1)
surgeTr = self._calculateThreatStatementTr(self._stats._onsetSurgeHour, surgeTr = self._calculateThreatStatementTr(self._stats._onsetSurgeHour,
self._stats._endSurgeHour, self._stats._endSurgeHour,
self._threatTrendValue) self._threatTrendValue)
@ -1731,7 +1728,7 @@ class StormSurgeSection(SectionCommon):
def _potentialImpactsSummary(self, segmentDict, productSegmentGroup, productSegment): def _potentialImpactsSummary(self, segmentDict, productSegmentGroup, productSegment):
if not self._textProduct._PopulateSurge: if not self._textProduct._PopulateSurge:
# SARAH - We do not want the '(For plausible worst case)' in the text # We do not want the '(For plausible worst case)' in the text
# self._setProductPartValue(segmentDict, 'potentialImpactsSummary', # self._setProductPartValue(segmentDict, 'potentialImpactsSummary',
# "Potential Impacts (For plausible worst case): Not available at this time. To be updated shortly.") # "Potential Impacts (For plausible worst case): Not available at this time. To be updated shortly.")
self._setProductPartValue(segmentDict, 'potentialImpactsSummary', self._setProductPartValue(segmentDict, 'potentialImpactsSummary',
@ -1948,28 +1945,28 @@ class SectionCommonStats():
self._currentAdvisory = self._textProduct._currentAdvisory['ZoneData'][self._segment] self._currentAdvisory = self._textProduct._currentAdvisory['ZoneData'][self._segment]
self._previousAdvisory = None self._previousAdvisory = None
# self._textProduct.debug_print("MATT textProduct._previousAdvisory = '%s'" % (textProduct._previousAdvisory)) self._textProduct.debug_print("textProduct._previousAdvisory = '%s'" % (self._textProduct._previousAdvisory))
if self._textProduct._previousAdvisory is not None: if self._textProduct._previousAdvisory is not None:
if self._textProduct._previousAdvisory['ZoneData'].has_key(self._segment): if self._textProduct._previousAdvisory['ZoneData'].has_key(self._segment):
self._previousAdvisory = self._textProduct._previousAdvisory['ZoneData'][self._segment] self._previousAdvisory = self._textProduct._previousAdvisory['ZoneData'][self._segment]
# self._textProduct.debug_print("MATT textProduct._previousPreviousAdvisory = '%s'" % \ self._textProduct.debug_print("textProduct._previousPreviousAdvisory = '%s'" % \
# (textProduct._previousPreviousAdvisory)) (self._textProduct._previousPreviousAdvisory))
self._previousPreviousAdvisory = None self._previousPreviousAdvisory = None
if self._textProduct._previousPreviousAdvisory is not None: if self._textProduct._previousPreviousAdvisory is not None:
self._previousPreviousAdvisory = self._textProduct._previousPreviousAdvisory['ZoneData'][self._segment] self._previousPreviousAdvisory = self._textProduct._previousPreviousAdvisory['ZoneData'][self._segment]
def _updateThreatStats(self, tr, statDict, threatGridName): def _updateThreatStats(self, tr, statDict, threatGridName):
self._textProduct.debug_print("statDict = '%s'" % (repr(statDict)), 1) self._textProduct.debug_print("statDict = '%s'" % (self._textProduct._pp.pformat(statDict)), 1)
threatLevel = self._textProduct.getStats(statDict, threatGridName) threatLevel = self._textProduct.getStats(statDict, threatGridName)
if threatLevel is not None: if threatLevel is not None:
threatLevels = self._textProduct._threatKeyOrder() threatLevels = self._textProduct._threatKeyOrder()
self._textProduct.debug_print("SARAH: updateThreatStats for %s" % (threatGridName), 1) self._textProduct.debug_print("updateThreatStats for %s" % (threatGridName), 1)
self._textProduct.debug_print("SARAH: threatLevel = %s" % (threatLevel), 1) self._textProduct.debug_print("threatLevel = %s" % (threatLevel), 1)
self._textProduct.debug_print("SARAH: maxThreat = %s" % (self._maxThreat), 1) self._textProduct.debug_print("maxThreat = %s" % (self._maxThreat), 1)
if self._maxThreat is None or \ if self._maxThreat is None or \
threatLevels.index(threatLevel) > threatLevels.index(self._maxThreat): threatLevels.index(threatLevel) > threatLevels.index(self._maxThreat):
self._textProduct.debug_print("SARAH: updating max threat to = %s" % (threatLevel), 1) self._textProduct.debug_print("updating max threat to = %s" % (threatLevel), 1)
self._maxThreat = threatLevel self._maxThreat = threatLevel
def _calculateHourOffset(self, targetTime): def _calculateHourOffset(self, targetTime):
@ -1992,8 +1989,8 @@ class WindSectionStats(SectionCommonStats):
self._windowTS = None self._windowTS = None
self._windowHU = None self._windowHU = None
print "*"*90 self._textProduct.debug_print("*"*90)
print "Setting wind stats for %s" % (segment) self._textProduct.debug_print("Setting wind stats for %s" % (segment), 1)
self._setStats(statList, timeRangeList) self._setStats(statList, timeRangeList)
@ -2006,7 +2003,6 @@ class WindSectionStats(SectionCommonStats):
dropFirstGridType = None dropFirstGridType = None
droppedFirstGrid = False droppedFirstGrid = False
periodWithFirstCorrectGrid = None periodWithFirstCorrectGrid = None
onsetTime = None
endTime = None endTime = None
class TimeInfo(): class TimeInfo():
@ -2031,6 +2027,7 @@ class WindSectionStats(SectionCommonStats):
statDict = statList[index] statDict = statList[index]
for periodIndex, periodTr in enumerate(self._textProduct._periodList): for periodIndex, periodTr in enumerate(self._textProduct._periodList):
self._textProduct.debug_print("\n\nperiodIndex = %d periodList tr = %s" % (periodIndex, repr(periodTr)), 1)
if (periodIndex == 0) and (tr.startTime().unixTime() < periodTr.startTime().unixTime()): if (periodIndex == 0) and (tr.startTime().unixTime() < periodTr.startTime().unixTime()):
# If the tr is before the first period, use the first period # If the tr is before the first period, use the first period
currentPeriod = periodIndex currentPeriod = periodIndex
@ -2065,7 +2062,7 @@ class WindSectionStats(SectionCommonStats):
self._onset34Hour = onsetEndInfo.onsetHour self._onset34Hour = onsetEndInfo.onsetHour
self._end34Hour = onsetEndInfo.endHour self._end34Hour = onsetEndInfo.endHour
self._textProduct.debug_print("SARAH: Tropical Storm Window:", 1) self._textProduct.debug_print("Tropical Storm Window:", 1)
self._windowTS = self._createWindow("Tropical Storm", self._windowTS = self._createWindow("Tropical Storm",
self._onset34Hour, self._onset34Hour,
self._end34Hour) self._end34Hour)
@ -2075,7 +2072,7 @@ class WindSectionStats(SectionCommonStats):
self._onset64Hour = onsetEndInfo.onsetHour self._onset64Hour = onsetEndInfo.onsetHour
self._end64Hour = onsetEndInfo.endHour self._end64Hour = onsetEndInfo.endHour
self._textProduct.debug_print("SARAH: Hurricane Window:", 1) self._textProduct.debug_print("Hurricane Window:", 1)
self._windowHU = self._createWindow("Hurricane", self._windowHU = self._createWindow("Hurricane",
self._onset64Hour, self._onset64Hour,
self._end64Hour) self._end64Hour)
@ -2091,76 +2088,92 @@ class WindSectionStats(SectionCommonStats):
pwsXXintStats.max = pwsXXint pwsXXintStats.max = pwsXXint
pwsXXintStats.onsetHour = self._calculateHourOffset(tr.startTime()) pwsXXintStats.onsetHour = self._calculateHourOffset(tr.startTime())
self._textProduct.debug_print("SARAH: Window Debug: pwsXXintStats gridName = %s" % (gridName), 1) self._textProduct.debug_print("Wind Window Debug: pwsXXintStats gridName = %s" % (gridName), 1)
self._textProduct.debug_print("SARAH: Window Debug: pwsXXintStats onsetHour = %s" % (pwsXXintStats.onsetHour), 1) self._textProduct.debug_print("Wind Window Debug: pwsXXintStats onsetHour = %s" % (pwsXXintStats.onsetHour), 1)
def _updateStatsForPwsTXX(self, tr, statDict, dayGridName, nightGridName, pwsTXXStats, period): def _updateStatsForPwsTXX(self, tr, statDict, dayGridName, nightGridName, pwsTXXStats, period):
pwsDXX = self._textProduct._getStatValue(statDict, dayGridName, "Max") pwsDXX = self._textProduct._getStatValue(statDict, dayGridName, "Max")
pwsNXX = self._textProduct._getStatValue(statDict, nightGridName, "Max") pwsNXX = self._textProduct._getStatValue(statDict, nightGridName, "Max")
if pwsTXXStats.firstRun: if pwsTXXStats.firstRun:
self._textProduct.debug_print("SARAH: first run for _updateStatsForPwsTXX!", 1) self._textProduct.debug_print("first run for _updateStatsForPwsTXX!", 1)
self._textProduct.debug_print("SARAH: grids: %s %s" % (dayGridName, nightGridName), 1) self._textProduct.debug_print("grids: %s %s" % (dayGridName, nightGridName), 1)
pwsTXXStats.firstRun = False pwsTXXStats.firstRun = False
localtime = time.localtime(self._textProduct._issueTime_secs) localtime = time.localtime(self._textProduct._issueTime_secs)
self._textProduct.debug_print("SARAH: localtime = %s" % (localtime), 1) self._textProduct.debug_print("localtime = %s" % (localtime), 1)
if localtime.tm_hour >= 15: # 3PM to midnight if localtime.tm_hour >= 15: # 3PM to midnight
self._textProduct.debug_print("SARAH: between 3PM and midnight!", 1) self._textProduct.debug_print("between 3PM and midnight!", 1)
pwsTXXStats.dropFirstGridType = "DAY" pwsTXXStats.dropFirstGridType = "DAY"
self._textProduct.debug_print("SARAH: need to drop the day grid(s) if they come first", 1) self._textProduct.debug_print("need to drop the day grid(s) if they come first", 1)
elif localtime.tm_hour >= 3 and localtime.tm_hour < 12: # 3AM to noon elif localtime.tm_hour >= 3 and localtime.tm_hour < 12: # 3AM to noon
self._textProduct.debug_print("SARAH: between 3AM and noon!", 1) self._textProduct.debug_print("between 3AM and noon!", 1)
pwsTXXStats.dropFirstGridType = "NIGHT" pwsTXXStats.dropFirstGridType = "NIGHT"
self._textProduct.debug_print("SARAH: need to drop the night grid(s) if they come first", 1) self._textProduct.debug_print("need to drop the night grid(s) if they come first", 1)
else: else:
self._textProduct.debug_print("SARAH: not dropping any grids!", 1) self._textProduct.debug_print("not dropping any grids!", 1)
maxPws = None maxPws = None
self._textProduct.debug_print("MATT %s pwsDXX = %s pwsNXX = %s " % self._textProduct.debug_print("%s pwsDXX = %s pwsNXX = %s " %
(repr(tr),pwsDXX, pwsNXX), 1) (self._textProduct._pp.pformat(tr),pwsDXX, pwsNXX), 1)
if pwsDXX is not None: # Determine coversion factor to get DAY and NIGHT in UTC
self._textProduct.debug_print("SARAH: Window Debug: pwsTXXStats DAY", 1) utcHourOffset = self._calculateUTCandLocalHourOffset()
# See if this hour a valid DAYtime hour
isValidDay = self._isValidDayTime(tr.startTime().hour,
self.DAY() + utcHourOffset,
self.NIGHT() + utcHourOffset)
# If we have pwsD data, and this is a time period it applies to
if pwsDXX is not None and isValidDay:
self._textProduct.debug_print("Wind Window Debug: pwsTXXStats DAY", 1)
if pwsTXXStats.dropFirstGridType == "DAY": if pwsTXXStats.dropFirstGridType == "DAY":
self._textProduct.debug_print("SARAH: Window Debug: dropping a day grid", 1) self._textProduct.debug_print("Wind Window Debug: dropping a day grid", 1)
self._textProduct.debug_print("SARAH: Window Debug: tr = %s, period = %s" % (tr, period), 1) self._textProduct.debug_print("Wind Window Debug: tr = %s, period = %s" % (tr, period), 1)
pwsTXXStats.droppedFirstGrid = True pwsTXXStats.droppedFirstGrid = True
return return
elif pwsTXXStats.dropFirstGridType == "NIGHT": elif pwsTXXStats.dropFirstGridType == "NIGHT":
# We dropped all the necessary grids now that we found a day grid so stop dropping # We dropped all the necessary grids now that we found a day grid so stop dropping
pwsTXXStats.dropFirstGridType = None pwsTXXStats.dropFirstGridType = None
pwsTXXStats.periodWithFirstCorrectGrid = period pwsTXXStats.periodWithFirstCorrectGrid = period
self._textProduct.debug_print("SARAH: Window Debug: found day grid; done dropping night grids", 1) self._textProduct.debug_print("Wind Window Debug: found day grid; done dropping night grids", 1)
self._textProduct.debug_print("SARAH: Window Debug: tr = %s, period = %s" % (tr, period), 1) self._textProduct.debug_print("Wind Window Debug: tr = %s, period = %s" % (tr, period), 1)
maxPws = pwsDXX maxPws = pwsDXX
elif pwsNXX is not None: # If we have pwsN data, and this is a time period it applies to
self._textProduct.debug_print("SARAH: Window Debug: pwsTXXStats NIGHT", 1) elif pwsNXX is not None and not isValidDay:
self._textProduct.debug_print("Wind Window Debug: pwsTXXStats NIGHT", 1)
if pwsTXXStats.dropFirstGridType == "NIGHT": if pwsTXXStats.dropFirstGridType == "NIGHT":
self._textProduct.debug_print("SARAH: Window Debug: dropping a night grid", 1) self._textProduct.debug_print("Wind Window Debug: dropping a night grid", 1)
self._textProduct.debug_print("SARAH: Window Debug: tr = %s, period = %s" % (tr, period), 1) self._textProduct.debug_print("Wind Window Debug: tr = %s, period = %s" % (tr, period), 1)
pwsTXXStats.droppedFirstGrid = True pwsTXXStats.droppedFirstGrid = True
return return
elif pwsTXXStats.dropFirstGridType == "DAY": elif pwsTXXStats.dropFirstGridType == "DAY":
# We dropped all the necessary grids now that we found a night grid so stop dropping # We dropped all the necessary grids now that we found a night grid so stop dropping
pwsTXXStats.dropFirstGridType = None pwsTXXStats.dropFirstGridType = None
pwsTXXStats.periodWithFirstCorrectGrid = period pwsTXXStats.periodWithFirstCorrectGrid = period
self._textProduct.debug_print("SARAH: Window Debug: found night grid; done dropping day grids", 1) self._textProduct.debug_print("Wind Window Debug: found night grid; done dropping day grids", 1)
self._textProduct.debug_print("SARAH: Window Debug: tr = %s, period = %s" % (tr, period), 1) self._textProduct.debug_print("Wind Window Debug: tr = %s, period = %s" % (tr, period), 1)
maxPws = pwsNXX maxPws = pwsNXX
elif pwsDXX is not None and tr.startTime().hour in [21, 0, 3]:
self._textProduct.debug_print("Wind Window Debug: pwsTXXStats DAY ignored", 1)
elif pwsNXX is not None and tr.startTime().hour in [9, 12, 15]:
self._textProduct.debug_print("Wind Window Debug: pwsTXXStats NIGHT ignored", 1)
threshold34index = 0 threshold34index = 0
threshold64index = 1 threshold64index = 1
if maxPws is not None: if maxPws is not None:
# Don't shift if the period with the first correct grid is period 0 # Don't shift if the period with the first correct grid is period 0
if pwsTXXStats.droppedFirstGrid and pwsTXXStats.periodWithFirstCorrectGrid != 0: if pwsTXXStats.droppedFirstGrid and pwsTXXStats.periodWithFirstCorrectGrid != 0:
period = period - 1 # We dropped the first grid so we are off-by-one period = period - 1 # We dropped the first grid so we are off-by-one
self._textProduct.debug_print("SARAH: shifting period back 1...new period = %s" % self._textProduct.debug_print("shifting period back 1...new period = %s" %
(period), 1) (period), 1)
if "64" in dayGridName: if "64" in dayGridName:
@ -2170,6 +2183,7 @@ class WindSectionStats(SectionCommonStats):
threshold = None threshold = None
thresholds = self._textProduct.windSpdProb_thresholds(threshold, threshold) thresholds = self._textProduct.windSpdProb_thresholds(threshold, threshold)
self._textProduct.debug_print("Getting probability threshold for period %s" % (period), 1)
if period == 0: if period == 0:
(thresholdLow, thresholdHigh) = thresholds[period][index] (thresholdLow, thresholdHigh) = thresholds[period][index]
threshold = thresholdLow threshold = thresholdLow
@ -2177,43 +2191,43 @@ class WindSectionStats(SectionCommonStats):
threshold = thresholds[period][index] threshold = thresholds[period][index]
if maxPws > threshold: if maxPws > threshold:
pwsTXXStats.onsetTime = tr.startTime()
pwsTXXStats.endTime = tr.endTime() pwsTXXStats.endTime = tr.endTime()
self._textProduct.debug_print("Wind Window Debug: probability threshold = %s (period index %s)" % (threshold, period), 1)
self._textProduct.debug_print("SARAH: Window Debug: pwsTXXStats dayGridName = %s" % (dayGridName), 1) self._textProduct.debug_print("Wind Window Debug: pwsTXXStats dayGridName = %s" % (dayGridName), 1)
self._textProduct.debug_print("SARAH: Window Debug: pwsTXXStats nightGridName = %s" % (nightGridName), 1) self._textProduct.debug_print("Wind Window Debug: pwsTXXStats nightGridName = %s" % (nightGridName), 1)
self._textProduct.debug_print("SARAH: Window Debug: pwsTXXStats original tr = %s" % (repr(tr)), 1) self._textProduct.debug_print("Wind Window Debug: pwsTXXStats original tr = %s" % (self._textProduct._pp.pformat(tr)), 1)
self._textProduct.debug_print("SARAH: Window Debug: pwsTXXStats maxPws = %s" %(repr(maxPws)), 1) self._textProduct.debug_print("Wind Window Debug: pwsTXXStats maxPws = %s" %(self._textProduct._pp.pformat(maxPws)), 1)
self._textProduct.debug_print("SARAH: Window Debug: pwsTXXStats onsetTime = %s" % (repr(pwsTXXStats.onsetTime)), 1) self._textProduct.debug_print("Wind Window Debug: pwsTXXStats endTime = %s" % (self._textProduct._pp.pformat(pwsTXXStats.endTime)), 1)
self._textProduct.debug_print("SARAH: Window Debug: pwsTXXStats endTime = %s" % (repr(pwsTXXStats.endTime)), 1)
def _updateWindTimeInfo(self, tr, wind, timeInfo, speed): def _updateWindTimeInfo(self, tr, wind, timeInfo, speed):
if wind >= speed: if wind >= speed:
timeInfo.endHour = self._calculateHourOffset(tr.endTime()) timeInfo.endHour = self._calculateHourOffset(tr.endTime())
self._textProduct.debug_print("SARAH: Window Debug: In _updateWindTimeInfo", 1) self._textProduct.debug_print("Wind Window Debug: In _updateWindTimeInfo", 1)
self._textProduct.debug_print("SARAH: Window Debug: timeInfo speed = %s" % (speed), 1) self._textProduct.debug_print("Wind Window Debug: timeInfo speed = %s" % (speed), 1)
self._textProduct.debug_print("SARAH: Window Debug: timeInfo maxWind = %s" % (self._maxWind), 1) self._textProduct.debug_print("Wind Window Debug: timeInfo maxWind = %s" % (self._maxWind), 1)
self._textProduct.debug_print("SARAH: Window Debug: timeInfo tr = %s" % (repr(tr)), 1) self._textProduct.debug_print("Wind Window Debug: timeInfo tr = %s" % (self._textProduct._pp.pformat(tr)), 1)
self._textProduct.debug_print("SARAH: Window Debug: timeInfo endHour = %s" % (timeInfo.endHour), 1) self._textProduct.debug_print("Wind Window Debug: timeInfo endHour = %s" % (timeInfo.endHour), 1)
if timeInfo.onsetHour is None: if timeInfo.onsetHour is None:
timeInfo.onsetHour = self._calculateHourOffset(tr.startTime()) timeInfo.onsetHour = self._calculateHourOffset(tr.startTime())
self._textProduct.debug_print("SARAH: Window Debug: onsetHour was None", 1) self._textProduct.debug_print("Wind Window Debug: onsetHour was None", 1)
self._textProduct.debug_print("SARAH: Window Debug: timeInfo speed = %s" % (speed), 1) self._textProduct.debug_print("Wind Window Debug: timeInfo speed = %s" % (speed), 1)
self._textProduct.debug_print("SARAH: Window Debug: timeInfo maxWind = %s" % (self._maxWind), 1) self._textProduct.debug_print("Wind Window Debug: timeInfo maxWind = %s" % (self._maxWind), 1)
self._textProduct.debug_print("SARAH: Window Debug: timeInfo tr = %s" % (repr(tr)), 1) self._textProduct.debug_print("Wind Window Debug: timeInfo tr = %s" % (self._textProduct._pp.pformat(tr)), 1)
self._textProduct.debug_print("SARAH: Window Debug: timeInfo onsetHour = %s" % (timeInfo.onsetHour), 1) self._textProduct.debug_print("Wind Window Debug: timeInfo onsetHour = %s" % (timeInfo.onsetHour), 1)
def _computeWindOnsetAndEnd(self, windTimeInfo, pwsXXintStats, pwsTXXStats): def _computeWindOnsetAndEnd(self, windTimeInfo, pwsXXintStats, pwsTXXStats):
onsetEndInfo = self.TimeInfo() onsetEndInfo = self.TimeInfo()
self._textProduct.debug_print("SARAH: Window Debug: In _computeWindOnsetAndEnd", 1) self._textProduct.debug_print("Wind Window Debug: In _computeWindOnsetAndEnd", 1)
self._textProduct.debug_print("SARAH: Window Debug: windTimeInfo.onsetHour = %s" % (windTimeInfo.onsetHour), 1) self._textProduct.debug_print("Wind Window Debug: windTimeInfo.onsetHour = %s" % (windTimeInfo.onsetHour), 1)
self._textProduct.debug_print("SARAH: Window Debug: pwsXXintStats.onsetHour = %s" % (pwsXXintStats.onsetHour), 1) self._textProduct.debug_print("Wind Window Debug: pwsXXintStats.onsetHour = %s" % (pwsXXintStats.onsetHour), 1)
self._textProduct.debug_print("SARAH: Window Debug: windTimeInfo.endHour = %s" % (windTimeInfo.endHour), 1) self._textProduct.debug_print("Wind Window Debug: windTimeInfo.endHour = %s" % (windTimeInfo.endHour), 1)
self._textProduct.debug_print("SARAH: Window Debug: pwsTXXStats.endTime = %s" % (pwsTXXStats.endTime), 1) self._textProduct.debug_print("Wind Window Debug: pwsTXXStats.endTime = %s" % (pwsTXXStats.endTime), 1)
if pwsTXXStats.endTime is not None:
self._textProduct.debug_print("Wind Window Debug: pwsTXXStats end hour = %s" % (self._calculateHourOffset(pwsTXXStats.endTime)), 1)
if windTimeInfo.onsetHour is None: if windTimeInfo.onsetHour is None:
# We won't have a timing window # We won't have a timing window
@ -2240,27 +2254,35 @@ class WindSectionStats(SectionCommonStats):
self._textProduct.debug_print("endTime for pwsTXXStats is not None", 1) self._textProduct.debug_print("endTime for pwsTXXStats is not None", 1)
endUnixTime = pwsTXXStats.endTime.unixTime() endUnixTime = pwsTXXStats.endTime.unixTime()
endLocalTime = time.localtime(endUnixTime) endLocalTime = time.localtime(endUnixTime)
startUnixTime = pwsTXXStats.onsetTime.unixTime() utcHourOffset = self._calculateUTCandLocalHourOffset()
startLocalTime = time.localtime(startUnixTime) self._textProduct.debug_print("utcHourOffset = %s" % (utcHourOffset), 1)
self._textProduct.debug_print("endTime for pwsTXXStats in local time is %s" %
(self._textProduct._pp.pformat(endLocalTime)), 1)
if endLocalTime.tm_hour >= 6 and endLocalTime.tm_hour < 18: # Remember these times are in local time zone, so hour 0 is
configuredTime = absTimeYMD(endLocalTime.tm_year, # midnight of the current calendar day.
endLocalTime.tm_mon, if endLocalTime.tm_hour > 6 and endLocalTime.tm_hour <= 18:
endLocalTime.tm_mday, configuredTime = absTimeYMD(pwsTXXStats.endTime.year,
self._textProduct.DAY()) pwsTXXStats.endTime.month,
elif endLocalTime.tm_hour < 6: pwsTXXStats.endTime.day,
# Use 6 PM of previous day
configuredTime = absTimeYMD(startLocalTime.tm_year,
startLocalTime.tm_mon,
startLocalTime.tm_mday,
self._textProduct.NIGHT()) self._textProduct.NIGHT())
else: else:
configuredTime = absTimeYMD(endLocalTime.tm_year, configuredTime = absTimeYMD(pwsTXXStats.endTime.year,
endLocalTime.tm_mon, pwsTXXStats.endTime.month,
endLocalTime.tm_mday, pwsTXXStats.endTime.day,
self._textProduct.NIGHT()) self._textProduct.DAY())
self._textProduct.debug_print("configuredTime (local time) = %s" %
(self._textProduct._pp.pformat(configuredTime)), 1)
# The configured hour is localtime so we need to add an offset to make the entire date UTC
configuredUnixTime = configuredTime.unixTime() + (utcHourOffset * 3600)
configuredTime = AbsTime(configuredUnixTime)
self._textProduct.debug_print("configuredTime (UTC time) = %s" %
(self._textProduct._pp.pformat(configuredTime)), 1)
probEndHour = self._calculateHourOffset(configuredTime) probEndHour = self._calculateHourOffset(configuredTime)
onsetEndInfo.endHour = int(round(self._textProduct.average(windTimeInfo.endHour, probEndHour))) onsetEndInfo.endHour = int(round(self._textProduct.average(windTimeInfo.endHour, probEndHour)))
self._textProduct.debug_print("endHour = " + str(onsetEndInfo.endHour), 1) self._textProduct.debug_print("endHour = " + str(onsetEndInfo.endHour), 1)
else: else:
@ -2271,13 +2293,13 @@ class WindSectionStats(SectionCommonStats):
def _createWindow(self, windowName, onsetHour, endHour): def _createWindow(self, windowName, onsetHour, endHour):
window = "Window for " + windowName + " force winds: " window = "Window for " + windowName + " force winds: "
self._textProduct.debug_print("SARAH: In _createWindow", 1) self._textProduct.debug_print("In _createWindow", 1)
self._textProduct.debug_print("SARAH: window stats:", 1) self._textProduct.debug_print("window stats:", 1)
self._textProduct.debug_print("SARAH: onsetHour = %s" % (onsetHour), 1) self._textProduct.debug_print("onsetHour = %s" % (onsetHour), 1)
self._textProduct.debug_print("SARAH: endHour = %s" % (endHour), 1) self._textProduct.debug_print("endHour = %s" % (endHour), 1)
if onsetHour is None: if onsetHour is None:
# SARAH - we do not want a statement of a non-existent window # We do not want a statement of a non-existent window
# window += "None" # window += "None"
window = None window = None
else: else:
@ -2287,7 +2309,7 @@ class WindSectionStats(SectionCommonStats):
windowPeriod = self._textProduct.makeTimeRange(startTime, endTime) windowPeriod = self._textProduct.makeTimeRange(startTime, endTime)
else: else:
windowPeriod = self._textProduct.makeTimeRange(startTime, startTime + 1) windowPeriod = self._textProduct.makeTimeRange(startTime, startTime + 1)
self._textProduct.debug_print("SARAH: window period = %s" % (windowPeriod), 1) self._textProduct.debug_print("window period = %s" % (windowPeriod), 1)
startTimeDescriptor = "" startTimeDescriptor = ""
if onsetHour >= 18: if onsetHour >= 18:
@ -2321,6 +2343,33 @@ class WindSectionStats(SectionCommonStats):
return window return window
def _calculateUTCandLocalHourOffset(self):
utc = time.gmtime()
local = time.localtime()
diffInSeconds = time.mktime(utc) - time.mktime(local)
return int(diffInSeconds // 3600)
def _isValidDayTime(self, trStartHour, utcDay, utcNight):
# Handle case where "night" starts at an "earlier" UTC hour than "day"
# (e.g. DAY = 18Z and NIGHT = 06Z)
if (utcNight < utcDay) and \
(trStartHour >= utcDay or trStartHour < utcNight):
# If we are toward the end of the daytime, and more than 1 hour
# from its end
if (trStartHour < utcNight) and (utcNight - trStartHour) > 1:
return True
# Handle "normal" case where "day" starts before "night" in UTC
elif trStartHour >= utcDay and trStartHour < utcNight and \
(utcNight - trStartHour) > 1:
return True
# If we made it this far, this is not a valid "day" hour
return False
class StormSurgeSectionStats(SectionCommonStats): class StormSurgeSectionStats(SectionCommonStats):
def __init__(self, textProduct, segment, intersectStatList, timeRangeList): def __init__(self, textProduct, segment, intersectStatList, timeRangeList):
@ -2338,7 +2387,7 @@ class StormSurgeSectionStats(SectionCommonStats):
possibleStop = 0 possibleStop = 0
self._textProduct.debug_print("*"*100, 1) self._textProduct.debug_print("*"*100, 1)
self._textProduct.debug_print("MATT phishStartTime = %s phishEndTime = %s possibleStop = %d" % self._textProduct.debug_print("phishStartTime = %s phishEndTime = %s possibleStop = %d" %
(str(phishStartTime), str(phishEndTime), possibleStop), 1) (str(phishStartTime), str(phishEndTime), possibleStop), 1)
for period in range(len(statList)): for period in range(len(statList)):
@ -2351,10 +2400,10 @@ class StormSurgeSectionStats(SectionCommonStats):
self._inundationMax = phishPeak self._inundationMax = phishPeak
curPhish = self._textProduct._getStatValue(statDict, "InundationTiming", "Max") curPhish = self._textProduct._getStatValue(statDict, "InundationTiming", "Max")
self._textProduct.debug_print("MATT tr = %s" % (repr(tr)), 1) self._textProduct.debug_print("tr = %s" % (self._textProduct._pp.pformat(tr)), 1)
self._textProduct.debug_print("MATT curPhish = '%s' possibleStop = %d" % self._textProduct.debug_print("curPhish = '%s' possibleStop = %d" %
(str(curPhish), possibleStop), 1) (str(curPhish), possibleStop), 1)
self._textProduct.debug_print("MATT 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 not None and possibleStop != 2: if curPhish is not None and possibleStop != 2:
@ -2379,15 +2428,15 @@ class StormSurgeSectionStats(SectionCommonStats):
self._onsetSurgeHour = self._calculateHourOffset(phishStartTime) self._onsetSurgeHour = self._calculateHourOffset(phishStartTime)
startTime = AbsTime(self._textProduct._issueTime_secs + self._onsetSurgeHour*60*60) startTime = AbsTime(self._textProduct._issueTime_secs + self._onsetSurgeHour*60*60)
self._textProduct.debug_print("MATT surge startTime = %s self._onsetSurgeHour = %s " % self._textProduct.debug_print("surge startTime = %s self._onsetSurgeHour = %s " %
(repr(startTime), self._onsetSurgeHour), 1) (self._textProduct._pp.pformat(startTime), self._onsetSurgeHour), 1)
if phishEndTime is not None: if phishEndTime is not None:
self._endSurgeHour = self._calculateHourOffset(phishEndTime) self._endSurgeHour = self._calculateHourOffset(phishEndTime)
endTime = AbsTime(self._textProduct._issueTime_secs + self._endSurgeHour*60*60) endTime = AbsTime(self._textProduct._issueTime_secs + self._endSurgeHour*60*60)
windowPeriod = self._textProduct.makeTimeRange(startTime, endTime) windowPeriod = self._textProduct.makeTimeRange(startTime, endTime)
else: else:
windowPeriod = self._textProduct.makeTimeRange(startTime, startTime + 1) windowPeriod = self._textProduct.makeTimeRange(startTime, startTime + 1)
self._textProduct.debug_print("SARAH: surge window period = %s" % (windowPeriod), 1) self._textProduct.debug_print("surge window period = %s" % (windowPeriod), 1)
startTimeDescriptor = self._textProduct._formatPeriod(windowPeriod) startTimeDescriptor = self._textProduct._formatPeriod(windowPeriod)
@ -2455,7 +2504,7 @@ class FloodingRainSectionStats(SectionCommonStats):
prevStatDict = extraRainfallStatList[period] prevStatDict = extraRainfallStatList[period]
prevStats = self._textProduct.getStats(prevStatDict, "QPF") prevStats = self._textProduct.getStats(prevStatDict, "QPF")
print "prevStats = ", prevStats self._textProduct.debug_print("prevStats = %s" % (prevStats), 1)
if prevStats is not None: if prevStats is not None:
self._prevAccum += prevStats self._prevAccum += prevStats
else: else:
@ -2497,8 +2546,8 @@ class XMLFormatter():
def execute(self, productDict): def execute(self, productDict):
xml = Element('product') xml = Element('product')
self.dictionary(xml, productDict) self.dictionary(xml, productDict)
self._textProduct.debug_print("SARAH: XML = %s" % (xml), 1) self._textProduct.debug_print("XML = %s" % (xml), 1)
self._textProduct.debug_print("SARAH: XML dump = %s", dump(xml), 1) self._textProduct.debug_print("XML dump = %s", dump(xml), 1)
prettyXML = minidom.parseString(tostring(xml)) prettyXML = minidom.parseString(tostring(xml))
return prettyXML.toprettyxml() #tostring(xml) return prettyXML.toprettyxml() #tostring(xml)
@ -2602,7 +2651,7 @@ class XMLFormatter():
if "._" in sectionKey: if "._" in sectionKey:
sectionKey = re.sub(".*\._", "", sectionKey) sectionKey = re.sub(".*\._", "", sectionKey)
self._textProduct.debug_print("SARAH: sectionKey = %s" % (sectionKey), 1) self._textProduct.debug_print("sectionKey = %s" % (sectionKey), 1)
return sectionKey return sectionKey
def dictionary(self, xml, productDict): def dictionary(self, xml, productDict):
@ -2622,7 +2671,7 @@ class XMLFormatter():
if key not in self.xmlKeys(): if key not in self.xmlKeys():
sectionKey = self.getSectionKey(key) sectionKey = self.getSectionKey(key)
if sectionKey not in self.sectionKeys(): if sectionKey not in self.sectionKeys():
self._textProduct.debug_print("SARAH: skipping '%s' in XML" % (key), 1) self._textProduct.debug_print("skipping '%s' in XML" % (key), 1)
continue continue
else: else:
key = sectionKey key = sectionKey
@ -2664,8 +2713,8 @@ class XMLFormatter():
if data is not None: if data is not None:
if 'info' in key and 'Section' in key: if 'info' in key and 'Section' in key:
subElement = SubElement(xml, key) subElement = SubElement(xml, key)
self._textProduct.debug_print("SARAH: info key = '%s'" % (key), 1) self._textProduct.debug_print("info key = '%s'" % (key), 1)
self._textProduct.debug_print("SARAH: value = %s" % (data), 1) self._textProduct.debug_print("value = %s" % (data), 1)
if isinstance(data, list): if isinstance(data, list):
subkey = 'info' + 'Sub' + key[4:] subkey = 'info' + 'Sub' + key[4:]
for value in data: for value in data:
@ -2714,7 +2763,7 @@ class LegacyFormatter():
@return text -- product string @return text -- product string
''' '''
text = '' text = ''
self._textProduct.debug_print("productParts = %s" % (repr(productParts)), 1) self._textProduct.debug_print("productParts = %s" % (self._textProduct._pp.pformat(productParts)), 1)
for part in productParts: for part in productParts:
valtype = type(part) valtype = type(part)
if valtype is str: if valtype is str:
@ -2925,5 +2974,3 @@ class LegacyFormatter():
newtext = self._processProductParts(subParts[i], infoDicts[i].get('partsList')) newtext = self._processProductParts(subParts[i], infoDicts[i].get('partsList'))
text += newtext text += newtext
return text return text

View file

@ -42,6 +42,7 @@
# start time from file's timestamp. # start time from file's timestamp.
# Oct 03, 2013 2402 bsteffen Make PythonDecoder more extendable. # Oct 03, 2013 2402 bsteffen Make PythonDecoder more extendable.
# Jun 10, 2014 3268 dgilling Update location of WclInfo class. # Jun 10, 2014 3268 dgilling Update location of WclInfo class.
# Dec 17, 2014 4953 randerso Fixed decoding of non-VTEC from command line
# </pre> # </pre>
# #
@ -111,10 +112,10 @@ class StdWarningDecoder():
self._timeOffset = 0 self._timeOffset = 0
#decode the command line #decode the command line
if text is None and filePath is None: if command is not None:
self._decodeCommandLine() self._decodeCommandLine()
self._rawMessage = None self._rawMessage = None
checkForWmo = False checkForWmo = True
else: else:
self._rawMessage = text self._rawMessage = text
checkForWmo = True checkForWmo = True

View file

@ -36,8 +36,13 @@
<setHeader headerName="notifygfe"> <setHeader headerName="notifygfe">
<simple>${body?.notifyGFE}</simple> <simple>${body?.notifyGFE}</simple>
</setHeader> </setHeader>
<setHeader headerName="drtstring">
<simple>${body?.drtString}</simple>
</setHeader>
<bean ref="practiceVtecDecoder" method="decode"/> <bean ref="practiceVtecDecoder" method="decode"/>
<bean ref="index" method="index"/> <bean ref="index" method="index"/>
<bean ref="processUtil" method="log"/>
<multicast parallelProcessing="false"> <multicast parallelProcessing="false">
<filter> <filter>
<simple>${header?.notifygfe.booleanValue}</simple> <simple>${header?.notifygfe.booleanValue}</simple>

View file

@ -19,7 +19,13 @@
**/ **/
package com.raytheon.uf.edex.activetable; package com.raytheon.uf.edex.activetable;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List; import java.util.List;
import java.util.TimeZone;
import java.util.concurrent.TimeUnit;
import com.raytheon.edex.esb.Headers; import com.raytheon.edex.esb.Headers;
import com.raytheon.uf.common.activetable.ActiveTableMode; import com.raytheon.uf.common.activetable.ActiveTableMode;
@ -45,6 +51,8 @@ import com.raytheon.uf.common.time.util.TimeUtil;
* Jul 14, 2009 #2950 njensen Multiple site support * Jul 14, 2009 #2950 njensen Multiple site support
* Dec 21, 2009 #4055 njensen No site filtering * Dec 21, 2009 #4055 njensen No site filtering
* Jun 17, 2014 3296 randerso Added performance logging * Jun 17, 2014 3296 randerso Added performance logging
* Dec 09, 2014 3885 dgilling Handle offset time from camel route
* headers.
* *
* </pre> * </pre>
* *
@ -80,7 +88,7 @@ public class ActiveTableSrv {
timer.start(); timer.start();
try { try {
ActiveTable activeTable = threadLocalActiveTable.get(); ActiveTable activeTable = threadLocalActiveTable.get();
if (records != null && records.size() > 0) { if ((records != null) && (records.size() > 0)) {
activeTable.merge(ActiveTableRecord.transformFromWarnings( activeTable.merge(ActiveTableRecord.transformFromWarnings(
records, ActiveTableMode.OPERATIONAL)); records, ActiveTableMode.OPERATIONAL));
} }
@ -102,19 +110,12 @@ public class ActiveTableSrv {
*/ */
public void practiceVtecArrived(List<AbstractWarningRecord> records, public void practiceVtecArrived(List<AbstractWarningRecord> records,
Headers headers) { Headers headers) {
Integer offsetSeconds = null; int offsetSeconds = getOffsetTime((String) headers.get("drtstring"));
if (headers != null) { if ((records != null) && (records.size() > 0)) {
offsetSeconds = (Integer) headers.get("offsetseconds");
}
if (offsetSeconds == null) {
offsetSeconds = Integer.valueOf(0);
}
if (records != null && records.size() > 0) {
ActiveTable activeTable = threadLocalActiveTable.get(); ActiveTable activeTable = threadLocalActiveTable.get();
try { try {
activeTable.merge(ActiveTableRecord.transformFromWarnings( activeTable.merge(ActiveTableRecord.transformFromWarnings(
records, ActiveTableMode.PRACTICE), offsetSeconds records, ActiveTableMode.PRACTICE), offsetSeconds);
.intValue());
} catch (Throwable t) { } catch (Throwable t) {
statusHandler statusHandler
.handle(Priority.PROBLEM, .handle(Priority.PROBLEM,
@ -123,4 +124,25 @@ public class ActiveTableSrv {
} }
} }
} }
private int getOffsetTime(String drtTimeString) {
if (drtTimeString != null) {
DateFormat drtParse = new SimpleDateFormat("yyyyMMdd_HHmm");
drtParse.setTimeZone(TimeZone.getTimeZone("GMT"));
try {
Date drtTime = drtParse.parse(drtTimeString);
Date currentTime = new Date();
long diffInMillis = drtTime.getTime() - currentTime.getTime();
return (int) TimeUnit.SECONDS.convert(diffInMillis,
TimeUnit.MILLISECONDS);
} catch (ParseException e) {
statusHandler.error("Could not parse DRT time string: "
+ drtTimeString, e);
}
}
return 0;
}
} }

View file

@ -46,6 +46,8 @@ import com.raytheon.uf.edex.python.decoder.PythonDecoder;
* used for all practice VTEC products * used for all practice VTEC products
* Changed to take in the SendPracticeProductRequest * Changed to take in the SendPracticeProductRequest
* to simplify spring wiring * to simplify spring wiring
* Changed to set the filepath when calling Python decoder
* so _checkForVTEC will work
* *
* </pre> * </pre>
* *
@ -103,7 +105,7 @@ public class PracticeVtecDecoder extends PythonDecoder {
// create an argument map to run the decoder // create an argument map to run the decoder
Map<String, Object> decoderArgs = new HashMap<String, Object>(4); Map<String, Object> decoderArgs = new HashMap<String, Object>(4);
decoderArgs.put("filePath", null); decoderArgs.put("filePath", file.getAbsolutePath());
decoderArgs.put("command", sb.toString()); decoderArgs.put("command", sb.toString());
return decode(decoderArgs); return decode(decoderArgs);