awips2/edexOsgi/com.raytheon.edex.uengine/utility/edex_static/base/python/AtcfTrackRequest.py
2018-06-20 17:39:08 -06:00

301 lines
No EOL
12 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 is a base file that is not intended to be overridden.
##
##
# uengine is deprecated and will be removed from the system soon. Migrate your
# apps to using the Data Access Framework (DAF).
##
#
# AtcfTrackRequest
#
# This code has been developed by the SIB for use in the AWIPS2 system.
# Request of ATCF track data.
#
# Usage:
#
#
# SOFTWARE HISTORY
#
# Date Ticket# Engineer Description
# ------------ ---------- ----------- --------------------------
# 09/07/10 284 mgamazaychikov Initial Creation
# 10/10/28 307 mgamazaychikov Updated to handle time-matching
import BaseRequest
from java.util import ArrayList
from com.raytheon.uf.common.message.response import ResponseMessageGeneric
from gov.noaa.nws.ncep.edex.uengine.utility import GempakConvert
class AtcfTrackRequest(BaseRequest.BaseRequest):
def __init__(self):
BaseRequest.BaseRequest.__init__(self, "atcf")
self.isTechniqueSet = False
self.time = None
self.StartTime = None
self.EndTime = None
self.isTimeList= False
self.AllTimesList = []
self.TimesList = []
self.Convert = GempakConvert()
def setTime(self, aTime=None):
self.time = aTime
def setStartTime(self, aTime=None):
if aTime :
self.StartTime = aTime
else:
# set StartTime to the First Available Time
self.StartTime = self.__getFirstTime()
def setEndTime(self, aTime=None):
if aTime :
self.EndTime = aTime
else:
# set StartTime to the Last Available Time
self.EndTime = self.__getLastTime()
def setTechnique(self, aTechnique):
self.technique = aTechnique
self.isTechniqueSet = True
def execute(self):
if self.time:
self.query.addParameter("dataTime", self.time)
else:
if not self.StartTime:
self.StartTime = self.__getFirstTime()
if not self.EndTime:
self.EndTime = self.__getLastTime()
if self.StartTime and self.EndTime:
self.timeRange = self.StartTime + "--" + self.EndTime
self.query.addParameter("dataTime", self.timeRange, "between")
else:
return self.__makeNullResponse("Could not set the time range")
# get the results from the database
self.queryResults = self.query.execute()
if self.queryResults is None or self.queryResults.size() == 0:
return self.__makeNullResponse()
else:
# process the results
return self.__makeResponse()
def __getFirstTime(self):
# check if the list of available times has been calculated
if self.isTimeList:
return self.Convert.dattimToDbtime(self.AllTimesList[0])
else:
# get the list of times and return the earliest available time
self.__getTimeList()
return self.Convert.dattimToDbtime(self.AllTimesList[0])
def __getLastTime(self):
# check if the list of available times has been calculated
if self.isTimeList:
return self.Convert.dattimToDbtime(self.AllTimesList[len(self.AllTimesList) -1])
else:
# get the list of times and return the last available time
self.__getTimeList()
return self.Convert.dattimToDbtime(self.AllTimesList[len(self.AllTimesList) -1])
def __getTimePlus(self, aTime, aPlus="168"):
return self.Convert.addHours(aTime, aPlus)
# def __createTimes(self):
# if self.time:
# self.TimesList.append(self.time)
# else:
# startIndex = self.AllTimesList.index(self.StartTime)
# endIndex = self.AllTimesList.index(self.EndTime)
# self.TimesList = self.AllTimesList[startIndex:endIndex]
def __getTimeList(self):
import GempakCatalogTimeQuery
tq = GempakCatalogTimeQuery.GempakCatalogTimeQuery("atcf")
tq.setReturnText()
self.AllTimesList = tq.execute().split("|")
self.isTimeList =True
def __getDictionaries(self):
import GempakSqlQuery
# list of time cyclone ID tuples:
# eg [('2010-08-28 06:00:00.0', 'EP9'), ('2010-08-28 12:00:00.0', 'EP8')]
timeIdTupleList = []
# timeIdTqDict - is the key-value dictionary of time-Id tuple Technique List dictionary
# each time has a corresponding dictionary of ID-Technique
# eg: {('2010-08-28 06:00:00.0','AL8'):['AEMI', 'AEMN', 'AP01', 'AP02'], ('2010-08-28 12:00:00.0','AL9'):['AP11', 'AP14', 'AP18']}
timeIdTqDict = {}
# idNumberDict - is the key-value dictionary of cycloneID-basin, cycloneNumb tuple pairs
# each cycloneId has a corresponding basin-cycloneNumb tuple
# eg: {'AL8': ('AL', '8'), 'AL9': ('AL', '9')}
idNumberDict = {}
for ii in range(self.queryResults.size()):
currentRecord = self.queryResults.get(ii)
# get the time
recordTime = str(currentRecord.getDataTime())
# get basin
basin = str(currentRecord.getBasin())
# get cyclone number
cycloneNumb = str(currentRecord.getCycloneNum())
# construct cyclone ID
# eg EP9
cycloneId = basin + cycloneNumb
# construct time - cyclone ID tuple
# eg ('2010-08-21 06:00:00.0', 'EP9')
timeIdTuple = (recordTime, cycloneId)
# check time - cyclone ID tuple old or new
if timeIdTuple in timeIdTupleList:
# existing time - cyclone ID tuple - do not add to list
pass
else:
timeIdTupleList.append(timeIdTuple)
# add the basin,cycloneNumb tuple as value to the idNumberDict dictionary
# for the key cycloneId, if has not been added already
if (basin, cycloneNumb) in idNumberDict.values():
pass
else:
idNumberDict[cycloneId] = (basin, cycloneNumb)
techniqueList = []
# check if the request is for a single technique
if self.isTechniqueSet:
techniqueList.append(self.technique)
else:
# perform the db query for the records with that cyclone ID
techniqueQuery = GempakSqlQuery.GempakSqlQuery()
# set the return type to text(string)
# not a ResponseMessageGEneric object
techniqueQuery.setReturnText()
# set the separator
techniqueQuery.setSeparator("|")
# set the query text
techniqueQueryText = "SELECT DISTINCT technique FROM atcf WHERE " + \
"basin ='" + idNumberDict[cycloneId][0] + "' AND " + \
"cyclonenum ='" + idNumberDict[cycloneId][1] + "' AND " + \
"reftime='" + recordTime + "'"
techniqueQuery.setQuery(techniqueQueryText)
# execute the query
techniqueQueryResults = techniqueQuery.execute()
# create a list of techniques
techniqueList = techniqueQueryResults.split("|")
# add technique as value to the to the time,cyclone ID - technique dictionary
timeIdTqDict[timeIdTuple] = techniqueList
return idNumberDict, timeIdTqDict
def __makeResponse(self):
from gov.noaa.nws.ncep.edex.uengine.tasks.atcf import AtcfCyclone, AtcfTrack
response = ArrayList()
idNumberDict, timeIdTqDict = self.__getDictionaries()
# traverse the time,cyclone ID - technique dictionary to obtain AtcfRecords and
# construct AtcfCyclone objects
for key, value in timeIdTqDict.items():
currentTime = key[0]
cycId = key[1]
techList = value
aBasin = idNumberDict[cycId][0]
aCycloneNumb = idNumberDict[cycId][1]
# create new AtcfCyclone object
aCyclone = AtcfCyclone(cycId)
for techniqueName in techList:
bsResults = None
# CARQ case
if techniqueName == "CARQ":
# first we need to create track for the past
BaseRequest.BaseRequest.__init__(self, "atcf")
self.query.addParameter("dataTime", currentTime)
self.query.addParameter("basin",aBasin)
self.query.addParameter("cycloneNum",aCycloneNumb)
self.query.addParameter("technique",techniqueName)
self.query.addParameter("radWind", "34")
self.query.addParameter("fcstHour","0", "<")
order = True
self.query.setSortBy("fcstHour", order)
bsResultsPast = self.query.execute()
bsResults = bsResultsPast
# second we need to create track for the future
BaseRequest.BaseRequest.__init__(self, "atcf")
timeRange = currentTime + "--" + self.__getTimePlus(currentTime)
self.query.addParameter("dataTime", timeRange, "between")
self.query.addParameter("basin",aBasin)
self.query.addParameter("cycloneNum",aCycloneNumb)
self.query.addParameter("technique",techniqueName)
self.query.addParameter("radWind", "34")
self.query.addParameter("fcstHour","0")
order = True
self.query.setSortBy("dataTime", order)
bsResultsFuture = self.query.execute()
count = 0
for ii in range(bsResultsFuture.size()):
recordToChange = bsResultsFuture.get(ii)
recordToChange.setFcstHour(ii*6)
bsResults.add(recordToChange)
# non-CARQ case
else:
BaseRequest.BaseRequest.__init__(self, "atcf")
self.query.addParameter("dataTime", currentTime)
self.query.addParameter("basin",aBasin)
self.query.addParameter("cycloneNum",aCycloneNumb)
self.query.addParameter("technique",techniqueName)
order = True
self.query.setSortBy("fcstHour", order)
bsResults = self.query.execute()
if bsResults is None or bsResults.size() == 0:
pass
else:
# create new AtcfTrack object
aTrack = AtcfTrack(techniqueName, bsResults)
# add AtcfTrack object to AtcfCyclone
aCyclone.addTrack(aTrack)
# add AtcfCyclone object to the response ArrayList
response.add(ResponseMessageGeneric(aCyclone))
return response
#
# Returns a string with a response message
#
def __makeNullResponse(self, aMessage="Database Query returned no results"):
return ResponseMessageGeneric(aMessage)