Issue #2661 Use only u,v to represent vector grids in derived parameters and D2D.

Change-Id: I7ea007f0f919017e8212716cc15712c7ed611e69

Former-commit-id: a8bcec4a2fa9ddd49dc300ebd63aebfdfb41723e
This commit is contained in:
Ben Steffensmeier 2014-01-14 11:47:50 -06:00
parent f8820538f4
commit ee11e5d13c
58 changed files with 447 additions and 2203 deletions

View file

@ -2,22 +2,16 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Derived Parameter Python Plug-in
Bundle-SymbolicName: com.raytheon.uf.viz.derivparam.python;singleton:=true
Bundle-Version: 1.0.0.qualifier
Bundle-Activator: com.raytheon.uf.viz.derivparam.python.Activator
Bundle-Version: 1.14.0.qualifier
Bundle-Vendor: RAYTHEON
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Bundle-ActivationPolicy: lazy
Require-Bundle: com.raytheon.uf.common.status;bundle-version="1.12.1174",
com.raytheon.uf.common.serialization;bundle-version="1.12.1174",
com.raytheon.uf.common.python;bundle-version="1.12.1174",
com.raytheon.uf.viz.core;bundle-version="1.12.1174",
com.raytheon.uf.viz.derivparam;bundle-version="1.12.1174",
com.raytheon.uf.common.datastorage;bundle-version="1.12.1174",
org.jep;bundle-version="1.0.0",
org.eclipse.ui;bundle-version="3.6.1",
org.eclipse.core.runtime;bundle-version="3.6.0",
com.raytheon.uf.common.util;bundle-version="1.12.1174",
com.raytheon.uf.common.python.concurrent;bundle-version="1.0.0",
com.raytheon.uf.common.wxmath
Require-Bundle: com.raytheon.uf.common.python,
com.raytheon.uf.common.python.concurrent,
com.raytheon.uf.viz.derivparam;bundle-version="1.14.0",
com.raytheon.uf.viz.core;bundle-version="1.13.0",
com.raytheon.uf.common.wxmath,
com.raytheon.uf.common.util,
com.raytheon.uf.common.datastorage
Export-Package: com.raytheon.uf.viz.derivparam.python,
com.raytheon.uf.viz.derivparam.python.function

View file

@ -18,10 +18,9 @@
# further licensing information.
##
from numpy import add
from numpy import array
from numpy import add,array,zeros_like
from Vector import execute as Vector
import Vector
def execute(*args):
""" Perform scalar or vector addition
@ -38,33 +37,11 @@ def scalarAddition(args):
return reduce(add, args)
def vectorAddition(args):
uResult = zeros_like(args[0][0])
vResult = zeros_like(args[0][0])
from numpy import zeros
for u, v in args:
uResult += u
vResult += v
targetShape = args[0][2].shape
targetType = args[0][2].dtype
uResult = zeros(shape=(targetShape), dtype=targetType)
vResult = zeros(shape=(targetShape), dtype=targetType)
for arg in args:
uResult = scalarAddition((uResult, arg[2]))
vResult = scalarAddition((vResult, arg[3]))
return Vector(uResult, vResult)
def test():
if not( all(execute(array([1., 2.]), array([3., 4.])) == array([4., 6.]))):
raise Exception
Vector1 = Vector(array([1.,2.]),array([0.,270.]),True)
Vector2 = Vector(array([3.,4.]),array([180.,90.]),True)
(mag, dir, u, v) = execute(Vector1,Vector2)
if not( all(mag == array([2., 2.])) and all(dir.round(0) == array([180., 90.]))):
raise Exception
if not( all(execute(array([1., 2.]), 3.) == array([4., 5.]))):
raise Exception
print "Add Test Complete"
return Vector.componentsTo(uResult, vResult)

View file

@ -20,7 +20,7 @@
## @file CompBy.py
from numpy import cos, sin, sqrt
from Vector import execute as Vector
import Vector
##
# This function is based on the comp_by.f Fortran function by J. Ramer, Jul 1 2003.
@ -50,8 +50,8 @@ def execute(Vecs, ThGrd, Angle=0):
# pi/180 for degrees to radians conversion
dgtord = 0.01745329252
Vecs_U, Vecs_V = Vecs[2], Vecs[3]
ThGrd_U, ThGrd_V = ThGrd[2], ThGrd[3]
Vecs_U, Vecs_V = Vecs
ThGrd_U, ThGrd_V = ThGrd
if Angle != 0:
# Strip off any 1000s from angle.
@ -85,7 +85,7 @@ def execute(Vecs, ThGrd, Angle=0):
comp = rotated_u * mag
comp2 = rotated_v * mag
return Vector(comp, comp2)
return Vector.componentsTo(comp, comp2)
else:
# initialize to u and v from ThGrd
rotated_u = ThGrd_U

View file

@ -49,7 +49,7 @@ def execute(A0, A1, B0, B1):
v1 = A1[3]
uDeriv = execute(u0, u1, B0, B1)
vDeriv = execute(v0, v1, B0, B1)
return Vector.execute(uDeriv, vDeriv)
return Vector.componentsTo(uDeriv, vDeriv)
Adiff = A1-A0
Bdiff = B1-B0

View file

@ -28,10 +28,7 @@ def execute(*args):
if type(diffArgs[0]) == tuple:
for i in range(1, len(diffArgs)):
diffVectorArg = list(diffArgs[i])
diffVectorArg[2] = -diffVectorArg[2]
diffVectorArg[3] = -diffVectorArg[3]
diffArgs[i] = tuple(diffVectorArg)
diffArgs[i] = (-diffArgs[i][0], -diffArgs[i][1])
return apply(Add, diffArgs)
else:
result = 0
@ -39,23 +36,3 @@ def execute(*args):
for i in range(1, len(diffArgs)):
result -= diffArgs[i]
return result
def test():
from numpy import array
if not(all(execute(array([1., 2.]), array([3., 4.])) == array([ - 2, - 2]))):
raise Exception
from Vector import execute as Vector
# using meteoroligcal directions
Vector1 = Vector(array([1., 2.]), array([0., 270.]), True)
Vector2 = Vector(array([3., 4.]), array([180., 90.]), True)
(mag, dir, u, v) = execute(Vector1, Vector2)
if not(all(mag == array([2., 2.])) and all(dir.round(0) == array([180., 90.]))):
print mag
print dir
raise Exception
print "Difference Test Complete"

View file

@ -43,8 +43,7 @@ def execute(vec, dx, dy, quan=1.0):
dvdy = diff_v/dy[i,j] \n
diverg[i,j] = (dudx + dvdy)/2 \n
"""
vec_U = vec[2]
vec_V = vec[3]
vec_U,vec_V = vec
vshape = shape(vec_U)

View file

@ -20,8 +20,7 @@
## @file Geowind.py
from numpy import isscalar
from numpy import NaN
from numpy import isscalar,NaN
import Vector
g = 9.806 # Gravitational acceleration (m/s^2)
@ -79,5 +78,5 @@ def execute(Height, dx, dy, coriolis):
result_U = result_U
result_V = result_V
result = Vector.execute(result_U, result_V)
result = Vector.componentsTo(result_U, result_V)
return result

View file

@ -66,5 +66,5 @@ def execute(scalar, dx, dy):
result_u[:,1:-1] = ans_u
result_v[1:-1,:] = ans_v
return Vector.execute(result_u, result_v)
return Vector.componentsTo(result_u, result_v)

View file

@ -20,7 +20,7 @@
from Add import execute as Add
from Multiply import execute as Multiply
from numpy import zeros, ndarray
from numpy import zeros_like, ndarray
def execute(*args):
"""Perform a linear transform
@ -35,16 +35,13 @@ def execute(*args):
if type(args[0]) == tuple:
targetShape = args[0][0].shape
targetType = args[0][0].dtype
zeroArray = zeros(shape=(targetShape), dtype=targetType)
result = (zeroArray, zeroArray.copy(), zeroArray.copy(), zeroArray.copy())
zeroArray = zeros_like(args[0][0])
result = (zeroArray, zeroArray.copy())
else:
for arg in args:
if (type(arg) == ndarray):
targetShape = arg.shape
targetType = arg.dtype
result = zeros(shape=targetShape, dtype=targetType)
result = zeros_like(arg)
break
termLength = 2
@ -58,23 +55,3 @@ def execute(*args):
result = Add(result, Multiply(coefficient, variable))
return result
def test():
from numpy import array
if not( all(execute(array([1., 2.]), array([3., 4.]), array([1., 2.]), array([3., 4.])) == array([6., 16.]))):
raise Exception
from Vector import execute as Vector
# using meteorological direction
Vector1 = Vector(array([1., 2.]), array([0., 270.]), True)
Vector2 = Vector(array([3., 4.]), array([180., 90.]), True)
(mag, dir, u, v) = execute(Vector1, array([3., 4.]), Vector2, array([3., 4.]))
if not( all(mag == array([6., 8.])) and all(dir.round(0) == array([180., 90.]))):
print mag
print dir
raise Exception
print "LinTrans Test Complete"

View file

@ -21,9 +21,8 @@
from numpy import log, exp
import PartialDerivative as Partial
import DgeoComps as DgeoComps
from Vector import execute as Vector
import DgeoComps
import Vector
##
# Find Q vectors from height, temp, and pressure.
#
@ -44,7 +43,7 @@ from Vector import execute as Vector
def execute(GHxSM, TxSM, P, dx, dy, coriolis):
result_u, result_v, dtdx, dtdy = calculate(GHxSM, TxSM, P, dx, dy, coriolis)
# convert the results we want to unmasked arrays
return Vector(result_u, result_v)
return Vector.componentsTo(result_u, result_v)
##
# Find Q vectors and dtemp/dx and dtemp/dy from height, temp, and pressure.

View file

@ -22,7 +22,7 @@ from numpy import log, exp
import PartialDerivative as Partial
import DgeoComps as DgeoComps
from Vector import execute as Vector
import Vector
##
# Find Q vectors from upper and lower height and pressure.
@ -47,7 +47,7 @@ def execute(height_up, height_lo, pressure_up, pressure_lo, dx, dy, coriolis):
qx, qy, dtdx, dtdy = calculate(height_up, height_lo, pressure_up, pressure_lo, dx, dy, coriolis)
# unmask the arrays we're interested in
return Vector(qx, qy)
return Vector.componentsTo(qx, qy)
##
# Find Q vectors and dtdx and dtdy from upper and lower height and pressure.

View file

@ -29,34 +29,6 @@ def execute(*args):
"""
if type(args[0]) == tuple:
return vectorMagnitude(args[0])
return hypot(args[0][0], args[0][1])
else:
return componentMagnitude(args[0], args[1])
def vectorMagnitude(vector):
""" Return the first item in the vector tuple (its the magnitude)
vector tuples are assumed to follow the tuple returned by the
Vector.execute method. That is (mag,dir,u,v)
"""
return vector[0]
def componentMagnitude(u, v):
return hypot(u, v)
def test():
from Vector import execute as Vector
from numpy import array
testVector = Vector(array([1., 2.]), array([180., 270.]), True)
result = execute(testVector)
if not(all(result == array([1.,2.]))):
raise Exception
result = execute(testVector[2],testVector[3])
if not(all(result == array([1.,2.]))):
raise Exception
print "Magnitude Test Complete"
return hypot(args[0], args[1])

View file

