From 7948807821af97d4883def3ec7a6e9d9edc29efc Mon Sep 17 00:00:00 2001 From: William Patton Date: Wed, 31 Jul 2024 12:37:06 -0700 Subject: [PATCH] expand tests to cover incomplete metadata --- tests/fixtures/metadatas/empty.json | 1 + tests/fixtures/metadatas/incomplete1.json | 9 ++++ tests/fixtures/metadatas/incomplete2.json | 7 +++ tests/fixtures/metadatas/incomplete3.json | 19 +++++++ tests/test_array.py | 63 ++++++++++++++--------- tests/test_datasets.py | 5 +- tests/test_metadata.py | 37 ++++++++++++- 7 files changed, 114 insertions(+), 27 deletions(-) create mode 100644 tests/fixtures/metadatas/empty.json create mode 100644 tests/fixtures/metadatas/incomplete1.json create mode 100644 tests/fixtures/metadatas/incomplete2.json create mode 100644 tests/fixtures/metadatas/incomplete3.json diff --git a/tests/fixtures/metadatas/empty.json b/tests/fixtures/metadatas/empty.json new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/tests/fixtures/metadatas/empty.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/tests/fixtures/metadatas/incomplete1.json b/tests/fixtures/metadatas/incomplete1.json new file mode 100644 index 0000000..b87b4ef --- /dev/null +++ b/tests/fixtures/metadatas/incomplete1.json @@ -0,0 +1,9 @@ +{ + "axis_names": [ + "c0^", + "c1^", + "d0", + "d1", + "d2" + ] +} \ No newline at end of file diff --git a/tests/fixtures/metadatas/incomplete2.json b/tests/fixtures/metadatas/incomplete2.json new file mode 100644 index 0000000..2d9629c --- /dev/null +++ b/tests/fixtures/metadatas/incomplete2.json @@ -0,0 +1,7 @@ +{ + "units": [ + "", + "", + "" + ] +} \ No newline at end of file diff --git a/tests/fixtures/metadatas/incomplete3.json b/tests/fixtures/metadatas/incomplete3.json new file mode 100644 index 0000000..b0443bd --- /dev/null +++ b/tests/fixtures/metadatas/incomplete3.json @@ -0,0 +1,19 @@ +{ + "offset": [ + 0, + 0, + 0 + ], + "voxel_size": [ + 1, + 1, + 1 + ], + "axis_names": [ + "c0^", + "c1^", + "d0", + "d1", + "d2" + ] +} \ No newline at end of file diff --git a/tests/test_array.py b/tests/test_array.py index 8956dac..4f13165 100644 --- a/tests/test_array.py +++ b/tests/test_array.py @@ -17,7 +17,7 @@ def test_constructor(): Array(data, offset, (2, 2, 2)) # dims don't match - with pytest.raises(AssertionError): + with pytest.raises(ValueError): Array(data, offset, (1, 1)) Array(data, offset, (1, 1, 3)) @@ -25,10 +25,12 @@ def test_constructor(): Array(data, (1, 1, 1), (1, 1, 2)) + def test_dtype(): for dtype in [np.float32, np.uint8, np.uint64]: assert Array(np.zeros((1,), dtype=dtype), (0,), (1,)).dtype == dtype + def test_getitem(): a = Array(np.arange(0, 10).reshape(2, 5), (0, 0), (1, 1)) @@ -62,6 +64,7 @@ def test_getitem(): b = a[Roi((1, 1), (1, 4))] np.testing.assert_array_equal(b, [[6, 7, 8, 9]]) + def test_setitem(): # set entirely with numpy array @@ -136,6 +139,7 @@ def test_setitem(): assert a[Coordinate((1, 1))] == 1 assert a[Coordinate((1, 2))] == 2 + def test_to_ndarray(): a = Array(np.arange(0, 10).reshape(2, 5), (0, 0), (1, 1)) @@ -163,8 +167,11 @@ def test_to_ndarray(): ) np.testing.assert_array_equal(b, compare) + def test_to_ndarray_with_slices(): - a = Array(np.arange(0, 10*10).reshape(10, 2, 5), (0, 0), (1, 1), adapter=slice(0, 1)) + a = Array( + np.arange(0, 10 * 10).reshape(10, 2, 5), (0, 0), (1, 1), adapter=slice(0, 1) + ) b = a.to_ndarray(Roi((0, 0), (1, 5))) compare = np.array([[[0, 1, 2, 3, 4]]]) @@ -180,32 +187,43 @@ def test_to_ndarray_with_slices(): b = a.to_ndarray(Roi((0, 0), (5, 5)), fill_value=1) compare = np.array( - [[ - [0, 1, 2, 3, 4], - [5, 6, 7, 8, 9], - [1, 1, 1, 1, 1], - [1, 1, 1, 1, 1], - [1, 1, 1, 1, 1], - ]] + [ + [ + [0, 1, 2, 3, 4], + [5, 6, 7, 8, 9], + [1, 1, 1, 1, 1], + [1, 1, 1, 1, 1], + [1, 1, 1, 1, 1], + ] + ] ) np.testing.assert_array_equal(b, compare) + def test_adapters(): - a = Array(np.arange(0, 10*10).reshape(10, 2, 5), (0, 0), (1, 1)) + a = Array(np.arange(0, 10 * 10).reshape(10, 2, 5), (0, 0), (1, 1)) assert a.dtype == int - a = Array(np.arange(0, 10*10).reshape(10, 2, 5), (0, 0), (1, 1), adapter=lambda x: x > 2) + a = Array( + np.arange(0, 10 * 10).reshape(10, 2, 5), (0, 0), (1, 1), adapter=lambda x: x > 2 + ) assert a.dtype == bool - a = Array(np.arange(0, 10*10).reshape(10, 2, 5), (0, 0), (1, 1), adapter=lambda x: x + 0.5) + a = Array( + np.arange(0, 10 * 10).reshape(10, 2, 5), + (0, 0), + (1, 1), + adapter=lambda x: x + 0.5, + ) assert a.dtype == float + def test_slicing(): - a = Array(np.arange(0, 4*4).reshape(4, 2, 2), (0, 0), (1, 1)) - + a = Array(np.arange(0, 4 * 4).reshape(4, 2, 2), (0, 0), (1, 1)) + a.adapt(np.s_[0:3, 1, :]) assert a.shape == (3, 2) - assert a.axis_names == ["c0^", "d1"] + assert a.axis_names == ["c0^", "d1"], a.axis_names assert a.units == [""] a.adapt(np.s_[2, :]) @@ -217,11 +235,10 @@ def test_slicing(): assert all([x == 42 for x in a._source_data[2, 1, :]]), a._source_data[2, 1, :] - # test with list indexing - a = Array(np.arange(0, 4*4).reshape(4, 2, 2), (0, 0), (1, 1)) + a = Array(np.arange(0, 4 * 4).reshape(4, 2, 2), (0, 0), (1, 1)) - a.adapt(np.s_[[0,1,2], 1, :]) + a.adapt(np.s_[[0, 1, 2], 1, :]) assert a.shape == (3, 2) assert a.axis_names == ["c0^", "d1"] assert a.units == [""] @@ -235,11 +252,10 @@ def test_slicing(): assert all([x == 42 for x in a._source_data[2, 1, :]]), a._source_data[:] - # test weird case - a = Array(np.arange(0, 4*4).reshape(4, 2, 2), (0, 0), (1, 1)) + a = Array(np.arange(0, 4 * 4).reshape(4, 2, 2), (0, 0), (1, 1)) - a.adapt(np.s_[[2,2,2], 1, :]) + a.adapt(np.s_[[2, 2, 2], 1, :]) assert a.shape == (3, 2) assert a.axis_names == ["c0^", "d1"] assert a.units == [""] @@ -247,14 +263,13 @@ def test_slicing(): a[:, :] = np.array([42, 43, 44]).reshape(3, 1) assert all([x == 44 for x in a._source_data[2, 1, :]]), a._source_data[2, 1, :] - # test_bool_indexing - a = Array(np.arange(0, 4*4).reshape(4, 2, 2), (0, 0), (1, 1)) + a = Array(np.arange(0, 4 * 4).reshape(4, 2, 2), (0, 0), (1, 1)) a.adapt(np.s_[np.array([True, True, True, False]), 1, :]) assert a.shape == (3, 2) assert a.axis_names == ["c0^", "d1"] assert a.units == [""] - + with pytest.raises(RuntimeError): a[:, :] = np.array([42, 43, 44]).reshape(3, 1) diff --git a/tests/test_datasets.py b/tests/test_datasets.py index 29cb12c..a60206c 100644 --- a/tests/test_datasets.py +++ b/tests/test_datasets.py @@ -20,8 +20,11 @@ @pytest.mark.parametrize("store", stores.keys()) @pytest.mark.parametrize("dtype", [np.float32, np.uint8, np.uint64]) def test_helpers(tmpdir, store, dtype): + shape = Coordinate(1, 1, 10, 20, 30) + chunk_shape = Coordinate(2, 3, 10, 10, 10) store = tmpdir / store metadata = MetaDataFormat().parse( + shape, { "offset": [100, 200, 400], "voxel_size": [1, 2, 3], @@ -29,8 +32,6 @@ def test_helpers(tmpdir, store, dtype): "units": ["nm", "nm", "nm"], } ) - shape = Coordinate(1, 1, 10, 20, 30) - chunk_shape = Coordinate(2, 3, 10, 10, 10) # test prepare_ds fails if array does not exist and mode is read with pytest.raises(ArrayNotFoundError): diff --git a/tests/test_metadata.py b/tests/test_metadata.py index 1dcb08e..4ed14ac 100644 --- a/tests/test_metadata.py +++ b/tests/test_metadata.py @@ -7,6 +7,16 @@ fixtures_dir = Path(__file__).parent / "fixtures" +incomplete_metadatas = { + "incomplete1": "metadatas/incomplete1.json", + "incomplete2": "metadatas/incomplete2.json", + "incomplete3": "metadatas/incomplete3.json", +} +incomplete_metadata_formats = { + "incomplete1": MetaDataFormat(), + "incomplete2": MetaDataFormat(), + "incomplete3": MetaDataFormat(), +} metadata_jsons = { "default": "metadatas/default.json", "simple": "metadatas/simple.json", @@ -27,10 +37,12 @@ ), } + @pytest.fixture(params=metadata_jsons.keys()) def metadata(request): return metadata_formats[request.param].parse( - json.loads(open(fixtures_dir / metadata_jsons[request.param]).read()) + (10, 2, 100, 100, 100), + json.loads(open(fixtures_dir / metadata_jsons[request.param]).read()), ) @@ -39,3 +51,26 @@ def test_parse_metadata(metadata): assert metadata.voxel_size == Coordinate(1, 2, 3) assert metadata.axis_names == ["sample^", "channel^", "z", "y", "x"] assert metadata.units == ["nm", "nm", "nm"] + + +@pytest.fixture(params=incomplete_metadatas.keys()) +def incomplete_metadata(request): + return incomplete_metadata_formats[request.param].parse( + (10, 2, 100, 100, 100), + json.loads(open(fixtures_dir / incomplete_metadatas[request.param]).read()), + ) + + +def test_parse_incomplete_metadata(incomplete_metadata): + assert incomplete_metadata.offset == Coordinate(0, 0, 0) + assert incomplete_metadata.voxel_size == Coordinate(1, 1, 1) + assert incomplete_metadata.axis_names == ["c0^", "c1^", "d0", "d1", "d2"] + assert incomplete_metadata.units == ["", "", ""] + + +def test_empty_metadata(): + metadata = MetaDataFormat().parse((10, 2, 100, 100, 100), {}) + assert metadata.offset == Coordinate(0, 0, 0, 0, 0) + assert metadata.voxel_size == Coordinate(1, 1, 1, 1, 1) + assert metadata.axis_names == ["d0", "d1", "d2", "d3", "d4"] + assert metadata.units == ["", "", "", "", ""]