From 258338de205563fa090020e6c76d16e532c6a384 Mon Sep 17 00:00:00 2001 From: Arrielle Opotowsky Date: Sat, 11 Jan 2025 06:23:54 +0000 Subject: [PATCH 1/6] protect against the existential threat of single element numpy arrays --- armi/bookkeeping/db/database.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/armi/bookkeeping/db/database.py b/armi/bookkeeping/db/database.py index 672e905fd..927112110 100644 --- a/armi/bookkeeping/db/database.py +++ b/armi/bookkeeping/db/database.py @@ -970,6 +970,12 @@ def _getShape(arr: [np.ndarray, List, Tuple]): # check if temp is a jagged array if any(isinstance(x, (np.ndarray, list)) for x in temp): jagged = len(set([_getShape(x) for x in temp])) != 1 + # Sometimes temp is a list of single-element np.arrays mixed with + # other items and when np.array(temp) is called: FAIL. + temp = [ + t.item() if isinstance(t, np.ndarray) and len(t) == 1 else t + for t in temp + ] else: jagged = False data = ( From 8f7dac61994d4f66a3c4f5b75f6a26fd5f9d59ca Mon Sep 17 00:00:00 2001 From: Arrielle Opotowsky Date: Sat, 11 Jan 2025 06:53:57 +0000 Subject: [PATCH 2/6] have this eval to jagged = true as opposed to prior fix, which was fixing the list after jagged was deemed false --- armi/bookkeeping/db/database.py | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/armi/bookkeeping/db/database.py b/armi/bookkeeping/db/database.py index 927112110..2202e3f22 100644 --- a/armi/bookkeeping/db/database.py +++ b/armi/bookkeeping/db/database.py @@ -922,7 +922,8 @@ def _getShape(arr: [np.ndarray, List, Tuple]): elif isinstance(arr, (list, tuple)): return (len(arr),) else: - return (1,) + # not a list, tuple, or array (likely int, float, or None) + return 1 c = comps[0] groupName = c.__class__.__name__ @@ -970,12 +971,6 @@ def _getShape(arr: [np.ndarray, List, Tuple]): # check if temp is a jagged array if any(isinstance(x, (np.ndarray, list)) for x in temp): jagged = len(set([_getShape(x) for x in temp])) != 1 - # Sometimes temp is a list of single-element np.arrays mixed with - # other items and when np.array(temp) is called: FAIL. - temp = [ - t.item() if isinstance(t, np.ndarray) and len(t) == 1 else t - for t in temp - ] else: jagged = False data = ( From 0f9541f0dacf6321e8767cb5b4a714dd631019e6 Mon Sep 17 00:00:00 2001 From: Arrielle Opotowsky Date: Sat, 11 Jan 2025 06:56:19 +0000 Subject: [PATCH 3/6] release notes --- doc/release/0.5.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/release/0.5.rst b/doc/release/0.5.rst index 0e49b8e5a..98ba031c4 100644 --- a/doc/release/0.5.rst +++ b/doc/release/0.5.rst @@ -18,6 +18,7 @@ API Changes Bug Fixes --------- +#. Fix database class bug in check for jagged arrays. (`PR#XXXX `_) #. TBD Quality Work From bcda60320abee00d2450f5ea6cd98836dde6ea9d Mon Sep 17 00:00:00 2001 From: Arrielle Opotowsky Date: Mon, 13 Jan 2025 23:19:38 +0000 Subject: [PATCH 4/6] make a static method and then add a unit test --- armi/bookkeeping/db/database.py | 23 +++++++++++---------- armi/bookkeeping/db/tests/test_database3.py | 14 +++++++++++++ 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/armi/bookkeeping/db/database.py b/armi/bookkeeping/db/database.py index 2202e3f22..1a19dbcd9 100644 --- a/armi/bookkeeping/db/database.py +++ b/armi/bookkeeping/db/database.py @@ -914,17 +914,18 @@ def _compose(self, comps, cs, parent=None): return comp - def _writeParams(self, h5group, comps) -> tuple: - def _getShape(arr: [np.ndarray, List, Tuple]): - """Get the shape of a np.ndarray, list, or tuple.""" - if isinstance(arr, np.ndarray): - return arr.shape - elif isinstance(arr, (list, tuple)): - return (len(arr),) - else: - # not a list, tuple, or array (likely int, float, or None) - return 1 + @staticmethod + def _getArrayShape(arr: [np.ndarray, List, Tuple]): + """Get the shape of a np.ndarray, list, or tuple.""" + if isinstance(arr, np.ndarray): + return arr.shape + elif isinstance(arr, (list, tuple)): + return (len(arr),) + else: + # not a list, tuple, or array (likely int, float, or None) + return 1 + def _writeParams(self, h5group, comps) -> tuple: c = comps[0] groupName = c.__class__.__name__ if groupName not in h5group: @@ -970,7 +971,7 @@ def _getShape(arr: [np.ndarray, List, Tuple]): else: # check if temp is a jagged array if any(isinstance(x, (np.ndarray, list)) for x in temp): - jagged = len(set([_getShape(x) for x in temp])) != 1 + jagged = len(set([self._getArrayShape(x) for x in temp])) != 1 else: jagged = False data = ( diff --git a/armi/bookkeeping/db/tests/test_database3.py b/armi/bookkeeping/db/tests/test_database3.py index 91246ac57..09491fb9a 100644 --- a/armi/bookkeeping/db/tests/test_database3.py +++ b/armi/bookkeeping/db/tests/test_database3.py @@ -23,6 +23,7 @@ import numpy as np from armi.bookkeeping.db import _getH5File, database, loadOperator +from armi.bookkeeping.db.database import Database from armi.bookkeeping.db.databaseInterface import DatabaseInterface from armi.bookkeeping.db.jaggedArray import JaggedArray from armi.reactor import parameters @@ -283,6 +284,19 @@ def _compareRoundTrip(self, data): roundTrip = database.unpackSpecialData(packed, attrs, "testing") self._compareArrays(data, roundTrip) + def test_getArrayShape(self): + """Tests a helper method for ``_writeParams``.""" + base = [1, 2, 3, 4] + self.assertEqual(Database._getArrayShape(base), (4,)) + self.assertEqual(Database._getArrayShape(tuple(base)), (4,)) + arr = np.array(base) + self.assertEqual(Database._getArrayShape(arr), (4,)) + arr = np.array([base]) + self.assertEqual(Database._getArrayShape(arr), (1, 4)) + # not array type + self.assertEqual(Database._getArrayShape(1), 1) + self.assertEqual(Database._getArrayShape(None), 1) + def test_writeToDB(self): """Test writing to the database. From 6ede0459c89f272461e35a3682561f7a20f00e18 Mon Sep 17 00:00:00 2001 From: Arrielle Opotowsky Date: Mon, 13 Jan 2025 17:20:47 -0600 Subject: [PATCH 5/6] Update doc/release/0.5.rst --- doc/release/0.5.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/release/0.5.rst b/doc/release/0.5.rst index 98ba031c4..92248f4b7 100644 --- a/doc/release/0.5.rst +++ b/doc/release/0.5.rst @@ -18,7 +18,7 @@ API Changes Bug Fixes --------- -#. Fix database class bug in check for jagged arrays. (`PR#XXXX `_) +#. Fix check for jagged arrays during ``_writeParams``. (`PR#2051 `_) #. TBD Quality Work From dd868b82044f9c78356d2f0e5eed150f7bbc4ea8 Mon Sep 17 00:00:00 2001 From: John Stilley <1831479+john-science@users.noreply.github.com> Date: Tue, 14 Jan 2025 10:16:06 -0800 Subject: [PATCH 6/6] Minor thing --- doc/release/0.5.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/release/0.5.rst b/doc/release/0.5.rst index 92248f4b7..cb6fe1be8 100644 --- a/doc/release/0.5.rst +++ b/doc/release/0.5.rst @@ -18,7 +18,7 @@ API Changes Bug Fixes --------- -#. Fix check for jagged arrays during ``_writeParams``. (`PR#2051 `_) +#. Fixing check for jagged arrays during ``_writeParams``. (`PR#2051 `_) #. TBD Quality Work