From f1739a734ffb0113822c96513bbc0aeaaaa5f4a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20Wiik=20=C3=85nes?= Date: Wed, 7 Dec 2022 20:28:56 +0100 Subject: [PATCH 01/10] Complete coverage by removing unnecessary figure closing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Håkon Wiik Ånes --- orix/tests/test_vector3d.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/orix/tests/test_vector3d.py b/orix/tests/test_vector3d.py index 45b6bfdb..ca468462 100644 --- a/orix/tests/test_vector3d.py +++ b/orix/tests/test_vector3d.py @@ -493,7 +493,7 @@ def test_ipdf_plot(self): def test_ipdf_plot_hemisphere_raises(self): with pytest.raises(ValueError, match="Hemisphere must be either "): v = Vector3d(np.random.randn(1_000, 3)).unit - fig = v.inverse_pole_density_function( + _ = v.inverse_pole_density_function( symmetry=symmetry.Th, return_figure=True, colorbar=True, From 928b7dbb9fb6c5774f69f096ed79c15e36683b19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20Wiik=20=C3=85nes?= Date: Wed, 7 Dec 2022 20:29:52 +0100 Subject: [PATCH 02/10] Allow 10 column EDAX TSL .ang file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Håkon Wiik Ånes --- orix/io/plugins/ang.py | 179 ++++++++++++++++++++++++----------------- 1 file changed, 104 insertions(+), 75 deletions(-) diff --git a/orix/io/plugins/ang.py b/orix/io/plugins/ang.py index c664632b..a88868af 100644 --- a/orix/io/plugins/ang.py +++ b/orix/io/plugins/ang.py @@ -117,15 +117,16 @@ def file_reader(filename: str) -> CrystalMap: ) # Set which data points are not indexed - if vendor in ["orix", "tsl"]: - data_dict["phase_id"][np.where(data_dict["prop"]["ci"] == -1)] = -1 # TODO: Add not-indexed convention for INDEX ASTAR + if vendor in ["orix", "tsl"]: + not_indexed = data_dict["prop"]["ci"] == -1 + data_dict["phase_id"][not_indexed] = -1 # Set scan unit - if vendor in ["tsl", "emsoft"]: - scan_unit = "um" - else: # NanoMegas + if vendor == "astar": scan_unit = "nm" + else: + scan_unit = "um" data_dict["scan_unit"] = scan_unit # Create rotations @@ -194,77 +195,101 @@ def _get_vendor_columns(header: List[str], n_cols_file: int) -> Tuple[str, List[ footprint_line = line break - # Vendor column names + # Variants of vendor column names encountered in real data sets column_names = { - "unknown": [ - "euler1", - "euler2", - "euler3", - "x", - "y", - "unknown1", - "unknown2", - "phase_id", - ], - "tsl": [ - "euler1", - "euler2", - "euler3", - "x", - "y", - "iq", # Image quality from Hough transform - "ci", # Confidence index - "phase_id", - "unknown1", - "fit", # Pattern fit - "unknown2", - "unknown3", - "unknown4", - "unknown5", - ], - "emsoft": [ - "euler1", - "euler2", - "euler3", - "x", - "y", - "iq", # Image quality from Krieger Lassen's method - "dp", # Dot product - "phase_id", - ], - "astar": [ - "euler1", - "euler2", - "euler3", - "x", - "y", - "ind", # Correlation index - "rel", # Reliability - "phase_id", - "relx100", # Reliability x 100 - ], - "orix": [ - "euler1", - "euler2", - "euler3", - "x", - "y", - "iq", - "ci", - "phase_id", - "detector_signal", - "fit", - ], + "tsl": { + 0: [ + "euler1", + "euler2", + "euler3", + "x", + "y", + "iq", # Image quality from Hough transform + "ci", # Confidence index + "phase_id", + "unknown1", + "fit", # Pattern fit + "unknown2", + "unknown3", + "unknown4", + "unknown5", + ], + 1: [ + "euler1", + "euler2", + "euler3", + "x", + "y", + "iq", + "ci", + "phase_id", + "unknown1", + "fit", + ], + }, + "emsoft": { + 0: [ + "euler1", + "euler2", + "euler3", + "x", + "y", + "iq", # Image quality from Krieger Lassen's method + "dp", # Dot product + "phase_id", + ] + }, + "astar": { + 0: [ + "euler1", + "euler2", + "euler3", + "x", + "y", + "ind", # Correlation index + "rel", # Reliability + "phase_id", + "relx100", # Reliability x 100 + ], + }, + "orix": { + 0: [ + "euler1", + "euler2", + "euler3", + "x", + "y", + "iq", + "ci", + "phase_id", + "detector_signal", + "fit", + ], + }, + "unknown": { + 0: [ + "euler1", + "euler2", + "euler3", + "x", + "y", + "unknown1", + "unknown2", + "phase_id", + ] + }, } - n_cols_expected = len(column_names[vendor]) + n_variants = len(column_names[vendor]) + n_cols_expected = [len(column_names[vendor][k]) for k in range(n_variants)] if vendor == "orix" and "Column names" in footprint_line: # Append names of extra properties found, if any, in the orix # .ang file header - n_cols = len(column_names[vendor]) + vendor_column_names = column_names[vendor][0] + n_cols = n_cols_expected[0] extra_props = footprint_line.split(":")[1].split(",")[n_cols:] - column_names[vendor] += [i.lstrip(" ").replace(" ", "_") for i in extra_props] - elif n_cols_file != n_cols_expected: + vendor_column_names += [i.lstrip(" ").replace(" ", "_") for i in extra_props] + elif n_cols_file not in n_cols_expected: warnings.warn( f"Number of columns, {n_cols_file}, in the file is not equal to " f"the expected number of columns, {n_cols_expected}, for the \n" @@ -273,13 +298,17 @@ def _get_vendor_columns(header: List[str], n_cols_file: int) -> Tuple[str, List[ "phase_id, unknown3, unknown4, etc." ) vendor = "unknown" - n_cols_unknown = len(column_names["unknown"]) - if n_cols_file > n_cols_unknown: - # Add potential extra columns to properties - for i in range(n_cols_file - n_cols_unknown): - column_names["unknown"].append("unknown" + str(i + 3)) + vendor_column_names = column_names[vendor][0] + n_cols = len(vendor_column_names) + if n_cols_file > n_cols: + # Add any extra columns as properties + for i in range(n_cols_file - n_cols): + vendor_column_names.append("unknown" + str(i + 3)) + else: + idx = np.where(np.equal(n_cols_file, n_cols_expected))[0][0] + vendor_column_names = column_names[vendor][idx] - return vendor, column_names[vendor] + return vendor, vendor_column_names def _get_phases_from_header( From 44135b5b2a0176ca2236cc4848ebf3373f39f2f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20Wiik=20=C3=85nes?= Date: Mon, 30 Jan 2023 21:57:59 +0100 Subject: [PATCH 03/10] Update .ang file reader tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Håkon Wiik Ånes --- orix/tests/conftest.py | 19 ++++------ orix/tests/io/test_ang.py | 79 +++++++++++++++++++-------------------- 2 files changed, 47 insertions(+), 51 deletions(-) diff --git a/orix/tests/conftest.py b/orix/tests/conftest.py index d6a2cdaa..a58b02fd 100644 --- a/orix/tests/conftest.py +++ b/orix/tests/conftest.py @@ -36,12 +36,6 @@ def rotations(): return Rotation([(2, 4, 6, 8), (-1, -3, -5, -7)]) -@pytest.fixture() -def eu(): - return np.random.rand(10, 3) - - -# TODO: Exchange for a multiphase header (change `phase_id` accordingly) ANGFILE_TSL_HEADER = ( "# TEM_PIXperUM 1.000000\n" "# x-star 0.413900\n" @@ -174,7 +168,7 @@ def temp_file_path(request): [4.48549, 0.95242, 0.79150], [1.34390, 0.27611, 0.82589], ] - ), # rotations as rows of Euler angle triplets + ), # Rotations as rows of Euler angle triplets ) ] ) @@ -193,7 +187,7 @@ def angfile_tsl(tmpdir, request): phase_id : numpy.ndarray Array of map size with phase IDs in header. n_unknown_columns : int - Number of columns with unknown values. + Number of columns with values of unknown nature. rotations : numpy.ndarray A sample, smaller than the map size, of example rotations as rows of Euler angle triplets. @@ -238,7 +232,8 @@ def angfile_tsl(tmpdir, request): comments="", ) - return f + yield f + gc.collect() @pytest.fixture( @@ -302,7 +297,8 @@ def angfile_astar(tmpdir, request): comments="", ) - return f + yield f + gc.collect() @pytest.fixture( @@ -358,7 +354,8 @@ def angfile_emsoft(tmpdir, request): comments="", ) - return f + yield f + gc.collect() @pytest.fixture( diff --git a/orix/tests/io/test_ang.py b/orix/tests/io/test_ang.py index 3fedf5c3..442c879d 100644 --- a/orix/tests/io/test_ang.py +++ b/orix/tests/io/test_ang.py @@ -86,7 +86,7 @@ def test_loadang(angfile_astar, expected_data): @pytest.mark.filterwarnings("ignore:Argument `z` is deprecated and will be removed in") class TestAngReader: @pytest.mark.parametrize( - "angfile_tsl, map_shape, step_sizes, phase_id, example_rot", + "angfile_tsl, map_shape, step_sizes, phase_id, n_unknown_cols, example_rot", [ ( # Read by angfile_tsl() via request.param (passed via `indirect` below) @@ -102,6 +102,7 @@ class TestAngReader: (5, 3), (0.1, 0.1), np.zeros(5 * 3, dtype=int), + 5, np.array( [[1.59942, 2.37748, 4.53419], [1.59331, 2.37417, 4.53628]] ), # rotations as rows of Euler angle triplets @@ -111,7 +112,7 @@ class TestAngReader: (8, 4), # map_shape (1.5, 1.5), # step_sizes np.zeros(8 * 4, dtype=int), # phase_id - 5, # n_unknown_columns + 1, # n_unknown_columns np.array( [[5.81107, 2.34188, 4.47345], [6.16205, 0.79936, 1.31702]] ), # rotations as rows of Euler angle triplets @@ -119,6 +120,7 @@ class TestAngReader: (8, 4), (1.5, 1.5), np.zeros(8 * 4, dtype=int), + 1, np.array( [[5.81107, 2.34188, 4.47345], [6.16205, 0.79936, 1.31702]] ), # rotations as rows of Euler angle triplets @@ -127,7 +129,7 @@ class TestAngReader: indirect=["angfile_tsl"], ) def test_load_ang_tsl( - self, angfile_tsl, map_shape, step_sizes, phase_id, example_rot + self, angfile_tsl, map_shape, step_sizes, phase_id, n_unknown_cols, example_rot ): xmap = load(angfile_tsl) @@ -136,22 +138,16 @@ def test_load_ang_tsl( assert non_indexed_fraction == np.sum(~xmap.is_indexed) # Properties - assert list(xmap.prop.keys()) == [ - "iq", - "ci", - "unknown1", - "fit", - "unknown2", - "unknown3", - "unknown4", - "unknown5", - ] + prop_names = ["iq", "ci", "unknown1", "fit"] + prop_names += [f"unknown{i + 2}" for i in range(n_unknown_cols - 1)] + assert list(xmap.prop.keys()) == prop_names # Coordinates ny, nx = map_shape dy, dx = step_sizes assert np.allclose(xmap.x, np.tile(np.arange(nx) * dx, ny)) assert np.allclose(xmap.y, np.sort(np.tile(np.arange(ny) * dy, nx))) + assert xmap.scan_unit == "um" # Map shape and size assert xmap.shape == map_shape @@ -234,41 +230,42 @@ def test_load_ang_tsl( def test_load_ang_astar( self, angfile_astar, map_shape, step_sizes, phase_id, example_rot ): - cm = load(angfile_astar) + xmap = load(angfile_astar) # Properties - assert list(cm.prop.keys()) == ["ind", "rel", "relx100"] + assert list(xmap.prop.keys()) == ["ind", "rel", "relx100"] # Coordinates ny, nx = map_shape dy, dx = step_sizes - assert np.allclose(cm.x, np.tile(np.arange(nx) * dx, ny)) - assert np.allclose(cm.y, np.sort(np.tile(np.arange(ny) * dy, nx))) + assert np.allclose(xmap.x, np.tile(np.arange(nx) * dx, ny)) + assert np.allclose(xmap.y, np.sort(np.tile(np.arange(ny) * dy, nx))) + assert xmap.scan_unit == "nm" # Map shape and size - assert cm.shape == map_shape - assert cm.size == np.prod(map_shape) + assert xmap.shape == map_shape + assert xmap.size == np.prod(map_shape) # Attributes are within expected ranges or have a certain value - assert cm.prop["ind"].max() <= 100 - assert cm.prop["rel"].max() <= 1 - assert cm.prop["relx100"].max() <= 100 - relx100 = (cm.prop["rel"] * 100).astype(int) - assert np.allclose(cm.prop["relx100"], relx100) + assert xmap.prop["ind"].max() <= 100 + assert xmap.prop["rel"].max() <= 1 + assert xmap.prop["relx100"].max() <= 100 + relx100 = (xmap.prop["rel"] * 100).astype(int) + assert np.allclose(xmap.prop["relx100"], relx100) # Phase IDs - assert np.allclose(cm.phase_id, phase_id) + assert np.allclose(xmap.phase_id, phase_id) # Rotations - rot_unique = np.unique(cm.rotations.to_euler(), axis=0) + rot_unique = np.unique(xmap.rotations.to_euler(), axis=0) assert np.allclose( np.sort(rot_unique, axis=0), np.sort(example_rot, axis=0), atol=1e-6 ) # Phases - assert cm.phases.size == 1 - assert cm.phases.ids == [1] - phase = cm.phases[1] + assert xmap.phases.size == 1 + assert xmap.phases.ids == [1] + phase = xmap.phases[1] assert phase.name == "Nickel" assert phase.point_group.name == "432" @@ -336,36 +333,37 @@ def test_load_ang_astar( def test_load_ang_emsoft( self, angfile_emsoft, map_shape, step_sizes, phase_id, example_rot ): - cm = load(angfile_emsoft) + xmap = load(angfile_emsoft) # Properties - assert list(cm.prop.keys()) == ["iq", "dp"] + assert list(xmap.prop.keys()) == ["iq", "dp"] # Coordinates ny, nx = map_shape dy, dx = step_sizes - assert np.allclose(cm.x, np.tile(np.arange(nx) * dx, ny)) - assert np.allclose(cm.y, np.sort(np.tile(np.arange(ny) * dy, nx))) + assert np.allclose(xmap.x, np.tile(np.arange(nx) * dx, ny)) + assert np.allclose(xmap.y, np.sort(np.tile(np.arange(ny) * dy, nx))) + assert xmap.scan_unit == "um" # Map shape and size - assert cm.shape == map_shape - assert cm.size == np.prod(map_shape) + assert xmap.shape == map_shape + assert xmap.size == np.prod(map_shape) # Attributes are within expected ranges or have a certain value - assert cm.prop["iq"].max() <= 100 - assert cm.prop["dp"].max() <= 1 + assert xmap.prop["iq"].max() <= 100 + assert xmap.prop["dp"].max() <= 1 # Phase IDs - assert np.allclose(cm.phase_id, phase_id) + assert np.allclose(xmap.phase_id, phase_id) # Rotations - rot_unique = np.unique(cm.rotations.to_euler(), axis=0) + rot_unique = np.unique(xmap.rotations.to_euler(), axis=0) assert np.allclose( np.sort(rot_unique, axis=0), np.sort(example_rot, axis=0), atol=1e-5 ) # Phases (change if file header is changed!) - phases_in_data = cm["indexed"].phases_in_data + phases_in_data = xmap["indexed"].phases_in_data assert phases_in_data.size == 2 assert phases_in_data.ids == [1, 2] assert phases_in_data.names == ["austenite", "ferrite/ferrite"] @@ -524,6 +522,7 @@ def test_write_read_loop(self, crystal_map, tmp_path): xmap_reload.rotations.to_euler(), crystal_map.rotations.to_euler() ) assert np.allclose(xmap_reload.phase_id - 1, crystal_map.phase_id) + assert xmap_reload.scan_unit == "um" @pytest.mark.parametrize( "crystal_map_input, desired_shape, desired_step_sizes", From e6012755923cead852342af2cfbd06c45d664cda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20Wiik=20=C3=85nes?= Date: Wed, 7 Dec 2022 20:31:53 +0100 Subject: [PATCH 04/10] New 0.10.3 patch release entry in changelog MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Håkon Wiik Ånes --- CHANGELOG.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index b75af4a2..9291d910 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -41,6 +41,13 @@ Fixed Security -------- +2022-12-08 - version 0.10.3 +=========================== + +Fixed +----- +- Reading of EDAX TSL .ang files with ten columns should now work. + 2022-10-25 - version 0.10.2 =========================== From 98072d55e2289b5b0142af03234091f4d0cc72ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20Wiik=20=C3=85nes?= Date: Mon, 30 Jan 2023 21:58:26 +0100 Subject: [PATCH 05/10] Bump version to 0.10.3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Håkon Wiik Ånes --- orix/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/orix/__init__.py b/orix/__init__.py index 0db59181..d46b3ae5 100644 --- a/orix/__init__.py +++ b/orix/__init__.py @@ -1,5 +1,5 @@ __name__ = "orix" -__version__ = "0.11.dev0" +__version__ = "0.10.3" __author__ = "orix developers" __author_email__ = "pyxem.team@gmail.com" __description__ = "orix is an open-source Python library for handling crystal orientation mapping data." From 6664e71e1292a54e67b7bf91c47b5a11ac30b243 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20Wiik=20=C3=85nes?= Date: Wed, 7 Dec 2022 21:15:52 +0100 Subject: [PATCH 06/10] Mention change in IO scan_unit nm/um behavior MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Håkon Wiik Ånes --- CHANGELOG.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 9291d910..c5ad04dd 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -48,6 +48,10 @@ Fixed ----- - Reading of EDAX TSL .ang files with ten columns should now work. +Changed +------- +- Only ASTAR .ang files return crystal maps with ``"nm"`` as scan unit. + 2022-10-25 - version 0.10.2 =========================== From 286a68aac0a401f15824371717654670b6eca975 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20Wiik=20=C3=85nes?= Date: Thu, 8 Dec 2022 23:18:24 +0100 Subject: [PATCH 07/10] Rename 'unknown1' column to 'detector_signal' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Håkon Wiik Ånes --- orix/io/plugins/ang.py | 14 +++++--------- orix/tests/io/test_ang.py | 8 ++++---- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/orix/io/plugins/ang.py b/orix/io/plugins/ang.py index a88868af..1d941015 100644 --- a/orix/io/plugins/ang.py +++ b/orix/io/plugins/ang.py @@ -35,11 +35,6 @@ __all__ = ["file_reader", "file_writer"] -# MTEX has this format sorted out, check out their readers when fixing -# issues and adapting to other versions of this file format in the future: -# https://github.com/mtex-toolbox/mtex/blob/develop/interfaces/loadEBSD_ang.m -# https://github.com/mtex-toolbox/mtex/blob/develop/interfaces/loadEBSD_ACOM.m - # Plugin description format_name = "ang" file_extensions = ["ang"] @@ -174,7 +169,8 @@ def _get_vendor_columns(header: List[str], n_cols_file: int) -> Tuple[str, List[ Returns ------- vendor - Determined vendor (``"tsl"``, ``"astar"``, or ``"emsoft"``). + Determined vendor (``"tsl"``, ``"astar"``, ``"emsoft"`` or + ``"orix"``). column_names List of column names. """ @@ -207,12 +203,12 @@ def _get_vendor_columns(header: List[str], n_cols_file: int) -> Tuple[str, List[ "iq", # Image quality from Hough transform "ci", # Confidence index "phase_id", - "unknown1", + "detector_signal", "fit", # Pattern fit + "unknown1", "unknown2", "unknown3", "unknown4", - "unknown5", ], 1: [ "euler1", @@ -223,7 +219,7 @@ def _get_vendor_columns(header: List[str], n_cols_file: int) -> Tuple[str, List[ "iq", "ci", "phase_id", - "unknown1", + "detector_signal", "fit", ], }, diff --git a/orix/tests/io/test_ang.py b/orix/tests/io/test_ang.py index 442c879d..56658764 100644 --- a/orix/tests/io/test_ang.py +++ b/orix/tests/io/test_ang.py @@ -138,8 +138,8 @@ def test_load_ang_tsl( assert non_indexed_fraction == np.sum(~xmap.is_indexed) # Properties - prop_names = ["iq", "ci", "unknown1", "fit"] - prop_names += [f"unknown{i + 2}" for i in range(n_unknown_cols - 1)] + prop_names = ["iq", "ci", "detector_signal", "fit"] + prop_names += [f"unknown{i + 1}" for i in range(n_unknown_cols - 1)] assert list(xmap.prop.keys()) == prop_names # Coordinates @@ -399,12 +399,12 @@ def test_get_header(self, temp_ang_file): "iq", "ci", "phase_id", - "unknown1", + "detector_signal", "fit", + "unknown1", "unknown2", "unknown3", "unknown4", - "unknown5", ], ANGFILE_TSL_HEADER, ), From 7faaacc36f7d5aedc9748aced14dd42b736176d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20Wiik=20=C3=85nes?= Date: Mon, 30 Jan 2023 21:55:13 +0100 Subject: [PATCH 08/10] Run tests in parallel on GitHub Actions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Håkon Wiik Ånes --- .github/workflows/build.yml | 64 ++++++++++++++++++++++++------------- orix/tests/conftest.py | 5 +++ setup.py | 1 + 3 files changed, 48 insertions(+), 22 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ff2ea9c5..ebc802d1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,48 +1,64 @@ name: build -on: [push, pull_request] +on: + push: + branches: + - '*' + pull_request: + branches: + - '*' + workflow_dispatch: + workflow: '*' + +env: + MPLBACKEND: agg jobs: code: name: code style runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 + - uses: psf/black@stable - - uses: actions/setup-python@v2 + + - uses: actions/setup-python@v4 with: python-version: 3.9 + - uses: isort/isort-action@master with: configuration: --profile black --filter-files --force-sort-within-sections --check-only --diff - name: Install Black with Jupyter extension - run: pip install black[jupyter] + run: | + pip install black[jupyter] - name: Check code style of Jupyter notebooks - run: black doc/**/*.ipynb --check + run: | + black doc/**/*.ipynb --check # Make sure all necessary files will be included in a release manifest: name: check manifest runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - - uses: actions/setup-python@v2 + - uses: actions/setup-python@v4 - name: Install dependencies - run: pip install manifix + run: | + pip install manifix - name: Check MANIFEST.in file - run: python setup.py manifix + run: | + python setup.py manifix build-with-pip: name: ${{ matrix.os }}-py${{ matrix.python-version }}${{ matrix.LABEL }} runs-on: ${{ matrix.os }} timeout-minutes: 15 - env: - MPLBACKEND: agg strategy: fail-fast: false matrix: @@ -55,26 +71,28 @@ jobs: DEPENDENCIES: diffpy.structure==3 matplotlib==3.3 LABEL: -oldest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} - - name: Display Python and pip versions - run: python -V; pip -V - - name: Install depedencies and package shell: bash - run: pip install -U -e .'[doc, tests]' + run: | + pip install -U -e .'[doc, tests]' - name: Install oldest supported version if: ${{ matrix.OLDEST_SUPPORTED_VERSION }} - run: pip install ${{ matrix.DEPENDENCIES }} + run: | + pip install ${{ matrix.DEPENDENCIES }} - - name: Display package versions - run: pip list + - name: Display Python, pip and package versions + run: | + python -V + pip -V + pip list - name: Run docstring tests if: ${{ matrix.os == 'ubuntu-latest' }} @@ -83,11 +101,13 @@ jobs: pytest --doctest-modules --ignore-glob=orix/tests orix/*.py - name: Run tests - run: pytest --cov=orix --pyargs orix + run: | + pytest -n 2 --cov=orix --pyargs orix - name: Generate line coverage if: ${{ matrix.os == 'ubuntu-latest' }} - run: coverage report --show-missing + run: | + coverage report --show-missing - name: Upload coverage to Coveralls if: ${{ matrix.os == 'ubuntu-latest' }} diff --git a/orix/tests/conftest.py b/orix/tests/conftest.py index a58b02fd..939d1f85 100644 --- a/orix/tests/conftest.py +++ b/orix/tests/conftest.py @@ -36,6 +36,11 @@ def rotations(): return Rotation([(2, 4, 6, 8), (-1, -3, -5, -7)]) +@pytest.fixture() +def eu(): + return np.random.rand(10, 3) + + ANGFILE_TSL_HEADER = ( "# TEM_PIXperUM 1.000000\n" "# x-star 0.413900\n" diff --git a/setup.py b/setup.py index 74bf73d6..f6dba090 100644 --- a/setup.py +++ b/setup.py @@ -30,6 +30,7 @@ "numpydoc", "pytest >= 5.4", "pytest-cov >= 2.8.1", + "pytest-xdist", ], } extra_feature_requirements["dev"] = [ From 88904f782c0e90ad01cc32aabb7ca9a41833a62c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20Wiik=20=C3=85nes?= Date: Tue, 31 Jan 2023 09:35:16 +0100 Subject: [PATCH 09/10] Remove planned 0.10.3 patch release and instead go for 0.11.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Håkon Wiik Ånes --- CHANGELOG.rst | 13 ++----------- orix/__init__.py | 2 +- 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index c5ad04dd..67e73052 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -28,6 +28,7 @@ Added Changed ------- - Bumped minimal version of ``diffpy.structure >= 3.0.2``. +- Only ASTAR .ang files return crystal maps with ``"nm"`` as scan unit. Deprecated ---------- @@ -37,21 +38,11 @@ Removed Fixed ----- +- Reading of EDAX TSL .ang files with ten columns should now work. Security -------- -2022-12-08 - version 0.10.3 -=========================== - -Fixed ------ -- Reading of EDAX TSL .ang files with ten columns should now work. - -Changed -------- -- Only ASTAR .ang files return crystal maps with ``"nm"`` as scan unit. - 2022-10-25 - version 0.10.2 =========================== diff --git a/orix/__init__.py b/orix/__init__.py index d46b3ae5..0db59181 100644 --- a/orix/__init__.py +++ b/orix/__init__.py @@ -1,5 +1,5 @@ __name__ = "orix" -__version__ = "0.10.3" +__version__ = "0.11.dev0" __author__ = "orix developers" __author_email__ = "pyxem.team@gmail.com" __description__ = "orix is an open-source Python library for handling crystal orientation mapping data." From c20bbf7a2e7ca7daabc73ba5d5b61d4c872c8327 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20Wiik=20=C3=85nes?= Date: Tue, 31 Jan 2023 09:58:07 +0100 Subject: [PATCH 10/10] Ease failing Symmetry.plot() tests due to unexpected no. collections MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Håkon Wiik Ånes --- orix/quaternion/symmetry.py | 2 +- orix/tests/quaternion/test_symmetry.py | 24 +++++++++++++----------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/orix/quaternion/symmetry.py b/orix/quaternion/symmetry.py index 3e300ea3..219456b9 100644 --- a/orix/quaternion/symmetry.py +++ b/orix/quaternion/symmetry.py @@ -476,7 +476,7 @@ def plot( default marker style for reprojected vectors is "+". Values used for vector(s) on the visible hemisphere are used unless another value is passed here. - kwargs + **kwargs Keyword arguments passed to :meth:`~orix.plot.StereographicPlot.scatter`, which passes these on to :meth:`matplotlib.axes.Axes.scatter`. diff --git a/orix/tests/quaternion/test_symmetry.py b/orix/tests/quaternion/test_symmetry.py index 03634b10..cf41fdd6 100644 --- a/orix/tests/quaternion/test_symmetry.py +++ b/orix/tests/quaternion/test_symmetry.py @@ -513,24 +513,26 @@ def test_hash_persistence(): assert all(h1a == h2a for h1a, h2a in zip(h1, h2)) -@pytest.mark.parametrize("symmetry", [C1, C4, Oh]) -def test_symmetry_plot(symmetry): - figure = symmetry.plot(return_figure=True) - assert isinstance(figure, plt.Figure) - assert len(figure.axes) == 1 - ax = figure.axes[0] - num = 1 if symmetry.is_proper else 2 - assert len(ax.collections) == num +@pytest.mark.parametrize("pg", [C1, C4, Oh]) +def test_symmetry_plot(pg): + fig = pg.plot(return_figure=True) + + assert isinstance(fig, plt.Figure) + assert len(fig.axes) == 1 + ax = fig.axes[0] + c0 = ax.collections[0] - assert len(c0.get_offsets()) == np.count_nonzero(~symmetry.improper) + assert len(c0.get_offsets()) == np.count_nonzero(~pg.improper) assert c0.get_label().lower() == "upper" - if num > 1: + if not pg.is_proper: c1 = ax.collections[1] - assert len(c1.get_offsets()) == np.count_nonzero(symmetry.improper) + assert len(c1.get_offsets()) == np.count_nonzero(pg.improper) assert c1.get_label().lower() == "lower" + assert len(ax.texts) == 2 assert ax.texts[0].get_text() == "$e_1$" assert ax.texts[1].get_text() == "$e_2$" + plt.close("all")