Skip to content
Snippets Groups Projects
Commit 715d0df5 authored by Philip Elson's avatar Philip Elson :snake:
Browse files

Merge branch 'maint/testing_nan_and_inf' into 'master'

Improve array conversion from Java & add a test for nan and inf values from Java

See merge request !61
parents cd70947e 922d2fef
Branches
Tags v2.2.3
1 merge request!61Improve array conversion from Java & add a test for nan and inf values from Java
Pipeline #2364372 failed
import jpype as jp
import numpy as np
import pytest
import pyjapc
@pytest.mark.parametrize("shape, dtype", [
((10000, 10000), np.int32),
((10000, 10000), np.float32),
((10000, 10000), np.float64),
((1, 1), np.int32),
((1, 1), np.float32),
((1, 1), np.float64),
((1_000_000, ), np.int32),
((1_000_000, ), np.float32),
((1_000_000, ), np.float64),
])
def test_big_array(benchmark, shape, dtype):
japc = pyjapc.PyJapc()
data = np.linspace(0, 1000, np.prod(shape)).astype(dtype)
DoubleArrayValue = jp.JClass("cern.japc.value.spi.value.simple.FloatArrayValue")
v = DoubleArrayValue(jp.JArray(jp.JFloat)(data))
benchmark(japc._convertSimpleValToPy, v)
...@@ -1318,36 +1318,6 @@ class PyJapc(object): ...@@ -1318,36 +1318,6 @@ class PyJapc(object):
parValNew = self._simpleParameterValueFactory.newValue(jVal) parValNew = self._simpleParameterValueFactory.newValue(jVal)
return parValNew return parValNew
def _convert2DJarrayToNumpy(self, jArr):
"""Faster conversion of 2D JArrays to numpy arrays.
If jArr is 2D then jArr[:] will be a list of 1D JArrays. 1D JArrays can
be converted fast to numpy with 1djArr[:].
Due to a `bug <https://github.com/originell/jpype/issues/133>`_ this
will return a list on Windows and a numpy array on Linux.
"""
if len(jArr) > 0 and len(jArr[0]) > 0:
arrType = np.array(jArr[0][0]).dtype
else:
# Workaround for empty arrays.
return np.array(jArr)
if arrType.kind in {'U', 'S'}:
# Workaround for str arrays which cannot benefit
# from this optimisation due to us needing to know the length
# of the longest string upfront in order to define the dtype
# (since numpy strings have a length).
return np.array(jArr)
arrShape = (len(jArr), len(jArr[0]))
resultArray = np.empty(arrShape, dtype=arrType)
for i, cols in enumerate(jArr[:]):
# This should work on Win (list) and Linux (numpy array)
resultArray[i, :] = cols[:]
return resultArray
def _convertSimpleValToPy(self, val): def _convertSimpleValToPy(self, val):
"""Convert the Java JAPC SimpleParameterValue object to a Python type """Convert the Java JAPC SimpleParameterValue object to a Python type
or numpy array we do getXXX() for primitives and array2D.getXXXArray2D() or numpy array we do getXXX() for primitives and array2D.getXXXArray2D()
...@@ -1405,7 +1375,6 @@ class PyJapc(object): ...@@ -1405,7 +1375,6 @@ class PyJapc(object):
for knownType in knownTypes: for knownType in knownTypes:
if tStr.startswith(knownType): if tStr.startswith(knownType):
# We found a type match! # We found a type match!
# Check if it is not an array (tStr does not contain any []) # Check if it is not an array (tStr does not contain any [])
# Then we can use the simple .getInt() function # Then we can use the simple .getInt() function
if tStr.find("[]") == -1: if tStr.find("[]") == -1:
...@@ -1417,13 +1386,7 @@ class PyJapc(object): ...@@ -1417,13 +1386,7 @@ class PyJapc(object):
jArr = getattr(val.getArray2D(), getFunctionName)() jArr = getattr(val.getArray2D(), getFunctionName)()
# Safest but _EEXTREMELY_ slow npArr = np.atleast_1d(np.array(jArr).squeeze())
# npArr = np.atleast_1d(np.array(jArr).squeeze())
# Fastest but n-D array not supported by JPype yet
# npArr = np.atleast_1d(jArr[:].squeeze())
npArr = np.atleast_1d(self._convert2DJarrayToNumpy(jArr).squeeze())
# If the array only contains one value, return the naked value # If the array only contains one value, return the naked value
if npArr.size == 1: if npArr.size == 1:
......
...@@ -55,16 +55,27 @@ def test_convert_py_to_val_int(japc, simple_descriptor): ...@@ -55,16 +55,27 @@ def test_convert_py_to_val_int(japc, simple_descriptor):
assert back == val assert back == val
def test_convert_py_to_val_float(japc, simple_descriptor): def round_trip_double(japc, value):
japc_type = jp.JClass("cern.japc.value.spi.value.simple.DoubleValue") simple_descriptor = jp.JClass("cern.japc.core.spi.value.SimpleDescriptorImpl")
value_descriptor = simple_descriptor(jp.JClass("cern.japc.value.ValueType").DOUBLE) value_descriptor = simple_descriptor(jp.JClass("cern.japc.value.ValueType").DOUBLE)
java_val = japc._convertPyToVal(value, value_descriptor)
round_tripped_value = japc._convertValToPy(java_val)
return java_val, round_tripped_value
val = 3.14
r = japc._convertPyToVal(val, value_descriptor)
assert r == japc_type(val)
back = japc._convertValToPy(r) @pytest.mark.parametrize(['value'], [[3.14], [-np.inf], [np.inf]])
assert back == val def test_convert_py_to_val_float(japc, value):
japc_type = jp.JClass("cern.japc.value.spi.value.simple.DoubleValue")
java_val, py_val = round_trip_double(japc, value)
assert java_val == japc_type(value)
assert py_val == value
def test_convert_py_to_val_nan(japc):
japc_type = jp.JClass("cern.japc.value.spi.value.simple.DoubleValue")
java_val, py_val = round_trip_double(japc, np.nan)
assert java_val == japc_type(np.nan)
assert np.isnan(py_val)
@pytest.mark.parametrize(['jprimitive', 'expectation'], [ @pytest.mark.parametrize(['jprimitive', 'expectation'], [
...@@ -310,13 +321,23 @@ def test_array_conversions(japc, np_array, arr_val_type): ...@@ -310,13 +321,23 @@ def test_array_conversions(japc, np_array, arr_val_type):
def test_double_array_to_py_conversion(japc): def test_double_array_to_py_conversion(japc):
arr = np.array([1.2, 2.4, 4.8], dtype=np.double) arr = np.array([1.2, 2.4, 4.8], dtype=np.float64)
DoubleArrayValue = jp.JClass("cern.japc.value.spi.value.simple.DoubleArrayValue") DoubleArrayValue = jp.JClass("cern.japc.value.spi.value.simple.DoubleArrayValue")
v = DoubleArrayValue(jp.JArray(jp.JDouble)(arr)) v = DoubleArrayValue(jp.JArray(jp.JDouble)(arr))
r = japc._convertSimpleValToPy(v) r = japc._convertSimpleValToPy(v)
assert isinstance(r, np.ndarray) assert isinstance(r, np.ndarray)
np.testing.assert_array_equal(r, arr) np.testing.assert_array_equal(r, arr)
assert r.dtype == np.double assert r.dtype == np.float64
def test_float_array_to_py_conversion(japc):
arr = np.array([1.2, 2.4, 4.8], dtype=np.float32)
FloatArrayValue = jp.JClass("cern.japc.value.spi.value.simple.FloatArrayValue")
v = FloatArrayValue(jp.JArray(jp.JFloat)(arr))
r = japc._convertSimpleValToPy(v)
assert isinstance(r, np.ndarray)
np.testing.assert_array_equal(r, arr)
assert r.dtype == np.float32
def test_py_to_simple_discrete_function(japc, simple_descriptor): def test_py_to_simple_discrete_function(japc, simple_descriptor):
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment