Former-commit-id:63dddc5f5f
[formerlye845c605e6
] [formerly0ba69044a2
[formerly 9dd41e6322bad3e7dced1a32867d9a7f886d70cf]] Former-commit-id:0ba69044a2
Former-commit-id:cc21977c35
389 lines
14 KiB
Python
389 lines
14 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.
|
|
##
|
|
|
|
import os, string, copy
|
|
import tempfile, stat
|
|
import LogStream, pprint
|
|
|
|
from fips2cities import *
|
|
from zones2cities import *
|
|
|
|
#
|
|
# Creates area dictionary specific to a site. Somewhat ported from AWIPS-I.
|
|
#
|
|
#
|
|
# SOFTWARE HISTORY
|
|
#
|
|
# Date Ticket# Engineer Description
|
|
# ------------ ---------- ----------- --------------------------
|
|
# 01/08/10 #1209 randerso Initial Creation.
|
|
# 10/19/12 #1091 dgilling Support localMaps.py.
|
|
#
|
|
#
|
|
#
|
|
|
|
CityLocationDict = {}
|
|
|
|
# obtain real time zone string from shapefile TIME_ZONE variable
|
|
def getRealTimeZone(tzstring):
|
|
d = {'M':"MST7MDT",'m':"MST7",'V':'America/Puerto_Rico',
|
|
'E':"EST5EDT",'e':"EST5",
|
|
'C':"CST6CDT",'P':"PST8PDT",'A':"America/Anchorage",
|
|
'H':"Pacific/Honolulu",'G':"Pacific/Guam",
|
|
'J':"Pacific/Palu", 'K': "Pacific/Wake", 'F': "Pacific/Ponape"}
|
|
tzones = []
|
|
for tz in tzstring:
|
|
if d.has_key(tz):
|
|
tzones.append(d[tz])
|
|
|
|
if len(tzones) > 1:
|
|
return tzones
|
|
elif len(tzones) == 1:
|
|
return tzones[0]
|
|
else:
|
|
LogStream.logProblem("No time zone information decodable: ", tzstring)
|
|
return None
|
|
|
|
# sorts the cities by decending population
|
|
def citysort(c1, c2):
|
|
if c1[1] is None and c2[1] is None:
|
|
return 0
|
|
elif c1[1] is None:
|
|
return 1
|
|
elif c2[1] is None:
|
|
return -1
|
|
elif c1[1] < c2[1]:
|
|
return 1
|
|
elif c1[1] > c2[1]:
|
|
return -1
|
|
else:
|
|
return 0
|
|
|
|
# Creates the city string part of the area dictionary, based on population
|
|
def makeCityString(dictRecord):
|
|
if dictRecord.has_key("cities"):
|
|
cities = copy.deepcopy(dictRecord["cities"])
|
|
if len(cities) == 0:
|
|
return None
|
|
cities.sort(citysort)
|
|
locs = {}
|
|
s = ""
|
|
count = 0
|
|
maxPop = cities[0][1] #population of largest city
|
|
for x in xrange(len(cities)):
|
|
|
|
#limit small cities to 25% of the large city population
|
|
if maxPop is not None and cities[x][1] is not None and \
|
|
cities[x][1] * 4 < maxPop:
|
|
break
|
|
elif maxPop is not None and cities[x][1] is None:
|
|
break
|
|
|
|
s = s + "..." + cities[x][0]
|
|
|
|
# save data to cifyLocation dictionary
|
|
locs[cities[x][0]] = tuple(map(float, cities[x][2:4]))
|
|
|
|
#max of 6 cities in the list
|
|
count = count + 1
|
|
if count > 6:
|
|
break
|
|
|
|
return s, locs
|
|
|
|
# handle marine states
|
|
def checkMarineState(ugcCode):
|
|
#returns None if unknown, description if known
|
|
areas = {'AM': 'ATLANTIC COASTAL WATERS', 'GM': 'GULF OF MEXICO',
|
|
'LE': 'LAKE ERIE', 'LO': 'LAKE ONTARIO', 'LH': 'LAKE HURON',
|
|
'SC': 'LAKE ST CLAIR', 'LM': 'LAKE MICHIGAN', 'LS': 'LAKE SUPERIOR',
|
|
'PZ': 'PACIFIC COASTAL WATERS', 'PK': 'ALASKAN COASTAL WATERS',
|
|
'PH': 'HAWAIIAN COASTAL WATERS', 'PM': 'MARIANAS WATERS',
|
|
'AN': 'ATLANTIC COASTAL WATERS', 'PS': 'AMERICAN SAMOA COASTAL WATERS',
|
|
'SL': 'ST LAWRENCE RIVER'}
|
|
area = ugcCode[0:2]
|
|
return areas.get(area, None)
|
|
|
|
|
|
# Utility to create the area dictionary, based on the map background data
|
|
def createAreaDictionary(outputDir, mapDict):
|
|
LogStream.logEvent("Generating AreaDictionary")
|
|
areadict = {}
|
|
mapIter = mapDict.entrySet().iterator()
|
|
while mapIter.hasNext():
|
|
entry = mapIter.next()
|
|
ean = str(entry.getKey())
|
|
att = entry.getValue()
|
|
if len(ean):
|
|
try:
|
|
d = {}
|
|
if att.containsKey('zone') and att.containsKey('state'):
|
|
d['ugcCode'] = str(att.get('state')) + "Z" + str(att.get('zone'))
|
|
elif att.containsKey('id'):
|
|
d['ugcCode'] = str(att.get('id'))
|
|
elif att.containsKey('fips') and att.containsKey('state') and \
|
|
att.containsKey('countyname'):
|
|
d['ugcCode'] = str(att.get('state')) + "C" + str(att.get('fips'))[-3:]
|
|
d['ugcName'] = string.strip(str(att.get('countyname')))
|
|
else:
|
|
continue
|
|
|
|
if att.containsKey('state'):
|
|
d["stateAbbr"] = str(att.get('state'))
|
|
|
|
if att.containsKey('name'):
|
|
d["ugcName"] = string.strip(str(att.get('name')))
|
|
|
|
if att.containsKey('time_zone'):
|
|
tzvalue = getRealTimeZone(str(att.get('time_zone')))
|
|
if tzvalue is not None:
|
|
d["ugcTimeZone"] = tzvalue
|
|
|
|
if zonedata.has_key(d['ugcCode']):
|
|
cityDict = zonedata[d['ugcCode']]
|
|
elif fipsdata.has_key(d['ugcCode']):
|
|
cityDict = fipsdata[d['ugcCode']]
|
|
else:
|
|
cityDict = None
|
|
|
|
if cityDict:
|
|
cityString = makeCityString(cityDict)
|
|
if cityString is not None:
|
|
cityString, locs = cityString
|
|
if len(cityString):
|
|
d["ugcCityString"] = cityString
|
|
CityLocationDict[ean] = locs
|
|
|
|
# partOfState codes
|
|
if zonedata.has_key(d['ugcCode']):
|
|
if zonedata[d['ugcCode']].has_key('partOfState'):
|
|
d["partOfState"] = \
|
|
zonedata[d['ugcCode']]['partOfState']
|
|
elif fipsdata.has_key(d['ugcCode']):
|
|
if fipsdata[d['ugcCode']].has_key('partOfState'):
|
|
d["partOfState"] = \
|
|
fipsdata[d['ugcCode']]['partOfState']
|
|
|
|
# full state name
|
|
if zonedata.has_key(d['ugcCode']):
|
|
if zonedata[d['ugcCode']].has_key('fullStateName'):
|
|
d["fullStateName"] = \
|
|
zonedata[d['ugcCode']]['fullStateName']
|
|
elif fipsdata.has_key(d['ugcCode']):
|
|
if fipsdata[d['ugcCode']].has_key('fullStateName'):
|
|
d["fullStateName"] = \
|
|
fipsdata[d['ugcCode']]['fullStateName']
|
|
else:
|
|
marineState = checkMarineState(d['ugcCode'])
|
|
if marineState is not None:
|
|
d['fullStateName'] = marineState
|
|
|
|
|
|
if areadict.has_key(ean) and d != areadict[ean]:
|
|
LogStream.logDiag("Mismatch of definitions in " +\
|
|
"AreaDictionary creation. EditAreaName=", ean,
|
|
"AreaDict=\n", areadict[ean], "\nIgnored=\n", d)
|
|
else:
|
|
areadict[ean] = d
|
|
except:
|
|
LogStream.logProblem("Problem with ", ean, LogStream.exc())
|
|
|
|
s = """
|
|
# ----------------------------------------------------------------------------
|
|
# 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.
|
|
#
|
|
# AreaDictionary
|
|
# AreaDictionary file
|
|
#
|
|
# Author: GFE Installation Script
|
|
# ----------------------------------------------------------------------------
|
|
|
|
# Format:
|
|
# AreaDictionary = {
|
|
# "editArea" : {
|
|
# "ugcCode": "STZxxx",
|
|
# "ugcName": "EditAreaName",
|
|
# "ugcCityString": "...CITY1...CITY2",
|
|
# "ugcTimeZone": "MST7MDT",
|
|
# "fullStateName": "COLORADO",
|
|
# "partOfState": "NORTHEAST",
|
|
# "stateAbbr": "CO",
|
|
# "independentCity": 0,
|
|
# "locationName": "GeneralAreaName",
|
|
# }
|
|
# ...
|
|
# }
|
|
# ugcTimeZone: This field should be replace with the correct time zone
|
|
# for that zone. If it is different from the time zone of
|
|
# the local WFO, it's time zone will appear in the header of
|
|
# some products in parentheses.
|
|
# Using any other strings to define
|
|
# the time zone may produce undesirable results.
|
|
# The time zone may also be a list of time zones in case
|
|
# a forecast zone happens to cover an area that contains
|
|
# two time zones.
|
|
# e.g. "ugcTimeZone" : ["MST7MDT", "PST8PDT"]
|
|
#
|
|
# ugcCode: This field contains the ugc coding for this area, such as COZ023
|
|
#
|
|
# ugcName: This field contains the descriptive name for this area. It
|
|
# is used in various products, including Hazard products. This is
|
|
# the official county or zone name.
|
|
#
|
|
# locationName: This field is optional, but provides an alternate name that
|
|
# is used in the text of some products to describe the area. The
|
|
# FFA product uses this value if available.
|
|
#
|
|
# ugcCityString: This field contains the list of cities as a string for
|
|
# hazard and routine products.
|
|
#
|
|
# fullStateName: This field is used in hazard products to fully describe
|
|
# the state in which this edit area resides.
|
|
#
|
|
# partOfState: This field describes the location within a state (such as
|
|
# NORTHEAST) for this area. It is used in hazard products.
|
|
#
|
|
# stateAbbr: State Abbreviation for the fullStateName.
|
|
#
|
|
# independentCity: Set to 0 or 1. Some counties (FIPS coding) are actually
|
|
# cities. Setting the flag to 1 will instruct those formatters
|
|
# to mention independent cities, rather than include this "county"
|
|
# in the county list of the product.
|
|
|
|
#
|
|
|
|
|
|
AreaDictionary = \
|
|
"""
|
|
pp = pprint.PrettyPrinter()
|
|
s = s + pp.pformat(areadict)
|
|
|
|
if not os.path.isdir(outputDir):
|
|
os.makedirs(outputDir)
|
|
|
|
outName = os.path.join(outputDir, "AreaDictionary.py")
|
|
|
|
fh = None
|
|
try:
|
|
fh, fpath = tempfile.mkstemp(dir=outputDir, suffix=".py")
|
|
os.write(fh, s)
|
|
os.chmod(fpath, stat.S_IRUSR | stat.S_IWUSR |
|
|
stat.S_IRGRP | stat.S_IWGRP |
|
|
stat.S_IROTH)
|
|
os.close(fh)
|
|
fh = None
|
|
os.rename(fpath, outName)
|
|
except:
|
|
LogStream.logProblem("Error writing area dictionary", LogStream.exc())
|
|
finally:
|
|
if fh is not None:
|
|
os.close(fh)
|
|
|
|
|
|
# Utility to create the city location dictionary
|
|
def createCityLocation(outputDir, mapDict):
|
|
LogStream.logEvent("Generating CityLocation")
|
|
|
|
citydict = CityLocationDict
|
|
|
|
if dict != type(mapDict):
|
|
import JUtil
|
|
mapDict = JUtil.javaObjToPyVal(mapDict)
|
|
|
|
for mapname in mapDict.keys():
|
|
if mapname.find("Cities") == -1:
|
|
continue
|
|
|
|
attList = mapDict[mapname]
|
|
for att in attList:
|
|
#LogStream.logProblem("att:", att)
|
|
ean = att['name']
|
|
state = att['st']
|
|
county_FIP = att['county_fip']
|
|
|
|
if len(ean) and len(state) and len(county_FIP):
|
|
fip = state + 'C' + county_FIP
|
|
if not citydict.has_key(fip):
|
|
citydict[fip] = {}
|
|
try:
|
|
latitude = float(string.strip(att['lat']))
|
|
longitude = float(string.strip(att['lon']))
|
|
citydict[fip][ean.upper()] = (latitude, longitude)
|
|
except:
|
|
LogStream.logProblem("Problem creating city location ",
|
|
ean, att, LogStream.exc())
|
|
|
|
s = """
|
|
# ----------------------------------------------------------------------------
|
|
# 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.
|
|
#
|
|
# CityLocation
|
|
# CityLocation file
|
|
#
|
|
# Author: GFE Installation Script
|
|
# ----------------------------------------------------------------------------
|
|
|
|
# Format:
|
|
# CityLocation = {
|
|
# "editArea": {"cityName1" : (latitude, longitude),
|
|
# "cityName2" : (latitude, longitude),
|
|
# ...
|
|
# }
|
|
# ...
|
|
# }
|
|
#
|
|
# editArea: name of edit area as in AreaDictionary
|
|
#
|
|
# cityName: name of the city - should be the same as in AreaDictionary.
|
|
#
|
|
# latitude/longitude: city's lat/lon location.
|
|
#
|
|
|
|
|
|
CityLocation = \
|
|
"""
|
|
pp = pprint.PrettyPrinter()
|
|
s = s + pp.pformat(citydict)
|
|
|
|
if not os.path.isdir(outputDir):
|
|
os.makedirs(outputDir)
|
|
|
|
outName = os.path.join(outputDir, "CityLocation.py")
|
|
|
|
fh = None
|
|
try:
|
|
fh, fpath = tempfile.mkstemp(dir=outputDir, suffix=".py")
|
|
os.write(fh, s)
|
|
os.chmod(fpath, stat.S_IRUSR | stat.S_IWUSR |
|
|
stat.S_IRGRP | stat.S_IWGRP |
|
|
stat.S_IROTH)
|
|
os.close(fh)
|
|
fh = None
|
|
os.rename(fpath, outName)
|
|
except:
|
|
LogStream.logProblem("Error writing city location", LogStream.exc())
|
|
finally:
|
|
if fh is not None:
|
|
os.close(fh)
|
|
|