@ -19,7 +19,7 @@
##
from numpy import multiply
from Vector import execute as Vector
import Vector
def execute(*args):
""" Perform multiplication of any number of scalars or of a vector and a scalar.
@ -32,27 +32,8 @@ def execute(*args):
return scalarMultiply(args)
def scalarMultiply(args):
return reduce(multiply, args)
def vectorMultiply(args):
vector = args[0]
scalar = args[1]
return Vector(scalarMultiply((vector[2], scalar)), scalarMultiply((vector[3], scalar)))
def test():
from numpy import array
if not(all(execute(array([2., 4.]), 2.) == array([4., 8.]))):
raise Exception
vector = Vector(array([2., 4.]), array([0., 270.]), True)
(mag, dir, u, v) = execute(vector, 2.)
if not(all(mag == array([4., 8.])) and all(dir == array([0., 270.]))):
raise Exception
print "Multiply Test Complete"
return Vector.componentsTo(scalarMultiply((args[0][0], args[1])), scalarMultiply((args[0][1], args[1])))

View file

@ -21,10 +21,9 @@
#import sys
#sys.path.append("..")
from numpy import ndarray,NaN
from numpy import float32
from Vector import execute as Vector
from numpy import ndarray,NaN, float32
from Multiply import execute as Multiply
import Vector
##
# This routine computes the non-advective local change of an arbitrary
@ -72,72 +71,4 @@ def execute(u, v, a, dx, dy):
# calculate values for the middle
dadydt[1:-1,1:-1] = -0.5 * (dudy*dadx + dvdy*dady)
return Vector(-dadxdt, dadydt)
def test():
ua = [[-1.38, -1.88, -2.49000001, -3.12999988, -3.7099998, -4.0999999],
[-1.22000003, -1.68999994, -2.26999998, -2.88999987, -3.46000004, -3.82999992],
[-1.03999996, -1.46999991, -2.00999999, -2.5999999, -3.12999988, -3.49000001],
[-0.84999996, -1.24000001, -1.70999992, -2.24000001, -2.73000002, -3.07999992],
[-0.64999998, -0.98999995, -1.39999998, -1.8499999, -2.28999996, -2.62999988],
[-0.44999999, -0.75, -1.09000003, -1.45999992, -1.82999992, -2.15999985]]
va = [[ 5.10999966, 5.42999983, 5.76999998, 6.10999966, 6.40999985, 6.63999987],
[ 4.63999987, 4.94000006, 5.23999977, 5.53999996, 5.80999994, 6.06999969],
[ 4.17000008, 4.44999981, 4.73999977, 5.01999998, 5.26999998, 5.52999973],
[ 3.68999982, 3.99000001, 4.27999973, 4.53999996, 4.76999998, 5.03999996],
[ 3.22000003, 3.53999996, 3.83999991, 4.0999999, 4.32999992, 4.5999999],
[ 2.75, 3.0999999, 3.41999984, 3.69999981, 3.92999983, 4.19000006]]
aa = [[ 441.26159668, 440.68197632, 440.29559326, 439.90917969, 439.71600342,
439.52279663],
[ 441.06838989, 440.68197632, 440.29559326, 439.90917969, 439.52279663,
439.52279663],
[ 441.06838989, 440.68197632, 440.29559326, 439.90917969, 439.52279663,
439.52279663],
[ 441.06838989, 440.68197632, 440.48876953, 440.10238647, 439.71600342,
439.52279663],
[ 441.06838989, 440.68197632, 440.48876953, 440.10238647, 439.90917969,
439.71600342],
[ 441.06838989, 440.68197632, 440.48876953, 440.10238647, 439.90917969,
439.71600342]]
dxa = [[ 34735.1328125, 34695.375, 34642.5625, 34590.0078125,
34537.7265625, 34485.7109375],
[ 34823.0859375, 34783.625, 34731.25390625, 34679.13671875,
34627.28125, 34575.69921875],
[ 34939.6328125, 34900.6171875, 34848.8359375, 34797.3046875,
34746.03125, 34695.01953125],
[ 35055.359375, 35016.7890625, 34965.6015625, 34914.6484375,
34863.953125, 34813.5234375],
[ 35170.2421875, 35132.125, 35081.5234375, 35031.1640625,
34981.046875, 34931.1875],
[ 35284.27734375, 35246.60546875, 35196.59765625, 35146.82421875,
35097.29296875, 35048.0078125]]
dya = [[ 34735.1328125, 34695.375, 34642.5625, 34590.0078125,
34537.7265625, 34485.7109375],
[ 34823.0859375, 34783.625, 34731.25390625, 34679.13671875,
34627.28125, 34575.69921875],
[ 34939.6328125, 34900.6171875, 34848.8359375, 34797.3046875,
34746.03125, 34695.01953125],
[ 35055.359375, 35016.7890625, 34965.6015625, 34914.6484375,
34863.953125, 34813.5234375],
[ 35170.2421875, 35132.125, 35081.5234375, 35031.1640625,
34981.046875, 34931.1875],
[ 35284.27734375, 35246.60546875, 35196.59765625, 35146.82421875,
35097.29296875, 35048.0078125 ]]
u = ndarray([6, 6], float32)
v = ndarray([6, 6], float32)
a = ndarray([6, 6], float32)
dx = ndarray([6, 6], float32)
dy = ndarray([6, 6], float32)
for i in range(0,6):
for j in range(0,6):
u[i,j] = ua[i][j]
v[i,j] = va[i][j]
a[i,j] = aa[i][j]
dx[i,j] = dxa[i][j]
dy[i,j] = dya[i][j]
res = execute(u, v, a, dx, dy)
print res[2].flatten()
print res[3].flatten()
#test()
return Vector.componentsTo(-dadxdt, dadydt)

View file

@ -19,15 +19,12 @@
###
## @file Negate.py
import numpy
from Vector import execute as Vector
import Vector
##
# Negates input
def execute(input):
if type(input) == tuple:
u = -input[2]
v = -input[3]
return Vector(u,v)
return Vector.componentTo(-input[0], -input[1])
else:
return -input

View file

@ -50,8 +50,8 @@ import Vorticity
def execute(p_up, p_lo, o_up, o_lo, vector_up, vector_lo, dx, dy, coriolis):
"Calculate the isentropic potential vorticity through a layer."
u_up, v_up = vector_up[2], vector_up[3]
u_lo, v_lo = vector_lo[2], vector_lo[3]
u_up, v_up = vector_up
u_lo, v_lo = vector_lo
# Calculate the absolute vorticity at each isentropic surface.

View file

@ -60,8 +60,8 @@ import Vorticity
def execute(t_up, t_lo, p_up, p_lo, vector_up, vector_lo, dx, dy, coriolis):
""
u_up, v_up = vector_up[2], vector_up[3]
u_lo, v_lo = vector_lo[2], vector_lo[3]
u_up, v_up = vector_up
u_lo, v_lo = vector_lo
# Calculate the absolute vorticity at each isobaric surface.
avort1 = Vorticity.execute(u_up, v_up, coriolis, dx, dy)
@ -70,8 +70,8 @@ def execute(t_up, t_lo, p_up, p_lo, vector_up, vector_lo, dx, dy, coriolis):
# Calculate the temperature gradient on each surface.
grad_lo = Gradient.execute(t_lo, dx, dy)
grad_up = Gradient.execute(t_up, dx, dy)
dtdx1, dtdy1 = grad_lo[2], grad_lo[3]
dtdx2, dtdy2 = grad_up[2], grad_up[3]
dtdx1, dtdy1 = grad_lo
dtdx2, dtdy2 = grad_up
# Calculate difference arrays.
dp = p_up - p_lo
dt = t_up - t_lo

View file

@ -19,9 +19,9 @@
##
from Add import execute as Add
from Vector import execute as Vector
from numpy import array
from numpy import dot
from math import radians,cos,sin
from numpy import array,dot
import Vector
def execute(*args):
"""Rotate a vector
@ -39,54 +39,31 @@ def execute(*args):
return vectorTransformMatrix(args)
def rotateDegrees(args):
magnitude = args[0][0]
direction = Add(args[0][1], args[1]) % 360
return Vector(magnitude, direction, True)
v = args[0]
r = radians(args[1])
s = sin(r)
c = cos(r)
return vectorTransformMatrix(v,c,-s,s,c)
def vectorTransformMatrix(args):
uComponent = args[0][2]
vComponent = args[0][3]
uComponent,vComponent = args[0]
uComponentShape = uComponent.shape
vComponentShape = vComponent.shape
# in-place flatten the arrays
uComponent.resize((uComponent.size,))
vComponent.resize((vComponent.size,))
uComponent = uComponent.reshape((uComponent.size,))
vComponent = vComponent.reshape((vComponent.size,))
vector = array([uComponent, vComponent])
transform = array([[args[1], args[2]], [args[3], args[4]]],dtype=uComponent.dtype)
(u,v) = dot(transform, vector)
u,v = dot(transform, vector)
# resize the arrays back to appropriate size
u.resize(uComponentShape)
v.resize(vComponentShape)
return Vector(u, v)
def test():
from numpy import all
from numpy import array
try:
execute(1, 2, 3, 4);
raise Exception
except ValueError:
pass
(mag, dir, u, v) = execute((array([1., 2.]), array([90., 270.])), 180.)
if not(all(mag == array([1., 2.])) and all(dir == array([270., 90.]))):
raise Exception
(mag, dir, u, v) = execute((None, None, array([1., 3.]), array([2., 4.])), 3., 4., 5., 6.)
if not(all(u == array([11., 25.])) and all(v == array([17., 39.]))):
raise Exception
print "Rotate Test Complete"
return Vector.componentsTo(u, v)

View file

@ -1,36 +0,0 @@
##
# 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 unittest
import numpy as np
import AdiabaticTemp
class TestAdiabaticTemp(unittest.TestCase):
def setup(self):
pass
def testExecute(self):
intemp = np.array([268.54, 270.5], dtype=np.float32)
inpres = np.array([770, 770], dtype=np.float32)
result = AdiabaticTemp.execute(intemp, inpres)
correct = np.array([278.37, 281.93], dtype=np.float32)
self.failUnless(np.allclose(result,correct, 0.01, 0.01), "result = " + repr(result))

View file

@ -1,93 +0,0 @@
##
# 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 unittest
import numpy as np
import Advection
class TestAdvection(unittest.TestCase):
def setUp(self):
"""Set up arrays for calls to Advection.execute()."""
self.U = np.ones((5,5), dtype=np.float32)
self.V = np.ones_like(self.U);
self.Wind = (self.U,self.V)
self.Q = np.ones_like(self.U) * 0.5
self.dx = np.ones_like(self.U)
self.dy = np.ones_like(self.U)
def testOuterEdge(self):
"""Confirm that the outer edge is set to the invalid placeholder (1e37). """
vrtct = Advection.execute(self.Wind, self.Q, self.dx, self.dy)
self.assertEquals((5,5), vrtct.shape, "vrtct.shape")
self.assertEquals(np.float32, vrtct.dtype, "vrtct.dtype")
correctAnswer = np.array([[1e37, 1e37, 1e37, 1e37, 1e37],
[1e37, 0, 0, 0, 1e37],
[1e37, 0, 0, 0, 1e37],
[1e37, 0, 0, 0, 1e37],
[1e37, 1e37, 1e37, 1e37, 1e37]], dtype=np.float32)
self.failUnless(np.all(correctAnswer==vrtct))
def testMiddleMath(self):
"""Test """
self.U[1,2] = 5
self.V[1,2] = 5
self.Q[3,2] = 0.8
vrtct = Advection.execute(self.Wind, self.Q, self.dx, self.dy)
correctAnswer = np.array([[1e37, 1e37, 1e37, 1e37, 1e37],
[1e37, 0, 0, 0, 1e37],
[1e37, 0, -0.15, 0, 1e37],
[1e37, -0.15, 0, 0.15, 1e37],
[1e37, 1e37, 1e37, 1e37, 1e37]], dtype=np.float32)
self.failUnless(np.all(correctAnswer==vrtct), "Advection is incorrect.\n" + repr(vrtct))
def testScalarDxDy(self):
"""Test Advection calculation when dx and dy are scalars instead of arrays."""
self.U[1,2] = 5
self.V[1,2] = 5
self.Q[3,2] = 0.8
vrtct = Advection.execute(self.Wind, self.Q, 0.1, 0.5)
correctAnswer = np.array([[1e37, 1e37, 1e37, 1e37, 1e37],
[1e37, 0, 0, 0, 1e37],
[1e37, 0, -1.5, 0, 1e37],
[1e37, -0.3, 0, 0.3, 1e37],
[1e37, 1e37, 1e37, 1e37, 1e37]], dtype=np.float32)
self.failUnless(np.all(correctAnswer==vrtct), "Advection is incorrect.\n" + repr(vrtct))
def testInvalidCell(self):
"""Test when a cell contains an invalid value."""
self.U[1,2] = 5
self.U[2,2] = 1e37
self.V[1,2] = 5
self.Q[3,2] = 0.8
vrtct = Advection.execute(self.Wind, self.Q, self.dx, self.dy)
correctAnswer = np.array([[1e37, 1e37, 1e37, 1e37, 1e37],
[1e37, 0, 0, 0, 1e37],
[1e37, 0, 1e37, 0, 1e37],
[1e37, -0.15, 0, 0.15, 1e37],
[1e37, 1e37, 1e37, 1e37, 1e37]], dtype=np.float32)
self.failUnless(np.all(correctAnswer==vrtct), "Advection is incorrect.\n" + repr(vrtct))
if "__main__" == __name__:
unittest.main()

View file

@ -1,142 +0,0 @@
##
# 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 unittest
import numpy as np
import CompBy
class TestCompBy(unittest.TestCase):
"""Unit tests for CompBy function."""
def setUp(self):
"""Create arrays to use in calls to CompBy.execute()."""
self.U = np.ones((3,3), dtype=np.float32) * np.sqrt(2)
self.U[1,0] = np.sqrt(3)
self.V = np.ones((3,3), dtype=np.float32) * np.sqrt(2)
self.V[0,2] = -self.V[0,2]
self.Vector = (self.U, self.V)
self.ThU = np.ones((3,3), dtype=np.float32) * 0.1
self.ThU = np.cumsum(self.ThU, axis=0)
self.ThV = np.zeros((3,3), dtype=np.float32)
self.ThGrd = (self.ThU, self.ThV)
def testAngleZero(self):
"""Test with no rotation."""
comp = CompBy.execute(self.Vector, self.ThGrd, 0.0)
correctAnswer_U = np.ones((3,3), dtype=np.float32) * np.sqrt(2)
correctAnswer_U[1,0] = 1.73205078
correctAnswer_V = np.array([[0,0,0], [0,0,0], [0,0,0]], dtype=np.float32)
# check for correct answers.
if not np.all(correctAnswer_U==comp[0]):
self.fail(repr(comp))
if not np.all(correctAnswer_V==comp[1]):
self.fail(repr(comp))
def testAngle45(self):
"""Test with 45 degree rotation."""
comp = CompBy.execute(self.Vector, self.ThGrd, 45.0)
correctAnswer_U = np.zeros((3,3), dtype=np.float32)
correctAnswer_U[0,2] = np.sqrt(2)
correctAnswer_U[1,0] = 0.15891865
correctAnswer_V = np.zeros((3,3), dtype=np.float32)
correctAnswer_V[0,2] = -np.sqrt(2)
correctAnswer_V[1,0] = -0.15891865
# check for correct answers.
if not np.all(correctAnswer_U==comp[0]):
self.fail(repr(comp))
if not np.all(correctAnswer_V==comp[1]):
self.fail(repr(comp))
def testAngle90(self):
"""Test with rotation of 90 degrees."""
comp = CompBy.execute(self.Vector, self.ThGrd, 90.0)
correctAnswer_U = np.zeros((3,3), dtype=np.float32)
correctAnswer_V = np.ones((3,3), dtype=np.float32) * np.sqrt(2)
correctAnswer_V[0,2] = -np.sqrt(2)
# check for correct answers.
# note: We have to use allclose(a,b) instead of all(a==b) because of
# rounding errors in the degrees-to-radians conversion constant.
# Since this is the same constant used in the original Fortran code,
# the error should be identical.
if not np.allclose(correctAnswer_U,comp[0]):
self.fail(repr(comp))
if not np.all(correctAnswer_V==comp[1]):
self.fail(repr(comp))
def testAngle120(self):
"""Test angles above 90 but below 180."""
comp = CompBy.execute(self.Vector, self.ThGrd, 120.0)
correctAnswer_U = np.ones((3,3), dtype=np.float32) * 0.96592587
correctAnswer_U[0,2] = -0.25881901
correctAnswer_U[1,0] = 1.04538524
correctAnswer_U[2,:] = np.ones((1,3)) * 0.96592593
correctAnswer_V = np.ones((3,3), dtype=np.float32) * 1.67303264
correctAnswer_V[0,2] = -0.44828767
correctAnswer_V[1,0] = 1.81066024
correctAnswer_V[2,:] = np.ones((1,3)) * 1.67303276
# check for correct answers.
if not np.all(correctAnswer_U==comp[0]):
self.fail(repr(comp))
if not np.all(correctAnswer_V==comp[1]):
self.fail(repr(comp))
def testAngle225(self):
"""Test angles above 180 but below 1000."""
comp = CompBy.execute(self.Vector, self.ThGrd, 225.0)
correctAnswer_U = np.ones((3,3), dtype=np.float32) * np.sqrt(2)
correctAnswer_U[1,0] = 1.73205078
correctAnswer_V = np.array([[0,0,0], [0,0,0], [0,0,0]], dtype=np.float32)
# check for correct answers.
if not np.all(correctAnswer_U==comp[0]):
self.fail(repr(comp))
if not np.all(correctAnswer_V==comp[1]):
self.fail(repr(comp))
def testAngle2090(self):
"""Test with rotation of 2090 degrees."""
# 2000 portion should be stripped off, so values should be the same as testAngle90.
comp = CompBy.execute(self.Vector, self.ThGrd, 2090.0)
correctAnswer_U = np.zeros((3,3), dtype=np.float32)
correctAnswer_V = np.ones((3,3), dtype=np.float32) * np.sqrt(2)
correctAnswer_V[0,2] = -np.sqrt(2)
# check for correct answers.
# note: We have to use allclose(a,b) instead of all(a==b) because of
# rounding errors in the degrees-to-radians conversion constant.
# Since this is the same constant used in the original Fortran code,
# the error should be identical.
if not np.allclose(correctAnswer_U,comp[0]):
self.fail(repr(comp))
if not np.all(correctAnswer_V==comp[1]):
self.fail(repr(comp))
def testBigV(self):
"""Test with different ThGrd but no rotation."""
self.V = self.V + 8
comp = CompBy.execute(self.Vector, self.ThGrd, 0.0)
correctAnswer_U = np.ones((3,3), dtype=np.float32) * np.sqrt(2)
correctAnswer_U[1,0] = 1.73205078
correctAnswer_V = np.array([[0,0,0], [0,0,0], [0,0,0]], dtype=np.float32)
# check for correct answers.
if not np.all(correctAnswer_U==comp[0]):
self.fail(repr(comp))
if not np.all(correctAnswer_V==comp[1]):
self.fail(repr(comp))

