awips2/cave/com.raytheon.viz.gfe/localization/gfe/userPython/procedures/Align_Grids.py
2022-05-05 12:34:50 -05:00

258 lines
11 KiB
Python

##
# 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
# 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
#
# See the AWIPS II Master Rights File ("Master Rights File.pdf") for
# further licensing information.
##
# ----------------------------------------------------------------------------
# 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.
#
# Align_Grids
#
# Author: Paul Jendrowski
# Version: 1.0 - 11/08/2004
#
# Description:
# This procedure will align the time ranges of selected
# weather elements with the time range of another element.
# For instance, this will redo the PoP grid to match
# the timeranges of individual Wx grids. Note that WindGust
# is always forced to match the Wind grid.
#
# If a grid does not exist, then it will be created from scratch.
# If the grid to align does exist, the max value of all original
# grids that are within the time range of the source grid is
# used for PoP, Sky, WindGust. Rate based parameters
# (QPF, SnowAmt, etc.) are fragmented then summed.
#
# You can add whatever elements you wish to VariableList. However,
# you must add an appropriate entry in the __init__ method
# to defing if the variable needs to be fragmented (i.e., rate
# based parameters like QPF must be fragmented to sum correctly),
# split (generally all non-rate based should be split before
# being recombined into the aligned grids). _methdodDict
# defines how to recompute the value for the aligned grid from
# the original grid. This value is any value that can be used
# as the mode argument to SmartScript.getGrids method. In addition,
# you can also use "Last" to get the last grid or "MaxTime" which
# will select the grid that has the highest percentage time in the
# period (if a tie for highest percentage, the first is used).
# method is generally for Wx/discrete grids that cannot be
# averaged or summed. Finally, the execute method needs to be
# edited to define time ranges to use for each new element.
#
# Installation:
# Install this file as a Procedure. This procedure also requires
# getGridsTool and MakeTmpGrid SmartTools to be installed.
# ----------------------------------------------------------------------------
##
# This is an absolute override file, indicating that a higher priority version
# of the file will completely replace a lower priority version of the file.
##
# The MenuItems list defines the GFE menu item(s) under which the
# Procedure is to appear.
# Possible items are: Populate, Edit, Consistency, Verify
MenuItems = ["Edit"]
Supported_elements=["Wx", "PoP", "Sky", "QPF","SnowAmt","IceAccum","Wind","WindGust"]
VariableList = [
("Select Time Range:","All", "radio",
["Selected Time", "All"]),
("Source Grid:" , "Wx", "radio",["Wx", "PoP", "QPF"]),
("Aligned Grids:" , [], "check",Supported_elements),
]
import SmartScript
import TimeRange
import time
class Procedure (SmartScript.SmartScript):
def __init__(self, dbss):
SmartScript.SmartScript.__init__(self, dbss)
# These are the elements that need to be split before rederiving the
# values in the newly aligned grids.
self._splitElements = ["Wx", "PoP", "Sky","Wind", "WindGust"]
# These are the elements that need to be fragmented before
# rederiving the values in the newly aligned grids.
self._fragmentElements = ["QPF", "SnowAmt","IceAccum"]
# Method to use the populate values in the aligned grid from the
# original values.
#**** There must be a key for every element in the "Aligned Grids:"
#**** VariableList entry!!!
# This value is any value except "List" that can be used
# as the mode argument to SmartScript.getGrids method. In addition,
# you can also use "Last" to get the last grid or "MaxTime" which
# will select the grid that has the highest percentage time in the
# period (if a tie for highest percentage, the first is used).
# method is generally for Wx/discrete grids that cannot be
# averaged or summed.
self._methodDict = {
"Wx" : "MaxTime",
"PoP" : "Max",
"Sky" : "Max",
"WindGust" : "Max",
"Wind" : "TimeWtAverage",
"QPF" : "Sum",
"SnowAmt" : "Sum",
"IceAccum" : "Sum",
}
def execute(self, timeRange, varDict):
# First make a list of grids to make from the selection
# Get time range from varDict
period = varDict["Select Time Range:"]
srcGrid = varDict["Source Grid:"]
gridsToMake = []
doWindGust = 0
for elem in varDict["Aligned Grids:"]:
if elem == "WindGust":
doWindGust = 1
elif elem != srcGrid:
gridsToMake.append(elem)
# Get current Greenwich Mean Time (GMT)
GMT = time.gmtime(time.time())
# Get current hour from GMT
gmthour = GMT[3]
#print "GMT hour=", gmthour
# Create the timeranges over which to create the grids from scratch
# (timerange varies by element and initial period)
timeRangeDict = {}
srcTR = self._getGridTimeRange("Fcst", srcGrid, "SFC", timeRange)
#print "str=",timeRange, "SrcTR=",srcTR
#*** If and element is added to VariableList, you must set up the timeRangeDict
#*** for that element in the following if-else block
if period == "Selected Time":
# Set time range of grids that are actually there
for elem in Supported_elements:
timeRangeDict[elem] = srcTR
timeRangeDict["WindGust"] = self._getGridTimeRange("Fcst", "Wind", "SFC", timeRange)
# print "Selected tr=",timeRange
else:
#
# Here is where you can adjust the ending times of the preset time ranges used by the
# "All" option. To change these, simply modify the ending time of the following calls
# to createTimeRange to meet your local needs.
#
# First set a reasonable time range then determine which grids are
# actually there. The start time is the current hour in GMT time.
# Set up elements for full time range
tr = self.createTimeRange(gmthour, 192, "Zulu")
#for elem in ["Wx", "PoP", "Sky", "QPF","SnowAmt","IceAccum","Wind","WindGust"]:
for elem in Supported_elements:
timeRangeDict[elem] = self._getGridTimeRange("Fcst", srcGrid, "SFC", tr)
# Override the default time ranges explicitly for selected elements
tr = self.createTimeRange(gmthour, 60, "Zulu")
timeRangeDict["SnowAmt"] = self._getGridTimeRange("Fcst", srcGrid, "SFC", tr)
tr = self.createTimeRange(gmthour, 60, "Zulu")
timeRangeDict["IceAccum"] = self._getGridTimeRange("Fcst", srcGrid, "SFC", tr)
tr = self.createTimeRange(gmthour, 96, "Zulu")
timeRangeDict["QPF"] = self._getGridTimeRange("Fcst", srcGrid, "SFC", tr)
tr = self.createTimeRange(gmthour, 96, "Zulu")
timeRangeDict["Wind"] = self._getGridTimeRange("Fcst", srcGrid, "SFC", tr)
tr = self.createTimeRange(gmthour, 96, "Zulu")
timeRangeDict["WindGust"] = self._getGridTimeRange("Fcst", "Wind", "SFC", tr)
# Create temporary grid of each element to be aligned then remake
# the grid from scratch with the time range from the source grid
for elem in gridsToMake:
#print "_alignGrid",elem,srcGrid,timeRangeDict[elem]
self._alignGrid(elem,srcGrid,timeRangeDict[elem])
if doWindGust:
elem = "WindGust"
#print "_alignGrid",elem,srcGrid,timeRangeDict[elem]
self._alignGrid(elem,"Wind",timeRangeDict[elem])
def _alignGrid(self,elem,srcGrid,timeRange):
tmpName = "tmp" + elem
varDict = {}
varDict["Model"] = "Fcst"
varDict["gridName"] = tmpName
madeTmp=0
# First check if any old grids exist
elemGridInfo = self.getGridInfo("Fcst", elem, "SFC", timeRange)
#print elem, len(elemGridInfo)
if len(elemGridInfo) > 0:
madeTmp = 1
self.callSmartTool("MakeTmpGrid", elem, varDict=varDict,
timeRange=timeRange)
srcGridInfo = self.getGridInfo("Fcst", srcGrid, "SFC", timeRange)
# Step through each of the source grids and create a scratch
# grid with the same time range as the source grid.
for info in srcGridInfo:
#print info.gridTime()
self.createFromScratchCmd([elem], info.gridTime(), 0, 0)
# Check if the temporary version of the element needs
# to be split. The temporary grid will be used to recompute
# the values in the scratch grids
if madeTmp and elem in self._splitElements:
if len(self.getGridInfo("Fcst", tmpName, "SFC", info.gridTime())) > 0:
self.splitCmd([tmpName], info.gridTime())
if madeTmp > 0:
varDict["Element"] = tmpName
if elem in self._fragmentElements:
self.fragmentCmd([tmpName], timeRange)
if elem in self._methodDict:
varDict["Mode"] = self._methodDict[elem]
self.callSmartTool("getGridsTool", elem, varDict=varDict,
timeRange=timeRange)
# Delete the temp grids
#try:
# self.deleteObject(tmpName, "FcstGrid")
#except:
# pass
try:
self.unloadWE("Fcst", tmpName, "SFC")
except:
pass
def _getGridTimeRange(self, model,parm,level,timeRange):
# Returns a timeRange covering any grids that intersect input timeRange
# Returns a timeRange with duration less than 3600 if no grids found
info = self.getGridInfo(model, parm, level, timeRange)
if info != []:
st = info[0].gridTime().startTime()
et = info[len(info) - 1].gridTime().endTime()
tr = TimeRange.TimeRange(st,et)
else:
tr = TimeRange.TimeRange(timeRange.startTime(),timeRange.startTime() + 1)
return tr
## Error Handling
## Call self.abort(errorString) to stop execution of your script and
## display a message to the user.
## For example:
## if x > 1000:
## self.abort("x is too large")
##