Former-commit-id:a02aeb236c
[formerly9f19e3f712
] [formerlya02aeb236c
[formerly9f19e3f712
] [formerly06a8b51d6d
[formerly 64fa9254b946eae7e61bbc3f513b7c3696c4f54f]]] Former-commit-id:06a8b51d6d
Former-commit-id:8e80217e59
[formerly3360eb6c5f
] Former-commit-id:377dcd10b9
221 lines
No EOL
7.1 KiB
Python
221 lines
No EOL
7.1 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.
|
|
##
|
|
|
|
from numpy import arctan2
|
|
from numpy import hypot
|
|
from numpy import cos
|
|
from numpy import sin
|
|
from numpy import degrees
|
|
from numpy import radians
|
|
from numpy import abs
|
|
from numpy import isscalar, empty, float32
|
|
|
|
def execute(u, v, legacyOption=None):
|
|
""" Make a vector from u,v or mag, dir.
|
|
|
|
@param legacyOption
|
|
controls how the function operates on the given u and v values.
|
|
When the legacyOption is specified and is a constant scalar value
|
|
the u and v input values are assumed to be speed and direction.
|
|
|
|
positive :: assume meteorological direction
|
|
negative :: assume mathematical direction
|
|
|
|
abs(legacyOption) == 1 :: assume degrees
|
|
abs(legacyOption) != 1 :: assume radians
|
|
|
|
abs(legacyOption) == 1 || 2 :: assume first two args are speed and
|
|
direction
|
|
|
|
Otherwise if the legacy option is not a constant, the first two
|
|
inputs are components that determine the direction, and the third
|
|
is the speed to use.
|
|
@return: tuple of (magnitude,direction,u,v)
|
|
|
|
"""
|
|
# If either u or v is a single number, expand it to match an entire Grid
|
|
if isscalar(u) and not(isscalar(v)):
|
|
tmp = empty(v.shape, float32)
|
|
tmp.fill(u)
|
|
u = tmp
|
|
|
|
if isscalar(v) and not(isscalar(u)):
|
|
tmp = empty(u.shape, float32)
|
|
tmp.fill(v)
|
|
v = tmp
|
|
|
|
# These will be parsed by legacy opts
|
|
polar=False
|
|
mathematicalDirection=False
|
|
useRadians=False
|
|
speed = None
|
|
|
|
# Handle the crazy legacy options
|
|
if legacyOption != None:
|
|
if type(legacyOption) == float:
|
|
mathematicalDirection = legacyOption < 0
|
|
useRadians = abs(legacyOption) != 1
|
|
polar = abs(legacyOption) == 1 or abs(legacyOption) == 2
|
|
elif type(legacyOption) == bool:
|
|
polar = legacyOption
|
|
else:
|
|
speed = legacyOption
|
|
|
|
completeRevolution = 360 if not useRadians else radians(360.0)
|
|
|
|
if (polar):
|
|
mag = u
|
|
dir = v
|
|
|
|
# replace all negative angles with their corresponding positive values
|
|
negDirMask = dir < 0
|
|
dir[negDirMask] = (- dir[negDirMask]) % completeRevolution
|
|
dir[negDirMask] = completeRevolution - dir[negDirMask]
|
|
|
|
dir[dir > completeRevolution] %= completeRevolution
|
|
theta = radians(dir) if not useRadians else dir
|
|
u = mag * sin(theta)
|
|
v = mag * cos(theta)
|
|
else:
|
|
u = - u if not mathematicalDirection else u
|
|
v = - v if not mathematicalDirection else v
|
|
mag = 0 if speed != None else hypot(u, v)
|
|
theta = arctan2(u, v)
|
|
dir = degrees(theta) if not useRadians else theta
|
|
dir[dir < 0] += completeRevolution
|
|
|
|
u = - u if not mathematicalDirection else u
|
|
v = - v if not mathematicalDirection else v
|
|
|
|
dir[dir == completeRevolution] = 0
|
|
|
|
if speed == None:
|
|
return (mag, dir, u, v)
|
|
else:
|
|
return execute(speed,dir,polar=True)
|
|
|
|
def test():
|
|
|
|
from numpy import array
|
|
|
|
angles = array([0., 45., 90., 135., 180., 225., 270., 315., 360., - 675., 405.])
|
|
magnitudes = angles.copy()
|
|
magnitudes[:] = 2
|
|
|
|
targetDir = array([0., 45., 90., 135., 180., 225., 270., 315., 0., 45., 45.])
|
|
targetU = array([ 0., 1.41, 2., 1.41, 0., - 1.41, - 2., - 1.41, - 0., 1.41, 1.41])
|
|
targetV = array([ 2., 1.41, 0., - 1.41, - 2., - 1.41, 0., 1.41, 2., 1.41, 1.41])
|
|
|
|
# perform regular mathematical vector tests
|
|
|
|
(mag, dir, u, v) = execute(magnitudes, angles, polar=True, mathematicalDirection=True)
|
|
|
|
if not (all(dir == targetDir) and all(u.round(2) == targetU) and all(v.round(2) == targetV)):
|
|
print dir
|
|
print targetDir
|
|
print u.round(2)
|
|
print targetU
|
|
print v.round(2)
|
|
print targetV
|
|
raise Exception
|
|
|
|
(mag, dir, u, v) = execute(u, v, mathematicalDirection=True)
|
|
|
|
if not (all(dir.round(0) == targetDir) and all(mag == magnitudes)):
|
|
raise Exception
|
|
|
|
# perform meteorological vector tests
|
|
|
|
(mag,dir,u,v) = execute(mag,dir,polar=True)
|
|
|
|
if not (all(mag == magnitudes) and
|
|
all(dir.round(0) == targetDir) and
|
|
all(u.round(2) == -targetU) and
|
|
all(v.round(2) == -targetV)):
|
|
print mag
|
|
print magnitudes
|
|
print mag == magnitudes
|
|
print dir
|
|
print targetDir
|
|
print dir == targetDir
|
|
print -u.round(2)
|
|
print targetU
|
|
print u.round(2) == -targetU
|
|
print -v.round(2)
|
|
print targetV
|
|
print v.round(2) == -targetV
|
|
raise Exception
|
|
|
|
(mag,dir,u,v) = execute(u,v)
|
|
|
|
if not (all(mag == magnitudes) and
|
|
all(dir.round(0) == targetDir) and
|
|
all(u.round(2) == -targetU) and
|
|
all(v.round(2) == -targetV)):
|
|
print mag
|
|
print magnitudes
|
|
print mag == magnitudes
|
|
print dir
|
|
print targetDir
|
|
print dir.round(0) == targetDir
|
|
print u.round(2)
|
|
print -targetU
|
|
print u.round(2) == -targetU
|
|
print v.round(2)
|
|
print -targetV
|
|
print v.round(2) == -targetV
|
|
raise Exception
|
|
|
|
# make sure the goofy legacy option works as expected
|
|
|
|
(mag,dir,u,v) = execute(mag,dir,1.0)
|
|
|
|
if not(all(u.round(2) == -targetU) and
|
|
all(v.round(2) == -targetV) and
|
|
all(mag == magnitudes) and
|
|
all(dir.round(0) == targetDir)):
|
|
raise Exception
|
|
|
|
(mag,dir,u,v) = execute(mag,dir,-1.0)
|
|
|
|
if not(all(u.round(2) == targetU) and
|
|
all(v.round(2) == targetV) and
|
|
all(mag == magnitudes) and
|
|
all(dir.round(0) == targetDir)):
|
|
print mag,dir,u,v
|
|
raise Exception
|
|
|
|
otherMag = magnitudes.copy()
|
|
otherMag[:] = 7
|
|
(mag,dir,u,v) = execute(-targetU,-targetV,otherMag)
|
|
|
|
if not(u.round(2)[0] == 0 and
|
|
v.round(2)[0] == -7 and
|
|
all(mag == otherMag) and
|
|
all(dir.round(0) == targetDir)):
|
|
print u.round(2)[0] == 0
|
|
print v.round(2)[0] == -7
|
|
print mag == otherMag
|
|
print dir.round(0)
|
|
print targetDir
|
|
print dir.round(0) == targetDir
|
|
raise Exception
|
|
|
|
print "Vector Test Complete" |