View file

@ -1,58 +0,0 @@
##
# 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 unittest
import numpy as np
import Deformation
##
# Unit test class for Deformation
class TestDeformation(unittest.TestCase):
def setUp(self):
self.U = np.ones((5,5), dtype=np.float32)
self.U += np.eye(5,5,0)
self.V = np.ones((5,5), dtype=np.float32)
self.V += np.eye(5,5,0).transpose()
self.Vector = (self.U, self.V)
self.dx = np.ones((5,5), dtype=np.float32)
self.dy = np.ones((5,5), dtype=np.float32)
def testExecute(self):
"Test basic results of execute method."
result = Deformation.execute(self.Vector, self.dx, self.dy)
correctAnswer = np.array([[1e37, 1e37, 1e37, 1e37, 1e37],
[1e37, 0, 1, 0, 1e37],
[1e37, 1, 0, 1, 1e37],
[1e37, 0, 1, 0, 1e37],
[1e37, 1e37, 1e37, 1e37, 1e37]], dtype=np.float32)
self.failUnless(np.allclose(result, correctAnswer), "Wrong answers: " + repr(result))
def testMasked(self):
"Check that invalid data results in cells with ourNaN (1e37)"
self.Vector[1][1,1] = 1e37
result = Deformation.execute(self.Vector, self.dx, self.dy)
correctAnswer = np.array([[1e37, 1e37, 1e37, 1e37, 1e37],
[1e37, 0, 1e37, 0, 1e37],
[1e37, 1e37, 0, 1, 1e37],
[1e37, 0, 1, 0, 1e37],
[1e37, 1e37, 1e37, 1e37, 1e37]], dtype=np.float32)
self.failUnless(np.allclose(result, correctAnswer), "Wrong answers: " + repr(result))

View file

@ -1,53 +0,0 @@
##
# 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 unittest
import numpy as np
import Derivative
bad = 1e36
class TestDerivative(unittest.TestCase):
""
def setUp(self):
""
self.A0 = np.ones((3,3), dtype=np.float32)
self.A1 = np.array( range(9), dtype=np.float32).reshape((3,3))
self.A1 *= self.A1
self.A1 += self.A0
self.A0[0,1] = 1e37
self.A1[1,0] = 1e37
self.B0 = np.ones((3,3), dtype=np.float32) * 0.5
self.B1 = np.array( range(9), dtype=np.float32).reshape((3,3))
self.B1 += self.B0
self.B1[1,-1] = self.B0[1,-1]
self.B1[-1, 1] = 1e37
def testDerivative(self):
"Test the derivative function."
result = Derivative.execute(self.A0, self.A1, self.B0, self.B1)
correct = np.array([[1e37, 1e37, 2],
[1e37, 4, 1e37],
[ 6, 1e37, 8]], dtype=np.float32)
if not np.allclose(result, correct):
self.fail("Incorrect answer:" + repr(result))

View file

@ -1,98 +0,0 @@
##
# 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 unittest
import numpy as np
import DgeoComps
from constants import bad
import nan
class TestDgeoComps(unittest.TestCase):
""
def failIfArraysDifferent(self, arr, arr_correct, arr_name):
if not np.allclose(arr, arr_correct, 0.01, 0.01):
failMsg = ""
if not arr.shape == arr_correct.shape:
failMsg += "%s.shape = " % (arr_name)
failMsg += arr.shape + "\n"
if not arr.dtype == arr_correct.dtype:
failMsg += "%s.dtype = " % (arr_name)
failMsg += arr.dtype + "\n"
if arr.shape==arr_correct.shape and \
arr.dtype==arr_correct.dtype:
for xidx in range(5):
for yidx in range(5):
if np.abs(arr[xidx,yidx]-arr_correct[xidx,yidx])>0.01:
failMsg += "%s[%d,%d] = %g" % (arr_name,xidx,yidx, arr[xidx,yidx])
failMsg += ", expected %g\n" % arr_correct[xidx,yidx]
self.fail(failMsg)
def setUp(self):
""
self.height = np.array(range(25), dtype=np.float32).reshape((5,5))
self.height[1,1] = 1e37
self.height = nan.nan_greater(self.height, bad, copy=False)
self.dx = np.ones((5,1)) * np.array([1,2,1,1,1], dtype=np.float32)
self.dy = np.ones((5,1)) * np.array([1,2,1,1,1], dtype=np.float32)
self.dy = self.dx.transpose()
pi = 3.1415927
self.coriolis = np.array(range(5), dtype=np.float32).reshape((5,1)) + 40
self.coriolis *= pi/180
self.coriolis = np.sin(self.coriolis) * 3.0 * np.ones((5,))
def testDgeoComps(self):
dugdx, dugdy, dvgdx, dvgdy = DgeoComps.execute(self.height, self.dx, self.dy, self.coriolis)
dugdx = nan.nan_filled(dugdx, 1e37)
dugdy = nan.nan_filled(dugdy, 1e37)
dvgdx = nan.nan_filled(dvgdx, 1e37)
dvgdy = nan.nan_filled(dvgdy, 1e37)
dugdx_correct = np.array([[ 1e37, 1e37, 1e37, 1e37, 1e37],
[ 1e37, -0.00, -0.00, -0.00, 1e37],
[ 1e37, -0.00, 1e37, -0.00, 1e37],
[ 1e37, -0.00, -0.00, -0.00, 1e37],
[ 1e37, 1e37, 1e37, 1e37, 1e37]], dtype=np.float32)
dugdy_correct = np.array([[ 1e37, 1e37, 1e37, 1e37, 1e37],
[ 1e37, 1e37, 1e37, -0.00, 1e37],
[ 1e37, 0.00, 0.00, -0.00, 1e37],
[ 1e37, -0.00, -0.00, -0.00, 1e37],
[ 1e37, 1e37, 1e37, 1e37, 1e37]], dtype=np.float32)
dvgdx_correct = np.array([[ 1e37, 1e37, 1e37, 1e37, 1e37],
[ 1e37, 1e37, 0, 0, 1e37],
[ 1e37, 1e37, 0, 0, 1e37],
[ 1e37, 0, 0, 0, 1e37],
[ 1e37, 1e37, 1e37, 1e37, 1e37]], dtype=np.float32)
dvgdy_correct = np.array([[ 1e37, 1e37, 1e37, 1e37, 1e37],
[ 1e37, 0.00, 0.00, 0.00, 1e37],
[ 1e37, 0.00, 1e37, 0.00, 1e37],
[ 1e37, 0.00, 0.00, 0.00, 1e37],
[ 1e37, 1e37, 1e37, 1e37, 1e37]], dtype=np.float32)
self.failIfArraysDifferent(dugdx, dugdx_correct, "dugdx")
self.failIfArraysDifferent(dugdy, dugdy_correct, "dugdy")
self.failIfArraysDifferent(dvgdx, dvgdx_correct, "dvgdx")
self.failIfArraysDifferent(dvgdy, dvgdy_correct, "dvgdy")
if '__main__' == __name__:
unittest.main()

View file

@ -1,125 +0,0 @@
##
# 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 unittest
import numpy as np
import Divergence
## Unit test for Divergence function.
class TestDivergence(unittest.TestCase):
"""Unit tests for the divergence function."""
def testOuterEdge(self):
"""Make sure Divergence.execute() fills the outer edge with
the "invalid" placeholder value (1e37)."""
U = np.ones((4,4), dtype=np.float32)
V = np.ones_like(U);
Wind = (U,V)
dx = np.ones_like(U)
dy = np.ones_like(U)
dvgnc = Divergence.execute(Wind,dx,dy)
self.assertEquals((4,4), dvgnc.shape, "dvgnc.shape")
self.assertEquals(np.float32, dvgnc.dtype, "dvgnc.dtype")
correctAnswer = np.array([[1e37, 1e37, 1e37, 1e37],
[1e37, 0, 0, 1e37],
[1e37, 0, 0, 1e37],
[1e37, 1e37, 1e37, 1e37]], dtype=np.float32)
self.failUnless(np.all(correctAnswer==dvgnc), repr(dvgnc))
def testMiddleMath(self):
"""Confirm that the inner cells are calculated correctly."""
U = np.array([[1,1,1,1,1],
[1,1,5,1,1],
[1,1,1,1,1],
[1,1,1,1,1],
[1,1,1,1,1]], dtype=np.float32)
V = np.array([[1,1,1,1,1],
[1,1,5,1,1],
[1,1,1,1,1],
[1,1,1,1,1],
[1,1,1,1,1]], dtype=np.float32)
Wind = (U,V)
dx = np.ones_like(U);
dy = np.ones_like(U);
dvgnc = Divergence.execute(Wind,dx,dy)
correctAnswer = np.array([[1e37, 1e37, 1e37, 1e37, 1e37],
[1e37, 2, 0, -2, 1e37],
[1e37, 0, -2, 0, 1e37],
[1e37, 0, 0, 0, 1e37],
[1e37, 1e37, 1e37, 1e37, 1e37]], dtype=np.float32)
self.failUnless(np.all(correctAnswer==dvgnc), "Divergence is incorrect.\n" + repr(dvgnc))
def testScalarDxDy(self):
"""Confirm that the inner cells are calculated correctly
when dx and dy are scalars instead of arrays."""
U = np.array([[1,1,1,1,1],
[1,1,5,1,1],
[1,1,1,1,1],
[1,1,1,1,1],
[1,1,1,1,1]], dtype=np.float32)
V = np.array([[1,1,1,1,1],
[1,1,5,1,1],
[1,1,1,1,1],
[1,1,1,1,1],
[1,1,1,1,1]], dtype=np.float32)
Wind = (U,V)
dx = 1
dy = 1
dvgnc = Divergence.execute(Wind,dx,dy)
correctAnswer = np.array([[1e37, 1e37, 1e37, 1e37, 1e37],
[1e37, 2, 0, -2, 1e37],
[1e37, 0, -2, 0, 1e37],
[1e37, 0, 0, 0, 1e37],
[1e37, 1e37, 1e37, 1e37, 1e37]], dtype=np.float32)
self.failUnless(np.all(correctAnswer==dvgnc), "Divergence is incorrect.\n" + repr(dvgnc))
def testWithQ(self):
"""Confirm that the inner cells are calculated correctly when quan is provided."""
U = np.array([[1,1,1,1,1],
[1,1,5,1,1],
[1,1,1,1,1],
[1,1,1,1,1],
[1,1,1,1,1]], dtype=np.float32)
V = np.array([[1,1,1,1,1],
[1,1,5,1,1],
[1,1,1,1,1],
[1,1,1,1,1],
[1,1,1,1,1]], dtype=np.float32)
Wind = (U,V)
dx = np.ones_like(U);
dy = np.ones_like(U);
Q = np.array([[1,1,1,1,1],
[1,1,1,1,1],
[1,1,1,1,1],
[1,1,4,1,1],
[1,1,1,1,1]])
dvgnc = Divergence.execute(Wind,dx,dy,Q)
correctAnswer = np.array([[1e37, 1e37, 1e37, 1e37, 1e37],
[1e37, 2, 0, -2, 1e37],
[1e37, 0, -0.5, 0, 1e37],
[1e37, 1.5, 0, -1.5, 1e37],
[1e37, 1e37, 1e37, 1e37, 1e37]], dtype=np.float32)
self.failUnless(np.all(correctAnswer==dvgnc), "Divergence is incorrect.\n" + repr(dvgnc))
if "__main__" == __name__:
unittest.main()

