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

Former-commit-id: 766685c4ec [formerly 7fd3b02016b0d9eed7ecca9c2fd70c3f83695abc]
Former-commit-id: 8ced3a4c73
This commit is contained in:
Fay.Liang 2014-11-14 12:47:46 -05:00
commit b7da8368d3
25 changed files with 3842 additions and 28 deletions

View file

@ -0,0 +1,97 @@
# ----------------------------------------------------------------------------
# This software is in the public domain, furnished "as is", without technical
# support, and with no warranty, express or implied, as to its usefulness for
# any purpose.
#
# MFLFloodingRainThreat
#
# Author: M. Volkmer/P. Santos
# ----------------------------------------------------------------------------
from gfeConfig import *
HideConfigFile = 1
#------------------------------------------------------------------------
# GIF/PNG Graphic Product Generation (ifpIMAGE program)
#------------------------------------------------------------------------
# IMAGE SIZE
# You can set the height and width (in pixels) for the Png images.
# It is only necessary to set one of these, as the other will
# be calculated using the aspect ratio of your office domain.
# Do not include decimal points after the numbers.
# Both default to 400
#Png_height = 720
Png_width = 492
#NAME OF ELEMENT DISPLAYED AS IMAGE
Png_image = 'FloodingRainThreat'
Png_parms = ['FloodingRainThreat_SFC:_Official -1']
FloodingRainThreat_spatialImageType = ["Image"]
# Smoothing...
#Png_smoothImage = 1
# NWS Logos
Png_logo = 1
Png_logoString = "Flooding Rain Threat - NWS Miami FL"
# Turn off Color Bar
Png_omitColorBar = 0
# COLOR TABLES
FloodingRainThreat_defaultColorTable='GFE/gHLS_new'
# FloodThreat_maxColorTableValue = 6.0
# FloodThreat_minColorTableValue = 0.0
ImageLegend_color = 'black'
bgColor = 'white'
Counties_MFL_graphicColor = 'black'
Zones_MFL_graphicColor = 'black'
Marine_Zones_MFL_graphicColor = 'black'
Interstates_graphicColor = 'blue'
States_graphicColor = 'gray'
Lakes_graphicColor = 'blue'
# MAP BACKGROUNDS
#MapBackgrounds_default = ['Counties','Marine_Zones_MFL','Interstates']
MapBackgrounds_default = ['Zones_MFL','Marine_Zones_MFL','Interstates','States','Lakes']
MFL_mask = "MFL_NO_LAKE"
DefaultSamples = ['MFLFloodingRainThreat']
# Customize FONT SIZES here.
#TextFont0 = "Bitstream Vera Sans Mono-bold-10"
#TextFont1 = "Bitstream Vera Sans Mono-bold-10"
#TextFont2 = "Bitstream Vera Sans Mono-bold-11"
#TextFont3 = "Bitstream Vera Sans Mono-bold-10"
#TextFont4 = "Bitstream Vera Sans Mono-bold-10"
SESample_font = 1
SELegend_font = 2
SEColorBar_fgTextColor = "black"
#CONFIGURATION FILE SETTINGS
Png_filenamePrefix = 'MFLFloodingRainThreat'
Png_baseTimeFormat = ''
#LEGENDS
# Ability to turn on/off legends for the graphic generation. Applies
# only to graphic product generation and not GFE. Defaults to on
# if not specified. Do not include a decimal point after the number.
Png_legend = 1 #1 for visible, 0 for invisible
# Legends display mode - 0 for UTC, 1 for local time
# Do not include a decimal point after the number.
Png_localTime = 1 # legend displays time in local or UTC (default to UTC)
# Legend weather element name mode - 0 for weather element name,
# 1 for weather element descriptive name
#Png_descriptiveWeName = 1
Png_descriptiveWeName = "ALT"
Png_FloodingRainThreat_AltName = "Updated"
Png_legendFormat_LT_dur = ""
#Png_legendFormat_LT_start = "%A %b %d"
Png_legendFormat_LT_start = "%I %p %a %h %d"
# Png_legendFormat_LT_start = ""
Png_legendFormat_LT_end = ""

View file

@ -0,0 +1,93 @@
# ----------------------------------------------------------------------------
# This software is in the public domain, furnished "as is", without technical
# support, and with no warranty, express or implied, as to its usefulness for
# any purpose.
#
# MFLStormSurgeThreat
#
# Author: M. Volkmer/P. Santos
# ----------------------------------------------------------------------------
from gfeConfig import *
#HideConfigFile = 1
#------------------------------------------------------------------------
# GIF/PNG Graphic Product Generation (ifpIMAGE program)
#------------------------------------------------------------------------
# IMAGE SIZE
# Both default to 400
#Png_height = 720
Png_width = 492
#NAME OF ELEMENT DISPLAYED AS IMAGE
Png_image = 'StormSurgeThreat'
Png_parms = ['StormSurgeThreat_SFC:_Official -1']
StormSurgeThreat_spatialImageType = ["Image"]
# Smoothing...
#Png_smoothImage = 1
# NWS Logos
Png_logo = 1
Png_logoString = "Storm Surge Threat - NWS Miami FL"
# Turn off Color Bar
Png_omitColorBar = 0
# COLOR TABLES
StormSurgeThreat_defaultColorTable='GFE/gHLS_new'
#LocalSurgeThreat_maxColorTableValue = 6.0
#LocalSurgeThreat_minColorTableValue = 0.0
ImageLegend_color = 'black'
bgColor = 'white'
# Counties_graphicColor = 'grey'
Counties_MFL_graphicColor = 'black'
Zones_MFL_graphicColor = 'black'
Marine_Zones_MFL_graphicColor = 'black'
Interstates_graphicColor = 'blue'
States_graphicColor = 'gray'
Lakes_graphicColor = 'blue'
# MAP BACKGROUNDS
# MapBackgrounds_default = ['Counties','Marine_Zones_MFL','Interstates']
MapBackgrounds_default = ['Zones_MFL','Marine_Zones_MFL','Interstates','States','Lakes']
MFL_mask = "StormSurgeWW_EditArea"
DefaultSamples = ['MFLStormSurgeThreat']
# Customize FONT SIZES here
#TextFont0 = "Bitstream Vera Sans Mono-bold-10"
#TextFont1 = "Bitstream Vera Sans Mono-bold-10"
#TextFont2 = "Bitstream Vera Sans Mono-bold-11"
#TextFont3 = "Bitstream Vera Sans Mono-bold-10"
#TextFont4 = "Bitstream Vera Sans Mono-bold-10"
SESample_font = 1
SELegend_font = 2
SEColorBar_fgTextColor = "black"
#CONFIGURATION FILE SETTINGS
Png_filenamePrefix = 'MFLStormSurgeThreat'
Png_baseTimeFormat = ''
#LEGENDS
# Ability to turn on/off legends for the graphic generation. Applies
# only to graphic product generation and not GFE. Defaults to on
# if not specified. Do not include a decimal point after the number.
Png_legend = 1 #1 for visible, 0 for invisible
# Legends display mode - 0 for UTC, 1 for local time
# Do not include a decimal point after the number.
Png_localTime = 1 # legend displays time in local or UTC (default to UTC)
# Legend weather element name mode - 0 for weather element name,
# 1 for weather element descriptive name
#Png_descriptiveWeName = 1
Png_descriptiveWeName = "ALT"
Png_StormSurgeThreat_AltName="Updated"
Png_legendFormat_LT_dur = ""
#Png_legendFormat_LT_start = "%A %b %d"
Png_legendFormat_LT_start = "%I %p %a %h %d"
# Png_legendFormat_LT_start = ""
Png_legendFormat_LT_end = ""

View file

@ -0,0 +1,88 @@
# ----------------------------------------------------------------------------
# This software is in the public domain, furnished "as is", without technical
# support, and with no warranty, express or implied, as to its usefulness for
# any purpose.
#
# gHLSMFLTornadoThreat
#
# Author: M. Volkmer/P. Santos
# ----------------------------------------------------------------------------
from gfeConfig import *
#------------------------------------------------------------------------
# GIF/PNG Graphic Product Generation (ifpIMAGE program)
#------------------------------------------------------------------------
# IMAGE SIZE
#Png_height = 720
Png_width = 492
#NAME OF ELEMENT DISPLAYED AS IMAGE
Png_image = 'TornadoThreat'
Png_parms = ['TornadoThreat_SFC:_Official -1']
TornadoThreat_spatialImageType = ["Image"]
# Smoothing...
#Png_smoothImage = 1
# NWS Logos
Png_logo = 1
Png_logoString = "Tornado Threat - NWS Miami FL"
# Turn off Color Bar
Png_omitColorBar = 0
# COLOR TABLES
TornadoThreat_defaultColorTable='GFE/gHLS_new'
#MFLTornadoThreat_maxColorTableValue = 6.0
#MFLTornadoThreat_minColorTableValue = 0.0
ImageLegend_color = 'black'
bgColor = 'white'
Counties_MFL_graphicColor = 'black'
Zones_MFL_graphicColor = 'black'
Marine_Zones_MFL_graphicColor = 'black'
Interstates_graphicColor = 'blue'
States_graphicColor = 'gray'
Lakes_graphicColor = 'blue'
# MAP BACKGROUNDS
#MapBackgrounds_default = ['Counties','Marine_Zones_MFL','Interstates']
MapBackgrounds_default = ['Zones_MFL','Marine_Zones_MFL','Interstates','States','Lakes']
MFL_mask = "MFL_CWA"
DefaultSamples = ['MFLTornadoThreat']
# Customize FONT SIZES here
#TextFont0 = "Bitstream Vera Sans Mono-bold-10"
#TextFont1 = "Bitstream Vera Sans Mono-bold-10"
#TextFont2 = "Bitstream Vera Sans Mono-bold-11"
#TextFont3 = "Bitstream Vera Sans Mono-bold-10"
#TextFont4 = "Bitstream Vera Sans Mono-bold-10"
SESample_font = 1
SELegend_font = 2
SEColorBar_fgTextColor = "black"
#CONFIGURATION FILE SETTINGS
Png_filenamePrefix = 'MFLTornadoThreat'
Png_baseTimeFormat = ''
#LEGENDS
# Ability to turn on/off legends for the graphic generation. Applies
# only to graphic product generation and not GFE. Defaults to on
# if not specified. Do not include a decimal point after the number.
Png_legend = 1 #1 for visible, 0 for invisible
# Legends display mode - 0 for UTC, 1 for local time
# Do not include a decimal point after the number.
Png_localTime = 1 # legend displays time in local or UTC (default to UTC)
Png_descriptiveWeName = "ALT"
Png_TornadoThreat_AltName = "Updated"
Png_legendFormat_LT_dur = ""
#Png_legendFormat_LT_start = "%A %b %d"
Png_legendFormat_LT_start = "%I %p %a %h %d"
# Png_legendFormat_LT_start = ""
Png_legendFormat_LT_end = ""

View file

@ -0,0 +1,98 @@
# ----------------------------------------------------------------------------
# This software is in the public domain, furnished "as is", without technical
# support, and with no warranty, express or implied, as to its usefulness for
# any purpose.
#
# MFLWindThreat
#
# Author: M. Volkmer/P. Santos
# ----------------------------------------------------------------------------
from gfeConfig import *
#------------------------------------------------------------------------
# GIF/PNG Graphic Product Generation (ifpIMAGE program)
#------------------------------------------------------------------------
# IMAGE SIZE
# You can set the height and width (in pixels) for the Png images.
# It is only necessary to set one of these, as the other will
# be calculated using the aspect ratio of your office domain.
# Do not include decimal points after the numbers.
# Both default to 400
#Png_height = 720
Png_width = 492
#NAME OF ELEMENT DISPLAYED AS IMAGE
Png_image = 'WindThreat'
Png_parms = ['WindThreat_SFC:_Official -1']
WindThreat_spatialImageType = ["Image"]
# Smoothing...
#Png_smoothImage = 1
# NWS Logos
Png_logo = 1
Png_logoString = "Wind Threat - NWS Miami FL"
# Turn off Color Bar
Png_omitColorBar = 0
# COLOR TABLES
WindThreat_defaultColorTable='GFE/gHLS_new'
# FloodThreat_maxColorTableValue = 6.0
# FloodThreat_minColorTableValue = 0.0
ImageLegend_color = 'black'
bgColor = 'white'
Counties_MFL_graphicColor = 'black'
Zones_MFL_graphicColor = 'black'
Marine_Zones_MFL_graphicColor = 'black'
Interstates_graphicColor = 'blue'
States_graphicColor = 'gray'
Lakes_graphicColor = 'blue'
# MAP BACKGROUNDS
#MapBackgrounds_default = ['Counties','Marine_Zones_MFL','Interstates']
MapBackgrounds_default = ['Zones_MFL','Marine_Zones_MFL','Interstates','States','Lakes']
MFL_mask = "MFL"
DefaultSamples = ['MFLWindThreat']
# Customize FONT SIZES here
#TextFont0 = "Bitstream Vera Sans Mono-bold-10"
#TextFont1 = "Bitstream Vera Sans Mono-bold-10"
#TextFont2 = "Bitstream Vera Sans Mono-bold-11"
#TextFont3 = "Bitstream Vera Sans Mono-bold-10"
#TextFont4 = "Bitstream Vera Sans Mono-bold-10"
SESample_font = 1
SELegend_font = 2
SEColorBar_fgTextColor = "black"
#CONFIGURATION FILE SETTINGS
Png_filenamePrefix = 'MFLWindThreat'
Png_baseTimeFormat = ''
#LEGENDS
# Ability to turn on/off legends for the graphic generation. Applies
# only to graphic product generation and not GFE. Defaults to on
# if not specified. Do not include a decimal point after the number.
Png_legend = 1 #1 for visible, 0 for invisible
# Legends display mode - 0 for UTC, 1 for local time
# Do not include a decimal point after the number.
Png_localTime = 1 # legend displays time in local or UTC (default to UTC)
# Legend weather element name mode - 0 for weather element name,
# 1 for weather element descriptive name
#Png_descriptiveWeName = 1
Png_descriptiveWeName = "ALT"
Png_WindThreat_AltName = "Updated"
Png_legendFormat_LT_dur = ""
#Png_legendFormat_LT_start = "%A %b %d"
Png_legendFormat_LT_start = "%I %p %a %h %d"
# Png_legendFormat_LT_start = ""
Png_legendFormat_LT_end = ""

View file