View file

@ -1,59 +0,0 @@
##
# 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 unittest
import numpy as np
import GeoWind
import time
class testGeoWind(unittest.TestCase):
def setUp(self):
self.Height = np.array( range(64), dtype=np.float32).reshape((8,8))
self.dx = np.ones((8,8), dtype=np.float32) * 0.5
self.dy = np.ones((8,8), dtype=np.float32) * 0.5
self.coriolis = np.cos( np.arange(0, 3.14159, 3.14159/8, dtype=np.float32))
self.coriolis = np.ones((8,1)) * self.coriolis
def testExecute(self):
result = GeoWind.execute(self.Height, self.dx, self.dy, self.coriolis)
correct_u = np.array([[ 1e37, 1e37, 1e37, 1e37, 1e37, 1e37, 1e37, 1e37],
[ 1e37, -21.23, -27.74, -51.25,-1.54e7, 51.25, 27.74, 1e37],
[ 1e37, -21.23, -27.74, -51.25,-1.54e7, 51.25, 27.74, 1e37],
[ 1e37, -21.23, -27.74, -51.25,-1.54e7, 51.25, 27.74, 1e37],
[ 1e37, -21.23, -27.74, -51.25,-1.54e7, 51.25, 27.74, 1e37],
[ 1e37, -21.23, -27.74, -51.25,-1.54e7, 51.25, 27.74, 1e37],
[ 1e37, -21.23, -27.74, -51.25,-1.54e7, 51.25, 27.74, 1e37],
[ 1e37, 1e37, 1e37, 1e37, 1e37, 1e37, 1e37, 1e37]],
dtype=np.float32)
correct_v = np.array([[ 1e37, 1e37, 1e37, 1e37, 1e37, 1e37, 1e37, 1e37],
[ 1e37, 169.82, 221.88, 409.98, 1.24e8,-409.99,-221.88, 1e37],
[ 1e37, 169.82, 221.88, 409.98, 1.24e8,-409.99,-221.88, 1e37],
[ 1e37, 169.82, 221.88, 409.98, 1.24e8,-409.99,-221.88, 1e37],
[ 1e37, 169.82, 221.88, 409.98, 1.24e8,-409.99,-221.88, 1e37],
[ 1e37, 169.82, 221.88, 409.98, 1.24e8,-409.99,-221.88, 1e37],
[ 1e37, 169.82, 221.88, 409.98, 1.24e8,-409.99,-221.88, 1e37],
[ 1e37, 1e37, 1e37, 1e37, 1e37, 1e37, 1e37, 1e37]],
dtype=np.float32)
if not np.allclose(result[0], correct_u, 0.01, 0.01):
self.fail("Wrong answer for u:" + repr(result[0]))
if not np.allclose(result[1], correct_v, 0.01, 0.01):
self.fail("Wrong answer for v:" + repr(result[1]))

View file

@ -1,64 +0,0 @@
##
# 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 unittest
import numpy as np
import Gradient
class TestGradient(unittest.TestCase):
def setUp(self):
self.data = np.ones((5,5), dtype=np.float32) * 2.0
np.cumsum(self.data, axis=0, out=self.data)
np.cumsum(self.data, axis=1, out=self.data)
self.dx = np.ones((5,5), dtype=np.float32) * 0.5
self.dy = np.ones((5,5), dtype=np.float32) * 0.5
def testMath(self):
"Check that simple gradients match expectations."
grd_u, grd_v = Gradient.execute(self.data, self.dx, self.dy)
correct_u = np.array([[1e37, 1e37, 1e37, 1e37, 1e37],
[ 4.0, 8.0, 12.0, 16.0, 20.0],
[ 4.0, 8.0, 12.0, 16.0, 20.0],
[ 4.0, 8.0, 12.0, 16.0, 20.0],
[1e37, 1e37, 1e37, 1e37, 1e37]], dtype=np.float32)
correct_v = correct_u.transpose()
if not np.allclose(grd_u, correct_u):
self.fail("" + repr(grd_u));
if not np.allclose(grd_v, correct_v):
self.fail("" + repr(grd_v))
def testClean(self):
"Check that input arrays are not modified."
self.data[1,1] = 1e37
self.dx[1,1] = 1e37
self.dy[1,1] = 1e37
dataCopy = np.copy(self.data)
dxCopy = np.copy(self.dx)
dyCopy = np.copy(self.dy)
dontcare_u, dontcare_v = Gradient.execute(self.data, self.dx, self.dy)
if not np.allclose(self.data, dataCopy):
fail("Data was changed.")
if not np.allclose(self.dx, dxCopy):
fail("dx was changed.")
if not np.allclose(self.dy, dyCopy):
fail("dy was changed.")

View file

@ -1,51 +0,0 @@
##
# 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 unittest
import numpy as np
import IsenStability
class TestIsenStability(unittest.TestCase):
"Unit test for IsenStability function."
def setUp(self):
self.p_up = np.array(range(9), dtype=np.float32).reshape((3,3)) + 900
self.p_lo = self.p_up + np.array(range(9), dtype=np.float32).reshape((3,3)) * 10
self.o_up = 2.1
self.o_lo = 0.1
def testMath(self):
"Test that correct answer is obtained."
result = IsenStability.execute(self.p_up, self.p_lo, self.o_up, self.o_lo)
correct = np.array(range(9), dtype=np.float32).reshape((3,3)) * 5
correct[0,0] = 5.0
if not np.allclose(result, correct):
self.fail("Incorrect result:" + repr(result))
def testInvalid(self):
"Test that invalid inputs result in invalid outputs."
self.p_up[2,2] = 1e37
result = IsenStability.execute(self.p_up, self.p_lo, self.o_up, self.o_lo)
correct = np.array([[5, 5, 10],
[15, 20, 25],
[30, 35, 1e37]], dtype=np.float32)
correct[0,0] = 5.0
if not np.allclose(result, correct):
self.fail("Incorrect result:" + repr(result))

View file

@ -1,52 +0,0 @@
##
# 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 unittest
import numpy as np
import Laplacian
class TestLaplacian(unittest.TestCase):
def setUp(self):
self.Q = np.ones((5,5), dtype=np.float32) * 1.5
self.Q += np.eye(5, 5, 0, dtype=self.Q.dtype) * 0.25
self.dx = np.ones(np.shape(self.Q), dtype=self.Q.dtype)
self.dy = np.ones(np.shape(self.Q), dtype=self.Q.dtype)
def testMath(self):
"Test basic Laplacian math function."
answer = Laplacian.execute(self.Q, self.dx, self.dy)
correctAnswer = np.array([[1e37,1e37,1e37,1e37,1e37],
[1e37,-1,0.5,0,1e37],
[1e37,0.5,-1,0.5,1e37],
[1e37,0, 0.5, -1,1e37],
[1e37,1e37,1e37,1e37,1e37]], dtype=self.Q.dtype)
self.failUnless(np.all(correctAnswer==answer), "Laplacian was incorrect. " + repr(answer))
def testInvalidCell(self):
"Test whether invalid cells are handled properly."
self.Q[1,1] = 1e37
answer = Laplacian.execute(self.Q, self.dx, self.dy)
correctAnswer = np.array([[1e37,1e37,1e37,1e37,1e37],
[1e37,1e37,1e37,0,1e37],
[1e37,1e37,-1,0.5,1e37],
[1e37,0, 0.5, -1,1e37],
[1e37,1e37,1e37,1e37,1e37]], dtype=self.Q.dtype)
self.failUnless(np.all(correctAnswer==answer), "Laplacian was incorrect. " + repr(answer))

View file

@ -1,64 +0,0 @@
##
# 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 unittest
import numpy as np
import LiftedIndex
class TestLiftedIndex(unittest.TestCase):
def setUp(self):
self.P = np.array([600, 700, 800, 900], dtype=np.float32)
self.T = np.array([250, 275, 290, 300], dtype=np.float32)
self.RH = np.array([30, 40, 50, 60], dtype=np.float32)
self.P_500MB = 500.0
self.T_500MB = np.array([290, 280, 270, 260], dtype=np.float32)
def testLiftedIndex(self):
"Test simple operation on 4 data points with P_500MB a scalar."
result = LiftedIndex.execute(self.P, self.T, self.RH, self.T_500MB, self.P_500MB)
correct = np.array([52.701, 27.634, 6.831, -12.093], dtype=np.float32)
if not np.allclose(result, correct, .001, .001):
self.fail("Wrong answer:"+ repr(result))
def testMaskedPValue(self):
self.P[2] = 1e37
result = LiftedIndex.execute(self.P, self.T, self.RH, self.T_500MB, self.P_500MB)
correct = np.array([52.701, 27.634, 1e37, -12.093], dtype=np.float32)
if not np.allclose(result, correct, .001, .001):
self.fail("Wrong answer:"+ repr(result))
def testBadTValue(self):
self.T[2] = 32.0
result = LiftedIndex.execute(self.P, self.T, self.RH, self.T_500MB, self.P_500MB)
correct = np.array([52.701, 27.634, 1e37, -12.093], dtype=np.float32)
if not np.allclose(result, correct, .001, .001):
self.fail("Wrong answer:"+ repr(result))
def testBlackHoleValue(self):
self.P = np.array([1008.18,1013.2], dtype=np.float32)
self.T = np.array([302.02026,299.95776], dtype=np.float32)
self.RH = np.array([88.98621,79.98621], dtype=np.float32)
self.T_500MB = np.array([284.5984,284.3484], dtype=np.float32)
self.P_500MB = 700
result = LiftedIndex.execute(self.P, self.T, self.RH, self.T_500MB, self.P_500MB)
correct = np.array([-3.70840454, 0.28149414], dtype=np.float32)
if not np.allclose(result, correct, .001, .001):
self.fail("Wrong answer:"+ repr(result))

View file

@ -1,74 +0,0 @@
##
# 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 unittest
import numpy as np
import PartialDerivative as Partial
class TestPartialDerivative(unittest.TestCase):
""
def failIfArraysDifferent(self, arr, arr_correct, arr_name):
failMsg = ""
if not arr.shape == arr_correct.shape:
failMsg += "%s.shape = " % (arr_name)
failMsg += arr.shape + "\n"
if not arr.dtype == arr_correct.dtype:
failMsg += "%s.dtype = " % (arr_name)
failMsg += arr.dtype + "\n"
if arr.shape==arr_correct.shape and \
arr.dtype==arr_correct.dtype:
for xidx in range(arr.shape[0]):
for yidx in range(arr.shape[1]):
if np.abs(arr[xidx,yidx]-arr_correct[xidx,yidx])<=0.01:
pass
elif np.isnan(arr[xidx,yidx]) and np.isnan(arr_correct[xidx,yidx]):
pass
else:
failMsg += "%s[%d,%d] = %g" % (arr_name,xidx,yidx, np.ma.filled(arr[xidx,yidx], np.NaN ) )
failMsg += ", expected %g\n" % np.ma.filled(arr_correct[xidx,yidx], np.NaN)
if "" != failMsg:
self.fail(failMsg)
def setUp(self):
self.Qarr = np.array( range(25), dtype=np.float32).reshape((5,5))
self.dx = np.ones((5,5), dtype=np.float32)
self.dx[2,:] = 2
self.dy = np.ones((5,5), dtype=np.float32)
self.dy[:,3] = 2
def testExecute(self):
""
dQdx, dQdy = Partial.calculate(self.Qarr, self.dx, self.dy)
dQdx_correct = np.array([[np.NaN, np.NaN, np.NaN, np.NaN, np.NaN],
[np.NaN, 5, 5, 5, np.NaN],
[np.NaN, 2.50, 2.50, 2.50, np.NaN],
[np.NaN, 5, 5, 5, np.NaN],
[np.NaN, np.NaN, np.NaN, np.NaN, np.NaN]],
dtype=np.float32)
self.failIfArraysDifferent(dQdx, dQdx_correct, "dQdx")
dQdy_correct = np.ma.array([[np.NaN, np.NaN, np.NaN, np.NaN, np.NaN],
[np.NaN, 1, 1, 0.5, np.NaN],
[np.NaN, 1, 1, 0.5, np.NaN],
[np.NaN, 1, 1, 0.5, np.NaN],
[np.NaN, np.NaN, np.NaN, np.NaN, np.NaN]],
dtype=np.float32)
self.failIfArraysDifferent(dQdy, dQdy_correct, "dQdy")

View file

@ -1,70 +0,0 @@
##
# 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 unittest
import numpy as np
import PotVortK
class TestPotVortK(unittest.TestCase):
"Unit test class for PotVortK function."
def setUp(self):
self.p_lo = np.ones((5,5), dtype=np.float32) * 900.0
self.p_up = self.p_lo + 100.0
self.o_up = 285.0
self.o_lo = 283.0
self.u_lo = np.ones_like(self.p_lo) * 4.0
self.v_lo = np.ones_like(self.p_lo) * 3.0
self.Wind_lo = (self.u_lo, self.v_lo)
self.u_up = self.u_lo + 1.0
self.v_up = self.v_lo + 1.0
self.Wind_up = (self.u_up, self.v_up)
self.dx = np.ones_like(self.p_lo)
self.dy = np.ones_like(self.p_lo)
self.coriolis = np.ones_like(self.p_lo) * np.sqrt(2)
def testMath(self):
"Test basic operation."
result = PotVortK.execute(self.p_up, self.p_lo, self.o_up, self.o_lo,
self.Wind_up, self.Wind_lo,
self.dx, self.dy, self.coriolis)
ansr = 2.82842696e-01 # obtained from early test run
correct = np.array([[1e37, 1e37, 1e37, 1e37, 1e37],
[1e37, ansr, ansr, ansr, 1e37],
[1e37, ansr, ansr, ansr, 1e37],
[1e37, ansr, ansr, ansr, 1e37],
[1e37, 1e37, 1e37, 1e37, 1e37]], dtype=np.float32)
if not np.allclose(correct, result):
self.fail("Incorrect value:" + repr(result))
def testMasked(self):
"Send invalid input and make sure output reflects it."
self.p_up[1,1] = 1e37
result = PotVortK.execute(self.p_up, self.p_lo, self.o_up, self.o_lo,
self.Wind_up, self.Wind_lo,
self.dx, self.dy, self.coriolis)
ansr = 2.82842696e-01 # obtained from early test run
correct = np.array([[1e37, 1e37, 1e37, 1e37, 1e37],
[1e37, 1e37, ansr, ansr, 1e37],
[1e37, ansr, ansr, ansr, 1e37],
[1e37, ansr, ansr, ansr, 1e37],
[1e37, 1e37, 1e37, 1e37, 1e37]], dtype=np.float32)
if not np.allclose(correct, result):
self.fail("Incorrect value:" + repr(result))

View file

@ -1,75 +0,0 @@
##
# 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 unittest
import numpy as np
import PotVortMB
class TestPotVortMB(unittest.TestCase):
def setUp(self):
self.t_lo = np.ones((5,5), dtype=np.float32) * 273.15
self.t_up = self.t_lo + 12.5
self.p_lo = np.ones_like(self.t_lo) * 900.0
self.p_up = self.p_lo + 100.0
self.u_lo = np.ones_like(self.t_lo) * 4.0
self.v_lo = np.ones_like(self.t_lo) * 3.0
self.Wind_lo = (self.u_lo, self.v_lo)
self.u_up = self.u_lo + 1.0
self.v_up = self.v_lo + 1.0
self.Wind_up = (self.u_up, self.v_up)
self.dx = np.ones_like(self.t_lo)
self.dy = np.ones_like(self.t_lo)
self.coriolis = np.ones_like(self.t_lo) * np.sqrt(2)
def testMath(self):
"Test simplest operation."
result = PotVortMB.execute(self.t_up, self.t_lo, self.p_up, self.p_lo,
self.Wind_up, self.Wind_lo,
self.dx, self.dy, self.coriolis)
av = 2.82842707634
ansr = -0.5 * (av*12.5 + 1.0*0.0 - 1.0*0.0) / 100
correct = np.array([[1e37, 1e37, 1e37, 1e37, 1e37],
[1e37, ansr, ansr, ansr, 1e37],
[1e37, ansr, ansr, ansr, 1e37],
[1e37, ansr, ansr, ansr, 1e37],
[1e37, 1e37, 1e37, 1e37, 1e37]], dtype=np.float32)
if not np.allclose(correct, result):
self.fail("Incorrect result:" + repr(result))
def testMasked(self):
"Test that function doesn't crash when an input cell is ourNaN."
self.t_up[1,1] = 1e37
result = PotVortMB.execute(self.t_up, self.t_lo, self.p_up, self.p_lo,
self.Wind_up, self.Wind_lo,
self.dx, self.dy, self.coriolis)
av = 2.82842707634
ansr = -0.5 * (av*12.5 + 1.0*0.0 - 1.0*0.0) / 100
correct = np.array([[1e37, 1e37, 1e37, 1e37, 1e37],
[1e37, 1e37, 1e37, ansr, 1e37],
[1e37, 1e37, ansr, ansr, 1e37],
[1e37, ansr, ansr, ansr, 1e37],
[1e37, 1e37, 1e37, 1e37, 1e37]], dtype=np.float32)
if not np.allclose(correct, result):
self.fail("Incorrect result:" + repr(result))

View file

@ -1,50 +0,0 @@
##
# 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 unittest
import numpy as np
import TempOfTe
class TestTempOfTe(unittest.TestCase):
def setUp(self):
pass
def testExecute(self):
'Test operation for 2x1 and 1x2 inputs.'
# This test's arrays are small enough to follow easily in the debugger.
temp = np.array( range(260,315,50), dtype=np.float32)
temp.resize((len(temp),1))
pressure = np.array( range(700,800, 50), dtype=np.float32)
result = TempOfTe.execute(temp, pressure)
correct = np.array( [[256.05, 256.26],[281.49, 282.18]], dtype=np.float32)
if not np.allclose(result, correct, 0.01, 0.01):
self.fail("Wrong answer:" + repr(result))
def testOuterLimits(self):
""
temp = np.array([100.0, 192.0, 193.0, 194.0, 332.0, 333.0, 334.0], dtype=np.float32)
pressure = np.array([730, 730, 730, 730, 730, 730, 730], dtype=np.float32)
result = TempOfTe.execute(temp, pressure)
correct = np.array([100.0, 192.0, 193.0, 194.0, 288.0, 288.0, 1e37], dtype=np.float32)
if not np.allclose(result, correct, 0.01, 0.01):
self.fail("Wrong answer:" + repr(result))

View file

@ -1,78 +0,0 @@
##
# 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 unittest
import numpy as np
import Vorticity
class TestVorticity(unittest.TestCase):
def setUp(self):
"""Set up arrays for calls to Vorticity.execute()."""
self.U = np.ones((5,5), dtype=np.float32)
self.V = np.ones_like(self.U);
self.Wind = (self.U,self.V)
self.Q = np.ones_like(self.U) * 0.5
self.dx = np.ones_like(self.U)
self.dy = np.ones_like(self.U)
def testOuterEdge(self):
"""Confirm that the outer edge is set to the invalid placeholder (1e37). """
vrtct = Vorticity.execute(self.Wind, 0, self.dx, self.dy)
self.assertEquals((5,5), vrtct.shape, "vrtct.shape")
self.assertEquals(np.float32, vrtct.dtype, "vrtct.dtype")
correctAnswer = np.array([[1e37, 1e37, 1e37, 1e37, 1e37],
[1e37, 0, 0, 0, 1e37],
[1e37, 0, 0, 0, 1e37],
[1e37, 0, 0, 0, 1e37],
[1e37, 1e37, 1e37, 1e37, 1e37]], dtype=np.float32)
self.failUnless(np.all(correctAnswer==vrtct))
def testMiddleMath(self):
"""Test """
self.U[1,2] = 5
self.V[1,2] = 5
self.Q[3,2] = 0.8
vrtct = Vorticity.execute(self.Wind, self.Q, self.dx, self.dy)
correctAnswer = np.array([[1e37, 1e37, 1e37, 1e37, 1e37],
[1e37, -1.5, 0.5, 2.5, 1e37],
[1e37, 0.5, -1.5, 0.5, 1e37],
[1e37, 0.5, 0.8, 0.5, 1e37],
[1e37, 1e37, 1e37, 1e37, 1e37]], dtype=np.float32)
self.failUnless(np.all(correctAnswer==vrtct), "Vorticity is incorrect.\n" + repr(vrtct))
def testScalarDxDy(self):
"""Test Vorticity calculation when dx and dy are scalars instead of arrays."""
self.U[1,2] = 5
self.V[1,2] = 5
self.Q[3,2] = 0.8
vrtct = Vorticity.execute(self.Wind, self.Q, 0.1, 0.5)
correctAnswer = np.array([[1e37, 1e37, 1e37, 1e37, 1e37],
[1e37, -3.5, 0.5, 4.5, 1e37],
[1e37, 0.5, -19.5, 0.5, 1e37],
[1e37, 0.5, 0.8, 0.5, 1e37],
[1e37, 1e37, 1e37, 1e37, 1e37]], dtype=np.float32)
self.failUnless(np.all(correctAnswer==vrtct), "Vorticity is incorrect.\n" + repr(vrtct))
if "__main__" == __name__:
unittest.main()

View file

@ -1,78 +0,0 @@
##
# 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 unittest
import numpy as np
import VorticityAdv
class TestVorticityAdv(unittest.TestCase):
def setUp(self):
"""Set up arrays for calls to Vorticity.execute()."""
self.U = np.ones((5,5), dtype=np.float32)
self.V = np.ones_like(self.U);
self.Wind = (self.U,self.V)
self.Q = np.ones_like(self.U) * 0.5
self.dx = np.ones_like(self.U)
self.dy = np.ones_like(self.U)
def testOuterEdge(self):
"""Confirm that the outer edge is set to the invalid placeholder (1e37). """
vrtcta = VorticityAdv.execute(self.Wind, self.Q, self.dx, self.dy)
self.assertEquals((5,5), vrtcta.shape, "vrtcta.shape")
self.assertEquals(np.float32, vrtcta.dtype, "vrtcta.dtype")
correctAnswer = np.array([[1e37, 1e37, 1e37, 1e37, 1e37],
[1e37, 0, 0, 0, 1e37],
[1e37, 0, 0, 0, 1e37],
[1e37, 0, 0, 0, 1e37],
[1e37, 1e37, 1e37, 1e37, 1e37]], dtype=np.float32)
self.failUnless(np.all(correctAnswer==vrtcta))
def testMiddleMath(self):
"""Test """
self.U[1,2] = 5
self.V[1,2] = 5
self.Q[3,2] = 0.8
vrtcta = VorticityAdv.execute(self.Wind, self.Q, self.dx, self.dy)
correctAnswer = np.array([[1e37, 1e37, 1e37, 1e37, 1e37],
[1e37, 4.0, 0, 4.0, 1e37],
[1e37, 0, -4.15, 0, 1e37],
[1e37, -0.15, 0, 0.15, 1e37],
[1e37, 1e37, 1e37, 1e37, 1e37]], dtype=np.float32)
self.failUnless(np.all(correctAnswer==vrtcta), "VorticityAdv is incorrect.\n" + repr(vrtcta))
def testScalarDxDy(self):
"""Test Vorticity calculation when dx and dy are scalars instead of arrays."""
self.U[1,2] = 5
self.V[1,2] = 5
self.Q[3,2] = 0.8
vrtcta = VorticityAdv.execute(self.Wind, self.Q, 0.1, 0.5)
correctAnswer = np.array([[1e37, 1e37, 1e37, 1e37, 1e37],
[1e37, 80, 0, 80, 1e37],
[1e37, 0, -81.5, 0, 1e37],
[1e37, -0.3, 0, 0.3, 1e37],
[1e37, 1e37, 1e37, 1e37, 1e37]], dtype=np.float32)
self.failUnless(np.all(correctAnswer==vrtcta), "VorticityAdv is incorrect.\n" + repr(vrtcta))
if "__main__" == __name__:
unittest.main()

View file