@ -1,19 +1,19 @@
##
# This software was developed and / or modified by Raytheon Company,
# pursuant to Contract DG133W-05-CQ-1067 with the US Government.
#
# U.S. EXPORT CONTROLLED TECHNICAL DATA
# pursuant to Contract DG133W-05-CQ-1067 with the US Government.
#
# U.S. EXPORT CONTROLLED TECHNICAL DATA
# This software product contains export-restricted data whose
# export/transfer/disclosure is restricted by U.S. law. Dissemination
# to non-U.S. persons whether in the United States or abroad requires
# an export license or other authorization.
#
# Contractor Name: Raytheon Company
# Contractor Address: 6825 Pine Street, Suite 340
# Mail Stop B8
# Omaha, NE 68106
# 402.291.0100
#
# Contractor Name: Raytheon Company
# Contractor Address: 6825 Pine Street, Suite 340
# Mail Stop B8
# Omaha, NE 68106
# 402.291.0100
#
# See the AWIPS II Master Rights File ("Master Rights File.pdf") for
# further licensing information.
##
@ -1193,6 +1193,73 @@ FogW_defaultColorTable = "Sat/WV/Gray Scale Water Vapor"
Hazards_defaultColorTable = "GFE/Hazards"
# Start HTI entries
ProposedSS_defaultColorTable="GFE/w"
ProposedSSnc_defaultColorTable="GFE/w"
InundationMax_defaultColorTable="GFE/Inundation"
InundationMax_maxColorTableValue = 30.0
InundationMax_minColorTableValue = 0.0
InundationMaxnc_defaultColorTable="GFE/Inundation"
InundationMaxnc_maxColorTableValue = 30.0
InundationMaxnc_minColorTableValue = 0.0
InundationTiming_defaultColorTable="GFE/Inundation"
InundationTiming_maxColorTableValue = 30.0
InundationTiming_minColorTableValue = 0.0
InundationTimingnc_defaultColorTable="GFE/Inundation"
InundationTimingnc_maxColorTableValue = 30.0
InundationTimingnc_minColorTableValue = 0.0
SurgeHtPlusTideMLLW_defaultColorTable="GFE/Inundation"
SurgeHtPlusTideMLLW_maxColorTableValue = 30.0
SurgeHtPlusTideMLLW_minColorTableValue = 0.0
SurgeHtPlusTideMLLWnc_defaultColorTable="GFE/Inundation"
SurgeHtPlusTideMLLWnc_maxColorTableValue = 30.0
SurgeHtPlusTideMLLWnc_minColorTableValue = 0.0
SurgeHtPlusTideMHHW_defaultColorTable="GFE/Inundation"
SurgeHtPlusTideMHHW_maxColorTableValue = 30.0
SurgeHtPlusTideMHHW_minColorTableValue = 0.0
SurgeHtPlusTideMHHWnc_defaultColorTable="GFE/Inundation"
SurgeHtPlusTideMHHWnc_maxColorTableValue = 30.0
SurgeHtPlusTideMHHWnc_minColorTableValue = 0.0
SurgeHtPlusTideNAVD_defaultColorTable="GFE/Inundation"
SurgeHtPlusTideNAVD_maxColorTableValue = 30.0
SurgeHtPlusTideNAVD_minColorTableValue = 0.0
SurgeHtPlusTideNAVDnc_defaultColorTable="GFE/Inundation"
SurgeHtPlusTideNAVDnc_maxColorTableValue = 30.0
SurgeHtPlusTideNAVDnc_minColorTableValue = 0.0
SurgeHtPlusTideMSL_defaultColorTable="GFE/Inundation"
SurgeHtPlusTideMSL_maxColorTableValue = 30.0
SurgeHtPlusTideMSL_minColorTableValue = 0.0
SurgeHtPlusTideMSLnc_defaultColorTable="GFE/Inundation"
SurgeHtPlusTideMSLnc_maxColorTableValue = 30.0
SurgeHtPlusTideMSLnc_minColorTableValue = 0.0
prob34_defaultColorTable="GFE/TPCprob"
prob64_defaultColorTable="GFE/TPCprob"
pwsD34_defaultColorTable="GFE/TPCprob"
pwsD64_defaultColorTable="GFE/TPCprob"
pwsN34_defaultColorTable="GFE/TPCprob"
pwsN64_defaultColorTable="GFE/TPCprob"
pws34int_defaultColorTable="GFE/TPCprob"
pws64int_defaultColorTable="GFE/TPCprob"
FloodingRainThreat_defaultColorTable = "GFE/gHLS_new"
StormSurgeThreat_defaultColorTable = "GFE/gHLS_new"
TornadoThreat_defaultColorTable = "GFE/gHLS_new"
WindThreat_defaultColorTable = "GFE/gHLS_new"
# End HTI entries
# TopDownWx
MaxTAloft_defaultColorTable="WarmNoseTemp"
WetBulb_defaultColorTable="WetBulbTemp"
@ -1611,6 +1678,9 @@ Scripts = [
"ifpAG -h {host} -r {port} -o {prddir}/AG/{ztime}.ag " +\
"-d {productDB} ",
"Make and Send HTI:" +
"xterm -e ssh px2 /awips2/GFESuite/hti/bin/make_hti.sh",
"Official Grids to LDAD: " +
"ifpAG -h {host} -r {port} -o - -d {productDB} | gzip -9 > " +
" /data/fxa/LDAD/ifp/Official/.incoming; " +

View file

@ -0,0 +1,149 @@
#--------------------------------------------------------------------------
# SVN: $Revision$ - $Date$
#
# Converted with gfePorter R3342 on Oct 01, 2013 18:43 GMT
# Not tested. Remove these 2 lines when ported and tested.
#
# ----------------------------------------------------------------------------
# This software is in the public domain, furnished "as is", without technical
# support, and with no warranty, express or implied, as to its usefulness for
# any purpose.
#
# CopyNHCProposed
#
# Author: T LeFebvre/P. Santos
# Last Modified: Sept 18, 2014
# ----------------------------------------------------------------------------
# The MenuItems list defines the GFE menu item(s) under which the
# Procedure is to appear.
# Possible items are: Populate, Edit, Consistency, Verify, Hazards
MenuItems = ["Populate"]
# The ToolList is optional, but recommended, if you are calling
# Smart Tools from your Script.
# If present, it can be used to show which grids will be
# modified by the Script.
ToolList = []
### If desired, Set up variables to be solicited from the user:
## If your script calls Smart Tools, this VariableList should cover
## cover all the variables necessary for the tools.
import SmartScript
from numpy import *
import TimeRange
import AbsTime
import time, re
## For documentation on the available commands,
## see the SmartScript Utility, which can be viewed from
## the Edit Actions Dialog Utilities window
Supported_elements=["ProposedSS"]
VariableList = [("Choose Hazards:" , ["ProposedSS"], "check", Supported_elements),
# ["ProposedSS"]),
]
class Procedure (SmartScript.SmartScript):
def __init__(self, dbss):
SmartScript.SmartScript.__init__(self, dbss)
# Makes a timeRange based on the specified start and end times.
# If no times are specified, returns the largest timeRange possible.
# This method will work in either an AWIPS I or AWIPS II environment.
def makeTimeRange(self, start=0, end=0):
try: # AWIPS 1 code
import TimeRange
import AbsTime
import AFPS
if start == 0 and end == 0:
return TimeRange.TimeRange.allTimes()
startTime = AbsTime.AbsTime(start)
endTime = AbsTime.AbsTime(end)
tr = TimeRange.TimeRange(startTime, endTime)
except: # AWIPS 2 code
import TimeRange, AbsTime
if start == 0 and end == 0:
return TimeRange.allTimes()
startTime = AbsTime.AbsTime(start)
endTime = AbsTime.AbsTime(end)
tr = TimeRange.TimeRange(startTime, endTime)
return tr
def makeNewTimeRange(self, hours):
startTime = int(time.time() / 3600) * 3600
endTime = startTime + hours * 3600
timeRange = self.makeTimeRange(startTime, endTime)
return timeRange
def getWEInventory(self, modelName, WEName, timeRange=None):
if timeRange is None:
timeRange = self.makeTimeRange()
gridInfo = self.getGridInfo(modelName, WEName, "SFC", timeRange)
trList = []
for g in gridInfo:
start = g.gridTime().startTime().unixTime()
end = g.gridTime().endTime().unixTime()
tr = self.makeTimeRange(start, end)
trList.append(tr)
return trList
def execute(self, varDict):
# Assign a timeRange from now to 48 hours from now
timeRange = self.makeNewTimeRange(48)
# Copy the ISC data into a grid
hazardsToCopy = varDict["Choose Hazards:"]
if len(hazardsToCopy) == 0:
self.statusBarMsg("You must choose at least one hazard.", "U")
return
weNames = ["ProposedSS"]
#weNames = ["ProposedSS"]
# Remove any pre-existing grids first
for weName in weNames:
if weName not in hazardsToCopy:
continue
trList = self.getWEInventory("Fcst", weName)
for delTR in trList:
self.deleteGrid("Fcst", weName, "SFC", delTR)
# Copy any Proposed nc grids into the Fcst
for weName in weNames:
if weName not in hazardsToCopy:
continue
iscWeName = weName + "nc"
trList = self.getWEInventory("ISC", iscWeName, timeRange)
if len(trList) == 0:
continue
gridTR = trList[-1] # only interested in the latest grid
iscGrid, iscKeys = self.getGrids("ISC", iscWeName, "SFC", gridTR)
self.createGrid("Fcst", weName, "DISCRETE", (iscGrid, iscKeys),
timeRange, discreteKeys=iscKeys, discreteOverlap=0,
discreteAuxDataLength=0, defaultColorTable="StormSurgeHazards")

View file

@ -0,0 +1,573 @@
# ----------------------------------------------------------------------------
# This software is in the public domain, furnished "as is", without technical
# support, and with no warranty, express or implied, as to its usefulness for
# any purpose.
#
# InlandFloodThreat
#
# Author: lefebvre,santos
# Last Modified: April 4, 2012 - Fixed to handle negative gridded FFG.
# Migrated procedure for AWIPS2. Updated 6/22/2012. S.O.
#
# Comment on 05/21/2014 (Santos): Some sites used QPF and others QPF6hr. Check that parameter
# in getQPFGrid method. Also in AWIPS 2 FFG is gridded and called just FFG.
# This is fixed in getRFCFFGModels method.
#
# LeFevbre/Santos: This is the version being turned in for baseline as of 10/20/2014
#
#Search for COMMENTS to see any local config step you might need to take.
# ----------------------------------------------------------------------------
MenuItems = ["Populate"]
VariableList = [("Gridded/Text FFG Blending Factor" , 0.75, "scale", [0, 1], 0.05)]
import SmartScript
import time
import popen2
import sys
import AbsTime
import TimeRange
# # For AWIPS 1/ AWIPS 2 compatibility
# try:
# from Numeric import *
# except:
# from numpy import *
from numpy import *
class Procedure (SmartScript.SmartScript):
def __init__(self, dbss):
SmartScript.SmartScript.__init__(self, dbss)
# Make a timeRange based on the start and end int times
def makeTimeRange(self, start, end):
try: # AWIPS 1 code
import AFPS
startTime = AFPS.AbsTime(start)
endTime = AFPS.AbsTime(end)
tr = AFPS.TimeRange(startTime, endTime)
except: # AWIPS 2 code
import TimeRange, AbsTime
startTime = AbsTime.AbsTime(start)
endTime = AbsTime.AbsTime(end)
#print 40 * "*"
#print "start and end times are:", startTime, endTime
tr = TimeRange.TimeRange(startTime, endTime)
return tr
def getWEInventory(self, modelName, WEName, timeRange=None):
allTimes = TimeRange.allTimes()
if timeRange is None:
timeRange = allTimes
trList = []
# getGridInfo will just die if the modelName or weName is not valid
# so wrap it in a try block and return [] if it fails
try:
gridInfo = self.getGridInfo(modelName, WEName, "SFC", timeRange)
except:
return trList
for g in gridInfo:
start = g.gridTime().startTime().unixTime()
end = g.gridTime().endTime().unixTime()
tr = self.makeTimeRange(start, end)
if timeRange.overlaps(tr):
trList.append(tr)
return trList
# get the current time, truncates to the last six hour value.
# returns a timeRange with this startTime until 72 hrs from this time
def make72hrTimeRange(self):
cTime = int(self._gmtime().unixTime()/ (3600 * 6)) * (3600 * 6)
startTime = AbsTime.AbsTime(cTime)
end = cTime + (3600 * 24 * 3)
endTime = AbsTime.AbsTime(end)
timeRange = TimeRange.TimeRange(startTime, endTime)
return timeRange
# returns a list of timeRange with the specified duration in hours over the
# specified timeRange
def makeTimeRangeList(self, timeRange, duration):
trList = []
sTime = timeRange.startTime().unixTime()
delta = duration * 3600
while sTime < timeRange.endTime().unixTime():
trList.append(self.makeTimeRange(sTime, sTime + delta))
sTime = sTime + delta
return trList
# Returns a list of model names matching the specified model name,
# weather element name and level
def getModelList(self, modelName, weName, weLevel):
modelList = []
availParms = self.availableParms()
for pName, level, dbID in availParms:
if dbID.modelName().find(modelName) > -1:
if pName.find(weName) > -1:
if level.find(weLevel) > -1:
if dbID.modelIdentifier() not in modelList:
modelList.append(dbID.modelIdentifier())
return modelList
# A small algorithm to determine the day number
def determineDay(self, modelTime, validTime):
diff = (validTime - modelTime) / 3600
if diff < 48:
return 1
elif diff < 72:
return 2
else
return 3
return 0
def getModelTime(self, modelName):
timeStr = modelName[-13:]
year = int(timeStr[0:4])
month = int(timeStr[4:6])
day = int(timeStr[6:8])
hour = int(timeStr[9:11])
absTime = AbsTime.absTimeYMD(year, month, day, hour, 0, 0)
return absTime.unixTime()
def getERPGrids(self):
ERPModelName = "HPCERP"
ERPVarName = "ppffg"
ERPLevel = "SFC"
# make a dict and fill with grids with the default value.
# These will be replaced when we find real grids
gridDict = {}
for i in range(1, 4):
gridDict[i] = None
# get the list of all available models
modelList = self.getModelList(ERPModelName, ERPVarName, ERPLevel)
modelList.sort() # sort oldest to latest
# for each available model, fetch all the grids
# keep only the most recent grids
for model in modelList:
trList = self.getWEInventory(model, ERPVarName)
modelTime = self.getModelTime(model)
for tr in trList:
dayNum = self.determineDay(modelTime,
tr.startTime().unixTime())
grid = self.getGrids(model, ERPVarName, ERPLevel, tr,
mode="First")
gridDict[dayNum] = grid
for i in range(1, 4):
if gridDict[i] == None:
errorStr = "Day" + str(i) + " grid not found in AWIPS database."
self.statusBarMsg(errorStr, "S")
return gridDict
# Use this method for testing if you have no luck getting products
# directly from the text database
def getTextProductFromFile(self, filename):
# replace the filename with one on your system
filename = "/tmp/FFGData/" + filename + ".txt"
f = file(filename, 'r')
textList = []
line = f.readline()
textList.append(line)
while line != "":
line = f.readline()
textList.append(line)
f.close()
return textList
# Retrieves a text product from the text database
def getTextProductFromDB(self, productID):
cmd = "textdb -r " + productID
(stdout, stdin, stderr) = popen2.popen3(cmd)
textList = []
line = stdout.readline()
textList.append(line)
while line != "":
line = stdout.readline()
textList.append(line)
return textList
# given a text product, this method decodes the ffg values and
# returns a dictionary {area : value}
def decodeFFGText(self, ffgText):
ffgDict = {}
for s in ffgText:
parts = s.split()
if len(parts) < 4:
continue
if len(parts[0]) != 6:
continue
if parts[0][2] != "Z":
continue
area = parts[0]
value6hr = float(parts[3][:-1]) # strip the "/"
ffgDict[area] = value6hr
return ffgDict
# Fetch all of the gridded FFG model names and return just the
# latest version of each type (region)
def getRFCFFGModelName(self, rfcName):
# Find all the models matching this description.
modelList = self.getModelList(rfcName, "FFG0624hr", "SFC")
for model in modelList:
# WARNING!!! This check should be more specific to the DBID string.
if model.find(rfcName) > -1:
return model
return None
# Smooths the specified grid by the specified factor
# With factor == 3, 3x3 smooth, factor == 5 5x5 smooth, etc.
# Even factors (4, 6, 8,...) round up to the next odd value
# If factors <3 are specified, the unmodified grid is returned.
def smoothGrid(self, grid, factor=3):
# factors of less than 3 are useless or dangerous
if factor < 3:
return grid
st = time.time()
half = int(factor)/ 2
sg = zeros(grid.shape, 'f8')
count = zeros(grid.shape, 'f8')
gridOfOnes = ones(grid.shape, 'f8')
for y in range(-half, half + 1):
for x in range(-half, half + 1):
if y < 0:
yTargetSlice = slice(-y, None, None)
ySrcSlice = slice(0, y, None)
if y == 0:
yTargetSlice = slice(0, None, None)
ySrcSlice = slice(0, None, None)
if y > 0:
yTargetSlice = slice(0, -y, None)
ySrcSlice = slice(y, None, None)
if x < 0:
xTargetSlice = slice(-x, None, None)
xSrcSlice = slice(0, x, None)
if x == 0:
xTargetSlice = slice(0, None, None)
xSrcSlice = slice(0, None, None)
if x > 0:
xTargetSlice = slice(0, -x, None)
xSrcSlice = slice(x, None, None)
target = [yTargetSlice, xTargetSlice]
src = [ySrcSlice, xSrcSlice]
sg[target] = sg[target] + grid[src]
count[target] = count[target] + gridOfOnes[src]
return sg / count
# Returns the list of RFCs that overlap the local GFE domain
# as defined by getSiteID().
def getOverlappingRFCs(self):
# The list of all the RFCs
RFCEditAreas = ["ISC_PTR", "ISC_RSA", "ISC_STR", "ISC_ACR", "ISC_KRF", "ISC_MSR", "ISC_TUA", "ISC_FWR", "ISC_ORN",
"ISC_TIR", "ISC_ALR", "ISC_RHA", "ISC_TAR"]
cwaEA = self.getSiteID()
cwaMask = self.encodeEditArea(cwaEA)
eaList = self.editAreaList()
rfcList = []
for rfc in RFCEditAreas:
rfcMask = None
if rfc in eaList:
rfcArea = self.getEditArea(rfc)
rfcMask = self.encodeEditArea(rfc)
if rfcMask is None:
continue
overlap = logical_and(cwaMask, rfcMask)
if overlap.any():
rfcList.append(rfc)
return rfcList
# First try to access the gridded FFG from the D2D files. If they exist
# mosaic all the ones we find and return the composite. If we can't
# find any gridded FFG, then fetch the FFG text product, decode it,
# and create a patchwork grid from the guidance value in each county
# or basin.
def getRFCFlashFloodGrid(self, productList, varDict):
ffgGrid = self._empty
foundGrids = False
factor = varDict["Gridded/Text FFG Blending Factor"]
RFCList = self.getOverlappingRFCs()
#print "RFCList is: ", RFCList
ffgWEName = "FFG0624hr"
# Fetch the gridded FFG, mosaic these into a single grid
for rfc in RFCList:
tmplist = rfc.split('_');
rfcsid = tmplist[1];
rfcName = 'FFG' + rfcsid;
# Find the model for this RFC
modelName = self.getRFCFFGModelName(rfcName)
#print "modelName:", modelName
if modelName is None:
self.statusBarMsg("No FFG database found for " + rfc, "S")
continue
trList = self.getWEInventory(modelName, ffgWEName)
if len(trList) == 0:
self.statusBarMsg("No FFG grids found in database " + modelName, "S")
continue
# get the first grid
tempGrid = self.getGrids(modelName, ffgWEName, "SFC", trList[0], mode="First")
# Make an rfc mask
rfcEA = self.getEditArea(rfc)
rfcMask = self.encodeEditArea(rfcEA)
mask = (tempGrid > 0.0) & rfcMask
ffgGrid = where(mask, tempGrid/25.4, ffgGrid)
foundGrids = True
# Comment this in to see intermediate FFG grid from gridded guidance
## tr = self.getTimeRange("Today")
## self.createGrid("Fcst","FFGFromGrid", "SCALAR", ffgGrid, tr,
## minAllowedValue = -1, maxAllowedValue=100,
## precision=2)
# Make another FFG grid from the text guidance
editAreaList = self.editAreaList()
ffgTextGrid = self._empty
for prod in productList:
# Uncomment the next line to fetch FFG data from a file
## ffgText = self.getTextProductFromFile(prod)
# Use this method to retrieve FFG data from the text database
ffgText = self.getTextProductFromDB(prod)
ffgDict = self.decodeFFGText(ffgText)
for area in ffgDict.keys():
if area not in editAreaList:
continue
refArea = self.getEditArea(area)
mask = self.encodeEditArea(refArea)
value = ffgDict[area]
ffgTextGrid = where(mask, value, ffgTextGrid)
# Comment this in to see intermediate FFG from text guidance
## tr = self.getTimeRange("Today")
## self.createGrid("Fcst","FFGFromText", "SCALAR", ffgTextGrid, tr,
## minAllowedValue = -1, maxAllowedValue=100,
## precision=2)
# Since the gridded FFG tends to have lots of holes in it,
# fill those holes with the text version of the FFG where the
# gridded FFG is less than its non-zero average.
# if we found the grids fill in it in with values from the text products.
if foundGrids:
# get the non-zero gridded average
mask = greater(ffgGrid, 0.0)
maskSum = sum(sum(mask))
gridSum = sum(sum(ffgGrid))
if maskSum > 0:
gridAvg = gridSum / maskSum
else: # nothing to do but return the text grid
return ffgTextGrid
# fill in textFFG where griddedFFG is less than average
#print "AVERAGE IS: ", gridAvg
ffgGrid = where(less(ffgGrid, gridAvg * factor), ffgTextGrid, ffgGrid)
else:
ffgGrid = ffgTextGrid
return ffgGrid
# Returns the QPF sum over the specified timeRange
def getQPFGrid(self, timeRange):
#
# This assumes QPF has a constraint of TC6NG. If not and your office uses QPF6 or QPF6hr you will need to change this here
# accordingly.
#
trList = self.getWEInventory("Fcst", "QPF", timeRange)
if len(trList) == 0:
return None
qpfGrid = self._empty
for tr in trList:
grid = self.getGrids("Fcst", "QPF", "SFC", timeRange, mode="First")
qpfGrid = qpfGrid + grid
return qpfGrid
def execute(self, varDict):
### CONFIGURATION SECTION ################################
### Levels must exactly match the levels in the inland threat
### weather element.
ratios = [0.0, 0.75, 1.0, 2.0, 100.0]
erps = [0.0, 5.0, 10.0, 15.0, 100.0]
cumqpfs = [0.0, 5.0, 10.0, 15.0, 20.0]
threatMatrix = [
["None", "Very Low", "Elevated", "Mod" ], # lowest ERP
["Very Low", "Elevated", "Mod", "High" ],
["Elevated", "Mod", "High", "Extreme"],
["Mod", "High", "Extreme", "Extreme"], # highest # ERP
] # low ------ QPF/FFG ratio -------->high
# COMMENTS: The list of FFG products that contain FFG data for your WFO
# The following is set up for testing only. Please change these
# entries for your particular office.
# productList = ["FFGSHV", "FFGALR"]
productList = ["ATLFFGMFL", "ATLFFGTBW", "ATLFFGMLB"]
### END CONFIGURATION SECTION #################################
## Replace the "Very Low" with "Elevated" if "Very Low" dows not exist
## in the list of discrete keys
try:
threatKeys = self.getDiscreteKeys("FloodingRainThreat")
except:
threatKeys = ["None", "Elevated", "Mod", "High", "Extreme"]
# replace "Very Low" with "Elevated"
if "Very Low" not in threatKeys:
for i in range(len(threatMatrix)):
for j in range(len(threatMatrix[i])):
if threatMatrix[i][j] == "Very Low":
threatMatrix[i][j] = "Elevated"
# make a 72 hour timeRange and a list of 6 hour timeRanges
timeRange = self.make72hrTimeRange()
trList = self.makeTimeRangeList(timeRange, 6)
maxFloodThreat = self._empty
cumqpf = self._empty
# Fetch the FFG grid either from gridded data or the text product
#print "Getting FFG Grid Now: "
ffgGrid = self.getRFCFlashFloodGrid(productList,varDict)
#print "GOT FFG Grid"
ffgGrid = where(less(ffgGrid, 0.0), 0.0, ffgGrid)
# get the ERP grids and stuff them in six hour time blocks to match
# the cummulative QPF grids will create later
erpGridDict = self.getERPGrids()
for i in range(len(trList)):
erpGrid = erpGridDict[int(i / 4 + 1)]
tr = trList[i]
#print "TIME RANGE IS:", tr
qpfGrid = self.getQPFGrid(tr)
if ffgGrid is None or qpfGrid is None:
self.statusBarMsg("FlashFlood or QPF grids missing at timeRange:" +
str(tr), "S")
continue
if erpGrid is None:
self.statusBarMsg("ERP grids missing at timeRange:" +
str(tr), "S")
continue
tempffgGrid = where(equal(ffgGrid, 0.0), 1000.0, ffgGrid)
ratioGrid = qpfGrid / tempffgGrid
ratioGrid = where(equal(ffgGrid, 0.0), 0.0, ratioGrid)
self.createGrid("Fcst", "ERP", "SCALAR", erpGrid, tr,
minAllowedValue = -1, maxAllowedValue=100,
precision=2)
self.createGrid("Fcst", "FFGNEW", "SCALAR", ffgGrid, tr,
minAllowedValue = 0, maxAllowedValue=10,
precision=2)
self.createGrid("Fcst", "QPFtoFFGRatio", "SCALAR",
ratioGrid, tr, precision=2,
minAllowedValue = 0, maxAllowedValue=1000)
floodThreat = zeros(self.getTopo().shape)
for e in range(len(erps) - 1):
for r in range(len(ratios) - 1):
eMin = erps[e]
eMax = erps[e+1]
rMin = ratios[r]
rMax = ratios[r+1]
ratioMask = logical_and(greater_equal(ratioGrid, rMin),
less(ratioGrid, rMax))
erpMask = logical_and(greater_equal(erpGrid, eMin),
less(erpGrid, eMax))
mask = logical_and(ratioMask, erpMask)
keyIndex = self.getIndex(threatMatrix[r][e], threatKeys)
floodThreat = where(mask, keyIndex, floodThreat)
self.createGrid("Fcst", "FloodThreat", "DISCRETE",
(floodThreat, threatKeys), tr,
discreteKeys=threatKeys,
discreteOverlap=0,
discreteAuxDataLength=2,
defaultColorTable="gHLS_new")
maxFloodThreat = where(floodThreat > maxFloodThreat, floodThreat, maxFloodThreat)
# make a 6 hour TimeRange
# startTime = trList[0].startTime()
startTime = int(self._gmtime().unixTime()/ 3600) * 3600 - (24 * 3600)
endTime = startTime + (24 * 3600 * 10)
dbTR = self.makeTimeRange(startTime, endTime)
cTime = int(self._gmtime().unixTime()/ 3600) * 3600
end = cTime + (6*3600)
threatTR = self.makeTimeRange(cTime, end)
self.deleteCmd(['FloodingRainThreat'], dbTR)
self.createGrid("Fcst", "FloodingRainThreat", "DISCRETE",
(maxFloodThreat, threatKeys), threatTR,
discreteKeys=threatKeys,
discreteOverlap=0,
discreteAuxDataLength=2,
defaultColorTable="gHLS_new")
return

View file

@ -0,0 +1,229 @@
# ----------------------------------------------------------------------------
# This software is in the public domain, furnished "as is", without technical
# support, and with no warranty, express or implied, as to its usefulness for
# any purpose.
#
# TCImpactGraphics_KML
#
# Author: P. Santos/Joe Maloney - 4/19/2011
#
# Last edited: 27 July 2012 - Shannon/R. Anderson - made A2 compatible
# Last Modified 30 July 2012 - J Maloney/P. Santos - made it work with A2
# Modified 09 Sept 2014 - J. Maloney - for 2015 season, removed MarineThreat,
# renamed CoastalThreat -> StormSurgeThreat, InlandThreat -> FloodingRainThreat,
# removed verylow from kml styles in header
# Modified 11 Sept 2014 - J. Maloney/S. White - site ID is now automatically
# retrieved from the environment.
# Modified 16 Sept 2014 - J. Maloney/T. Lefebvre - impact statements are now
# read from TCVDictionary (in Utilities) and formatted on-the-fly!
# Modified 21 Oct 2014 - J. Maloney - products now go in /awips2/GFESuite/hti/
# data.
#
# ----------------------------------------------------------------------------
MenuItems = ["Populate"]
import SmartScript
from numpy import *
import time
import os
import TimeRange
import AbsTime
from com.raytheon.uf.common.dataplugin.gfe.reference import ReferenceData_CoordinateType as CoordinateType
import TCVDictionary
class Procedure (SmartScript.SmartScript):
def __init__(self, dbss):
SmartScript.SmartScript.__init__(self, dbss)
def makeTimeRange(self):
cTime = int(self._gmtime().unixTime()/ 3600) * 3600
startTime = AbsTime.AbsTime(cTime - 12 * 3600)
endTime = AbsTime.AbsTime(cTime + 12 * 3600) # 12 hours
tr = TimeRange.TimeRange(startTime, endTime)
return tr
def makeThreatKML(self,threatWEName,threatKeys,threatGrid_kml):
# COMMENTS CONFIG READ: the directory below is the directory where the kml txt files will be dumped.
# From there it is synchronized to the web servers along with the graphics. If you set up
# your gHLS scripts and data directories in a different place than recommended in the install
# instructions, you would need to change that directory here. Do not change .kml.txt to .kml.
# Only .txt file can be uploaded as include files. In the servers a php script will convert the
# file name so that a browser can properly interpret it as a kml file to be open with Google
# Earth or equivalent application.
# Also, make sure the ownership of the kml.txt files created below is fxa:fxalpha with permissions set
# to 666.
# You can test the kml files created by copying them outside AWIPS and renaming them .kml. Then open them with
# Google Earth.
kml_filename = '/awips2/GFESuite/hti/data/' + threatWEName + '.kml.txt'
kml = open(kml_filename, 'w')
kml.write('<?xml version="1.0" encoding="UTF-8"?>\n')
kml.write('<kml xmlns="http://www.opengis.net/kml/2.2">\n')
kml.write('<Document><name>'+threatWEName+'.kml</name>\n<Style id="none"><PolyStyle><color>99e0e0e0</color><outline>0</outline></PolyStyle></Style>\n')
kml.write('<Style id="low"><PolyStyle><color>9900ffff</color><outline>0</outline></PolyStyle></Style>\n')
kml.write('<Style id="moderate"><PolyStyle><color>990fa7ff</color><outline>0</outline></PolyStyle></Style>\n')
kml.write('<Style id="high"><PolyStyle><color>990000ff</color><outline>0</outline></PolyStyle></Style>\n')
kml.write('<Style id="extreme"><PolyStyle><color>99cc00cc</color><outline>0</outline></PolyStyle></Style>\n')
kml.write('<Folder><name>'+threatWEName+'</name><open>0</open>\n')
kml.write('<ScreenOverlay><name>Product Legend</name><description>Product Legend</description><visibility>1</visibility><Icon>')
# each threatWEName has its own separate legend
# need site id, in lowercase
SiteID = self.getSiteID().lower()
if threatWEName == "StormSurgeThreat":
kml.write('<href>http://www.nws.noaa.gov/images/ghls/' + SiteID + '/stormsurgethreatlegend.png</href>')
elif threatWEName == "WindThreat":
kml.write('<href>http://www.nws.noaa.gov/images/ghls/' + SiteID + '/windthreatlegend.png</href>')
elif threatWEName == "FloodingRainThreat":
kml.write('<href>http://www.nws.noaa.gov/images/ghls/' + SiteID + '/floodingrainthreatlegend.png</href>')
elif threatWEName == "TornadoThreat":
kml.write('<href>http://www.nws.noaa.gov/images/ghls/' + SiteID + '/tornadothreatlegend.png</href>')
# Complete the kml legend
kml.write('</Icon><overlayXY x=".02" y=".01" xunits="fraction" yunits="fraction" /><screenXY x=".02" y=".01" xunits="fraction" yunits="fraction" /><rotationXY x=".02" y=".01" xunits="fraction" yunits="fraction" /><size x="-1" y="-1" xunits="fraction" yunits="fraction" /></ScreenOverlay>')
#threatKeys = self.getDiscreteKeys(threatWEName)
#print "THREATKEYS ARE: ", threatKeys
# initialize a flag. It will only be NO for the first polygon in the file.
flag = 'NO'
for key in threatKeys:
#print "Key:", key
# get index for this key
hazIndex = self.getIndex(key, threatKeys)
#print "hazIndex:", hazIndex
mask = equal(threatGrid_kml, hazIndex)
#print "Number of Grid Points: ", sum(sum(mask))
if sum(sum(mask)) == 0:
continue
# make an editArea from the mask
editArea = self.decodeEditArea(mask)
# extract the polygons from the edit area
polygons = editArea.getPolygons(CoordinateType.LATLON)
# pull out the impact statements from the TCVDictionary
# We need to match the threatWEName to the entries found
# in the TCVDictionary
if threatWEName == "TornadoThreat":
threat='Tornado'
elif threatWEName == "StormSurgeThreat":
threat='Storm Surge'
elif threatWEName == "WindThreat":
threat='Wind'
else:
threat='Flooding Rain'
# Extract the appropriate list from the dictionary, join them
# into a string, and make them separate bullets
impactStatement = ""
impactList = TCVDictionary.PotentialImpactStatements[threat][key]
impactStatement = "<br />* ".join(impactList)
impactStatement = "* " + impactStatement
# print "impactList:", impactList
# print "impactStatement:", impactStatement
if key == "None":
kmlHeader='<Placemark><name>Threat Level - None to Little</name><description><b>Potential for None to Little Impact:</b><br />' + impactStatement + '</description>\n<styleUrl>#none</styleUrl>\n'
elif key == "Elevated":
kmlHeader='<Placemark><name>Threat Level - Elevated</name><description><b>Potential for Limited Impact:</b><br />' + impactStatement + '</description>\n<styleUrl>#low</styleUrl>\n'
elif key == "Mod":
kmlHeader='<Placemark><name>Threat Level - Moderate</name><description><b>Potential for Significant Impact:</b><br />' + impactStatement + '</description>\n<styleUrl>#moderate</styleUrl>\n'
elif key == "High":
kmlHeader='<Placemark><name>Threat Level - High</name><description><b>Potential for Extensive Impact:</b><br />' + impactStatement + '</description>\n<styleUrl>#high</styleUrl>\n'
else:
kmlHeader='<Placemark><name>Threat Level - Extreme</name><description><b>Potential for Devastating to Catastrophic Impact:</b><br />' + impactStatement + '</description>\n<styleUrl>#extreme</styleUrl>\n'
for i in xrange(polygons.getNumGeometries()):
poly = polygons.getGeometryN(i)
shell = poly.getExteriorRing();
if shell:
# If shell is true, it's a new polygon
if flag == 'YES':
# If flag is YES, this is not the first polygon we're writing out
# so close the previous polygon before continuing.
kml.write('</Polygon></Placemark>\n')
kml.write(kmlHeader)
kml.write('<Polygon><outerBoundaryIs><LinearRing><coordinates>')
#print "Outer shell coordinates:"
for c in shell.getCoordinates():
#print "x:",c.x,"y:",c.y
line = str(c.x) + ',' + str(c.y) + ',0 \n'
kml.write(line)
kml.write('</coordinates></LinearRing></outerBoundaryIs>')
# Now that we've written at least one polygon, set flag to YES
flag = 'YES'
# CHECK FOR INNER LOOPS (HOLES)
for j in xrange(poly.getNumInteriorRing()):
hole = poly.getInteriorRingN(j)
#print "Hole",j,"coordinates:"
kml.write('<innerBoundaryIs><LinearRing><coordinates>')
for c in hole.getCoordinates():
#print "x:",c.x,"y:",c.y
line = str(c.x) + ',' + str(c.y) + ',0 \n'
kml.write(line)
kml.write('</coordinates></LinearRing></innerBoundaryIs>')
kmlEnd='</Polygon></Placemark>\n</Folder></Document></kml>\n'
kml.write(kmlEnd)
kml.close()
return
def execute(self, varDict):
tr = self.makeTimeRange()
threatlist = ['StormSurgeThreat','WindThreat','FloodingRainThreat','TornadoThreat']
#threatlist = ['TornadoThreat'] # Took out MarineThreat 8/6/12 S.O. # READDED MARINE THREAT JCM 5/21/14
for grid in threatlist:
threatWEName = grid
#print "Doing grid for time range: ", tr
threatGrid, threatKeys = self.getGrids("Fcst", threatWEName, "SFC", tr)
# COMMENTS CONFIG READ: For each threat element below, you need to change the edit area to the mask you are using
# in the config file to generate that impact graphic. For example, for CoastalThreat that would be
# XXXCoastalThreat where XXX is the 3 letter ID for your office. For WindThreat it would be XXXWindThreat.
# And so on.
if threatWEName == "StormSurgeThreat":
editArea = self.getEditArea("StormSurgeWW_EditArea")
elif threatWEName == "WindThreat":
editArea = self.getEditArea("MFL")
elif threatWEName == "FloodingRainThreat":
editArea = self.getEditArea("MFL")
elif threatWEName == "TornadoThreat":
editArea = self.getEditArea("MFL_CWA")
else:
editArea = self.getEditArea("Marinezones")
threatEditArea = self.encodeEditArea(editArea)
threatGrid_kml = where(threatEditArea, threatGrid, threatGrid-9.0)
self.makeThreatKML(threatWEName,threatKeys,threatGrid_kml)
# COMMENTS CONFIG READ: This path should be double-checked
os.system("/awips2/GFESuite/hti/bin/kml_legend.sh")
return

View file

@ -0,0 +1,582 @@
# ----------------------------------------------------------------------------
# This software is in the public domain, furnished "as is", without technical
# support, and with no warranty, express or implied, as to its usefulness for
# any purpose.
#
# CoastalThreat
#
# Author: Tom LeFebvre/Pablo Santos
# April 20, 2012 - To use gridded MSL TO NAVD and MSL to MLLW
# corrections and to get rid of Very Low.
# Last Modified: June 7, 2012 Shannon White - To fix the handling of time
# for A2 so it works for both real time and displaced real time
# Migrated TC Coastal Flood for AWIPS2. Updated 6/22/2012. S.O.
# March 11, 2014 to adapt to new PSURGE 2.0/PHISH and VDATUM Datasets in A1. PS
# May 21, 2014: for new PHISH but in AWIPS 2: PS/SW
# Aug 13, 2014: To rename SurgeHtPlustTide to InundationMax and incorporate InundationTiming. PS
# Sept 17, 2014: To finalize changes and clean up for 2015initial Baseline Check in.
#
# Last Modified: Sept 18, 2014: Added code to pull grids from NHC via ISC if PHISH not
# Available on time. Left inactive (commented out) for the moment until that can be fully tested later
# in 2014 or in 2015.
#
# ----------------------------------------------------------------------------
# The MenuItems list defines the GFE menu item(s) under which the
# Procedure is to appear.
# Possible items are: Populate, Edit, Consistency, Verify, Hazards
MenuItems = ["Populate"]
import SmartScript
import numpy as np
import TimeRange
import AbsTime
import time
import sys
VariableList = [("DEFAULT: Typical. Should only be changed in coordination with NHC SS Unit", "", "label"),
("Forecast Confidence?", "Typical (10% Exceedance; for most systems anytime within 48 hours)",
## "radio", ["Low (Prob-only; 10% Exceedance; for ill behaved systems)",
"radio", ["Typical (10% Exceedance; for most systems anytime within 48 hours)",
"Medium (20% Exceedance; for well-behaved systems within 12 hours of event)",
"High (30% Exceedance; for well-behaved systems within 6-12 hours of event)",
"Higher (40% Exceedance; for well-behaved systems within 6 hours of the event)",
"Highest (50% Exceedance; for well-behaved systems at time of the event)"]),
("Grid Smoothing?", "Yes", "radio", ["Yes","No"]),
("Make grids from PHISH\n or ICS?\n", "PHISH", "radio", ["PHISH", "ISC"]),
]
class Procedure (SmartScript.SmartScript):
def __init__(self, dbss):
SmartScript.SmartScript.__init__(self, dbss)
def getWEInventory(self, modelName, WEName, level):
allTimes = TimeRange.allTimes().toJavaObj()
gridInfo = self.getGridInfo(modelName, WEName, level, allTimes)
trList = []
for g in gridInfo:
start = g.gridTime().startTime().unixTime()
end = g.gridTime().endTime().unixTime()
tr = TimeRange.TimeRange(AbsTime.AbsTime(start),
AbsTime.AbsTime(end))
trList.append(tr)
return trList
def getAvgTopoGrid(self, topodb):
siteID = self.getSiteID()
# print "********************\n TOPO IS: ", topodb
dbName = siteID + "_D2D_" + topodb
weName = "avgTopo"
# timeRange = TimeRange.allTimes().toJavaObj()
trList = self.getWEInventory(dbName, weName, "SFC")
#print "NED Topo list is", trList
if len(trList)== 0:
#print "CRAP!!!"
return
for tr in trList:
# print "My time is", tr
topoGrid = self.getGrids(dbName, weName, "SFC", tr, mode="First")
# convert to feet
topoGrid = topoGrid * 3.281
#topoVal = topoGrid.copy()
min = -16000
max = 16000.0
mask1 = topoGrid < min
mask2 = topoGrid > max
topoGrid[mask1] = -80
topoGrid[mask2] = self.getTopo()[mask2]
# mask1 = topoVal< min
# mask2 = topoVal> max
# topoGrid = np.where(mask1,-80.0,topoVal)
# topoGrid = np.where(mask2,self.getTopo(),topoVal)
return topoGrid
def makeNewTimeRange(self, hours):
cTime = int(self._gmtime().unixTime()/ 3600) * 3600
startTime = AbsTime.AbsTime(cTime)
endTime = startTime + (hours * 3600)
threatTR = TimeRange.TimeRange(startTime, endTime)
timeRange = TimeRange.TimeRange(startTime, endTime)
return timeRange
def getModelIDList(self, matchStr):
availParms = self.availableParms()
modelList = []
for pName, level, dbID in availParms:
modelId = dbID.modelIdentifier()
if modelId.find(matchStr) > -1:
if modelId not in modelList:
modelList.append(modelId)
return modelList
def getExceedanceHeight(self, pctStr, level):
ap = self.availableParms()
dbName = self.getSiteID() + "_D2D_TPCSurgeProb"
modelIDList = self.getModelIDList("TPCSurgeProb")
modelIDList.sort()
if len(modelIDList) == 0:
self.statusBarMsg("No pSurge data found in your inventory.", "S")
return None, None, None
# the last one is the latest
# modelIDList[-1]
surgeModel = modelIDList[-1]
weName = "Surge" + pctStr + "Pct"
trList = self.getWEInventory(dbName, weName, level)
#print "Retreiving ", weName, " at ", level
for tr in trList:
grid = self.getGrids(dbName, weName, level, tr, mode="Max")
#maxGrid = maximum(grid, -100.0) # calculate the max as we go
surgeVal = grid.copy()
mask = surgeVal>-100
grid = np.where(mask,surgeVal*3.28, -80.0)
# print dir(grid)
return grid # convert meters to feet
def makePhishGrid(self, pctStr, level, smoothThreatGrid):
siteID = self.getSiteID()
dbName = siteID + "_D2D_TPCSurgeProb"
weName = "Surge" + pctStr + "Pctincr"
#print "Attempting to retrieve: ", weName, level
trList = self.getWEInventory(dbName, weName, level)
if len(trList) == 0:
self.statusBarMsg("No grids available for model:" + dbName, "S")
return None
n = 1
for tr in trList:
start = tr.startTime().unixTime() - 6*3600
if n == 1:
starttimeghls = tr.startTime().unixTime() - 3*3600
trdelete = TimeRange.TimeRange(AbsTime.AbsTime(starttimeghls - 100*3600),
AbsTime.AbsTime(starttimeghls + 100*3600))
self.deleteCmd(['InundationTiming'], trdelete)
n = n + 1
end = tr.startTime().unixTime()
tr6 = TimeRange.TimeRange(AbsTime.AbsTime(start),
AbsTime.AbsTime(end))
phishGrid = self.getGrids(dbName, weName, level, tr)
#
# For consistency we need to add smoothing here too as we do in execute.
#
if phishGrid is None:
self.statusBarMsg("No PHISH grid available for:" + repr(tr), "S")
continue
if smoothThreatGrid is "Yes":
phishGrid = np.where(np.greater(phishGrid, 0.0), self.smoothGrid(phishGrid,3), phishGrid)
grid = np.where(phishGrid>-100,phishGrid*3.28, -80.0)
self.createGrid("Fcst", "InundationTiming", "SCALAR", grid, tr6, precision=1)
return
#**************************************************************************************
# THis procedure was written to extract MSL to NAVD corrections from the VDATUMS D2D
# Database. It is not yet implemented because the VDATUMS database has not been
# finalized.
def getMSLtoNAVD(self):
siteID = self.getSiteID()
dbName = siteID + "_D2D_VDATUMS"
weName = "MSLtoNAVD88"
trList = self.getWEInventory(dbName, weName, "SFC")
if len(trList) == 0:
msgStr = weName + " does not exist in the VDATUMS model. "
self.statusBarMsg(msgStr, "S")
#maxGrid = zeros(self.getTopo().shape)
for tr in trList:
grid = self.getGrids(dbName, weName, "SFC", tr, mode="First")
#maxGrid = maximum(grid, -100.0) # calculate the max as we go
#maxGrid = where(greater(maxGrid,-100.0), maxGrid*3.28, maxGrid)
conversionGrid = grid.copy()
mask = conversionGrid>-0.40
grid = np.where(mask, conversionGrid*3.28, -80.0)
#return maxGrid # convert meters to feet
return grid
# THis procedure was written to extract MSL to MLLW corrections from the VDATUMS D2D
# Database. It is not yet implemented because the VDATUMS database has not been
# finalized.
def getMSLtoMLLW(self):
siteID = self.getSiteID()
dbName = siteID + "_D2D_VDATUMS"
weName = "MSLtoMLLW"
trList = self.getWEInventory(dbName, weName, "SFC")
# if len(trList) == 0:
# msgStr = weName + " does not exist in the VDATUMS model. "
# self.statusBarMsg(msgStr, "S")
#maxGrid = zeros(self.getTopo().shape)
for tr in trList:
grid = self.getGrids(dbName, weName, "SFC", tr, mode="First")
#maxGrid = maximum(grid, -100.0) # calculate the max as we go
#maxGrid = where(greater(maxGrid,-100.0),maxGrid*3.28, maxGrid)
conversionGrid = grid.copy()
mask = conversionGrid>0.0
grid = np.where(mask,conversionGrid *3.28, -80.0)
#return maxGrid # convert meters to feet
return grid
# THis procedure was written to extract MSL to MHHW corrections from the VDATUMS D2D
# Database. It is not yet implemented because the VDATUMS database has not been
# finalized.
def getMSLtoMHHW(self):
siteID = self.getSiteID()
dbName = siteID + "_D2D_VDATUMS"
weName = "MSLtoMHHW"
trList = self.getWEInventory(dbName, weName, "SFC")
if len(trList) == 0:
msgStr = weName + " does not exist in the VDATUMS model. "
self.statusBarMsg(msgStr, "S")
#maxGrid = zeros(self.getTopo().shape)
for tr in trList:
grid = self.getGrids(dbName, weName, "SFC", tr, mode="First")
#maxGrid = maximum(grid, -100.0) # calculate the max as we go
#maxGrid = where(greater(maxGrid,-100.0),maxGrid*3.28, maxGrid)
conversionGrid = grid.copy()
mask = conversionGrid>-3.09
grid = np.where(mask, conversionGrid*3.28, -80.0)
#return maxGrid # convert meters to feet
return grid
# THis procedure was written to extract NAVD88 to MLLW corrections from the VDATUMS D2D
# Database. It is not yet implemented because the VDATUMS database has not been
# finalized.
def getNAVDtoMLLW(self):
siteID = self.getSiteID()
dbName = siteID + "_D2D_VDATUMS"
weName = "NAVD88toMLLW"
trList = self.getWEInventory(dbName, weName, "SFC")
# if len(trList) == 0:
# msgStr = weName + " does not exist in the VDATUMS model. "
# self.statusBarMsg(msgStr, "S")
#maxGrid = zeros(self.getTopo().shape)
for tr in trList:
grid = self.getGrids(dbName, weName, "SFC", tr, mode="First")
#maxGrid = maximum(grid, -100.0) # calculate the max as we go
#maxGrid = where(greater(maxGrid,-100.0),maxGrid*3.28, maxGrid)
conversionGrid=grid.copy()
mask = conversionGrid>-2.20
grid = np.where(mask, conversionGrid*3.28, -80.0)
#return maxGrid # convert meters to feet
return grid
# THis procedure was written to extract NAVD88 to MLLW corrections from the VDATUMS D2D
# Database. It is not yet implemented because the VDATUMS database has not been
# finalized.
def getNAVDtoMHHW(self):
siteID = self.getSiteID()
dbName = siteID + "_D2D_VDATUMS"
weName = "NAVD88toMHHW"
trList = self.getWEInventory(dbName, weName, "SFC")
# if len(trList) == 0:
# msgStr = weName + " does not exist in the VDATUMS model. "
# self.statusBarMsg(msgStr, "S")
#maxGrid = zeros(self.getTopo().shape)
for tr in trList:
grid = self.getGrids(dbName, weName, "SFC", tr, mode="First")
#maxGrid = maximum(grid, -100.0) # calculate the max as we go
#maxGrid = where(greater(maxGrid,-100.0),maxGrid*3.28, maxGrid)
conversionGrid = grid.copy()
mask = conversionGrid>-3.40
grid = np.where(mask, conversionGrid*3.28, -80.0)
#return maxGrid # convert meters to feet
return grid
def smoothGrid(self, grid, factor):
# factors of less than 3 are useless or dangerous
if factor < 3:
return grid
st = time.time()
half = int(factor)/ 2
sg = np.zeros(grid.shape,"f8")
count = np.zeros(grid.shape,"f8")
gridOfOnes = np.ones(grid.shape,"f8")
for y in range(-half, half + 1):
for x in range(-half, half + 1):
if y < 0:
yTargetSlice = slice(-y, None, None)
ySrcSlice = slice(0, y, None)
if y == 0:
yTargetSlice = slice(0, None, None)
ySrcSlice = slice(0, None, None)
if y > 0:
yTargetSlice = slice(0, -y, None)
ySrcSlice = slice(y, None, None)
if x < 0:
xTargetSlice = slice(-x, None, None)
xSrcSlice = slice(0, x, None)
if x == 0:
xTargetSlice = slice(0, None, None)
xSrcSlice = slice(0, None, None)
if x > 0:
xTargetSlice = slice(0, -x, None)
xSrcSlice = slice(x, None, None)
target = [yTargetSlice, xTargetSlice]
src = [ySrcSlice, xSrcSlice]
sg[target] = np.where(np.greater(grid[src],-80.0),sg[target] + grid[src],sg[target])
count[target] = np.where(np.greater(grid[src],-80.0),count[target] + gridOfOnes[src],count[target])
return np.where(np.greater(count,0.0), sg / count, -80.0)
# Copies the specified weather elements in elementList into the Fcst database.
def copyISCGridstoFcst(self, elementList):
# First delete the existing grids so there's no confusion
cTime = int(self._gmtime().unixTime()/ 3600) * 3600
startTime = AbsTime.AbsTime(cTime - 24*3600)
endTime = startTime + 240*3600
timeRange = TimeRange.TimeRange(startTime, endTime)
for elem in elementList:
if elem == "InundationTiming":
#print "Deleting: ", elem
self.deleteCmd([elem], timeRange)
for weName in elementList:
iscWeName = weName + "nc"
# get the inventory for the ISC grids
try:
trList = self.getWEInventory("ISC", iscWeName, "SFC")
except:
self.statusBarMsg("No grids found in ISC database for " + iscWeName, "S")
continue
if len(trList) == 0:
self.statusBarMsg("No grids found in ISC database for " + iscWeName, "S")
continue
# Fetch the ISC grid and create the same grid in the Fcst database
for tr in trList:
grid = self.getGrids("ISC", iscWeName, "SFC", tr)
if iscWeName == "InundationTimingnc":
self.createGrid("Fcst", weName, "SCALAR", grid, tr, precision=2)
elif iscWeName == "InundationMaxnc":
surgePctGrid = grid
elif iscWeName == "SurgeHtPlusTideMSLnc":
surgePctGridMSL = grid
elif iscWeName == "SurgeHtPlusTideMLLWnc":
surgePctGridMLLW = grid
elif iscWeName == "SurgeHtPlusTideMHHWnc":
surgePctGridMHHW = grid
elif iscWeName == "SurgeHtPlusTideNAVDnc":
surgePctGridNAVD = grid
return surgePctGrid,surgePctGridMSL,surgePctGridMLLW,surgePctGridMHHW,surgePctGridNAVD
def execute(self, varDict):
# List of elements
# See if we should copy from ISC. If so, do the copy and exit
smoothThreatGrid = varDict["Grid Smoothing?"]
PHISHorISC = varDict["Make grids from PHISH\n or ICS?\n"]
#PHISHorISC = "PHISH"
topodb = "NED"
#topodb = varDict["Topographic Database?"]
editArea = self.getEditArea("StormSurgeWW_EditArea")
ssea = self.encodeEditArea(editArea)
Topo = self.getAvgTopoGrid(topodb)
confidenceStr = varDict["Forecast Confidence?"]
# extract the percent value from this string
pctPos = confidenceStr.find("%")
pctStr = confidenceStr[pctPos - 2:pctPos]
#print "pctStr is: ", pctStr
if PHISHorISC == "PHISH":
#initialize grids to zero
surgePctGrid = self._empty
surgePctGridNAVD = self._empty
# Now get the psurge
surgePctGrid = self.getExceedanceHeight(pctStr, "FHAG0")
surgePctGridNAVD = self.getExceedanceHeight(pctStr, "SFC")
#print "retrieved my grids"
#
# The following lines are the gridded vdatum corrections.
#
msltonavd = self.getMSLtoNAVD()
msltomllw = self.getMSLtoMLLW()
msltomhhw = self.getMSLtoMHHW()
navdtomllw = self.getNAVDtoMLLW()
navdtomhhw = self.getNAVDtoMHHW()
# Apply 3x3 smooth within the surge zone
# for values greater than 1 as to not underplay areas adjacent to zero value pixels.
# If you apply a smoother, for consistency among storm surge plus tide and derived
# grids, it must be done here.
if smoothThreatGrid is "Yes":
surgePctGrid = np.where(np.greater(surgePctGrid, 0.0), self.smoothGrid(surgePctGrid,3), surgePctGrid)
surgePctGridNAVD = np.where(np.greater(surgePctGridNAVD, -10.0), self.smoothGrid(surgePctGridNAVD,3), surgePctGridNAVD)
mask1 = np.logical_and(np.greater(msltonavd, -80.0),np.greater(surgePctGridNAVD,-80.0))
surgePctGridMSL= np.where(mask1, surgePctGridNAVD - msltonavd, -80.0) # MSL Grid
surgePctGridMLLW = np.where(np.greater(navdtomllw,-80.0) & np.greater(surgePctGridNAVD,-80.0), \
surgePctGridNAVD + navdtomllw, -80.0)# MLLW Grid
surgePctGridMHHW = np.where(np.greater(navdtomhhw,-80.0) & np.greater(surgePctGridNAVD,-80.0), \
surgePctGridNAVD + navdtomhhw, -80.0)# MHHW Grid
surgeDiffMLLWMHHW = np.where(np.greater(surgePctGridMLLW,-80.0) & np.greater(surgePctGridMHHW, -80.0), \
surgePctGridMLLW-surgePctGridMHHW, -80.0)# Diff Grid Between MLLW and MHHW
self.makePhishGrid(pctStr, "FHAG0", smoothThreatGrid)
else:
elementList = ["InundationMax","InundationTiming", "SurgeHtPlusTideMSL","SurgeHtPlusTideMLLW",
"SurgeHtPlusTideNAVD","SurgeHtPlusTideMHHW"]
surgePctGrid,surgePctGridMSL,surgePctGridMLLW,surgePctGridMHHW,surgePctGridNAVD = self.copyISCGridstoFcst(elementList)
threatWEName = "StormSurgeThreat"
threatKeys = self.getDiscreteKeys(threatWEName)
# Define a mapping between UI names and key names
# keyMap = {"Very Low" :"Very Low",
keyMap = {"Elevated" : "Elevated",
"Moderate" : "Mod",
"High" : "High",
"Extreme" : "Extreme",
}
threshDict = {} # a dict to store thresholds from the UI
for key in keyMap.keys():
# if not key in varDict.keys(): # This should never happen
# print "Error in mapping UI keys to DISCRETE keys."
# print "Please fix the keyMap dictionary."
# return
#threshDict[keyMap[key]] = varDict[key]
if keyMap[key] == "Extreme":
threshDict[keyMap[key]] = 9
elif keyMap[key] == "High":
threshDict[keyMap[key]] = 6
elif keyMap[key] == "Mod":
threshDict[keyMap[key]] = 3
elif keyMap[key] == "Elevated":
threshDict[keyMap[key]] = 1
#print "threshDict[keyMap[key]]: ", keyMap[key], threshDict[keyMap[key]]
# make a grid of zeros. This will be the CoastalThreat grid
coastalThreat = np.zeros(self.getTopo().shape)
# Yet another list to define the order in which we set grid values
# This order must be ranked lowest to highest
#keyList = ["Very Low", "Elevated", "Mod", "High", "Extreme"]
keyList = ["Elevated", "Mod", "High", "Extreme"]
# Set the grid values based on the surgePctGrid grid and thresholds
for key in keyList:
#print "THRESHOLD FOR KEY IS: ", key, threshDict[key]
thresh = threshDict[key]
keyIndex = self.getIndex(key, threatKeys)
coastalThreat = np.where(ssea & np.greater_equal(surgePctGrid, thresh), keyIndex,
coastalThreat)
# make a timeRange - 6 hours long
elementList = ["StormSurgeThreat","InundationMax","SurgeHtPlusTideMSL","SurgeHtPlusTideMLLW","SurgeHtPlusTideNAVD","SurgeHtPlusTideMHHW"]
cTime = int(self._gmtime().unixTime()/ 3600) * 3600
startTime = AbsTime.AbsTime(cTime - 24*3600)
endTime = startTime + 240*3600
timeRange = TimeRange.TimeRange(startTime, endTime)
#print "time range to delete is: ", timeRange
for elem in elementList:
#print "Deleting: ", elem
self.deleteCmd([elem], timeRange)
timeRange = self.makeNewTimeRange(6)
# display the D2D grid for debugging purposes only
self.createGrid("Fcst", "InundationMax", "SCALAR", surgePctGrid,
timeRange, precision=2)
self.createGrid("Fcst", "SurgeHtPlusTideMSL", "SCALAR", surgePctGridMSL,
timeRange, precision=2)
self.createGrid("Fcst", "SurgeHtPlusTideMLLW", "SCALAR", surgePctGridMLLW,
timeRange, precision=2)
self.createGrid("Fcst", "SurgeHtPlusTideNAVD", "SCALAR", surgePctGridNAVD,
timeRange, precision=2)
self.createGrid("Fcst", "SurgeHtPlusTideMHHW", "SCALAR", surgePctGridMHHW,
timeRange, precision=2)
# create the CoastalThreat Grid
self.createGrid("Fcst", threatWEName, "DISCRETE",
(coastalThreat, threatKeys), timeRange,
discreteKeys=threatKeys,
discreteOverlap=0,
discreteAuxDataLength=2,
defaultColorTable="Hazards")
return

View file

@ -0,0 +1,342 @@
# ----------------------------------------------------------------------------
#
# This software is in the public domain, furnished "as is", without technical
# support, and with no warranty, express or implied, as to its usefulness for
# any purpose.
#
# TornadoFloodThreat
#
# Author: Tom LeFebvre/Pablo Santos
# Updated: April 16, 2012 to lower Low Category Threshold and hide Sliding Bars
# Migrated procedure for AWIPS2. Updated 6/22/2012. S.O.
# Last Modified: Sept 19, 2014: Updated Low to Elevated for 2015 Official Implementation. PS
# ----------------------------------------------------------------------------
# The MenuItems list defines the GFE menu item(s) under which the
# Procedure is to appear.
# Possible items are: Populate, Edit, Consistency, Verify, Hazards
MenuItems = ["Populate"]
import SmartScript
import time
import sys
import AbsTime
import TimeRange
VariableList = [("NOTE: Day 1 Tornado Probabilities Used by Procedure:", "", "label"),
#("Very Low" , "02", "radio", ["02"]),
("Elevated" , "02", "radio", ["02"]),
("Mod" ,"15", "radio", ["15"]),
("High","30", "radio", ["30"]),
("Extreme" ,"45", "radio", ["45"]),
("Day 2: Prob Svr Wx (ptotsvr) >= 5: Elevated; ptotsvr >= 60%: Mod", "", "label"),
("Day 2: Prob Sig Svr Wx (ptotxsvr) >= 10: Elevated -> Mod and Mod -> High", "", "label"),
("Day 3: Prob Svr Wx (ptotsvr) >= 5: Elevated", "", "label"),
("Day 3: Prob Sig Svr Wx (ptotxsvr) >= 10: Elevated -> Mod", "", "label"),
("NOTE: After applying logic above", "", "label"),
("threat level is the max composite from Day 1-3", "", "label")
]
try:
from Numeric import *
except:
from numpy import *
class Procedure (SmartScript.SmartScript):
def __init__(self, dbss):
SmartScript.SmartScript.__init__(self, dbss)
# Make a timeRange based on the start and end int times
def makeTimeRange(self, start, end):
try: # AWIPS 1 code
import AFPS
startTime = AFPS.AbsTime(start)
endTime = AFPS.AbsTime(end)
tr = AFPS.TimeRange(startTime, endTime)
except: # AWIPS 2 code
import TimeRange, AbsTime
startTime = AbsTime.AbsTime(start)
endTime = AbsTime.AbsTime(end)
tr = TimeRange.TimeRange(startTime, endTime)
return tr
def variableExists(self, modelName, weName, weLevel):
# it turns out the the modelName will not match the dbID().model()
# directly, so it needs to be massaged a bit.
parts = modelName.split("_")
if len(parts) >= 4:
modelName = parts[3]
availParms = self.availableParms()
for pName, level, dbID in availParms:
if dbID.modelName().find(modelName) > -1:
if pName.find(weName) > -1 and level.find(weLevel) > -1:
return True
return False
def getWEInventory(self, modelName, WEName, timeRange = None):
allTimes = TimeRange.allTimes()
if timeRange is None:
timeRange = allTimes
weLevel = "SFC"
if not self.variableExists(modelName, WEName, weLevel):
#print WEName, "does not exist in model", modelName
return []
try:
gridInfo = self.getGridInfo(modelName, WEName, weLevel, timeRange)
except:
#print "GridInfo failed for:", modelName, WEName, weLevel, timeRange
return []
trList = []
for g in gridInfo:
start = g.gridTime().startTime().unixTime()
end = g.gridTime().endTime().unixTime()
tr = self.makeTimeRange(start, end)
if timeRange.overlaps(tr):
trList.append(tr)
return trList
# get the current time, truncates to the last six hour value.
# returns a timeRange with this startTime until 24 hrs from this time
def make6hrTimeRange(self):
startTime = int(self._gmtime().unixTime()/ (3600 * 6)) * 3600 * 6
endTime = startTime + (3600 * 6)
timeRange = self.makeTimeRange(startTime, endTime)
return timeRange
# Returns a list of dbIdentifiers that match the specified model
# name, weName and level.
def getModelList(self, modelName, weName, weLevel):
modelList = []
availParms = self.availableParms()
for pName, level, dbID in availParms:
if dbID.modelName().find(modelName) > -1:
if pName.find(weName) > -1:
if level.find(weLevel) > -1:
if dbID.modelIdentifier() not in modelList:
modelList.append(dbID.modelIdentifier())
return modelList
def determineDay(self, modelTime, validTime):
diff = (validTime - modelTime) / 3600
if diff < 36:
return 1
elif diff >= 36 and diff < 60:
return 2
elif diff >= 60:
return 3
return 0
# returns a unix time based on the specified model ID.
def getModelTime(self, modelName):
timeStr = modelName[-13:]
year = int(timeStr[0:4])
month = int(timeStr[4:6])
day = int(timeStr[6:8])
hour = int(timeStr[9:11])
absTime = AbsTime.absTimeYMD(year, month, day, hour, 0, 0)
absTime = AbsTime.absTimeYMD(year, month, day, hour, 0, 0)
return absTime.unixTime()
def getTornadoGrid(self, varName, dayNum):
siteID = self.getSiteID()
SPCModelName = siteID + "_D2D_SPC"
SPCVarName = varName
SPCLevel = "SFC"
modelList = self.getModelList("SPC", SPCVarName, SPCLevel)
#print "Processing varName, dayNum: ", varName, dayNum
hours24 = 24 * 3600
for modelName in modelList:
trList = self.getWEInventory(modelName, SPCVarName)
#print "modelName trList:", modelName, trList
if len(trList) == 0: # no grids found for this version
continue # go on to older versions
modelTime = self.getModelTime(modelName)
# get the current time rounded to the nearest 12Z
currentTime = (int(time.time() / hours24) * hours24) + (12 * 3600)
for tr in trList:
gridDayNum = self.determineDay(currentTime,
tr.startTime().unixTime())
#print "modelName, modelTime, and gridDayNum:", modelName, modelTime, gridDayNum
if gridDayNum == dayNum:
grid = self.getGrids(modelName, SPCVarName, SPCLevel, tr)
return grid
return None
# This method adjusts an existing threat grid
def adjustTornadoGrid(self, tornadoThreat, threatKeys, var, dayNum, extThreshold):
D2DGrid = self.getTornadoGrid(var, dayNum)
if D2DGrid is None:
#print "No grid found for", var, "day:", dayNum
return tornadoThreat
# Account for offices using the four key arrangement
# Just change the "Very Low" to "Low" in the threshDict
#if "Very Low" not in threatKeys:
# # find all places greater than "Very Low or Low" in the tornadoThreat
# lowIndex = self.getIndex("Low", threatKeys)
#else:
# lowIndex = self.getIndex("Very Low", threatKeys)
#lowMask = greater_equal(tornadoThreat, lowIndex)
lowMask = greater(tornadoThreat, 0)
# finds all places in the extreme grid >= to the extThreshold
xMask = greater_equal(D2DGrid, extThreshold)
# increment the threat where these masks intersect
mask = lowMask & xMask
# make sure we're not incremening too far
extremeIndex = self.getIndex("Extreme", threatKeys)
extremeMask = equal(tornadoThreat, extremeIndex)
mask = mask - extremeMask # subtract the extreme area
# increment the category. This code assumes that the categories are
# defined in increaing order of severity.
tornadoThreat = where(mask, tornadoThreat + 1, tornadoThreat)
return tornadoThreat
def setTornadoGrid(self, tornadoThreat, threatKeys, var, dayNum, threshDict):
D2DGrid = self.getTornadoGrid(var, dayNum)
if D2DGrid is None:
#print "No grid found for", var, "day:", dayNum
return tornadoThreat
# Account for offices using the four key arrangement
# Just change the "Very Low" to "Low" in the threshDict
#print "THREATKEYS ARE: ", threatKeys
#print "THRESHDICT IS: ", threshDict.keys()
if "Very Low" not in threatKeys:
for key in threshDict.keys():
if threshDict[key] == "Very Low":
threshDict[key] = "Elevated"
dictKeys = threshDict.keys()
#print "unsorted dictKeys: ", dictKeys
dictKeys.sort() # sort lowest to highest value
#print "sorted dictKeys: ", dictKeys
# Set the grid values based on the tornado prob grid and thresholds
for key in dictKeys:
thresh = int(key)
#print "THRESH IS: ", thresh
keyIndex = self.getIndex(threshDict[key], threatKeys)
# make a temp grid where the thresholds are exceeded
tempGrid = where(greater_equal(D2DGrid, thresh), keyIndex, 0)
# calculate areas where this temp grid exceeds the threatGrid
mask = greater(tempGrid, tornadoThreat)
# update the threatGrid for these areas only
tornadoThreat = where(mask, keyIndex, tornadoThreat)
return tornadoThreat
def execute(self, varDict):
threatWEName = "TornadoThreat"
threatKeys = self.getDiscreteKeys(threatWEName)
# make a dict to store thresholds from the UI
ptorDict = {}
for key in threatKeys:
if key == "None":
continue
ptorDict[varDict[key]] = key
#print "***************************"
#print "ptorDict is:", ptorDict
#print "***************************"
# Set up the data for processing the various grids.
# Each entry consists of the D2D variable to be checked,
# the day number of that grid, and a dictionary that defines
# each threshold value and the corresponding discrete value.
# Note the grids will be processed in the order defined in
# this list.
actionList = [
("ptor", 1, ptorDict, "sigtrndprob", 10), # ptorDict comes from the GUI
("prsvr", 2, { 5 : "Very Low",
#15 : "Elevated",
5 : "Elevated",
60 : "Mod",
},
"prsigsv", 10),
("prsvr", 3, { 5 : "Very Low",
#15 : "Elevated",
5 : "Elevated",
},
"prsigsv", 10),
]
# make a grid of zeros. This will be the TornadoThreat grid
tornadoThreat = zeros(self.getTopo().shape)
for var, dayNum, threshDict, xVar, xThreshold in actionList:
tornadoThreat = self.setTornadoGrid(tornadoThreat, threatKeys,
var, dayNum, threshDict)
# now adjust the grid based on the extreme grid category
tornadoThreat = self.adjustTornadoGrid(tornadoThreat, threatKeys,
xVar, dayNum, xThreshold)
# make a timeRange - 6 hours long, rounded to nearest hour
startTime = int(self._gmtime().unixTime()/ 3600) * 3600
endTime = startTime + (6 * 3600)
threatTR = self.makeTimeRange(startTime, endTime)
# remove any old grids that are lying around
startTime = int(self._gmtime().unixTime()/ 3600) * 3600 - (24 * 3600)
endTime = startTime + (24 * 3600 * 10)
removeTR = self.makeTimeRange(startTime, endTime)
self.deleteCmd([threatWEName], removeTR)
# create the TornadoThreat Grid
self.createGrid("Fcst", threatWEName, "DISCRETE",
(tornadoThreat, threatKeys), threatTR,
discreteKeys=threatKeys,
discreteOverlap=0,
discreteAuxDataLength=2,
defaultColorTable="Hazards")
return

View file

@ -0,0 +1,575 @@
# ----------------------------------------------------------------------------
# This software is in the public domain, furnished "as is", without technical
# support, and with no warranty, express or implied, as to its usefulness for
# any purpose.
#
# A2TCWindThreatFinal_3
# This version is for use with MLB's Graphical HLS.
# This version modifies the gHLS WindThreat element.
#
# Author: lefebvre 9/11/06
# Modified by: Volkmer/MLB and Santos/MFL 5/23/07
# More modifications: by LeFebvre/Santos/Sharp 05/7/09
# LeFebvre/Santos 07/20/10
# Modified: by Santos 04/26/2011 to accomodate alternate logic for NE Coast and hide bars
# Modified: by Santos 04/20/2012 to get rid off Very Low and tweak GUI.
# Modified: by Shannon/Pablo 06/19/2012 to make A2 and DRT compatible
# Modified: by Pablo/Shannon on 05/21/2014 to fix bug introduced in 2012 when Very Low was eliminated
# Last Modified: By Santos/Lefebvre 09/17/2014 to make changes for official implementation in 2015.
# ----------------------------------------------------------------------------
#
# THIS CODE SHALL NOT BE CHANGED WITHOUT CONSULTING ORIGINAL DEVELOPERS.
#
# The MenuItems list defines the GFE menu item(s) under which the
# Procedure is to appear.
# Possible items are: Populate, Edit, Consistency, Verify, Hazards
MenuItems = ["Populate","Edit"]
# The ToolList is optional, but recommended, if you are calling
# Smart Tools from your Script.
# If present, it can be used to show which grids will be
# modified by the Script.
VariableList = [("Forecast Confidence?", "Typical (Combined; For ill defined or for most systems anytime within 48 hours of landfall or closest approach)",
"radio", ["Typical (Combined; For ill defined or for most systems anytime within 48 hours of landfall or closest approach)",
"High (Combined; for well-behaved systems within 12 hours of landfall or closest approach)",
"Higher (Combined; for very well-behaved systems within 6 hours of landfall or closest approach)",
"Highest (Deterministic-only; assumes a perfect forecast)"]),
("WindMax Source?", "WFO Mesoscale (default)", "radio", ["WFO Mesoscale (default)","NHC/TCM Synoptic"]),
]
import SmartScript
import string
import TimeRange
import AbsTime
import time
import MetLib
import sys
from numpy import *
class Procedure (SmartScript.SmartScript):
def __init__(self, dbss):
SmartScript.SmartScript.__init__(self, dbss)
# Finds the TPC prob database, extracts all of the grids and returns
# the last one of each type
def getProbGrids(self):
ap = self.availableParms()
searchStr = self.getSiteID() + "_GRID_D2D_TPCProb"
probModel = ""
for elem, level, model in ap:
if string.find(model.modelIdentifier(), searchStr) > -1:
probModel = model.modelIdentifier()
break
if probModel == "":
self.statusBarMsg("TPC Wind probability grids not found.", "S")
return None, None, None
# make a big timeRange
timeRange = TimeRange.allTimes()
# get the TPC prob grids, and keep the last one
prob34List = self.getGrids(probModel, "prob34", "FHAG10", timeRange,
mode = "List")
prob34Grid = prob34List[-1]
prob50List = self.getGrids(probModel, "prob50", "FHAG10", timeRange,
mode = "List")
prob50Grid = prob50List[-1]
prob64List = self.getGrids(probModel, "prob64", "FHAG10", timeRange,
mode = "List")
prob64Grid = prob64List[-1]
return prob34Grid, prob50Grid, prob64Grid
def getWEInventory(self, modelName, WEName):
dbTime = self.makeDBTimeRange()
trList = []
try:
gridInfo = self.getGridInfo(modelName, WEName, "SFC", dbTime)
except:
return trList
for g in gridInfo:
start = g.gridTime().startTime().unixTime()
end = g.gridTime().endTime().unixTime()
startTime = AbsTime.AbsTime(start)
endTime = AbsTime.AbsTime(end)
tr = TimeRange.TimeRange(startTime, endTime)
if dbTime.overlaps(tr):
trList.append(tr)
return trList
# make a timeRange spanning from the current hour to 6 hours hence
def make6hrTimeRange(self):
cTime = int(self._gmtime().unixTime()/ 3600) * 3600
startTime = AbsTime.AbsTime(cTime)
endTime = AbsTime.AbsTime(cTime + (6 * 3600)) # 6 hours
tr = TimeRange.TimeRange(startTime, endTime)
return tr
# make a timeRange spanning the usual -24 to 10-day db
def makeDBTimeRange(self):
cTime = int(self._gmtime().unixTime()/ 3600) * 3600
startTime = AbsTime.AbsTime(cTime - (24*3600))
endTime = AbsTime.AbsTime(cTime + (240 * 3600)) # 10 days
tr = TimeRange.TimeRange(startTime, endTime)
return tr
# removes all grids from a selected set of temporary parms
def removeTempGrids(self):
elementList = ["Prob34", "Prob50", "Prob64", "WindMax"]
ap = self.availableParms()
tr = TimeRange.allTimes()
for elem, level, model in ap:
modelName = model.modelIdentifier()
if elem in elementList and level == "SFC":
self.deleteCmd([elem], tr)
return
# Smooths the specified grid by the specified factor
# With factor == 3, 3x3 smooth, factor == 5 5x5 smooth, etc.
# Even factors (4, 6, 8,...) round up to the next odd value
# If factors <3 are specified, the unmodified grid is returned.
def smoothGrid(self, grid, factor=3):
# factors of less than 3 are useless or dangerous
if factor < 3:
return grid
st = self._gmtime().unixTime()
half = int(factor)/ 2
sg = zeros(grid.shape,'f8')
count = zeros(grid.shape,'f8')
gridOfOnes = ones(grid.shape,'f8')
for y in range(-half, half + 1):
for x in range(-half, half + 1):
if y < 0:
yTargetSlice = slice(-y, None, None)
ySrcSlice = slice(0, y, None)
if y == 0:
yTargetSlice = slice(0, None, None)
ySrcSlice = slice(0, None, None)
if y > 0:
yTargetSlice = slice(0, -y, None)
ySrcSlice = slice(y, None, None)
if x < 0:
xTargetSlice = slice(-x, None, None)
xSrcSlice = slice(0, x, None)
if x == 0:
xTargetSlice = slice(0, None, None)
xSrcSlice = slice(0, None, None)
if x > 0:
xTargetSlice = slice(0, -x, None)
xSrcSlice = slice(x, None, None)
target = [yTargetSlice, xTargetSlice]
src = [ySrcSlice, xSrcSlice]
sg[target] = sg[target] + grid[src]
count[target] = count[target] + gridOfOnes[src]
return sg / count
#
def getStormCenter(self, windGrid, tr):
u, v = self.MagDirToUV(windGrid[0], windGrid[1])
vortGrid = MetLib.vorticity((u, v))
vortGrid = self.smoothGrid(vortGrid, 3)
vortGrid = clip(vortGrid, 0.0, 1000000)
## self.createGrid("Fcst", "Vorticity", "SCALAR", vortGrid, tr,
## minAllowedValue = 0.0, maxAllowedValue=1000000.0)
# find the max
maxVort = max(vortGrid.flat)
if maxVort < 10:
return None, None
# find the location of the max
mask = equal(vortGrid, maxVort)
maxPos = nonzero(mask.flat)[0]
# get x. y position of the center
row = maxPos / mask.shape[1]
col = maxPos % mask.shape[1]
return col, row
# Using the center, a distance grid from that center and a mask
# indictaing the area that includes the maxWind field this
# method returns the radius of that area in gridpoint units.
# Note this method adds 2 gridpoints since the area tends to
# fall a little short of the actual max wind value.
def calcRadius(self, center, distGrid, mask):
maskPoints = nonzero(mask)
if len(maskPoints) == 0:
return 0
histDict = {}
yCoords, xCoords = maskPoints
for i in range(len(yCoords)):
dist = int(distGrid[yCoords[i], xCoords[i]])
if not histDict.has_key(dist):
histDict[dist] = 1
else:
histDict[dist] = histDict[dist] + 1
histKeys = histDict.keys()
histKeys.sort()
lastKey = 0
for key in histKeys:
if key - lastKey >=2:
return lastKey + 2
lastKey = key
return lastKey + 2
# makes a grid of distance from the specified center
# which must be expressed as a tuple (x, y)
def makeDistGrid(self, center):
iGrid = indices(self._empty.shape)
yDist = center[1] - iGrid[0]
xDist = center[0] - iGrid[1]
distGrid = sqrt(pow(xDist, 2)+ pow(yDist, 2))
return distGrid
# Given a specified wind speed and direction grid along with
# a distance grid, this method computes a mask that covers
# the area defined by the ring of max winds.
def makeCoreMask(self, ws, wd, distGrid):
# Find the area inside the max wind ring
u, v = self.MagDirToUV(ws, wd)
windGrad = MetLib.gradient(ws)
distGrad = MetLib.gradient(distGrid)
dotGrid = MetLib.dot(windGrad, distGrad)
# smooth this grid to remove noise
dotGrid = self.smoothGrid(dotGrid, 9)
mask = greater(dotGrid, 0.0)
return mask
# This method returns the max wind speed value found in the
# specified wind speed grid. This method restricts the search
# to an area just inside and just outside the specified radius.
def getMaxWindValue(self, distGrid, radius, ws, tr):
maxWS = 0.0
lessMask = less(distGrid, radius + 2)
moreMask = greater(distGrid, radius - 7)
mask = lessMask & moreMask
## self.createGrid("Fcst", "MaxMask", "SCALAR", mask, tr)
ringGrid = ws * mask
thisMax = max(ringGrid.flat)
if thisMax > maxWS:
maxWS = thisMax
return maxWS
# This method adjusts and returns the specified maxWindGrid by
# temporally interpolating each wind grid found in the current
# inventory. A vorticity field is used to determine the storm
# center. Then the wind speed and direction grids are used to
# calculate the area surrounded by the ring of max winds. This
# area is used to calculate the radius of max wind and the all
# of the attributes are used to calculate the max wind field
# over the entire event by interpolating temporally. This max
# wind field is later used to calculate the WindThreat.
def adjustWindMax(self, maxWindGrid):
trList = self.getWEInventory("Fcst", "Wind")
if len(trList) == 0:
return
adjustedWindMax = maxWindGrid
stormMaxWindValue = -1
modifiedMask = zeros(self._empty.shape, 'b')
lastXPos = None
lastYPos = None
lastRadius = None
lastWindMax = None
for tr in trList:
ws, wd = self.getGrids("Fcst", "Wind", "SFC", tr, mode="First")
xPos, yPos = self.getStormCenter((ws, wd), tr)
# See if the storm os outside the GFE domain. If it is, just update
# the adjustedWindMax and the stormMaxWindValue
if xPos is None or yPos is None:
adjustedWindMax = where(greater(ws, adjustedWindMax), ws, adjustedWindMax)
gridWindMax = max(ws.flat) # max value over the whole grid
stormMaxWindValue = max(gridWindMax, stormMaxWindValue) # update the overall max
continue
# On 09/17/2014 took off these lines and assked a few above to fix problem wint returned Max Wind when storm
# center remained outside grid.
# ignore positions outside the domain
#if xPos < 0 or yPos < 0 or \
# xPos >= ws.shape[1] or yPos >= ws.shape[0]:
# continue
# calc change in wind speed as a function of radius
distGrid = self.makeDistGrid((xPos, yPos))
coreMask = self.makeCoreMask(ws, wd, distGrid)
# first time through just store the position
if lastXPos == None or lastYPos == None:
lastXPos = xPos
lastYPos = yPos
lastRadius = self.calcRadius((xPos, yPos), distGrid, coreMask)
lastWindMax = self.getMaxWindValue(distGrid, lastRadius, ws, tr)
continue
# get the maxWindRadius in grid cell coordinates
radius = self.calcRadius((xPos, yPos), distGrid, coreMask)
if radius is None:
continue
# Get the max wind value, but restrict it to near the radius
maxWindValue = self.getMaxWindValue(distGrid, radius, ws, tr)
#print "unrestricted max Wind Value: ", maxWindValue
dr = radius - lastRadius
# calc distance from last point
dx = xPos - lastXPos
dy = yPos - lastYPos
dWind = maxWindValue - lastWindMax
# one iteration per grid point
steps = abs(maximum(dx, dy))
for i in range(steps):
x = lastXPos + (float(dx) / steps) * i
y = lastYPos + (float(dy) / steps) * i
r = lastRadius + (float(dr) / steps) * i
windValue = lastWindMax + (float(dWind) / steps) * i
distGrid = self.makeDistGrid((x, y))
# change grids at the intersection of a circle defined by
# the center and radius and points that whose value is
# less than the current maxWind value
distMask = less_equal(distGrid, r)
lessMask = less(adjustedWindMax, windValue)
mask = distMask & lessMask # union of dist and less masks
adjustedWindMax = where(mask, windValue, adjustedWindMax)
modifiedMask = mask | modifiedMask
lastXPos = xPos
lastYPos = yPos
lastRadius = radius
lastWindMax = maxWindValue
# calculate the maximum wind value over the modified area
stormMaxWindValue = max((adjustedWindMax * modifiedMask).flat)
#print "stormMaxWindValue: ", stormMaxWindValue
# smooth out moderate values to remove "quadrant effect"
adjustedWindMax = self.smoothGrid(adjustedWindMax, 5)
return adjustedWindMax, stormMaxWindValue
# fetch a grid that represents the maxWind everywhere for the next 5 days
def getWindMax(self, timeRange):
cTime = int(self._gmtime().unixTime()/ 3600) * 3600
startTime = AbsTime.AbsTime(cTime)
endTime = startTime + (5 * 24 * 3600) # 5 days from the startTime
tr = TimeRange.TimeRange(startTime, endTime)
try:
windMax, dir = self.getGrids("Fcst", "Wind", "SFC", tr, mode = "Max")
except:
windMax = None
self.statusBarMsg("No Wind grids found. Please define Wind grids first.",
"S")
return windMax
def getMaxWindGrid(self):
try:
grid = self.getObject("TCMMaxWindGrid", "WindGrid")
maxWindValue = max(grid.flat)
return (grid, maxWindValue)
except:
self.statusBarMsg("No TCMMaxWindGrid found.",
"S")
return (None, None)
def execute(self, varDict):
# Get confidence value from the dialog
confidenceStr = varDict["Forecast Confidence?"]
tcmwindmax = varDict["WindMax Source?"]
# define a couple of boolean flags that will come in handy later
# allProb = confidenceStr == "Low (Probability-only; 10% Default-05% NE Coast)"
# allWind = confidenceStr == "Highest (Deterministic-only; MaxWind Composite)"
#allProb = confidenceStr == "Low (Probability-only; for ill-behaved systems)"
allWind = confidenceStr == "Highest (Deterministic-only; assumes a perfect forecast)"
typical = confidenceStr == "Typical (Combined; For ill defined or for most systems anytime within 48 hours of landfall or closest approach)"
high = confidenceStr == "High (Combined; for well-behaved systems within 12 hours of landfall or closest approach)"
higher = confidenceStr == "Higher (Combined; for very well-behaved systems within 6 hours of landfall or closest approach)"
#print "allProb and allWind are: ", allProb, allWind
# extract the percent value from this string
# pctPos = confidenceStr.find("% Default")
# pctStr = confidenceStr[pctPos - 2:pctPos]
pctStr="10"
if high:
pctStr="20"
elif higher:
pctStr="30"
# Percent thresholds for each confidence category
threatDict = {"10" : [10.0, 10.0, 10.0, 20.0, 30.0],
"20" : [20.0, 20.0, 20.0, 30.0, 40.0],
"30" : [30.0, 30.0, 30.0, 40.0, 50.0],
}
# wind thresholds for each threat category
windDict = {'None' : 0.0,
# 'Very Low' : 34.0,
#'Elevated' : 50.0,
'Elevated': 34.0,
'Mod' : 50.0,
'High1' : 64.0,
'High2' : 89.0,
'Extreme' : 96.0,
}
# Make sure the string is valid. If not then assign any value since the user
# has indicted Highest confidence in the wind field and is not using the
# probabilistic grids at all.
#if not threatDict.has_key(pctStr):
# pctStr = "10"
#print "pctStr is: ", pctStr
# Extract the proper list and assign thresholds
thresholdList = threatDict[pctStr]
#
t34TS1 = thresholdList[0]
t50TS2 = thresholdList[1]
t64Cat1 = thresholdList[2]
t64Cat2 = thresholdList[3]
t64Cat3 = thresholdList[4]
timeRange = self.make6hrTimeRange()
# Remove previous version of grids.
self.removeTempGrids()
# set up the indices for the discrete keys
keys = self.getDiscreteKeys("WindThreat")
## print "WindThreat keys are:", keys
noneIndex = self.getIndex("None", keys)
lowIndex = self.getIndex("Elevated", keys)
modIndex = self.getIndex("Mod", keys)
highIndex = self.getIndex("High", keys)
extremeIndex = self.getIndex("Extreme", keys)
# initialize the threat grid
threatGrid = self._empty # a grid of zeros
# Attempt to get the grid from the server.
windMax, maxWindValue = self.getMaxWindGrid()
#print "MAXWIND ACROSS DOMAIN IS: ", maxWindValue
if windMax is None or tcmwindmax == "WFO Mesoscale (default)": # use the old-fashioned method
# Get and adjust a grid of maximum wind over the entire storm
windMax = self.getWindMax(timeRange)
windMax, maxWindValue = self.adjustWindMax(windMax)
if windMax is not None:
self.createGrid("Fcst", "WindMax", "SCALAR", windMax, timeRange,
minAllowedValue=0, maxAllowedValue=200)
# assign values to the grid based on the probability grids
if allWind:
threatGrid = where(windMax < windDict["Elevated"], 0, threatGrid)
threatGrid = where(windMax >= windDict["Elevated"], lowIndex, threatGrid)
threatGrid = where(windMax >= windDict["Mod"], modIndex, threatGrid)
threatGrid = where(windMax >= windDict["High1"], highIndex, threatGrid)
threatGrid = where(windMax >= windDict["Extreme"], extremeIndex, threatGrid)
else:
# high and extreme threats require maxWind to meet particular windMax criteria
# Fetch the probabilistic grids
prob34Grid, prob50Grid, prob64Grid = self.getProbGrids()
#self.createGrid("Fcst", "Prob34", "SCALAR", prob34Grid, timeRange)
#self.createGrid("Fcst", "Prob50", "SCALAR", prob50Grid, timeRange)
#self.createGrid("Fcst", "Prob64", "SCALAR", prob64Grid, timeRange)
#print "MAXWIND IS: ", maxWindValue
threatGrid = zeros(prob64Grid.shape)
threatGrid = where(prob34Grid < t34TS1, 0, threatGrid)
threatGrid = where(prob34Grid >= t34TS1, lowIndex, threatGrid)
threatGrid = where(prob50Grid >= t50TS2, modIndex, threatGrid)
threatGrid = where(prob64Grid >= t64Cat1, highIndex, threatGrid)
if maxWindValue >= windDict['High2']:
threatGrid = where(prob64Grid >= t64Cat3, extremeIndex, threatGrid)
if maxWindValue >= windDict['Extreme']:
threatGrid = where(prob64Grid >= t64Cat2, extremeIndex, threatGrid)
# Upgrade windThreat based on windMax grid
##
# upgrade None to Elevated
windMask = (windMax >= windDict['Elevated']) & (windMax < windDict['Mod'])
threatMask = threatGrid < lowIndex
threatGrid = where(windMask & threatMask, lowIndex, threatGrid)
# upgrade Elevated to Med
windMask = (windMax >= windDict['Mod']) & (windMax < windDict['High1'])
threatMask = threatGrid < modIndex
threatGrid = where(windMask & threatMask, modIndex, threatGrid)
# upgrade Med to High
windMask = (windMax >= windDict['High1']) & (windMax < windDict['Extreme'])
threatMask = threatGrid < highIndex
threatGrid = where(windMask & threatMask, highIndex, threatGrid)
# upgrade High to Extreme
windMask = windMax >= windDict['Extreme']
threatMask = threatGrid < extremeIndex
threatGrid = where(windMask & threatMask, extremeIndex, threatGrid)
# Remove previous version of grid.
dbTimes = self.makeDBTimeRange()
self.deleteCmd(['WindThreat'], dbTimes)
# create the threat grid
self.createGrid("Fcst", "WindThreat", "DISCRETE", (threatGrid, keys),
timeRange, discreteKeys=keys, discreteAuxDataLength=5,
discreteOverlap=0)

View file

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<WEGroup name="HTI">
<WEItem parmID="SurgeHtPlusTideNAVDnc_SFC:MFL_GRID__ISC_00000000_0000" relativeCycleNumber="-1"/>
<WEItem parmID="SurgeHtPlusTideMLLWnc_SFC:MFL_GRID__ISC_00000000_0000" relativeCycleNumber="-1"/>
<WEItem parmID="SurgeHtPlusTideMSLnc_SFC:MFL_GRID__ISC_00000000_0000" relativeCycleNumber="-1"/>
<WEItem parmID="InundationTimingnc_SFC:MFL_GRID__ISC_00000000_0000" relativeCycleNumber="-1"/>
<WEItem parmID="InundationMaxnc_SFC:MFL_GRID__ISC_00000000_0000" relativeCycleNumber="-1"/>
<WEItem parmID="SurgeHtPlusTideMHHWnc_SFC:MFL_GRID__ISC_00000000_0000" relativeCycleNumber="-1"/>
<WEItem parmID="ProposedSS_SFC:MFL_GRID__ISC_00000000_0000" relativeCycleNumber="-1"/>
<WEItem parmID="ProposedSSnc_SFC:MFL_GRID__ISC_00000000_0000" relativeCycleNumber="-1"/>
<WEItem parmID="QPF_SFC:MFL_GRID__Fcst_00000000_0000" relativeCycleNumber="-1"/>
<WEItem parmID="QPFtoFFGRatio_SFC:MFL_GRID__Fcst_00000000_0000" relativeCycleNumber="-1"/>
<WEItem parmID="ProposedSS_SFC:MFL_GRID__Fcst_00000000_0000" relativeCycleNumber="-1"/>
<WEItem parmID="pwsN64_SFC:MFL_GRID__Fcst_00000000_0000" relativeCycleNumber="-1"/>
<WEItem parmID="prob64_SFC:MFL_GRID__Fcst_00000000_0000" relativeCycleNumber="-1"/>
<WEItem parmID="TornadoThreat_SFC:MFL_GRID__Fcst_00000000_0000" relativeCycleNumber="-1"/>
<WEItem parmID="WindGust_SFC:MFL_GRID__Fcst_00000000_0000" relativeCycleNumber="-1"/>
<WEItem parmID="Wind_SFC:MFL_GRID__Fcst_00000000_0000" relativeCycleNumber="-1"/>
<WEItem parmID="pwsD34_SFC:MFL_GRID__Fcst_00000000_0000" relativeCycleNumber="-1"/>
<WEItem parmID="prob34_SFC:MFL_GRID__Fcst_00000000_0000" relativeCycleNumber="-1"/>
<WEItem parmID="FloodingRainThreat_SFC:MFL_GRID__Fcst_00000000_0000" relativeCycleNumber="-1"/>
<WEItem parmID="StormSurgeThreat_SFC:MFL_GRID__Fcst_00000000_0000" relativeCycleNumber="-1"/>
<WEItem parmID="prob50_SFC:MFL_GRID__Fcst_00000000_0000" relativeCycleNumber="-1"/>
<WEItem parmID="pws64int_SFC:MFL_GRID__Fcst_00000000_0000" relativeCycleNumber="-1"/>
<WEItem parmID="pwsD64_SFC:MFL_GRID__Fcst_00000000_0000" relativeCycleNumber="-1"/>
<WEItem parmID="pws34int_SFC:MFL_GRID__Fcst_00000000_0000" relativeCycleNumber="-1"/>
<WEItem parmID="WindThreat_SFC:MFL_GRID__Fcst_00000000_0000" relativeCycleNumber="-1"/>
<WEItem parmID="pwsN34_SFC:MFL_GRID__Fcst_00000000_0000" relativeCycleNumber="-1"/>
<WEItem parmID="InundationMax_SFC:MFL_GRID__ISC_00000000_0000" relativeCycleNumber="-1"/>
<WEItem parmID="SurgeHtPlusTideMHHW_SFC:MFL_GRID__ISC_00000000_0000" relativeCycleNumber="-1"/>
<WEItem parmID="SurgeHtPlusTideMLLW_SFC:MFL_GRID__ISC_00000000_0000" relativeCycleNumber="-1"/>
<WEItem parmID="SurgeHtPlusTideMSL_SFC:MFL_GRID__ISC_00000000_0000" relativeCycleNumber="-1"/>
<WEItem parmID="SurgeHtPlusTideNAVD_SFC:MFL_GRID__ISC_00000000_0000" relativeCycleNumber="-1"/>
<WEItem parmID="InundationTiming_SFC:MFL_GRID__ISC_00000000_0000" relativeCycleNumber="-1"/>
<WEItem parmID="InundationMax_SFC:MFL_GRID__Fcst_00000000_0000" relativeCycleNumber="-1"/>
<WEItem parmID="SurgeHtPlusTideMHHW_SFC:MFL_GRID__Fcst_00000000_0000" relativeCycleNumber="-1"/>
<WEItem parmID="SurgeHtPlusTideMLLW_SFC:MFL_GRID__Fcst_00000000_0000" relativeCycleNumber="-1"/>
<WEItem parmID="SurgeHtPlusTideMSL_SFC:MFL_GRID__Fcst_00000000_0000" relativeCycleNumber="-1"/>
<WEItem parmID="SurgeHtPlusTideNAVD_SFC:MFL_GRID__Fcst_00000000_0000" relativeCycleNumber="-1"/>
<WEItem parmID="InundationTiming_SFC:MFL_GRID__Fcst_00000000_0000" relativeCycleNumber="-1"/>
<WEItem parmID="Hazards_SFC:MFL_GRID__Fcst_00000000_0000" relativeCycleNumber="-1"/>
</WEGroup>

File diff suppressed because one or more lines are too long

View file

@ -209,4 +209,16 @@
<alias base="NAHwave15">NAHwave15</alias>
<alias base="NAHwave10">NAHwave10</alias>
<alias base="NAHwave4">NAHwave4</alias>
<alias base="FFG-ALR">RFCFFG_ParameterInfo</alias>
<alias base="FFG-FWR">RFCFFG_ParameterInfo</alias>
<alias base="FFG-KRF">RFCFFG_ParameterInfo</alias>
<alias base="FFG-MSR">RFCFFG_ParameterInfo</alias>
<alias base="FFG-ORN">RFCFFG_ParameterInfo</alias>
<alias base="FFG-PTR">RFCFFG_ParameterInfo</alias>
<alias base="FFG-RHA">RFCFFG_ParameterInfo</alias>
<alias base="FFG-RSA">RFCFFG_ParameterInfo</alias>
<alias base="FFG-STR">RFCFFG_ParameterInfo</alias>
<alias base="FFG-TAR">RFCFFG_ParameterInfo</alias>
<alias base="FFG-TIR">RFCFFG_ParameterInfo</alias>
<alias base="FFG-TUA">RFCFFG_ParameterInfo</alias>
</aliasList>

View file

@ -41,9 +41,9 @@
# 03/20/2014 #2418 dgilling Remove unneeded D2D source PHISH.
# 04/17/2014 #2934 dgilling Remove alias for TPCSurgeProb D2D database.
# 05/09/2014 #3148 randerso Add tpHPCndfd to D2DAccumulativeElements for HPCERP
#
# 05/29/2014 #3224 randerso Added "SPC":8 to D2DDBVERSIONS
# 07/09/2014 #3146 randerso Removed unused import
# 07/10/2014 swhite Add surge and tropical threat WEs and their dependencies
########################################################################
#----------------------------------------------------------------------------
@ -162,7 +162,7 @@ VWaveDir = ("VWaveDir", SCALAR, "m/s", "V WaveDir Comp", 0.50, -0.50, 3, NO)
LkSfcT = ("LkSfcT", SCALAR, "C", "Lake Surface T", 40.0, -2.0, 1, NO)
SnowMap = ("SnowMap", SCALAR, "in", "Snowfall Map", 20.0, 0.0, 1, YES)
WaveDir = ("WaveDir", VECTOR, "m/s", "Wave Direction", 5.0, 0.0, 2, NO)
StormTotalQPF = ('StormTotalQPF', SCALAR, 'in', 'Storm Total QPF (in)', 10.0, 0.0, 2, YES)
StormTotalQPF = ('StormTotalQPF', SCALAR, 'in', 'Storm Total QPF (in)', 10.0, 0.0, 2, NO)
SeasonTotalSnow = ('SeasonTotalSnow', SCALAR, 'in', 'Season Total Snow (in)', 150.0, 0.0, 2, YES)
# Marine Weather Elements
@ -287,9 +287,31 @@ pwsN64 = ("pwsN64", SCALAR, "%", "Night64WSI PROB", 100.0, 0.0, 0, NO)
pws34int = ("pws34int", SCALAR, "%", "34WSIntPROB", 100.0, 0.0, 0, NO)
pws64int = ("pws64int", SCALAR, "%", "64WSIntPROB", 100.0, 0.0, 0, NO)
# Surge parms for HLS
SurgeHtPlusTide = ("SurgeHtPlusTide", SCALAR, "ft", "SurgeHtPlusTide", 50.0, -100.0, 2, NO)
SurgeHtPlusTideWTopo = ("SurgeHtPlusTideWTopo", SCALAR, "ft", "SurgeHtPlusTideWTopo", 50.0, -100.0, 2, NO)
# Surge parms for HLS/TCV
InundationMax = ("InundationMax", SCALAR, "ft", "Max Inundation", 30.0, -100.0, 1, NO)
InundationTiming = ("InundationTiming", SCALAR, "ft", "Incremental Inundation", 30.0, -100.0, 1, NO)
SurgeHtPlusTideMSL = ("SurgeHtPlusTideMSL", SCALAR, "ft", "Surge above MSL", 30.0, -100.0, 1, NO)
SurgeHtPlusTideMLLW = ("SurgeHtPlusTideMLLW", SCALAR, "ft", "Surge above MLLW", 30.0, -100.0, 1, NO)
SurgeHtPlusTideMHHW = ("SurgeHtPlusTideMHHW", SCALAR, "ft", "Surge above MHHW", 30.0, -100.0, 1, NO)
SurgeHtPlusTideNAVD = ("SurgeHtPlusTideNAVD", SCALAR, "ft", "Surge above NAVD88", 30.0, -100.0, 1, NO)
# parms for storm surge collaboration
SShazardKeys = [("<None>",""), ("SS.A", "STORM SURGE WATCH"), ("SS.W", "STORM SURGE WARNING")]
ProposedSS = ("ProposedSS", DISCRETE, "w/w/a", "Proposed StormSurge Hazards", YES, SShazardKeys, 7)
tempProposedSS = ("tempProposedSS", DISCRETE, "w/w/a", "Temp Proposed StormSurge Hazards",
YES, SShazardKeys, 4)
InitialSS = ("InitialSS", DISCRETE, "w/w/a", "Initial StormSurge Hazards",
YES, SShazardKeys, 4)
DiffSS = ("DiffSS", SCALAR, "None", "Difference StormSurge Hazards", 2.0, -1.0, 0, NO)
# parms for tropical cyclone threat graphics
Threat4Keys = [("None","None to Little"), ("Elevated","Elevated"), ("Mod", "Moderate"), ("High", "High"), ("Extreme","Extreme"),]
FloodingRainThreat = ("FloodingRainThreat", DISCRETE, "Cat", "Flooding Rain Threat", NO, Threat4Keys,2)
StormSurgeThreat = ("StormSurgeThreat", DISCRETE, "Cat", "Storm Surge Threat", NO, Threat4Keys,2)
WindThreat = ("WindThreat", DISCRETE, "Cat", "Wind Threat", NO, Threat4Keys,2)
TornadoThreat = ("TornadoThreat", DISCRETE, "Cat", "Tornado Threat", NO, Threat4Keys,2)
QPFtoFFGRatio = ("QPFtoFFGRatio", SCALAR, "", "QPF to FFG Ratio", 8.0, 0.0, 0, NO)
# Hazards
HazardKeys = []
@ -440,23 +462,23 @@ HAZE = ('H', 'Haze',
[INTEN_NONE],
[PRIMARY, MENTION])
BLWGSNOW = ('BS', 'Blowing Snow',
[AREAS,PATCHY,DEFN],
[PATCHY, AREAS, DEFN],
[INTEN_NONE],
[PRIMARY, MENTION])
BLWGSAND = ('BN', 'Blowing Sand',
[AREAS,PATCHY,DEFN],
[PATCHY, AREAS, DEFN],
[INTEN_NONE],
[PRIMARY, MENTION])
SMOKE = ('K', 'Smoke',
[AREAS, PATCHY, DEFN],
[PATCHY, AREAS, DEFN],
[INTEN_NONE],
[PRIMARY, MENTION])
BLWGDUST = ('BD', 'Blowing Dust',
[AREAS,PATCHY,DEFN],
[PATCHY, AREAS, DEFN],
[INTEN_NONE],
[PRIMARY, MENTION])
FROST = ('FR','Frost',
[AREAS, PATCHY, WIDE],
[PATCHY, AREAS, DEFN],
[INTEN_NONE],
[PRIMARY, MENTION, OUTLYNG])
FRZSPRAY = ('ZY','Freezing Spray',
@ -644,8 +666,8 @@ NDFD_Oceanic_10K = ('NDFD_Oceanic_10km', MERCATOR,
# Add a new domain for NHC purposes
GridForNHA = ('GridForNHA', LAMBERT_CONFORMAL,
(-102.551, 16.6069), (-50.5524, 47.3806),
(-95.0, 35.0), 35.0, 35.0, (1, 1), (1729,1601), 0.0, 0.0, 0.0)
(-103.929, 20.164), (-50.8894, 42.9545),
(-95.0, 35.0), 35.0, 35.0, (1, 1), (1833,1241), 0.0, 0.0, 0.0)
# list of all projections
allProjections = [Grid201, Grid202, Grid203, Grid204, Grid205, Grid206,
@ -830,7 +852,7 @@ SITES = {
'TIR' : ([220, 171], (59.0, 25.0), (13.0, 12.0), 'EST5EDT', Grid211, "rfc"),
'TUA' : ([281, 168], (39.0, 22.0), (18.0, 10.0), 'CST6CDT', Grid211, "rfc"),
#Special Sites - Updated NHC and OPC domains in OB9.3
#Special Sites - Added Hawaiian High Seas domain
'US' : ([267, 159], (18.0, 9.5), (67.0, 40.0), 'EDT5EDT', Grid211, "other"),
'FSL' : ([161, 145], (38.50, 27.00), (10.0, 9.0), 'MST7MDT', Grid211, "other"),
# 'NH1' : ([667, 461], (69.5, 4.5), (52.03125, 35.9375), 'EST5EDT', Grid204, "wfo"),
@ -839,6 +861,7 @@ SITES = {
'NH2' : ([1188, 363], (1328.0, 365.0), (1187.0, 362.0), 'EST5EDT', NDFD_Oceanic_10K, "wfo"),
'ONA' : ([244, 383], (68.9375, 19.5625), (15.1875, 23.875), 'EST5EDT', Grid211, "wfo"),
'ONP' : ([396, 415], (8.1875, 21.5625), (24.6875, 25.875), 'PST8PDT', Grid211, "wfo"),
'HPA' : ([899, 671], (284.0, 30.0), (898.0, 670.0), 'Pacific/Honolulu', NDFD_Oceanic_10K, "wfo"),
#Ice Desk for AFC
'AICE' : ([560, 340], (9.0, 11.0), (29.0, 19.0), 'America/Anchorage',
@ -856,8 +879,9 @@ SITES = {
#National Centers
'HAK' : ( [825,553], ( 1.0, 1.0), (103.0, 69.0), 'EST5EDT', Grid214AK, "nc"),
'HUS' : ([1073,689], (19.0, 8.0), ( 67.0, 43.0), 'EST5EDT', Grid211, "nc"),
'NHA' : ([1729,1601], (1.0,1.0), (1728.0, 1600.0), 'EST5EDT', GridForNHA, "nc"),
'HUS' : ([1073,689], (19.0, 8.0), ( 67.0, 43.0), 'EST5EDT', Grid211, "nc"),
#'NHA' : ([1729,1601], (1.0,1.0), (1728.0, 1600.0), 'EST5EDT', GridForNHA, "nc"),
'NHA' : ([1833,1241], (41.5,5.0), (54.0,40.5), 'EST5EDT', Grid211, "nc"),
}
@ -1202,6 +1226,18 @@ elif SID in CONUS_EAST_SITES:
'NPHwave4',
'WPHwave10',
'GLOBHwave',
('FFG-ALR', 'FFGALR'),
('FFG-FWR', 'FFGFWR'),
('FFG-KRF', 'FFGKRF'),
('FFG-MSR', 'FFGMSR'),
('FFG-ORN', 'FFGORN'),
('FFG-PTR', 'FFGPTR'),
('FFG-RHA', 'FFGRHA'),
('FFG-RSA', 'FFGRSA'),
('FFG-STR', 'FFGSTR'),
('FFG-TAR', 'FFGTAR'),
('FFG-TIR', 'FFGTIR'),
('FFG-TUA', 'FFGTUA'),
]
else: #######DCS3501 WEST_CONUS
@ -1260,6 +1296,18 @@ else: #######DCS3501 WEST_CONUS
'NPHwave4',
'WPHwave10',
'GLOBHwave',
('FFG-ALR', 'FFGALR'),
('FFG-FWR', 'FFGFWR'),
('FFG-KRF', 'FFGKRF'),
('FFG-MSR', 'FFGMSR'),
('FFG-ORN', 'FFGORN'),
('FFG-PTR', 'FFGPTR'),
('FFG-RHA', 'FFGRHA'),
('FFG-RSA', 'FFGRSA'),
('FFG-STR', 'FFGSTR'),
('FFG-TAR', 'FFGTAR'),
('FFG-TIR', 'FFGTIR'),
('FFG-TUA', 'FFGTUA'),
]
if SID in GreatLake_SITES:
@ -1288,6 +1336,7 @@ elif SID == "HFO":
elif SID == "SJU":
NETCDFDIRS = [('/awips2/edex/data/gfe/topo/NED3ARCSTOPO','CRMTopo'),
('/awips2/edex/data/gfe/topo/NED3ARCSTOPONEW','NED'),
('/awips2/edex/data/gfe/topo/VDATUMS','VDATUMS'),
]
@ -1301,6 +1350,7 @@ elif SID in CONUS_EAST_SITES:
('/awips2/edex/data/gfe/climo/NCDC'),
('/awips2/edex/data/gfe/topo/NED3ARCSTOPO','CRMTopo'),
('/awips2/edex/data/gfe/topo/NED3ARCSTOPONEW','NED'),
('/awips2/edex/data/gfe/topo/VDATUMS','VDATUMS'),
]
@ -1309,6 +1359,7 @@ else: #######DCS3501 WEST_CONUS
('/awips2/edex/data/gfe/climo/NCDC'),
('/awips2/edex/data/gfe/topo/NED3ARCSTOPO','CRMTopo'),
('/awips2/edex/data/gfe/topo/NED3ARCSTOPONEW','NED'),
('/awips2/edex/data/gfe/topo/VDATUMS','VDATUMS'),
]
@ -1601,7 +1652,7 @@ TRANSMIT_SCRIPT = GFESUITE_HOME + '/bin/gfe_msg_send -s %SUBJECT -a %ADDRESSES -
# to the ISC database that is your own office type. The format of this
# entry is a list of tuples. The tuple is a list of weather elements
# objects (such as Temp and not "T"), and an office type, such as "rfc".
EXTRA_ISC_PARMS = [([QPF], 'rfc'), ([QPF], 'wfo')]
EXTRA_ISC_PARMS = [([QPF,FloodingRainThreat], 'rfc'), ([QPF,FloodingRainThreat], 'wfo'), ([ProposedSS,Hazards,InundationMax,InundationTiming,SurgeHtPlusTideMSL,SurgeHtPlusTideMLLW,SurgeHtPlusTideMHHW,SurgeHtPlusTideNAVD], 'nc'),([ProposedSS,Hazards,InundationMax,InundationTiming,SurgeHtPlusTideMSL,SurgeHtPlusTideMLLW,SurgeHtPlusTideMHHW,SurgeHtPlusTideNAVD], 'wfo')]
#---------------------------------------------------------------------------
#
@ -1792,11 +1843,13 @@ OFFICIALDBS = [([Temp, Td, Wind, Weather, Sky, FzLevel, SnowLevel], TC1),
([Wetflag], FireWx1300TC),
([StormTotalSnow], TC1),
# Tropical parms
([prob34, prob50, prob64], TC1),
([pws34,pws50,pws64,SurgeHtPlusTide,SurgeHtPlusTideWTopo], TC1),
([prob34, prob50, prob64,pws34,pws50,pws64,], TC1),
([InundationMax,SurgeHtPlusTideMSL,SurgeHtPlusTideMLLW,SurgeHtPlusTideMHHW,SurgeHtPlusTideNAVD], TC1),
([ProposedSS,DiffSS,tempProposedSS,InitialSS], TC1),
([WindThreat,StormSurgeThreat,FloodingRainThreat,TornadoThreat], TC1),
([pwsD34,pwsD64], PWSDTC),
([pwsN34,pwsN64], PWSNTC),
([pws34int,pws64int], TC6NG),
([pws34int,pws64int,InundationTiming,QPFtoFFGRatio], TC6NG),
# DR20541 and 20482
([PoP12hr], TC12NG),
([QPF6hr, SnowAmt6hr], TC6NG),

View file

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8"?>
<gridParamInfo xmlns:ns2="group">
<valtimeMINUSreftime>
<fcst>0</fcst>
<fcst>21600</fcst>
<fcst>43200</fcst>
<fcst>64800</fcst>
<fcst>86400</fcst>
</valtimeMINUSreftime>
<gridParameterInfo xsi:typ="parameterInfo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<short_name>FFG0624hr</short_name>
<long_name>6 hr flash flood guidance</long_name>
<units>mm</units>
<udunits>millimeters</udunits>
<uiname>totalprecip</uiname>
<valid_range>0.0</valid_range>
<valid_range>1000.0</valid_range>
<fillValue>-99999.0</fillValue>
<n3D>1</n3D>
<levelsDesc>SFC</levelsDesc>
<levels>
<level>SFC</level>
</levels>
</gridParameterInfo>
<gridParameterInfo xsi:typ="parameterInfo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<short_name>FFG0324hr</short_name>
<long_name>3 hr flash flood guidance</long_name>
<units>mm</units>
<udunits>millimeters</udunits>
<uiname>totalprecip</uiname>
<valid_range>0.0</valid_range>
<valid_range>1000.0</valid_range>
<fillValue>-99999.0</fillValue>
<n3D>1</n3D>
<levelsDesc>SFC</levelsDesc>
<levels>
<level>SFC</level>
</levels>
</gridParameterInfo>
<gridParameterInfo xsi:typ="parameterInfo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<short_name>FFG0124hr</short_name>
<long_name>1 hr flash flood guidance</long_name>
<units>mm</units>
<udunits>millimeters</udunits>
<uiname>totalprecip</uiname>
<valid_range>0.0</valid_range>
<valid_range>1000.0</valid_range>
<fillValue>-99999.0</fillValue>
<n3D>1</n3D>
<levelsDesc>SFC</levelsDesc>
<levels>
<level>SFC</level>
</levels>
</gridParameterInfo>
</gridParamInfo>

View file

@ -0,0 +1,259 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<colorMap>
<color a="0.0" b="0.0" g="0.0" r="0.0"/>
<color a="1.0" b="0.8901961" g="0.8901961" r="0.8901961"/>
<color a="1.0" b="0.8901961" g="0.8901961" r="0.8901961"/>
<color a="1.0" b="0.8901961" g="0.8901961" r="0.8901961"/>
<color a="1.0" b="0.8901961" g="0.8901961" r="0.8901961"/>
<color a="1.0" b="0.8901961" g="0.8901961" r="0.8901961"/>
<color a="1.0" b="0.8901961" g="0.8901961" r="0.8901961"/>
<color a="1.0" b="0.8901961" g="0.8901961" r="0.8901961"/>
<color a="1.0" b="0.0" g="1.0" r="1.0"/>
<color a="1.0" b="0.0" g="1.0" r="1.0"/>
<color a="1.0" b="0.0" g="1.0" r="1.0"/>
<color a="1.0" b="0.0" g="1.0" r="1.0"/>
<color a="1.0" b="0.0" g="1.0" r="1.0"/>
<color a="1.0" b="0.0" g="1.0" r="1.0"/>
<color a="1.0" b="0.0" g="1.0" r="1.0"/>
<color a="1.0" b="0.0" g="1.0" r="1.0"/>
<color a="1.0" b="0.0" g="1.0" r="1.0"/>
<color a="1.0" b="0.0" g="1.0" r="1.0"/>
<color a="1.0" b="0.0" g="1.0" r="1.0"/>
<color a="1.0" b="0.0" g="1.0" r="1.0"/>
<color a="1.0" b="0.0" g="1.0" r="1.0"/>
<color a="1.0" b="0.0" g="1.0" r="1.0"/>
<color a="1.0" b="0.0" g="1.0" r="1.0"/>
<color a="1.0" b="0.0" g="1.0" r="1.0"/>
<color a="1.0" b="0.0" g="1.0" r="1.0"/>
<color a="1.0" b="0.0" g="0.6" r="1.0"/>
<color a="1.0" b="0.0" g="0.6" r="1.0"/>
<color a="1.0" b="0.0" g="0.6" r="1.0"/>
<color a="1.0" b="0.0" g="0.6" r="1.0"/>
<color a="1.0" b="0.0" g="0.6" r="1.0"/>
<color a="1.0" b="0.0" g="0.6" r="1.0"/>
<color a="1.0" b="0.0" g="0.6" r="1.0"/>
<color a="1.0" b="0.0" g="0.6" r="1.0"/>
<color a="1.0" b="0.0" g="0.6" r="1.0"/>
<color a="1.0" b="0.0" g="0.6" r="1.0"/>
<color a="1.0" b="0.0" g="0.6" r="1.0"/>
<color a="1.0" b="0.0" g="0.6" r="1.0"/>
<color a="1.0" b="0.0" g="0.6" r="1.0"/>
<color a="1.0" b="0.0" g="0.6" r="1.0"/>
<color a="1.0" b="0.0" g="0.6" r="1.0"/>
<color a="1.0" b="0.0" g="0.6" r="1.0"/>
<color a="1.0" b="0.0" g="0.6" r="1.0"/>
<color a="1.0" b="0.0" g="0.6" r="1.0"/>
<color a="1.0" b="0.0" g="0.6" r="1.0"/>
<color a="1.0" b="0.0" g="0.6" r="1.0"/>
<color a="1.0" b="0.0" g="0.6" r="1.0"/>
<color a="1.0" b="0.0" g="0.6" r="1.0"/>
<color a="1.0" b="0.0" g="0.6" r="1.0"/>
<color a="1.0" b="0.0" g="0.6" r="1.0"/>
<color a="1.0" b="0.0" g="0.6" r="1.0"/>
<color a="1.0" b="0.0" g="0.6" r="1.0"/>
<color a="1.0" b="0.0" g="0.0" r="1.0"/>
<color a="1.0" b="0.0" g="0.0" r="1.0"/>
<color a="1.0" b="0.0" g="0.0" r="1.0"/>
<color a="1.0" b="0.0" g="0.0" r="1.0"/>
<color a="1.0" b="0.0" g="0.0" r="1.0"/>
<color a="1.0" b="0.0" g="0.0" r="1.0"/>
<color a="1.0" b="0.0" g="0.0" r="1.0"/>
<color a="1.0" b="0.0" g="0.0" r="1.0"/>
<color a="1.0" b="0.0" g="0.0" r="1.0"/>
<color a="1.0" b="0.0" g="0.0" r="1.0"/>
<color a="1.0" b="0.0" g="0.0" r="1.0"/>
<color a="1.0" b="0.0" g="0.0" r="1.0"/>
<color a="1.0" b="0.0" g="0.0" r="1.0"/>
<color a="1.0" b="0.0" g="0.0" r="1.0"/>
<color a="1.0" b="0.0" g="0.0" r="1.0"/>
<color a="1.0" b="0.0" g="0.0" r="1.0"/>
<color a="1.0" b="0.0" g="0.0" r="1.0"/>
<color a="1.0" b="0.0" g="0.0" r="1.0"/>
<color a="1.0" b="0.0" g="0.0" r="1.0"/>
<color a="1.0" b="0.0" g="0.0" r="1.0"/>
<color a="1.0" b="0.0" g="0.0" r="1.0"/>
<color a="1.0" b="0.0" g="0.0" r="1.0"/>
<color a="1.0" b="0.0" g="0.0" r="1.0"/>
<color a="1.0" b="0.0" g="0.0" r="1.0"/>
<color a="1.0" b="0.0" g="0.0" r="1.0"/>
<color a="1.0" b="0.0" g="0.0" r="1.0"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
<color a="1.0" b="0.8" g="0.0" r="0.8"/>
</colorMap>

View file

@ -0,0 +1,155 @@
<!-- ====================
This is a colormap file that is read via JaXB to marshel the ColorMap class.
====================-->
<colorMap>
<color r=" 1.0 " g=" 1.0 " b=" 1.0 " a=" 1.0 " />
<color r=" 1.0 " g=" 1.0 " b=" 1.0 " a=" 1.0 " />
<color r=" 0.0549019607843 " g=" 0.337254901961 " b=" 0.0823529411765 " a=" 1.0 " />
<color r=" 0.0549019607843 " g=" 0.337254901961 " b=" 0.0823529411765 " a=" 1.0 " />
<color r=" 0.0549019607843 " g=" 0.337254901961 " b=" 0.0823529411765 " a=" 1.0 " />
<color r=" 0.0549019607843 " g=" 0.337254901961 " b=" 0.0823529411765 " a=" 1.0 " />
<color r=" 0.0549019607843 " g=" 0.337254901961 " b=" 0.0823529411765 " a=" 1.0 " />
<color r=" 0.0549019607843 " g=" 0.337254901961 " b=" 0.0823529411765 " a=" 1.0 " />
<color r=" 0.0549019607843 " g=" 0.337254901961 " b=" 0.0823529411765 " a=" 1.0 " />
<color r=" 0.0 " g=" 0.498039215686 " b=" 0.00392156862745 " a=" 1.0 " />
<color r=" 0.0 " g=" 0.498039215686 " b=" 0.00392156862745 " a=" 1.0 " />
<color r=" 0.0 " g=" 0.498039215686 " b=" 0.00392156862745 " a=" 1.0 " />
<color r=" 0.0 " g=" 0.498039215686 " b=" 0.00392156862745 " a=" 1.0 " />
<color r=" 0.0 " g=" 0.498039215686 " b=" 0.00392156862745 " a=" 1.0 " />
<color r=" 0.0 " g=" 0.498039215686 " b=" 0.00392156862745 " a=" 1.0 " />
<color r=" 0.0 " g=" 0.498039215686 " b=" 0.00392156862745 " a=" 1.0 " />
<color r=" 0.0 " g=" 0.498039215686 " b=" 0.00392156862745 " a=" 1.0 " />
<color r=" 0.0 " g=" 0.498039215686 " b=" 0.00392156862745 " a=" 1.0 " />
<color r=" 0.0 " g=" 0.498039215686 " b=" 0.00392156862745 " a=" 1.0 " />
<color r=" 0.0 " g=" 0.498039215686 " b=" 0.00392156862745 " a=" 1.0 " />
<color r=" 0.0 " g=" 0.498039215686 " b=" 0.00392156862745 " a=" 1.0 " />
<color r=" 0.0 " g=" 0.498039215686 " b=" 0.00392156862745 " a=" 1.0 " />
<color r=" 0.0 " g=" 0.498039215686 " b=" 0.00392156862745 " a=" 1.0 " />
<color r=" 0.0 " g=" 0.498039215686 " b=" 0.00392156862745 " a=" 1.0 " />
<color r=" 0.0 " g=" 0.498039215686 " b=" 0.00392156862745 " a=" 1.0 " />
<color r=" 0.0 " g=" 0.498039215686 " b=" 0.00392156862745 " a=" 1.0 " />
<color r=" 0.0 " g=" 0.498039215686 " b=" 0.00392156862745 " a=" 1.0 " />
<color r=" 0.0 " g=" 0.498039215686 " b=" 0.00392156862745 " a=" 1.0 " />
<color r=" 0.0 " g=" 0.498039215686 " b=" 0.00392156862745 " a=" 1.0 " />
<color r=" 0.0 " g=" 0.498039215686 " b=" 0.00392156862745 " a=" 1.0 " />
<color r=" 0.0 " g=" 1.0 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 0.0 " g=" 1.0 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 0.0 " g=" 1.0 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 0.0 " g=" 1.0 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 0.0 " g=" 1.0 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 0.0 " g=" 1.0 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 0.0 " g=" 1.0 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 0.0 " g=" 1.0 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 0.0 " g=" 1.0 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 0.0 " g=" 1.0 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 0.0 " g=" 1.0 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 0.0 " g=" 1.0 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 0.0 " g=" 1.0 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 0.0 " g=" 1.0 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 0.0 " g=" 1.0 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 0.0 " g=" 1.0 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 0.0 " g=" 1.0 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 0.0 " g=" 1.0 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 0.0 " g=" 1.0 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 0.0 " g=" 1.0 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 0.0 " g=" 1.0 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 0.0 " g=" 1.0 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 0.0 " g=" 1.0 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 0.0 " g=" 1.0 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 0.0 " g=" 1.0 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 0.0 " g=" 1.0 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 0.0 " g=" 1.0 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 0.0 " g=" 1.0 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 0.0 " g=" 1.0 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 0.0 " g=" 1.0 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 0.843137254902 " g=" 1.0 " b=" 0.396078431373 " a=" 1.0 " />
<color r=" 0.843137254902 " g=" 1.0 " b=" 0.396078431373 " a=" 1.0 " />
<color r=" 0.843137254902 " g=" 1.0 " b=" 0.396078431373 " a=" 1.0 " />
<color r=" 0.843137254902 " g=" 1.0 " b=" 0.396078431373 " a=" 1.0 " />
<color r=" 0.843137254902 " g=" 1.0 " b=" 0.396078431373 " a=" 1.0 " />
<color r=" 0.843137254902 " g=" 1.0 " b=" 0.396078431373 " a=" 1.0 " />
<color r=" 0.843137254902 " g=" 1.0 " b=" 0.396078431373 " a=" 1.0 " />
<color r=" 0.843137254902 " g=" 1.0 " b=" 0.396078431373 " a=" 1.0 " />
<color r=" 0.843137254902 " g=" 1.0 " b=" 0.396078431373 " a=" 1.0 " />
<color r=" 0.843137254902 " g=" 1.0 " b=" 0.396078431373 " a=" 1.0 " />
<color r=" 0.843137254902 " g=" 1.0 " b=" 0.396078431373 " a=" 1.0 " />
<color r=" 0.843137254902 " g=" 1.0 " b=" 0.396078431373 " a=" 1.0 " />
<color r=" 0.843137254902 " g=" 1.0 " b=" 0.396078431373 " a=" 1.0 " />
<color r=" 0.843137254902 " g=" 1.0 " b=" 0.396078431373 " a=" 1.0 " />
<color r=" 0.843137254902 " g=" 1.0 " b=" 0.396078431373 " a=" 1.0 " />
<color r=" 0.843137254902 " g=" 1.0 " b=" 0.396078431373 " a=" 1.0 " />
<color r=" 0.843137254902 " g=" 1.0 " b=" 0.396078431373 " a=" 1.0 " />
<color r=" 0.843137254902 " g=" 1.0 " b=" 0.396078431373 " a=" 1.0 " />
<color r=" 0.843137254902 " g=" 1.0 " b=" 0.396078431373 " a=" 1.0 " />
<color r=" 0.843137254902 " g=" 1.0 " b=" 0.396078431373 " a=" 1.0 " />
<color r=" 0.843137254902 " g=" 1.0 " b=" 0.396078431373 " a=" 1.0 " />
<color r=" 0.843137254902 " g=" 1.0 " b=" 0.396078431373 " a=" 1.0 " />
<color r=" 0.843137254902 " g=" 1.0 " b=" 0.396078431373 " a=" 1.0 " />
<color r=" 0.843137254902 " g=" 1.0 " b=" 0.396078431373 " a=" 1.0 " />
<color r=" 0.843137254902 " g=" 1.0 " b=" 0.396078431373 " a=" 1.0 " />
<color r=" 0.843137254902 " g=" 1.0 " b=" 0.396078431373 " a=" 1.0 " />
<color r=" 0.843137254902 " g=" 1.0 " b=" 0.396078431373 " a=" 1.0 " />
<color r=" 0.843137254902 " g=" 1.0 " b=" 0.396078431373 " a=" 1.0 " />
<color r=" 0.843137254902 " g=" 1.0 " b=" 0.396078431373 " a=" 1.0 " />
<color r=" 0.843137254902 " g=" 1.0 " b=" 0.396078431373 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.992156862745 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.992156862745 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.992156862745 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.992156862745 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.992156862745 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.992156862745 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.992156862745 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.992156862745 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.992156862745 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.992156862745 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.992156862745 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.992156862745 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.992156862745 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.992156862745 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.992156862745 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.992156862745 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.992156862745 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.992156862745 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.992156862745 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.992156862745 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.992156862745 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.992156862745 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.992156862745 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.992156862745 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.992156862745 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.992156862745 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.992156862745 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.992156862745 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.992156862745 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.992156862745 " b=" 0.0117647058824 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.607843137255 " b=" 0.0313725490196 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.607843137255 " b=" 0.0313725490196 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.607843137255 " b=" 0.0313725490196 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.607843137255 " b=" 0.0313725490196 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.607843137255 " b=" 0.0313725490196 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.607843137255 " b=" 0.0313725490196 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.607843137255 " b=" 0.0313725490196 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.607843137255 " b=" 0.0313725490196 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.607843137255 " b=" 0.0313725490196 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.607843137255 " b=" 0.0313725490196 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.607843137255 " b=" 0.0313725490196 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.607843137255 " b=" 0.0313725490196 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.607843137255 " b=" 0.0313725490196 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.607843137255 " b=" 0.0313725490196 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.607843137255 " b=" 0.0313725490196 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.0470588235294 " b=" 0.0156862745098 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.0470588235294 " b=" 0.0156862745098 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.0470588235294 " b=" 0.0156862745098 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.0470588235294 " b=" 0.0156862745098 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.0470588235294 " b=" 0.0156862745098 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.0470588235294 " b=" 0.0156862745098 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.0470588235294 " b=" 0.0156862745098 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.0470588235294 " b=" 0.0156862745098 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.0470588235294 " b=" 0.0156862745098 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.0470588235294 " b=" 0.0156862745098 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.0470588235294 " b=" 0.0156862745098 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.0470588235294 " b=" 0.0156862745098 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.0470588235294 " b=" 0.0156862745098 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.0470588235294 " b=" 0.0156862745098 " a=" 1.0 " />
<color r=" 1.0 " g=" 0.0470588235294 " b=" 0.0156862745098 " a=" 1.0 " />
</colorMap>

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<colorMap xmlns:ns2="http://www.example.org/productType">
<color r="0.8862745" g="0.8862745" b="0.8862745" a="1.0"/>
<color r="1.0" g="1.0" b="0.0" a="1.0"/>
<color r="1.0" g="0.6" b="0.0" a="1.0"/>
<color r="1.0" g="0.0" b="0.0" a="1.0"/>
<color r="0.8" g="0.0" b="0.8" a="1.0"/>
</colorMap>

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<colorMap>
<color a="0.45490196" b="0.0" g="0.0" r="0.0"/>
<color a="1.0" b="0.1254902" g="0.48235294" r="1.0"/>
<color a="1.0" b="0.03529412" g="0.15686275" r="1.0"/>
</colorMap>

View file

@ -48,6 +48,7 @@ mask=ISC_Send_Area
parmlist1="-p MaxT -p MinT -p MaxRH -p MinRH -p T -p Td -p RH -p WindChill -p HeatIndex -p ApparentT"
parmlist2="-p PoP -p PoP12 -p Sky -p Wx -p Hazards -p SnowLevel -p QPF -p SnowAmt -p IceAccum -p Wind -p WindGust"
parmlist3="-p ClearIndex -p FreeWind -p LAL -p Haines -p MixHgt -p VentRate -p TransWind -p Wind20ft -p CLRIndx"
parmlist4="-p StormSurgeThreat -p WindThreat -p FloodingRainThreat -p TornadoThreat"
parmlist5=""
parmlist6=""
parmlist="$parmlist1 $parmlist2 $parmlist3 $parmlist4 $parmlist5 $parmlist6"

View file

@ -0,0 +1,90 @@
#!/bin/sh
#
# kml_legend.sh - creates legends for the KML files.
#
# requirements: imagemagick (tested on version 6.2.8);
# file logos.png must be in the same directory as this script
#
# UPDATED: 26 June 2012 - JCM - changed legend text per DWS request
# UPDATED: 19 July 2012 - JCM - changed legend text to black from white
# UPDATED: 08 Sept 2014 - JCM - changed None and Low to new phraseology;
# removed marine legend; updated coastal
# and inland threats
# UPDATED: 11 Sept 2014 - JCM - completed updates above
# UPDATED: 20 Oct. 2014 - JCM - set up for 2015 season
#
########################################################################
# CONFIGURATION SECTION BELOW
########################################################################
GFESUITE_HOME="/awips2/GFESuite"
HTI_HOME="${GFESUITE_HOME}/hti"
site=$(hostname|cut -c 5-)
if [ ! -f ${HTI_HOME}/etc/sitevars.${site} ]; then
cp ${HTI_HOME}/etc/sitevars.ccc ${HTI_HOME}/etc/sitevars.${site}
fi
# SITES CAN CUSTOMIZE THE SITEVARS AS NEEDED
. ${HTI_HOME}/etc/sitevars.${site}
########################################################################
# BEGIN MAIN SCRIPT
########################################################################
cd ${HTI_HOME}/bin
# create a canvas, 200x500
convert -size 200x500 xc:black temp.png
# make the image transparent
##convert temp.png -alpha transparent transparent.png
convert temp.png null: -matte -compose Clear -composite -compose Over transparent.png
# insert the logos at the bottom
composite -gravity south -geometry +0+0 logos.png transparent.png trans2.png
# write the date onto the image
DATE=`date +"Issued %F %H%MZ"`
# DATE= " "
convert trans2.png -font Century-Schoolbook-Bold -pointsize 16 -fill black -annotate +0+400 "$DATE" trans2a.png
convert trans2a.png -fill black -draw 'rectangle 5,340 25,360' \
-fill "#E5E5E5" -draw 'rectangle 6,341 24,359' \
-font Century-Schoolbook-Bold -pointsize 16 -fill black -annotate +30+355 "None to Little" \
-fill black -draw 'rectangle 5,320 25,340' \
-fill "#FFFF00" -draw 'rectangle 6,321 24,339' \
-font Century-Schoolbook-Bold -pointsize 16 -fill black -annotate +30+335 "Elevated" \
-fill black -draw 'rectangle 5,300 25,320' \
-fill "#FFA70F" -draw 'rectangle 6,301 24,319' \
-font Century-Schoolbook-Bold -pointsize 16 -fill black -annotate +30+315 "Moderate" \
-fill black -draw 'rectangle 5,280 25,300' \
-fill "#FF0000" -draw 'rectangle 6,281 24,299' \
-font Century-Schoolbook-Bold -pointsize 16 -fill black -annotate +30+295 "High" \
-fill black -draw 'rectangle 5,260 25,280' \
-fill "#CC00CC" -draw 'rectangle 6,261 24,279' \
-font Century-Schoolbook-Bold -pointsize 16 -fill black -annotate +30+275 "Extreme" \
trans2b.png
# Now, draw labels for Flooding Rain, Storm Surge, Tornado, and Wind threats and create
# the final legend png files.
# inland flood threat (Flooding Rain Threat)
convert trans2b.png -font Century-Schoolbook-Bold -pointsize 20 -fill black -annotate +5+250 "Threat" \
-annotate +5+230 "Flooding Rain" floodingrainthreatlegend.png
# coastal flood threat (Storm Surge Threat)
convert trans2b.png -font Century-Schoolbook-Bold -pointsize 20 -fill black -annotate +5+250 "Threat" \
-annotate +5+230 "Storm Surge" stormsurgethreatlegend.png
# tornado threat
convert trans2b.png -font Century-Schoolbook-Bold -pointsize 20 -fill black -annotate +5+250 "Threat" \
-annotate +5+230 "Tornado" tornadothreatlegend.png
# wind threat
convert trans2b.png -font Century-Schoolbook-Bold -pointsize 20 -fill black -annotate +5+250 "Threat" \
-annotate +5+230 "Wind" windthreatlegend.png
#echo ${PRODUCTdir}
chmod 666 *legend.png
mv *legend.png ${PRODUCTdir}/
# clean up scraps
rm temp.png transparent.png trans2.png trans2a.png trans2b.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

View file

@ -0,0 +1,199 @@
#!/bin/bash -l
# UNIX Shell Script
# Tested Operating System(s): RHEL 3, 4, 5, 6
# Tested Run Level(s): 3, 5
# Shell Used: BASH shell
# Original Author(s): Douglas.Gaer@noaa.gov
# File Creation Date: 01/27/2009
# Date Last Modified: 10/20/2014
#
# Contributors:
# Joe Maloney (MFL), Pablo Santos (MFL)
# -----------------------------------------------------------
# ------------- Program Description and Details -------------
# -----------------------------------------------------------
#
# This script uses ifpImage to create PNG graphics of tropical threat
# grids, then runProcedure to create KML of the same grids. Finally,
# the output files are rsync'd to LDAD and finally the webfarm.
#
# To execute:
# ./make_hti.sh wfo
# (where wfo is the three letter wfo id)
#
# The script can be launched from the Scripts... menu in GFE, though
# it should also be run via trigger.
#
# Directory program runs from: /awips2/GFESuite/hti/bin
#
# Needed configuration on ls2/3: /data/ldad/hti needs to exist. The
# script will create this directory if
# it is missing.
#
# History:
# 20 OCT 2014 - jcm - created from make_ghls.sh, broke out of webapps
# package. Renamed make_hti.sh.
#
########################################################################
# CHECK TO SEE IF SITE ID WAS PASSED AS ARGUMENT
# IF NOT THEN EXIT FROM THE SCRIPT
########################################################################
if [ $# -lt 1 ] ;then
echo Invalid number of arguments.
echo Script stopped.
echo ./rsyncGridsToCWF.sh wfo
exit
else
SITE=$(echo ${1} | tr '[a-z]' '[A-Z]')
site=$(echo ${1} | tr '[A-Z]' '[a-z]')
fi
########################################################################
# CONFIGURATION SECTION BELOW
########################################################################
GFESUITE_HOME="/awips2/GFESuite"
HTI_HOME="${GFESUITE_HOME}/hti"
if [ ! -f ${HTI_HOME}/etc/sitevars.${site} ]; then
cp ${HTI_HOME}/etc/sitevars.ccc ${HTI_HOME}/etc/sitevars.${site}
fi
# SITES CAN CUSTOMIZE THE SITEVARS AS NEEDED
. ${HTI_HOME}/etc/sitevars.${site}
########################################################################
# BEGIN MAIN SCRIPT
########################################################################
# set current data and log file name
currdate=$(date -u +%Y%m%d)
export LOG_FILE="${HTI_HOME}/logs/${currdate}/make_hti.log"
# check to see if log directory structure exists.
if [ ! -d ${HTI_HOME}/logs ] ;then
mkdir -p ${HTI_HOME}/logs
chmod 777 ${HTI_HOME}/logs
chown awips:fxalpha ${HTI_HOME}/logs
fi
if [ ! -d ${HTI_HOME}/logs/${currdate} ] ;then
mkdir -p ${HTI_HOME}/logs/${currdate}
chmod 777 ${HTI_HOME}/logs/${currdate}
chown awips:fxalpha ${HTI_HOME}/logs/${currdate}
fi
# Log file header
echo " " >> $LOG_FILE
echo "####################################################################################" >> $LOG_FILE
echo "# Starting Make_HTI Script.... #" >> $LOG_FILE
echo "####################################################################################" >> $LOG_FILE
chmod 666 $LOG_FILE
# Check to see if ${PRODUCTdir} exists. If not, create.
echo "Making sure that ${PRODUCTdir} exists at $(date)" >> $LOG_FILE
if [ ! -d ${PRODUCTdir} ]; then
echo " **** ${PRODUCTdir} directory not found." >> $LOG_FILE
echo " **** Creating ${PRODUCTdir} directory..." >> $LOG_FILE
mkdir -p $PRODUCTdir
echo " **** Changing permissions of ${PRODUCTdir} directory..." >> $LOG_FILE
chmod 777 $PRODUCTdir
echo " **** Changing ownership of ${PRODUCTdir} directory..." >> $LOG_FILE
chown awips:fxalpha $PRODUCTdir
else
echo " ${PRODUCTdir} exists." >> $LOG_FILE
fi
echo "...finished." >> $LOG_FILE
echo " " >> $LOG_FILE
# THESE SHOULD MATCH THREAT GRIDS IN GFE
PARMS="WindThreat FloodingRainThreat StormSurgeThreat TornadoThreat"
echo "Starting ifpIMAGE loop." >> $LOG_FILE
for PARM in $PARMS
do
# NOTE: cannot run ifpIMAGE on dx3/dx4 - must ssh to a px
echo "Creating ${PARM} image..." >> $LOG_FILE
ssh px1 "unset DISPLAY; ${GFEBINdir}/ifpIMAGE -site ${SITE} -c ${SITE}${PARM} -o ${PRODUCTdir}"
convert ${PRODUCTdir}/${SITE}${PARM}.png -resize 104x148 ${PRODUCTdir}/${SITE}${PARM}_sm.png
done
rm -f ${PRODUCTdir}/*.info
# Generate KML automatically via runProcedure
echo "Running KML procedure." >> $LOG_FILE
#ssh px1 "unset DISPLAY; ${GFEBINdir}/runProcedure -site ${SITE} -n TCImpactGraphics_KML -c gfeConfig"
ssh px1 "unset DISPLAY; ${GFEBINdir}/runProcedure -site ${SITE} -n TCImpactGraphics_KML2015 -c gfeConfig"
# Create legends for KML
${HTI_HOME}/bin/kml_legend.sh
echo "Copying image and kml files to LDAD for WEB processing" >> $LOG_FILE
/usr/bin/ssh -o stricthostkeychecking=no -x ${LDADuser}@${LDADserver} mkdir -p ${LDAD_DATA} &> /dev/null
/usr/bin/rsync -av --force --progress --stats -e "/usr/bin/ssh -o stricthostkeychecking=no -x" ${PRODUCTdir}/*.txt ${PRODUCTdir}/*.png ${LDADuser}@${LDADserver}:/${LDAD_DATA}/.
echo "Done copying image and text files to LDAD" >> $LOG_FILE
# NOTE: The lines below are for SR and ER sites to upload images to the National Website
# NOTE: This can be ran as any AWIPS user so we must SSH as ldad@ls1 and run the commands via an SSH tunnel
echo "Copying graphics to NWSHQ Web farm ${NWSHQ_RSYNCSERVER}" >> $LOG_FILE
CMD="/usr/bin/rsync -av --force --progress --stats ${LDAD_DATA}/*.png ${NWSHQ_RSYNCSERVER}::ghls_images/${site}"
echo "/usr/bin/ssh -o stricthostkeychecking=no -x ${LDADuser}@${LDADserver} ${CMD}" >> $LOG_FILE
/usr/bin/ssh -o stricthostkeychecking=no -x ${LDADuser}@${LDADserver} ${CMD}
echo "Copying KML.TXT files to NWSHQ Web farm ${NWSHQ_RSYNCSERVER}" >> $LOG_FILE
CMD="/usr/bin/rsync -av --force --progress --stats ${LDAD_DATA}/*.txt ${NWSHQ_RSYNCSERVER}::ghls_includes/${siteid}"
echo "/usr/bin/ssh -o stricthostkeychecking=no -x ${LDADuser}@${LDADserver} ${CMD}" >> $LOG_FILE
/usr/bin/ssh -o stricthostkeychecking=no -x ${LDADuser}@${LDADserver} "${CMD}"
echo "Copy to ${NWSHQ_RSYNCSERVER} complete" >> $LOG_FILE
# NOTE: Local processing is site specific and not required.
# NOTE: If you site is doing any local processing you must set local processing to TRUE and make sure
# NOTE: all you local lw processing variables are setup in your /awips2/GFESuite/hti/etc/sitevars.ccc file
# NOTE: If you want local lw processing on for all scripts add the following line to the
# NOTE: /awips2/GFESuite/hti/etc/sitevars.ccc (where ccc is your siteid).
# NOTE: LOCALlw_PROCESSING="TRUE"
if [ "${LOCALlw_PROCESSING}" == "" ]; then LOCALlw_PROCESSING="FALSE"; fi
if [ "${LOCALlw_PROCESSING}" == "TRUE" ]
then
# NOTE: This can be ran as any AWIPS user so we must SSH as ldad@ls1 and run the commands via and SSH tunnel
echo "Copying image and text files to ${LOCALlwserver} Linux system for local WEB processing and archiving" >> $LOG_FILE
CMD="/usr/bin/rsync -av --force --progress --stats -e ssh ${LDAD_DATA}/*.txt ${LDAD_DATA}/*.png ${LOCALlwuser}@${LOCALlwserver}:${LOCAL_LWDATA}/."
echo "/usr/bin/ssh -o stricthostkeychecking=no -x ${LDADuser}@${LDADserver} ${CMD}" >> $LOG_FILE
/usr/bin/ssh -o stricthostkeychecking=no -x ${LDADuser}@${LDADserver} "${CMD}"
echo "Done copying image and text files to ${LOCALlwserver}" >> $LOG_FILE
fi
# Archive *Threat.png and *kml.txt files if desired
if [ "${ARCHIVE}" == "YES" ]
then
echo "Begin archiving process..." >> $LOG_FILE
echo "Making sure ${PRODUCTdir}/archive exists at $(date)" >> $LOG_FILE
if [ ! -d ${PRODUCTdir}/archive ]; then
echo " ${PRODUCTdir}/archive directory not found!" >> $LOG_FILE
echo " Creating archive directory..." >> $LOG_FILE
mkdir -p ${PRODUCTdir}/archive
echo " Changing permissions on ${PRODUCTdir}/archive..." >> $LOG_FILE
chmod 777 ${PRODUCTdir}/archive
echo " Changing ownership on ${PRODUCTdir}/archive..." >> $LOG_FILE
chown awips:fxalpha ${PRODUCTdir}/archive
else
echo " ${PRODUCTdir}/archive directory exists!" >> $LOG_FILE
fi
DATESTAMP=`date +%Y%m%d_%H%M`
if [ ! -d ${PRODUCTdir}/archive/${DATESTAMP} ]; then mkdir -p ${PRODUCTdir}/archive/${DATESTAMP} ; fi
ARCHFILES=`cd ${PRODUCTdir}; ls *Threat.png *kml.txt`
echo "Copying files to ${PRODUCTdir}/archive/${DATESTAMP} " >> $LOG_FILE
for ARCHFILE in $ARCHFILES
do
cp ${PRODUCTdir}/${ARCHFILE} ${PRODUCTdir}/archive/${DATESTAMP}/
done
echo "Archiving complete!" >> $LOG_FILE
else
echo "**** NO HTI PRODUCTS ARCHIVED! If you wish to archive HTI products, check " >> $LOG_FILE
echo "**** ${HTI_HOME}/etc/sitevars.${site}" >> $LOG_FILE
fi
echo "Script complete at $(date)" >> ${LOGfile}
echo " " >> ${LOGfile}
exit 0
########################################################################

View file

@ -0,0 +1,34 @@
# Configuration file for make_hti.sh & kml_legend.sh
GFESUITE_HOME="/awips2/GFESuite" # Where is GFESuite?
GFEBINdir="${GFESUITE_HOME}/bin" # Where is GFESuite/bin?
HTI_HOME="${GFESUITE_HOME}/hti" # Where the hti stuff lives
PRODUCTdir="${HTI_HOME}/data" # Where the hti output/data will go
ARCHIVE="YES" # YES, graphics/kml will be archived with
# each run, NO otherwise.
# LDAD setup
LDADserver="ls1-${site}" # Name of local rsync server
LDADuser="ldad" # User on local rsync server
LDAD_DATA="/data/ldad/hti" # Directory where output is stored on
# local rsync server
# CONSOLIDATED WEB FARM setup
NWSHQ_RSYNCSERVER="sync.weather.gov" # Name of remote rsync server
# OPTIONAL: Local office processing
# The setup below is for site that do processing on local office Linux
# workstations using Doug Gaer's webapps package. (NOTE: the webapps
# package is not supported by NCF or AWIPS.)
# If you wish to use this, set LOCALlw_PROCESSING to TRUE,
# then configure the following variables as appropriate
LOCALlw_PROCESSING="FALSE" # Set to TRUE to enable local processing
LOCALlwserver="machine.xxx.noaa.gov" # Name of local workstation where webapps
# is installed
LOCALlwuser="username" # User on local workstation where webapps
# is installed
LOCAL_LWDATA="/data/webapps" # Directory where output is stored on
# local workstation above