@ -27,27 +27,21 @@ from numpy import radians
from numpy import abs
from numpy import isscalar, empty, float32
def execute(u, v, legacyOption=None):
def execute(u, v, magDir=None):
""" Make a vector from u,v or mag, dir.
@param legacyOption
@param magDir
controls how the function operates on the given u and v values.
When the legacyOption is specified and is a constant scalar value
When the magDir 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
positive :: assume meteorological direction(direction from)
negative :: assume mathematical direction(direction to)
abs(legacyOption) == 1 :: assume degrees
abs(legacyOption) != 1 :: assume radians
abs(legacyOption) == 1 :: assume direction in degrees
abs(legacyOption) != 1 :: assume direction in 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)
@return: tuple of (u,v)
"""
# If either u or v is a single number, expand it to match an entire Grid
@ -61,161 +55,35 @@ def execute(u, v, legacyOption=None):
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
if magDir == None:
return componentsTo(u, v)
elif magDir == 1:
return magDirDegreesFrom(u, v);
elif magDir == -1:
return magDirDegreesTo(u, v);
elif magDir >= 0:
return magDirRadiansFrom(u, v);
else:
speed = legacyOption
return magDirRadiansTo(u, v);
completeRevolution = 360 if not useRadians else radians(360.0)
def componentsTo(u,v):
return (u, v)
if (polar):
mag = u
dir = v
def magDirRadiansTo(mag, dir):
u = sin(dir) * mag
v = cos(dir) * mag
return componentsTo(u,v)
# replace all negative angles with their corresponding positive values
negDirMask = dir < 0
dir[negDirMask] = (- dir[negDirMask]) % completeRevolution
dir[negDirMask] = completeRevolution - dir[negDirMask]
def magDirDegreesTo(mag, dir):
return magDirRadiansTo(mag, radians(dir))
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
def componentsFrom(u,v):
return componentsTo(-u,-v)
u = - u if not mathematicalDirection else u
v = - v if not mathematicalDirection else v
def magDirRadiansFrom(mag, dir):
u = sin(dir) * mag
v = cos(dir) * mag
return componentFrom(u,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"
def magDirDegreesFrom(mag, dir):
return magDirRadiansFrom(mag, radians(dir))

View file

@ -1,75 +0,0 @@
/**
* 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.
**/
package com.raytheon.uf.viz.derivparam.python;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.osgi.framework.BundleContext;
/**
* The activator class controls the plug-in life cycle
*/
public class Activator extends AbstractUIPlugin {
// The plug-in ID
public static final String PLUGIN_ID = "com.raytheon.uf.viz.derivparam.python";
// The shared instance
private static Activator plugin;
/**
* The constructor
*/
public Activator() {
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext
* )
*/
public void start(BundleContext context) throws Exception {
super.start(context);
plugin = this;
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext
* )
*/
public void stop(BundleContext context) throws Exception {
plugin = null;
super.stop(context);
}
/**
* Returns the shared instance
*
* @return the shared instance
*/
public static Activator getDefault() {
return plugin;
}
}

View file

@ -2,30 +2,23 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Derived Parameter Plug-in
Bundle-SymbolicName: com.raytheon.uf.viz.derivparam;singleton:=true
Bundle-Version: 1.12.1174.qualifier
Bundle-Activator: com.raytheon.uf.viz.derivparam.Activator
Bundle-Version: 1.14.0.qualifier
Bundle-Vendor: RAYTHEON
Require-Bundle: org.eclipse.core.runtime,
javax.measure,
com.raytheon.uf.viz.core;bundle-version="1.12.1174",
com.raytheon.uf.common.datastorage;bundle-version="1.12.1174",
com.raytheon.uf.common.pointdata;bundle-version="1.12.1174",
com.raytheon.uf.common.dataplugin.level;bundle-version="1.12.1174",
com.raytheon.uf.common.util;bundle-version="1.12.1174"
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Bundle-ActivationPolicy: lazy
Eclipse-RegisterBuddy: com.raytheon.uf.common.serialization
Import-Package: com.raytheon.uf.common.comm,
com.raytheon.uf.common.dataplugin,
com.raytheon.uf.common.derivparam.tree,
com.raytheon.uf.common.geospatial,
com.raytheon.uf.common.localization,
com.raytheon.uf.common.serialization,
com.raytheon.uf.common.serialization.adapters,
com.raytheon.uf.common.status,
Require-Bundle: com.raytheon.uf.common.derivparam,
com.raytheon.uf.common.time,
com.vividsolutions.jts.geom,
org.opengis.referencing.crs
com.raytheon.uf.common.dataplugin.level,
com.raytheon.uf.common.geospatial,
com.raytheon.uf.common.dataplugin,
com.raytheon.uf.common.datastorage,
com.raytheon.uf.common.pointdata;bundle-version="1.13.0",
com.raytheon.uf.viz.core;bundle-version="1.13.0",
com.raytheon.uf.common.util,
com.raytheon.uf.common.comm,
org.eclipse.core.runtime;bundle-version="3.8.0",
org.eclipse.ui.workbench;bundle-version="3.8.0",
javax.measure
Export-Package: com.raytheon.uf.viz.derivparam,
com.raytheon.uf.viz.derivparam.data,
com.raytheon.uf.viz.derivparam.inv,

View file

@ -18,9 +18,9 @@
See_the_AWIPS_II_Master_Rights_File_("Master_Rights_File.pdf")_for
further_licensing_information.
-->
<DerivedParameter abbreviation="FeatMot" name="Feature Motion" unit="kt">
<DerivedParameter abbreviation="FeatMot" name="Feature Motion" unit="kn">
<Method name="Vector">
<Field abbreviation="USTM"/>
<Field abbreviation="VSTM"/>
<Field abbreviation="USTM" unit="kn"/>
<Field abbreviation="VSTM" unit="kn"/>
</Method>
</DerivedParameter>

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<DerivedParameter unit="m/s" name="Wind Gust" abbreviation="Gust" xmlns:ns2="group">
<Method name="Vector" levels="Surface" models="obs">
<Field level="Station" abbreviation="windGust"/>
<Field level="Station" abbreviation="windGust" unit="m/s"/>
<Field abbreviation="WD" unit="deg"/>
<ConstantField value="1.0"/>
</Method>
@ -19,9 +19,4 @@
<Field abbreviation="WD" unit="deg"/>
<ConstantField value="1.0"/>
</Method>
<Method name="Vector">
<Field abbreviation="uW"/>
<Field abbreviation="vW"/>
<Field abbreviation="WGS" unit="m/s"/>
</Method>
</DerivedParameter>

View file

@ -23,8 +23,8 @@
<Field abbreviation="DMD"/>
</Method>
<Method name="Vector">
<Field abbreviation="USTM"/>
<Field abbreviation="VSTM"/>
<Field abbreviation="USTM" unit="kn"/>
<Field abbreviation="VSTM" unit="kn"/>
</Method>
<Method levels="Layer" name="Rotate">
<Field level="0-6kmAgl" abbreviation="Wind"/>

View file

@ -23,11 +23,11 @@
<Field abbreviation="Windmean"/>
</Method>
<Method name="Vector">
<Field abbreviation="uW"/>
<Field abbreviation="vW"/>
<Field abbreviation="uW" unit="m/s"/>
<Field abbreviation="vW" unit="m/s"/>
</Method>
<Method name="Vector">
<Field abbreviation="wSp"/>
<Field abbreviation="wSp" unit="m/s"/>
<Field abbreviation="WD" unit="deg"/>
<ConstantField value="1.0"/>
</Method>

View file

@ -18,13 +18,13 @@
See_the_AWIPS_II_Master_Rights_File_("Master_Rights_File.pdf")_for
further_licensing_information.
-->
<DerivedParameter abbreviation="Windmean" name="Mean Wind" unit="kt">
<DerivedParameter abbreviation="Windmean" name="Mean Wind" unit="kn">
<Method name="Vector">
<Field abbreviation="uWmean" unit="kts"/>
<Field abbreviation="vWmean" unit="kts"/>
<Field abbreviation="uWmean" unit="kn"/>
<Field abbreviation="vWmean" unit="kn"/>
</Method>
<Method name="Vector">
<Field abbreviation="WSmean" unit="kts"/>
<Field abbreviation="WSmean" unit="kn"/>
<Field abbreviation="WDmean" unit="deg"/>
<ConstantField value="1.0"/>
</Method>

View file

@ -1,57 +0,0 @@
package com.raytheon.uf.viz.derivparam;
import org.eclipse.core.runtime.Plugin;
import org.osgi.framework.BundleContext;
import com.raytheon.uf.viz.derivparam.library.DerivedParameterGenerator;
/**
* The activator class controls the plug-in life cycle
*/
public class Activator extends Plugin {
// The plug-in ID
public static final String PLUGIN_ID = "com.raytheon.uf.common.derivparam";
// The shared instance
private static Activator plugin;
/**
* The constructor
*/
public Activator() {
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.core.runtime.Plugins#start(org.osgi.framework.BundleContext)
*/
public void start(BundleContext context) throws Exception {
super.start(context);
plugin = this;
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.core.runtime.Plugin#stop(org.osgi.framework.BundleContext)
*/
public void stop(BundleContext context) throws Exception {
plugin = null;
super.stop(context);
DerivedParameterGenerator.shutdown();
}
/**
* Returns the shared instance
*
* @return the shared instance
*/
public static Activator getDefault() {
return plugin;
}
}

View file

@ -39,8 +39,9 @@ import com.raytheon.uf.viz.core.exception.VizException;
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jan 15, 2010 #3965 rjpeter Initial creation
* ------------- -------- ----------- --------------------------
* Jan 15, 2010 3965 rjpeter Initial creation
* Jan 14, 2014 2661 bsteffen Make vectors u,v only
*
* </pre>
*
@ -73,15 +74,12 @@ public class AliasRequestableData extends AbstractRequestableData {
}
} else if (rval instanceof FloatDataRecord[]) {
FloatDataRecord[] recs = (FloatDataRecord[]) rval;
FloatDataRecord[] newRecs = new FloatDataRecord[recs.length];
IDataRecord[] newRecs = new FloatDataRecord[recs.length];
rval = newRecs;
for (int i = 0; i < recs.length; i++) {
if (recs[i] instanceof FloatDataRecord) {
newRecs[i] = (FloatDataRecord) ((FloatDataRecord) recs[i])
.clone();
newRecs[i] = recs[i].clone();
if (this.parameter != null) {
((FloatDataRecord) newRecs[i]).setName(this.parameter);
}
newRecs[i].setName(this.parameter);
}
}
} else if (rval instanceof IDataRecord[]) {
@ -89,11 +87,9 @@ public class AliasRequestableData extends AbstractRequestableData {
IDataRecord[] newRecs = new IDataRecord[recs.length];
rval = newRecs;
for (int i = 0; i < recs.length; i++) {
if (recs[i] instanceof IDataRecord) {
newRecs[i] = ((IDataRecord) recs[i]).clone();
newRecs[i] = recs[i].clone();
if (this.parameter != null) {
((IDataRecord) newRecs[i]).setName(this.parameter);
}
newRecs[i].setName(this.parameter);
}
}
}
@ -118,17 +114,7 @@ public class AliasRequestableData extends AbstractRequestableData {
FloatDataRecord[] recs = (FloatDataRecord[]) rval;
if (recs.length != 1 || !unit.equals(NonSI.DEGREE_ANGLE)) {
for (int i = 0; i < recs.length; i++) {
// Currently arrays are only used for Vectors,
// Vectors
// are represented as [Mag,Dir,U,V], If we attempt
// to
// convert Dir it goes badly, so this skips it.
if (i == 1) {
continue;
}
if (recs[i] instanceof FloatDataRecord) {
float[] data = ((FloatDataRecord) recs[i])
.getFloatData();
float[] data = recs[i].getFloatData();
for (int c = 0; c < data.length; c++) {
if (data[c] > -9999) {
data[c] = (float) converter
@ -137,25 +123,15 @@ public class AliasRequestableData extends AbstractRequestableData {
}
}
}
}
} else if (rval instanceof IDataRecord[]) {
IDataRecord[] recs = (IDataRecord[]) rval;
if (recs.length != 1 || !unit.equals(NonSI.DEGREE_ANGLE)) {
for (int i = 0; i < recs.length; i++) {
// Currently arrays are only used for Vectors,
// Vectors
// are represented as [Mag,Dir,U,V], If we attempt
// to
// convert Dir it goes badly, so this skips it.
if (i == 1) {
continue;
}
if (recs[i] instanceof FloatDataRecord) {
float[] data = ((FloatDataRecord) recs[i])
.getFloatData();
for (int c = 0; c < data.length; c++) {
if (data[c] > -9999) {
data[c] = (float) converter
.convert(data[c]);
}

View file

@ -42,10 +42,12 @@ import com.raytheon.uf.viz.derivparam.tree.CubeLevel;
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* ------------- -------- ----------- --------------------------
* Mar 17, 2010 bsteffen Initial creation
* Jun 04, 2013 2041 bsteffen Switch derived parameters to use
* concurrent python for threading.
* Jan 14, 2014 2661 bsteffen Make vectors u,v only
*
*
* </pre>
*
@ -80,14 +82,14 @@ public class DerivedRequestableData extends AbstractRequestableData {
List<IDataRecord> finalResult = DerivedParameterGenerator
.calculate(request);
if (finalResult != null && !finalResult.isEmpty()) {
if (finalResult.size() == 4 || finalResult.size() == 1) {
if (finalResult.size() == 2 || finalResult.size() == 1) {
for (IDataRecord rec : finalResult) {
rec.setName(request.getParameterAbbreviation());
}
return finalResult.toArray(new IDataRecord[0]);
} else {
throw new VizException(
"Error processing derived parameter, expecting scalar or vector data. Vector data must return speed, dir, u, and v components.");
"Error processing derived parameter, expecting scalar or vector data. Vector data must return u and v components.");
}
}
} catch (ExecutionException e) {

View file

@ -24,8 +24,6 @@ import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
import com.raytheon.uf.common.serialization.ISerializableObject;
/**
* Metadata about a derived parameter field.
*
@ -35,8 +33,10 @@ import com.raytheon.uf.common.serialization.ISerializableObject;
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* 11/21/2009 #3576 rjpeter Initial version
* ------------- -------- ----------- --------------------------
* Nov 21, 2009 3576 rjpeter Initial version
* Jan 14, 2014 2661 bsteffen Remove ISerializableObject
*
* </pre>
*
* @author rjpeter
@ -44,8 +44,7 @@ import com.raytheon.uf.common.serialization.ISerializableObject;
*/
@XmlAccessorType(XmlAccessType.NONE)
@XmlRootElement
public class DerivParamConstantField implements ISerializableObject,
IDerivParamField {
public class DerivParamConstantField implements IDerivParamField {
@XmlAttribute(required = true)
private Float value;

View file

@ -30,7 +30,6 @@ import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import com.raytheon.uf.common.serialization.ISerializableObject;
import com.raytheon.uf.common.serialization.adapters.UnitAdapter;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
@ -45,8 +44,10 @@ import com.raytheon.uf.common.status.UFStatus.Priority;
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* 11/21/2009 #3576 rjpeter Initial version
* ------------- -------- ----------- --------------------------
* Nov 21, 2009 3576 rjpeter Initial version
* Jan 14, 2014 2661 bsteffen Remove ISerializableObject
*
* </pre>
*
* @author rjpeter
@ -54,7 +55,7 @@ import com.raytheon.uf.common.status.UFStatus.Priority;
*/
@XmlAccessorType(XmlAccessType.NONE)
@XmlRootElement(name = "DerivedParameter")
public class DerivParamDesc implements ISerializableObject {
public class DerivParamDesc {
private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(DerivParamDesc.class);

View file

@ -29,7 +29,6 @@ import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import com.raytheon.uf.common.dataplugin.level.mapping.LevelMapping;
import com.raytheon.uf.common.dataplugin.level.mapping.LevelMappingFactory;
import com.raytheon.uf.common.serialization.ISerializableObject;
import com.raytheon.uf.common.serialization.adapters.UnitAdapter;
import com.raytheon.uf.viz.core.exception.VizCommunicationException;
@ -42,8 +41,10 @@ import com.raytheon.uf.viz.core.exception.VizCommunicationException;
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* 11/21/2009 #3576 rjpeter Initial version
* ------------- -------- ----------- --------------------------
* Nov 21, 2009 3576 rjpeter Initial version
* Jan 14, 2014 2661 bsteffen Remove ISerializableObject
*
* </pre>
*
* @author rjpeter
@ -51,7 +52,7 @@ import com.raytheon.uf.viz.core.exception.VizCommunicationException;
*/
@XmlAccessorType(XmlAccessType.NONE)
@XmlRootElement
public class DerivParamField implements ISerializableObject, IDerivParamField {
public class DerivParamField implements IDerivParamField {
@XmlAttribute(name = "abbreviation", required = true)
private String param;

View file

@ -34,7 +34,6 @@ import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
import com.raytheon.uf.common.dataplugin.level.Level;
import com.raytheon.uf.common.serialization.ISerializableObject;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
@ -50,8 +49,10 @@ import com.raytheon.uf.viz.core.exception.VizException;
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* 11/21/2009 #3576 rjpeter Initial version
* ------------- -------- ----------- --------------------------
* Nov 21, 2009 3576 rjpeter Initial version
* Jan 14, 2014 2661 bsteffen Remove ISerializableObject
*
* </pre>
*
* @author rjpeter
@ -59,7 +60,7 @@ import com.raytheon.uf.viz.core.exception.VizException;
*/
@XmlAccessorType(XmlAccessType.NONE)
@XmlRootElement
public class DerivParamMethod implements ISerializableObject {
public class DerivParamMethod {
private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(DerivParamMethod.class);

View file

@ -42,6 +42,7 @@ import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.ui.services.IDisposable;
import com.raytheon.uf.common.datastorage.records.IDataRecord;
import com.raytheon.uf.common.localization.FileUpdatedMessage;
@ -55,29 +56,21 @@ import com.raytheon.uf.common.serialization.JAXBManager;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.viz.core.Activator;
import com.raytheon.uf.viz.derivparam.DerivParamFunctionType;
import com.raytheon.uf.viz.derivparam.IDerivParamFunctionAdapter;
import com.raytheon.uf.viz.derivparam.library.DerivParamMethod.MethodType;
/**
* A thread that accepts requests for a derived parameter, passes it to JEP and
* returns the request. It is important to note that this thread performs a
* sleep instead of a schedule to keep the JEP instance in the same thread. To
* properly interact with this thread, it is important to use
* <code>DerivedParameterRequest</code> and submit it using the static method
* <code>addTask</code>.<br/>
* <br/>
* <b>IMPORTANT</b> A call to <code>getDerivParamLib</code> should be made
* immediately after an instance of the datacube container is created or after a
* call to <code>requestDerivParamUpdate</code>. The reason for this is the main
* thread will load all derived parameters and then offer them via a synchronous
* queue. Until the queue is polled, the main derived parameter thread will
* hang.
* Primary public interface for derived parameters. Introspection on the derived
* parameters available can be done using {@link #getDerParLibrary()}. For
* actually performing derived parameters calculations the
* {@link #calculate(DerivedParameterRequest)} method can be used.
*
* <pre>
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* ------------- -------- ----------- --------------------------
* Jul 03, 2008 brockwoo Initial creation
* Nov 16, 2009 3120 rjpeter Removed use of LevelNameMappingFile.
* Nov 20, 2009 3387 jelkins Use derived script's variableId instead
@ -86,6 +79,8 @@ import com.raytheon.uf.viz.derivparam.library.DerivParamMethod.MethodType;
* Jun 04, 2013 2041 bsteffen Switch derived parameters to use
* concurrent python for threading.
* Nov 19, 2013 2361 njensen Only shutdown if initialized
* Jan 14, 2014 2661 bsteffen Shutdown using uf.viz.core.Activator
*
* </pre>
*
* @author brockwoo
@ -201,6 +196,13 @@ public class DerivedParameterGenerator implements ILocalizationFileObserver {
"Error creating derived parameter function type,"
+ " derived paramters will not be available");
}
Activator.getDefault().registerDisposable(new IDisposable() {
@Override
public void dispose() {
shutdown();
}
});
this.adapter = functionTypes[0].getAdapter();
this.extension = functionTypes[0].getExtension();
notifyJob.setSystem(true);
@ -251,8 +253,8 @@ public class DerivedParameterGenerator implements ILocalizationFileObserver {
for (LocalizationFile file : xmlFiles) {
try {
DerivParamDesc desc = (DerivParamDesc) jaxbMan
.unmarshalFromXmlFile(file.getFile());
DerivParamDesc desc = jaxbMan.unmarshalFromXmlFile(
DerivParamDesc.class, file.getFile());
if (derParLibrary.containsKey(desc.getAbbreviation())) {
DerivParamDesc oldDesc = derParLibrary.get(desc
.getAbbreviation());
@ -330,9 +332,10 @@ public class DerivedParameterGenerator implements ILocalizationFileObserver {
initLibrary();
}
public static void shutdown() {
public static synchronized void shutdown() {
if (instance != null) {
getInstance().adapter.shutdown();
instance = null;
}
}

View file

@ -50,8 +50,10 @@ import com.raytheon.uf.viz.core.exception.VizCommunicationException;
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* 11/21/2009 #3576 rjpeter Initial version
* ------------- -------- ----------- --------------------------
* Nov 21, 2009 3576 rjpeter Initial version
* Jan 14, 2014 2661 bsteffen Remove unnecessary exceptions
*
*
* &#064;author rjpeter
* @version 1.0
@ -149,8 +151,7 @@ public class ValidLevelGenerator {
return validLevels;
}
private void processLevelToken(String token)
throws VizCommunicationException, CommunicationException {
private void processLevelToken(String token) throws CommunicationException {
boolean negate = token.charAt(0) == '!';
int rangeIndex = token.indexOf('>');
@ -341,8 +342,7 @@ public class ValidLevelGenerator {
}
}
private Type determineType(String token) throws CommunicationException,
VizCommunicationException {
private Type determineType(String token) throws CommunicationException {
Type rval = null;
LevelMapping mapping = lmf.getLevelMappingForKey(token);

View file

@ -27,6 +27,8 @@ import org.geotools.referencing.GeodeticCalculator;
import com.raytheon.uf.common.geospatial.MapUtil;
import com.raytheon.uf.common.geospatial.ReferencedCoordinate;
import com.raytheon.uf.common.geospatial.interpolation.data.DataSource;
import com.raytheon.uf.common.geospatial.interpolation.data.FloatBufferWrapper;
import com.raytheon.uf.viz.core.IExtent;
import com.raytheon.uf.viz.core.IGraphicsTarget;
import com.raytheon.uf.viz.core.IGraphicsTarget.LineStyle;
@ -50,7 +52,7 @@ import com.vividsolutions.jts.geom.Coordinate;
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------- -------- ----------- --------------------------
* ------------- -------- ----------- -----------------------------------------
* Jun 22, 2010 bsteffen Initial creation
* Feb 07, 2011 7948 bkowal added a public method to get the
* direction.
@ -62,11 +64,14 @@ import com.vividsolutions.jts.geom.Coordinate;
* gridRelative flag to indicate whether
* direction data is relative to grid or
* true north
* Sep 09, 2013 16257 MPorricelli When setDestinationGeographicPoint fails (which can
* happen for global lat/lon grid winds displayed on
* Equidistant Cylindrical map) try again with different
* Sep 09, 2013 16257 MPorricelli When setDestinationGeographicPoint fails
* (which can happen for global lat/lon grid
* winds displayed on Equidistant
* Cylindrical map) try again with different
* pixel location.
* Sep 23, 2013 2363 bsteffen Add more vector configuration options.
* Jan 14, 2014 2661 bsteffen Switch magnitude and direction from
* buffers to DataSource
*
* </pre>
*
@ -75,9 +80,9 @@ import com.vividsolutions.jts.geom.Coordinate;
*/
public class GriddedVectorDisplay extends AbstractGriddedDisplay<Coordinate> {
private final FloatBuffer magnitude;
private final DataSource magnitude;
private final FloatBuffer direction;
private final DataSource direction;
private int lineWidth;
@ -96,20 +101,26 @@ public class GriddedVectorDisplay extends AbstractGriddedDisplay<Coordinate> {
private GeodeticCalculator gc;
/**
*
* @param magnitude
* a data source for the magnitude of vectors
* @param direction
* a data source for the direction of vectors
* @param descriptor
* the descriptor
* @param gridGeometryOfGrid
* @param size
* geometry of the data sources
* @param densityFactor
* adjustment factor to make density match A1
* @param gridRelative
* true if direction is grid relative, false if relative to true
* north
* @param displayType
* @param factory
* how to render the vector
* @param config
* custom rendering hints
*/
public GriddedVectorDisplay(FloatBuffer magnitude, FloatBuffer direction,
public GriddedVectorDisplay(DataSource magnitude, DataSource direction,
IMapDescriptor descriptor, GeneralGridGeometry gridGeometryOfGrid,
double densityFactor, boolean gridRelative,
DisplayType displayType, VectorGraphicsConfig config) {
@ -123,6 +134,21 @@ public class GriddedVectorDisplay extends AbstractGriddedDisplay<Coordinate> {
this.vectorConfig = config;
}
/**
* Construct using float buffers instead of data sources.
*
* @See {@link #GriddedVectorDisplay(DataSource, DataSource, IMapDescriptor, GeneralGridGeometry, double, boolean, DisplayType, VectorGraphicsConfig)}
*/
public GriddedVectorDisplay(FloatBuffer magnitude, FloatBuffer direction,
IMapDescriptor descriptor, GeneralGridGeometry gridGeometryOfGrid,
double densityFactor, boolean gridRelative,
DisplayType displayType, VectorGraphicsConfig config) {
this(new FloatBufferWrapper(magnitude, gridGeometryOfGrid),
new FloatBufferWrapper(direction, gridGeometryOfGrid),
descriptor, gridGeometryOfGrid, densityFactor, gridRelative,
displayType, config);
}
@Override
public void paint(IGraphicsTarget target, PaintProperties paintProps)
throws VizException {
@ -151,17 +177,18 @@ public class GriddedVectorDisplay extends AbstractGriddedDisplay<Coordinate> {
@Override
protected void paint(Coordinate ijcoord, PaintProperties paintProps,
Coordinate plotLoc, double adjSize) throws VizException {
int idx = (int) (ijcoord.x + (ijcoord.y * this.gridDims[0]));
float spd = this.magnitude.get(idx);
float dir = this.direction.get(idx);
double spd = this.magnitude.getDataValue((int) ijcoord.x,
(int) ijcoord.y);
double dir = this.direction.getDataValue((int) ijcoord.x,
(int) ijcoord.y);
if (dir < -999999 || dir > 9999999) {
// perhaps this check should limit +/- 180
return;
}
if (Float.isNaN(spd) || Float.isNaN(dir)) {
if (Double.isNaN(spd) || Double.isNaN(dir)) {
return;
}
int tryDiffPixLoc = 0;
@ -269,17 +296,6 @@ public class GriddedVectorDisplay extends AbstractGriddedDisplay<Coordinate> {
return false;
}
/**
* @return the magnitude
*/
public FloatBuffer getMagnitude() {
return magnitude;
}
public FloatBuffer getDirection() {
return direction;
}
@Override
protected void disposeResources() {
if (vectorRenderable != null) {

View file

@ -105,7 +105,7 @@ import com.vividsolutions.jts.geom.Coordinate;
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------- -------- ----------- --------------------------
* ------------- -------- ----------- -----------------------------------------
* Mar 09, 2011 bsteffen Initial creation
* May 08, 2013 1980 bsteffen Set paint status in GridResources for
* KML.
@ -113,8 +113,12 @@ import com.vividsolutions.jts.geom.Coordinate;
* Aug 27, 2013 2287 randerso Added new parameters required by
* GriddedVectorDisplay and
* GriddedIconDisplay
* Sep 24, 2013 2404 bclement colormap params now created using match criteria
* Sep 24, 2013 2404 bclement colormap params now created using match
* criteria
* Sep 23, 2013 2363 bsteffen Add more vector configuration options.
* Jan 14, 2014 2594 bsteffen Switch vector mag/dir to use data source
* instead of raw float data.
*
*
* </pre>
*
@ -525,7 +529,7 @@ public abstract class AbstractGridResource<T extends AbstractResourceData>
}
}
GriddedVectorDisplay vectorDisplay = new GriddedVectorDisplay(
data.getMagnitude(), data.getDirection(), descriptor,
data.getMagnitude(), data.getDirectionFrom(), descriptor,
gridGeometry, VECTOR_DENSITY_FACTOR, true, displayType,
config);
vectorDisplay.setColor(getCapability(ColorableCapability.class)
@ -844,8 +848,13 @@ public abstract class AbstractGridResource<T extends AbstractResourceData>
"Error transforming coordinate for interrogate", e);
}
Interpolation interpolation = getInspectInterpolation(data);
GridSampler sampler = new GridSampler(new FloatBufferWrapper(
GridSampler sampler = null;
if (data.isVector()) {
sampler = new GridSampler(data.getMagnitude(), interpolation);
} else {
sampler = new GridSampler(new FloatBufferWrapper(
data.getScalarData(), data.getGridGeometry()), interpolation);
}
double value = sampler.sample(pixel.x, pixel.y);
if (Double.isNaN(value)) {
return null;
@ -872,8 +881,7 @@ public abstract class AbstractGridResource<T extends AbstractResourceData>
result.put(INTERROGATE_UNIT, "");
}
if (data.isVector()) {
sampler.setSource(new FloatBufferWrapper(data.getDirection(), data
.getGridGeometry()));
sampler.setSource(data.getDirectionFrom());
Double dir = sampler.sample(pixel.x, pixel.y);
result.put(INTERROGATE_DIRECTION, dir);
}

View file

@ -42,6 +42,7 @@ import com.raytheon.uf.common.geospatial.interpolation.GridReprojection;
import com.raytheon.uf.common.geospatial.interpolation.GridSampler;
import com.raytheon.uf.common.geospatial.interpolation.Interpolation;
import com.raytheon.uf.common.geospatial.interpolation.PrecomputedGridReprojection;
import com.raytheon.uf.common.geospatial.interpolation.data.DataSource;
import com.raytheon.uf.common.geospatial.interpolation.data.FloatArrayWrapper;
import com.raytheon.uf.common.geospatial.interpolation.data.FloatBufferWrapper;
import com.vividsolutions.jts.geom.Coordinate;
@ -56,11 +57,14 @@ import com.vividsolutions.jts.geom.Coordinate;
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* ------------- -------- ----------- -----------------------------------------
* Mar 09, 2011 bsteffen Initial creation
* Jul 17, 2013 2185 bsteffen Cache computed grid reprojections.
* Aug 27, 2013 2287 randerso Removed 180 degree adjustment required by error
* in Maputil.rotation
* Aug 27, 2013 2287 randerso Removed 180 degree adjustment required by
* error in Maputil.rotation
* Jan 14, 2014 2661 bsteffen For vectors only keep uComponent and
* vComponent, calculate magnitude and
* direction on demand.
*
* </pre>
*
@ -71,13 +75,11 @@ public class GeneralGridData {
private GridGeometry2D gridGeometry;
private FloatBuffer scalarData;
private FloatBufferWrapper scalarData;
private FloatBuffer direction = null;
private FloatBufferWrapper uComponent = null;
private FloatBuffer uComponent = null;
private FloatBuffer vComponent = null;
private FloatBufferWrapper vComponent = null;
private Unit<?> dataUnit;
@ -100,18 +102,16 @@ public class GeneralGridData {
* used when both these representations are readily available to save time
* if one or the other is needed later.
*
* @param magnitude
* @param direction
* @param uComponent
* @param vComponent
* @param dataUnit
* @return
* @deprecated Magnitude and direction are ignored, use
* {@link #createVectorDataUV(GeneralGridGeometry, FloatBuffer, FloatBuffer, Unit)}
*/
@Deprecated
@SuppressWarnings("unused")
public static GeneralGridData createVectorData(
GeneralGridGeometry gridGeometry, FloatBuffer magnitude,
FloatBuffer direction, FloatBuffer uComponent,
FloatBuffer vComponent, Unit<?> dataUnit) {
return new GeneralGridData(gridGeometry, magnitude, direction,
return new GeneralGridData(gridGeometry,
uComponent, vComponent, dataUnit);
}
@ -127,8 +127,17 @@ public class GeneralGridData {
public static GeneralGridData createVectorData(
GeneralGridGeometry gridGeometry, FloatBuffer magnitude,
FloatBuffer direction, Unit<?> dataUnit) {
return new GeneralGridData(gridGeometry, magnitude, direction, null,
null, dataUnit);
magnitude.rewind();
direction.rewind();
FloatBuffer vComponent = FloatBuffer.allocate(magnitude.capacity());
FloatBuffer uComponent = FloatBuffer.allocate(magnitude.capacity());
while (magnitude.hasRemaining()) {
double angle = Math.toRadians(direction.get());
vComponent.put((float) (Math.cos(angle) * magnitude.get()));
uComponent.put((float) (Math.sin(angle) * magnitude.get()));
}
return new GeneralGridData(gridGeometry, uComponent, vComponent,
dataUnit);
}
/**
@ -143,25 +152,23 @@ public class GeneralGridData {
public static GeneralGridData createVectorDataUV(
GeneralGridGeometry gridGeometry, FloatBuffer uComponent,
FloatBuffer vComponent, Unit<?> dataUnit) {
return new GeneralGridData(gridGeometry, null, null, uComponent,
return new GeneralGridData(gridGeometry, uComponent,
vComponent, dataUnit);
}
private GeneralGridData(GeneralGridGeometry gridGeometry,
FloatBuffer scalarData, Unit<?> dataUnit) {
this.gridGeometry = GridGeometry2D.wrap(gridGeometry);
this.scalarData = scalarData;
this.scalarData = new FloatBufferWrapper(scalarData, this.gridGeometry);
;
this.dataUnit = dataUnit;
}
private GeneralGridData(GeneralGridGeometry gridGeometry,
FloatBuffer magnitude, FloatBuffer direction,
FloatBuffer uComponent, FloatBuffer vComponent, Unit<?> dataUnit) {
this.gridGeometry = GridGeometry2D.wrap(gridGeometry);
this.scalarData = magnitude;
this.direction = direction;
this.uComponent = uComponent;
this.vComponent = vComponent;
this.uComponent = new FloatBufferWrapper(uComponent, this.gridGeometry);
this.vComponent = new FloatBufferWrapper(vComponent, this.gridGeometry);
this.dataUnit = dataUnit;
}
@ -187,31 +194,34 @@ public class GeneralGridData {
return true;
}
if (scalarData != null) {
scalarData.rewind();
FloatBuffer newData = FloatBuffer.allocate(scalarData.capacity());
while (scalarData.hasRemaining()) {
newData.put((float) converter.convert(scalarData.get()));
FloatBuffer oldData = scalarData.getBuffer();
oldData.rewind();
FloatBuffer newData = FloatBuffer.allocate(oldData.capacity());
while (oldData.hasRemaining()) {
newData.put((float) converter.convert(oldData.get()));
}
newData.rewind();
scalarData = newData;
scalarData = new FloatBufferWrapper(newData, gridGeometry);
}
if (uComponent != null) {
uComponent.rewind();
FloatBuffer newData = FloatBuffer.allocate(uComponent.capacity());
while (uComponent.hasRemaining()) {
newData.put((float) converter.convert(uComponent.get()));
FloatBuffer oldData = uComponent.getBuffer();
oldData.rewind();
FloatBuffer newData = FloatBuffer.allocate(oldData.capacity());
while (oldData.hasRemaining()) {
newData.put((float) converter.convert(oldData.get()));
}
newData.rewind();
uComponent = newData;
uComponent = new FloatBufferWrapper(newData, gridGeometry);
}
if (vComponent != null) {
vComponent.rewind();
FloatBuffer newData = FloatBuffer.allocate(vComponent.capacity());
while (vComponent.hasRemaining()) {
newData.put((float) converter.convert(vComponent.get()));
FloatBuffer oldData = vComponent.getBuffer();
oldData.rewind();
FloatBuffer newData = FloatBuffer.allocate(oldData.capacity());
while (oldData.hasRemaining()) {
newData.put((float) converter.convert(oldData.get()));
}
newData.rewind();
vComponent = newData;
vComponent = new FloatBufferWrapper(newData, gridGeometry);
}
dataUnit = unit;
return true;
@ -278,76 +288,56 @@ public class GeneralGridData {
}
public boolean isVector() {
return (scalarData != null && direction != null)
|| (uComponent != null && vComponent != null);
return (uComponent != null && vComponent != null);
}
public FloatBuffer getMagnitude() {
if (scalarData == null && uComponent != null && vComponent != null) {
uComponent.rewind();
vComponent.rewind();
scalarData = FloatBuffer.allocate(uComponent.capacity());
while (vComponent.hasRemaining()) {
scalarData.put((float) Math.hypot(uComponent.get(),
vComponent.get()));
}
uComponent.rewind();
vComponent.rewind();
scalarData.rewind();
}
return scalarData;
public DataSource getMagnitude() {
return new MagnitudeDataSource(uComponent, vComponent);
}
public FloatBuffer getScalarData() {
return getMagnitude();
if (isVector()) {
FloatBufferWrapper tmp = new FloatBufferWrapper(gridGeometry);
DataSource mag = getMagnitude();
int w = gridGeometry.getGridRange2D().width;
int h = gridGeometry.getGridRange2D().height;
for (int i = 0; i < w; i += 1) {
for (int j = 0; j < h; j += 1) {
tmp.setDataValue(mag.getDataValue(i, j), i, j);
}
}
return tmp.getBuffer();
} else {
return scalarData.getBuffer();
}
}
public FloatBuffer getDirection() {
if (direction == null && uComponent != null && vComponent != null) {
uComponent.rewind();
vComponent.rewind();
direction = FloatBuffer.allocate(uComponent.capacity());
while (vComponent.hasRemaining()) {
direction.put((float) Math.toDegrees(Math.atan2(
uComponent.get(), vComponent.get())));
/**
* @return the direction from which the vector originates. This is commonly
* used in meteorology, espesially for winds. For example if a
* meteorologist says "The wind direction is North" it means the
* wind is coming from the north and moving to the south.
* @see #getDirectionTo()
*/
public DataSource getDirectionFrom() {
return new DirectionFromDataSource(uComponent, vComponent);
}
uComponent.rewind();
vComponent.rewind();
direction.rewind();
}
return direction;
/**
* @return the direction a vector is going towards. This is the common
* mathematical deffinition of a vector.
* @see #getDirectionFrom()
*/
public DataSource getDirectionTo() {
return new DirectionToDataSource(uComponent, vComponent);
}
public FloatBuffer getUComponent() {
if (uComponent == null && scalarData != null && direction != null) {
scalarData.rewind();
direction.rewind();
uComponent = FloatBuffer.allocate(scalarData.capacity());
while (scalarData.hasRemaining()) {
double angle = Math.toRadians(direction.get());
uComponent.put((float) (Math.sin(angle) * scalarData.get()));
}
scalarData.rewind();
direction.rewind();
uComponent.rewind();
}
return uComponent;
return uComponent.getBuffer();
}
public FloatBuffer getVComponent() {
if (vComponent == null && scalarData != null && direction != null) {
scalarData.rewind();
direction.rewind();
vComponent = FloatBuffer.allocate(scalarData.capacity());
while (scalarData.hasRemaining()) {
double angle = Math.toRadians(direction.get());
vComponent.put((float) (Math.cos(angle) * scalarData.get()));
}
scalarData.rewind();
direction.rewind();
vComponent.rewind();
}
return vComponent;
return vComponent.getBuffer();
}
public Unit<?> getDataUnit() {
@ -470,4 +460,58 @@ public class GeneralGridData {
}
}
}
private static abstract class VectorDataSource implements DataSource {
protected final DataSource uComponent;
protected final DataSource vComponent;
public VectorDataSource(DataSource uComponent, DataSource vComponent) {
this.uComponent = uComponent;
this.vComponent = vComponent;
}
}
private static final class MagnitudeDataSource extends VectorDataSource {
public MagnitudeDataSource(DataSource uComponent, DataSource vComponent) {
super(uComponent, vComponent);
}
@Override
public double getDataValue(int x, int y) {
return Math.hypot(uComponent.getDataValue(x, y),
vComponent.getDataValue(x, y));
}
}
private static final class DirectionFromDataSource extends VectorDataSource {
public DirectionFromDataSource(DataSource uComponent, DataSource vComponent) {
super(uComponent, vComponent);
}
@Override
public double getDataValue(int x, int y) {
return Math.toDegrees(Math.atan2(-uComponent.getDataValue(x, y),
-vComponent.getDataValue(x, y)));
}
}
private static final class DirectionToDataSource extends
VectorDataSource {
public DirectionToDataSource(DataSource uComponent,
DataSource vComponent) {
super(uComponent, vComponent);
}
@Override
public double getDataValue(int x, int y) {
return Math.toDegrees(Math.atan2(uComponent.getDataValue(x, y),
vComponent.getDataValue(x, y)));
}
}
}

View file

@ -49,9 +49,10 @@ import com.raytheon.uf.viz.core.rsc.LoadProperties;
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Mar 9, 2011 bsteffen Initial creation
* ------------- -------- ----------- ----------------------------------------
* Mar 09, 2011 bsteffen Initial creation
* Sep 24, 2013 2404 bclement match criteria built using GridStyleUtil
* Jan 14, 2014 2661 bsteffen Switch vectors to u,v only.
*
* </pre>
*
@ -104,15 +105,8 @@ public class GridResource<T extends AbstractResourceData> extends
} else if (dataRecs.length == 2) {
FloatBuffer mag = wrapDataRecord(dataRecs[0]);
FloatBuffer dir = wrapDataRecord(dataRecs[1]);
return GeneralGridData.createVectorData(gridGeometry, mag, dir,
return GeneralGridData.createVectorDataUV(gridGeometry, mag, dir,
dataUnit);
} else if (dataRecs.length == 4) {
FloatBuffer mag = wrapDataRecord(dataRecs[0]);
FloatBuffer dir = wrapDataRecord(dataRecs[1]);
FloatBuffer u = wrapDataRecord(dataRecs[2]);
FloatBuffer v = wrapDataRecord(dataRecs[3]);
return GeneralGridData.createVectorData(gridGeometry, mag, dir, u,
v, dataUnit);
}
return null;
}

View file

@ -33,22 +33,30 @@ import org.opengis.referencing.operation.TransformException;
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* 06/19/2012 14988 D. Friedman Initial revision
* 09/24/2013 DR 15972 D. Friedman Do not require contiguous mapping.
* ------------- -------- ----------- --------------------------
* Jun 19, 2012 14988 D. Friedman Initial revision
* Sep 24, 2013 15972 D. Friedman Do not require contiguous mapping.
* Jan 15, 2014 2661 bsteffen Disable output
*
* </pre>
*/
public class ConformalityUtil {
private static final boolean DEBUG = false;
public static boolean testConformality(GeneralGridGeometry sourceGG, GeneralGridGeometry destGG) {
ConformalityUtil test = new ConformalityUtil(sourceGG, destGG);
return test.testConformality();
}
GeneralGridGeometry sourceGG;
GeneralGridGeometry destGG;
double minRatio;
double maxRatio;
MathTransform lastMT;
private ConformalityUtil(GeneralGridGeometry sourceGG, GeneralGridGeometry destGG) {
@ -87,15 +95,20 @@ public class ConformalityUtil {
double rr = maxRatio / minRatio;
if (! evaluated || maxRatio / minRatio > maxRatioRatio) {
if (DEBUG) {
System.out.format("%s -> %s : not conformal enough (%f)\n",
sourceGG, destGG, maxRatio / minRatio);
}
return false;
}
resetRatios();
if (! evaluateNonContig(evaluatedDomain)) {
System.out.format("%s -> %s : not contiguous?\n", sourceGG, destGG);
if (DEBUG) {
System.out.format("%s -> %s : not contiguous?\n", sourceGG,
destGG);
}
return false;
/*
* This test is not necessary for AWIPS II because it can cope
@ -109,8 +122,10 @@ public class ConformalityUtil {
return false;
*/
} else {
if (DEBUG) {
System.out.format("%s -> %s : conformal enough (%f, %f)\n",
sourceGG, destGG, rr, maxRatio/minRatio);
sourceGG, destGG, rr, maxRatio / minRatio);
}
return true;
}
}