diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 503f8f3b0d..26065020cf 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -36,14 +36,23 @@ jobs: uses: actions/checkout@v3 with: submodules: true + - uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.10' + - name: Install Python dependencies + run: | + python -m pip install --upgrade pip + pip install sphinx myst-parser sphinx-markdown-tables sphinx_rtd_theme numpy - name: Add C++ Problem Matcher uses: ammaraskar/gcc-problem-matcher@0.2.0 - - name: Install Dependencies + - name: Install Dependencies - 2 run: | sudo apt-get -y install ninja-build - name: Install Sphinx run: | - sudo pip install sphinx myst-parser sphinx-markdown-tables sphinx_rtd_theme numpy + sudo pip3 install sphinx myst-parser sphinx-markdown-tables sphinx_rtd_theme numpy - name: Setup NuGet Credentials shell: bash run: | diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 26f98161c9..d083cfc9a5 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -24,10 +24,19 @@ jobs: - name: Checkout uses: actions/checkout@v3 with: - submodules: true + submodules: true + - uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.10' + - name: Install Python dependencies + run: | + python -m pip install --upgrade pip + pip install sphinx myst-parser sphinx-markdown-tables sphinx_rtd_theme numpy - name: Add C++ Problem Matcher uses: ammaraskar/gcc-problem-matcher@0.2.0 - - name: Install Dependencies + - name: Install Dependencies - 2 run: | brew install ninja - name: Install Sphinx diff --git a/CMakePresets.json b/CMakePresets.json index effc983a05..8093d23637 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -33,6 +33,10 @@ "type": "BOOL", "value": "ON" }, + "SIMPLNX_ENABLE_PYTHON_TESTS": { + "type": "BOOL", + "value": "ON" + }, "SIMPLNX_EMBED_PYTHON": { "type": "BOOL", "value": "OFF" @@ -121,6 +125,14 @@ "VCPKG_HOST_TRIPLET": { "type": "STRING", "value": "x64-osx-v11" + }, + "Python3_EXECUTABLE": { + "type": "PATH", + "value": "/Users/runner/hostedtoolcache/Python/3.10.13/x64/bin/python3.10" + }, + "SIMPLNX_PY_DISABLE_HIDDEN_VISIBILITY": { + "type": "BOOL", + "value": "ON" } } }, @@ -138,6 +150,14 @@ "VCPKG_HOST_TRIPLET": { "type": "STRING", "value": "arm64-osx-dynamic" + }, + "Python3_EXECUTABLE": { + "type": "PATH", + "value": "/Users/runner/hostedtoolcache/Python/3.10.13/x64/bin/python3.10" + }, + "SIMPLNX_PY_DISABLE_HIDDEN_VISIBILITY": { + "type": "BOOL", + "value": "ON" } } }, @@ -155,6 +175,10 @@ "VCPKG_HOST_TRIPLET": { "type": "STRING", "value": "x64-linux-dynamic" + }, + "Python3_EXECUTABLE": { + "type": "PATH", + "value": "/opt/hostedtoolcache/Python/3.10.13/x64/bin/python3.10" } } }, @@ -278,6 +302,10 @@ "SIMPLNX_PY_DISABLE_HIDDEN_VISIBILITY": { "type": "BOOL", "value": "ON" + }, + "Python3_EXECUTABLE": { + "type": "PATH", + "value": "/opt/local/anaconda3/envs/nx-build/bin/python" } } }, diff --git a/cmake/Utility.cmake b/cmake/Utility.cmake index 4b86bfc06e..2d6d9fa78c 100644 --- a/cmake/Utility.cmake +++ b/cmake/Utility.cmake @@ -460,3 +460,86 @@ function(cmpBuildDateRevisionString) endif() endfunction() + + +#------------------------------------------------------------------------------- +# @Brief function AddPythonTest +# @ NAME +# @ FILE +# @ PYTHONPATH +#------------------------------------------------------------------------------- +function(AddPythonTest) + set(options ) + set(oneValueArgs NAME FILE) + set(multiValueArgs PYTHONPATH) + cmake_parse_arguments(ARGS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + message(STATUS "ARGS_FILE:${ARGS_FILE}") + if(COMPLEX_BUILD_PYTHON) + if(WIN32) + add_test(NAME ${ARGS_NAME} + COMMAND ${complex_SOURCE_DIR}/wrapping/python/testing/anaconda_test.bat + ) + + set_property(TEST ${ARGS_NAME} + PROPERTY + ENVIRONMENT + "PYTHON_TEST_FILE=${ARGS_FILE}" + "Python3_EXECUTABLE=${Python3_EXECUTABLE}" + ) + else() + add_test(NAME ${ARGS_NAME} + COMMAND ${complex_SOURCE_DIR}/wrapping/python/testing/anaconda_test.sh + ) + set_property(TEST ${ARGS_NAME} + PROPERTY + ENVIRONMENT + "PYTHON_TEST_FILE=${ARGS_FILE}" + "Python3_EXECUTABLE=${Python3_EXECUTABLE}" + ) + endif() + else() + add_test(NAME ${ARGS_NAME} + COMMAND ${Python3_EXECUTABLE} ${ARGS_FILE} + ) + endif() + + if(WIN32) + string(REPLACE ";" "\\;" ARGS_PYTHONPATH "${ARGS_PYTHONPATH}") + else() + string(REPLACE ";" ":" ARGS_PYTHONPATH "${ARGS_PYTHONPATH}") + endif() + + set_property(TEST ${ARGS_NAME} + APPEND + PROPERTY + ENVIRONMENT + "PYTHONPATH=${ARGS_PYTHONPATH}" + ) +endfunction() + +#------------------------------------------------------------------------------- +# @Brief function CreatePythonTests +# @ PREFIX +# @ INPUT_DIR +# @ TEST_NAMES +#------------------------------------------------------------------------------- +function(CreatePythonTests) + set(options) + set(oneValueArgs PREFIX INPUT_DIR) + set(multiValueArgs TEST_NAMES) + cmake_parse_arguments(ARGS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + set(TESTS_PYTHONPATH + "$" + ) + + foreach(test ${ARGS_TEST_NAMES}) + string(REPLACE "/" "_" test_name ${test}) + set(PY_TEST_NAME ${ARGS_PREFIX}_${test_name}) + + AddPythonTest(NAME ${PY_TEST_NAME} + FILE ${ARGS_INPUT_DIR}/${test}.py + PYTHONPATH ${TESTS_PYTHONPATH} + ) + endforeach() +endfunction() diff --git a/src/Plugins/SimplnxCore/wrapping/python/simplnxpy.cpp b/src/Plugins/SimplnxCore/wrapping/python/simplnxpy.cpp index dfbb3fbc24..753e94613b 100644 --- a/src/Plugins/SimplnxCore/wrapping/python/simplnxpy.cpp +++ b/src/Plugins/SimplnxCore/wrapping/python/simplnxpy.cpp @@ -544,8 +544,11 @@ PYBIND11_MODULE(simplnx, mod) std::vector outputPaths; for(const auto* object : self.getTopLevelData()) { - auto topLevelPath = DataPath::FromString(object->getDataPaths()[0].getTargetName()).value(); - outputPaths.push_back(topLevelPath); + if(object != nullptr) + { + auto topLevelPath = DataPath::FromString(object->getDataPaths()[0].getTargetName()).value(); + outputPaths.push_back(topLevelPath); + } } return outputPaths; } diff --git a/src/simplnx/Utilities/DataGroupUtilities.cpp b/src/simplnx/Utilities/DataGroupUtilities.cpp index b7a80abdf4..d07d3213d3 100644 --- a/src/simplnx/Utilities/DataGroupUtilities.cpp +++ b/src/simplnx/Utilities/DataGroupUtilities.cpp @@ -186,7 +186,6 @@ std::optional> GetAllChildDataPaths(const DataStructure& d { bool ignore = false; DataPath childPath = parentGroup.createChildPath(childName); - const DataObject* dataObject = dataStructure.getData(childPath); for(const auto& ignoredPath : ignoredDataPaths) { if(childPath == ignoredPath) @@ -195,7 +194,8 @@ std::optional> GetAllChildDataPaths(const DataStructure& d break; } } - if(!ignore && (dataObjectType == DataObject::Type::DataObject || dataObject->getDataObjectType() == dataObjectType)) + const DataObject* dataObject = dataStructure.getData(childPath); + if(dataObject != nullptr && !ignore && (dataObjectType == DataObject::Type::DataObject || dataObject->getDataObjectType() == dataObjectType)) { childDataObjects.push_back(childPath); } @@ -211,7 +211,7 @@ std::optional> GetAllChildDataPaths(const DataStructure& d { std::vector childDataObjects; const DataObject* dataObject1 = dataStructure.getData(parent); - if(dataObject1->getDataObjectType() == DataObject::Type::DataArray || dataObject1->getDataObjectType() == DataObject::Type::DynamicListArray || + if(dataObject1 == nullptr || dataObject1->getDataObjectType() == DataObject::Type::DataArray || dataObject1->getDataObjectType() == DataObject::Type::DynamicListArray || dataObject1->getDataObjectType() == DataObject::Type::NeighborList || dataObject1->getDataObjectType() == DataObject::Type::ScalarData || dataObject1->getDataObjectType() == DataObject::Type::StringArray) { diff --git a/wrapping/python/CMakeLists.txt b/wrapping/python/CMakeLists.txt index 0aabc827f5..fc5ea08d8b 100644 --- a/wrapping/python/CMakeLists.txt +++ b/wrapping/python/CMakeLists.txt @@ -109,8 +109,8 @@ function(simplnx_create_pyi) set(PYI_TARGET_NAME ${ARGS_PYTHON_MODULE_NAME}CreateStubFile) add_custom_target(${PYI_TARGET_NAME} ALL - COMMAND ${MYPY_STUBGEN_EXE} -m ${ARGS_PYTHON_MODULE_NAME} -o $ - COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_LIST_DIR}/fix_pyi_file.py --input_file "$/${ARGS_PYTHON_MODULE_NAME}.pyi" + COMMAND "${MYPY_STUBGEN_EXE}" -m "${ARGS_PYTHON_MODULE_NAME}" -o "$" + COMMAND "${Python3_EXECUTABLE}" "${CMAKE_CURRENT_LIST_DIR}/fix_pyi_file.py" --input_file "$/${ARGS_PYTHON_MODULE_NAME}.pyi" COMMENT "${ARGS_PYTHON_MODULE_NAME}: Generating .pyi files" WORKING_DIRECTORY $ ) @@ -278,3 +278,46 @@ option(SIMPLNX_ENABLE_SPHINX_DOCS "Enables the Sphinx based documentation genera if(SIMPLNX_ENABLE_SPHINX_DOCS) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/docs ${simplnx_BINARY_DIR}/sphinx_docs) endif() + +#------------------------------------------------------------------------------ +# Create the Python Unit tests +#------------------------------------------------------------------------------ +option(COMPLEX_ENABLE_PYTHON_TESTS "Enables python based unit tests" OFF) +if(COMPLEX_ENABLE_PYTHON_TESTS) + + file(READ ${complex_SOURCE_DIR}/wrapping/python/complex_test_dirs.in.py COMPLEX_TEST_DIRS_FILE) + + string(REPLACE "\${CMAKE_LIBRARY_OUTPUT_DIRECTORY}" $ COMPLEX_TEST_DIRS_FILE ${COMPLEX_TEST_DIRS_FILE}) + string(REPLACE "\${complex_BINARY_DIR}" ${complex_BINARY_DIR} COMPLEX_TEST_DIRS_FILE ${COMPLEX_TEST_DIRS_FILE}) + string(REPLACE "\${DREAM3D_DATA_DIR}" ${DREAM3D_DATA_DIR} COMPLEX_TEST_DIRS_FILE ${COMPLEX_TEST_DIRS_FILE}) + string(REPLACE "\${complex_SOURCE_DIR}" ${complex_SOURCE_DIR} COMPLEX_TEST_DIRS_FILE ${COMPLEX_TEST_DIRS_FILE}) + + file(GENERATE + OUTPUT "$/complex_test_dirs.py" + CONTENT ${COMPLEX_TEST_DIRS_FILE} + ) + + set(PYTHON_TEST_INPUT_DIR "${complex_SOURCE_DIR}/wrapping/python/examples") + + set(COMPLEX_PYTHON_TESTS + "angle_conversion" + "basic_arrays" + "basic_ebsd_ipf" + "basic_numpy" + "create_ensemble_info" + "generated_file_list" + "geometry_examples" + "import_d3d" # Dependent on 'basic_ebsd_ipf' running first + "import_hdf5" # Dependent on 'basic_ebsd_ipf' running first + "output_file" + "pipeline" + "read_csv_file" + # "read_esprit_data" + ) + + CreatePythonTests(PREFIX "PY_COMPLEX" + INPUT_DIR ${PYTHON_TEST_INPUT_DIR} + TEST_NAMES ${COMPLEX_PYTHON_TESTS} + ) + +endif() diff --git a/wrapping/python/CxPybind/CxPybind/CxPybind.hpp b/wrapping/python/CxPybind/CxPybind/CxPybind.hpp index 7ce8128557..9e5019552e 100644 --- a/wrapping/python/CxPybind/CxPybind/CxPybind.hpp +++ b/wrapping/python/CxPybind/CxPybind/CxPybind.hpp @@ -397,7 +397,18 @@ auto BindFilter(py::handle scope, const Internals& internals) std::string executeSig = MakePythonSignature("execute", internals); std::string executeDocString = fmt::format("{}\n\nExecutes the filter\n", executeSig); - + filter.def_static("human_name", [&internals]() { + FilterT filter; + return filter.humanName(); + }); + filter.def_static("name", [&internals]() { + FilterT filter; + return filter.name(); + }); + filter.def_static("uuid", [&internals]() { + FilterT filter; + return filter.uuid(); + }); filter.def_static( "execute", [&internals](DataStructure& dataStructure, const py::kwargs& kwargs) { diff --git a/wrapping/python/complex_test_dirs.in.py b/wrapping/python/complex_test_dirs.in.py new file mode 100644 index 0000000000..e1a6881026 --- /dev/null +++ b/wrapping/python/complex_test_dirs.in.py @@ -0,0 +1,50 @@ +''' module to get build specific directories + This file is generated during the cmake configure phase. This file does *NOT* + however use the standard `cmake_configure_file()` command but instead uses + a custom generation cmake code. If you add new `${}` style variables, you will + need to update those custom CMake codes. + + ''' + + +import complex as cx + +def check_filter_result(filter: cx.IFilter, result: cx.IFilter.ExecuteResult): + if len(result.warnings) != 0: + print(f'{filter.name()} :: Warnings: {result.warnings}') + + has_errors = len(result.errors) != 0 + if has_errors: + print(f'{filter.name()} :: Errors: {result.errors}') + raise RuntimeError(result) + + print(f"{filter.name()} :: No errors running the filter") + + +def GetBuildDirectory(): + return '${CMAKE_LIBRARY_OUTPUT_DIRECTORY}' + +def GetTestDirectory(): + return '${complex_BINARY_DIR}/Testing' + +def GetTestTempDirectory(): + return '${complex_BINARY_DIR}/Testing/Temporary' + +def GetDataDirectory(): + return '${DREAM3D_DATA_DIR}' + +def GetComplexPythonSourceDir(): + return '${complex_SOURCE_DIR}/wrapping/python' + +def GetComplexSourceDir(): + return '${complex_SOURCE_DIR}' + +def print_all_paths(): + print(f'#### Important Filesystem Paths ####') + print(f' GetBuildDirectory: {GetBuildDirectory()}') + print(f' GetTestDirectory: {GetTestDirectory()}') + print(f' GetTestTempDirectory: {GetTestTempDirectory()}') + print(f' GetDataDirectory: {GetDataDirectory()}') + print(f' GetComplexPythonSourceDir: {GetComplexPythonSourceDir()}') + print(f' GetComplexSourceDir: {GetComplexSourceDir()}') + print('#######################################') \ No newline at end of file diff --git a/wrapping/python/docs/source/Overview.rst b/wrapping/python/docs/source/Overview.rst index 4215779c51..e4ec52a525 100644 --- a/wrapping/python/docs/source/Overview.rst +++ b/wrapping/python/docs/source/Overview.rst @@ -181,7 +181,49 @@ form a **Pipeline**, in which the data structure flows through the set of **Filt being modified along the way. If a **Filter** reads in data from outside of DREAM3D-NX, then the new data will be incorporated into the existing data structure. Or, if no data structure yet exists (e.g, starting from a “blank slate”), a new one will be -created. +created. + +.. py:class:: complex.IFilter + + This class holds an instantiation of a DREAM3D-NX filter. The filter can be + preflighted, executed or just held for later execution. + + .. py:method:: name() + + :return: The C++ classname of the filter + :rtype: str + + .. py:method:: human_name() + + :return: What the user would see in the DREAM3D-NX application + :rtype: str + + .. py:method:: uuid() + + :return: The unique identifier of the filter + :rtype: str + + .. py:method:: execute() + + :return: A complex.IFilter.Result object that contains any warnings or errors + that were encountered during the execution of the filter. + :rtype: complex.IFilter.Result + + .. py:method:: preflight() + + :return: A complex.IFilter.Result object that contains any warnings or errors + that were encountered during the preflight of the filter. + :rtype: complex.IFilter.Result + +.. code:: python + + create_array_filter = cx.CreateDataArray() + print(f'{create_array_filter.name()}') + print(f'{create_array_filter.human_name()}') + print(f'{create_array_filter.uuid()}') + +For examles of executing a filter, please see any of the example python files included +with the source package. .. _Pipeline: .. _Plugin: diff --git a/wrapping/python/examples/angle_conversion.py b/wrapping/python/examples/angle_conversion.py index 68cc601abd..eaa49a59fc 100644 --- a/wrapping/python/examples/angle_conversion.py +++ b/wrapping/python/examples/angle_conversion.py @@ -1,11 +1,54 @@ -# Import the DREAM3D Base library and Plugins -import simplnx as nx +""" +Important Note +============== + +This python file can be used as an example of how to execute a number of DREAM3D-NX +filters one after another, if you plan to use the codes below (and you are welcome to), +there are a few things that you, the developer, should take note of: + +Import Statements +----------------- + +You will most likely *NOT* need to include the following code: + + .. code:: python + + import complex_test_dirs as cxtest + +Filter Error Detection +---------------------- + +In each section of code a filter is created and executed immediately. This may or +may *not* be what you want to do. You can also preflight the filter to verify the +correctness of the filters before executing the filter **although** this is done +for you when the filter is executed. As such, you will want to check the 'result' +variable to see if there are any errors or warnings. If there **are** any then +you, as the developer, should act appropriately on the errors or warnings. +More specifically, this bit of code: + + .. code:: python + + cxtest.check_filter_result(cxor.ReadAngDataFilter, result) + +is used by the simplnx unit testing framework and should be replaced by your own +error checking code. You are welcome to look up the function definition and use +that. + +""" +import complex as cx import itkimageprocessing as cxitk import orientationanalysis as cxor +import complex_test_dirs as cxtest import numpy as np +#------------------------------------------------------------------------------ +# Print the various filesystem paths that are pregenerated for this machine. +#------------------------------------------------------------------------------ +cxtest.print_all_paths() + + # ------------------------------------------------------------------------------ # Create a DataArray that is as long as my CSV file (99 Rows in this case) # ------------------------------------------------------------------------------ @@ -19,17 +62,18 @@ tuple_dimensions=[[99]], output_data_array=array_path, initialization_value='0') -if len(result.errors) != 0: - print('Errors: {}', result.errors) - print('Warnings: {}', result.warnings) -else: - print("No errors running the CreateDataArray") +cxtest.check_filter_result(cx.CreateDataArray, result) + # Get a numpy.view into the newly created DataArray -npdata = data_structure[array_path].npview() +data_array = data_structure[array_path] +# Get the underlying DataStore object +data_store = data_array.store +# Get a Numpy View into the data +npdata = data_store.npview() # Read the CSV file into the DataArray using the numpy view -file_path = 'angles.csv' +file_path = cxtest.GetComplexPythonSourceDir() + '/examples/angles.csv' npdata[:] = np.loadtxt(file_path, delimiter=',') # ------------------------------------------------------------------------------ @@ -41,11 +85,8 @@ input_type=0, output_orientation_array_name='Quaternions', output_type=2) -if len(result.errors) != 0: - print('Errors: {}', result.errors) - print('Warnings: {}', result.warnings) -else: - print("No errors running the ConvertOrientations") +cxtest.check_filter_result(cxor.ConvertOrientations, result) + # Get the Quaternions and print them out. data_array = data_structure[quat_path] diff --git a/wrapping/python/examples/basic_arrays.py b/wrapping/python/examples/basic_arrays.py index d56e2a5a8e..2c4abbb6ef 100644 --- a/wrapping/python/examples/basic_arrays.py +++ b/wrapping/python/examples/basic_arrays.py @@ -1,32 +1,68 @@ -# Import the DREAM3D Base library and Plugins -import simplnx as nx +""" +Important Note +============== + +This python file can be used as an example of how to execute a number of DREAM3D-NX +filters one after another, if you plan to use the codes below (and you are welcome to), +there are a few things that you, the developer, should take note of: + +Import Statements +----------------- + +You will most likely *NOT* need to include the following code: + + .. code:: python + + import complex_test_dirs as cxtest + +Filter Error Detection +---------------------- + +In each section of code a filter is created and executed immediately. This may or +may *not* be what you want to do. You can also preflight the filter to verify the +correctness of the filters before executing the filter **although** this is done +for you when the filter is executed. As such, you will want to check the 'result' +variable to see if there are any errors or warnings. If there **are** any then +you, as the developer, should act appropriately on the errors or warnings. +More specifically, this bit of code: + + .. code:: python + + cxtest.check_filter_result(cxor.ReadAngDataFilter, result) + +is used by the simplnx unit testing framework and should be replaced by your own +error checking code. You are welcome to look up the function definition and use +that. + +""" +import complex as cx import itkimageprocessing as cxitk import orientationanalysis as cxor +import complex_test_dirs as cxtest import numpy as np +#------------------------------------------------------------------------------ +# Print the various filesystem paths that are pregenerated for this machine. +#------------------------------------------------------------------------------ +cxtest.print_all_paths() + # Create a Data Structure data_structure = nx.DataStructure() #------------------------------------------------------------------------------ # Create a top level group: (Not needed) #------------------------------------------------------------------------------ -result = nx.CreateDataGroup.execute(data_structure=data_structure, - data_object_path=nx.DataPath(['Group'])) -if len(result.errors) != 0: - print('Errors: {}', result.errors) - print('Warnings: {}', result.warnings) -else: - print("No errors running CreateDataGroup filter") - -result = nx.CreateDataGroup.execute(data_structure=data_structure, - data_object_path=nx.DataPath("/Some/Path/To/Group")); -if len(result.errors) != 0: - print('Errors: {}', result.errors) - print('Warnings: {}', result.warnings) -else: - print("No errors running CreateDataGroup filter") +result = cx.CreateDataGroup.execute(data_structure=data_structure, + data_object_path=cx.DataPath(['Group'])) +cxtest.check_filter_result(cx.CreateDataGroup, result) + + +result = cx.CreateDataGroup.execute(data_structure=data_structure, + data_object_path=cx.DataPath("/Some/Path/To/Group")); +cxtest.check_filter_result(cx.CreateDataGroup, result) + #------------------------------------------------------------------------------ # Create 1D Array @@ -43,11 +79,8 @@ numeric_type=array_type, output_data_array=output_array_path, tuple_dimensions=tuple_dims) -if len(result.errors) != 0: - print('Errors: {}', result.errors) - print('Warnings: {}', result.warnings) -else: - print("No errors running the filter") +cxtest.check_filter_result(cx.CreateDataArray, result) + # We can check the output of the filter by simply printing the array npdata = data_structure[output_array_path].npview() @@ -69,11 +102,8 @@ numeric_type=array_type, output_data_array=output_array_path, tuple_dimensions=tuple_dims) -if len(result.errors) != 0: - print('Errors: {}', result.errors) - print('Warnings: {}', result.warnings) -else: - print("No errors running the filter") +cxtest.check_filter_result(cx.CreateDataArray, result) + data_array = data_structure[output_array_path] print(f'name: {data_array.name}') @@ -94,18 +124,15 @@ output_array_path = nx.DataPath(["3D Array"]) tuple_dims = [[3, 2, 5]] create_array_filter = nx.CreateDataArray() -result = create_array_filter.execute(data_structure=data_structure, +result = create_array_filter.execute(data_structure=data_structure, component_count=1, data_format="", initialization_value="10", numeric_type=array_type, output_data_array=output_array_path, tuple_dimensions=tuple_dims) -if len(result.errors) != 0: - print('Errors: {}', result.errors) - print('Warnings: {}', result.warnings) -else: - print("No errors running the filter") +cxtest.check_filter_result(cx.CreateDataArray, result) + npdata = data_structure[output_array_path].npview() print(npdata) @@ -113,23 +140,16 @@ result = nx.CreateAttributeMatrixFilter.execute(data_structure=data_structure, data_object_path=nx.DataPath(["New Attribute Matrix"]), tuple_dimensions = [[100., 200., 300.]]) -if len(result.errors) != 0: - print('Errors: {}', result.errors) - print('Warnings: {}', result.warnings) -else: - print("No errors running CreateAttributeMatrixFilter filter") +cxtest.check_filter_result(cx.CreateAttributeMatrixFilter, result) -output_file_path = "/tmp/output_file_example.dream3d" -result = nx.WriteDREAM3DFilter.execute(data_structure=data_structure, +output_file_path = cxtest.GetTestTempDirectory() + "/output_file_example.dream3d" +result = cx.WriteDREAM3DFilter.execute(data_structure=data_structure, export_file_path=output_file_path, write_xdmf_file=True) -if len(result.errors) != 0: - print('Errors: {}', result.errors) - print('Warnings: {}', result.warnings) -else: - print("No errors running the filter") +cxtest.check_filter_result(cx.WriteDREAM3DFilter, result) + #------------------------------------------------------------------------------ diff --git a/wrapping/python/examples/basic_ebsd_ipf.py b/wrapping/python/examples/basic_ebsd_ipf.py index c9495804e4..d711f70111 100644 --- a/wrapping/python/examples/basic_ebsd_ipf.py +++ b/wrapping/python/examples/basic_ebsd_ipf.py @@ -1,11 +1,52 @@ -# Import the DREAM3D Base library and Plugins -import simplnx as nx +""" +Important Note +============== + +This python file can be used as an example of how to execute a number of DREAM3D-NX +filters one after another, if you plan to use the codes below (and you are welcome to), +there are a few things that you, the developer, should take note of: + +Import Statements +----------------- + +You will most likely *NOT* need to include the following code: + + .. code:: python + + import complex_test_dirs as cxtest + +Filter Error Detection +---------------------- + +In each section of code a filter is created and executed immediately. This may or +may *not* be what you want to do. You can also preflight the filter to verify the +correctness of the filters before executing the filter **although** this is done +for you when the filter is executed. As such, you will want to check the 'result' +variable to see if there are any errors or warnings. If there **are** any then +you, as the developer, should act appropriately on the errors or warnings. +More specifically, this bit of code: + + .. code:: python + + cxtest.check_filter_result(cxor.ReadAngDataFilter, result) + +is used by the simplnx unit testing framework and should be replaced by your own +error checking code. You are welcome to look up the function definition and use +that. + +""" +import complex as cx import itkimageprocessing as cxitk import orientationanalysis as cxor +import complex_test_dirs as cxtest import numpy as np -import matplotlib.pyplot as plt + +#------------------------------------------------------------------------------ +# Print the various filesystem paths that are pregenerated for this machine. +#------------------------------------------------------------------------------ +cxtest.print_all_paths() #------------------------------------------------------------------------------ # Create a Data Structure @@ -16,13 +57,10 @@ result = cxor.ReadAngDataFilter.execute(data_structure=data_structure, cell_attribute_matrix_name="Scan Data", cell_ensemble_attribute_matrix_name="Phase Data", - data_container_name=nx.DataPath(["Small IN100"]), - input_file="DREAM3D_Data/Data/SmallIN100/Slice_1.ang") -if len(result.errors) != 0: - print('Errors: {}', result.errors) - print('Warnings: {}', result.warnings) -else: - print("No errors running the ReadAngDataFilter") + data_container_name=cx.DataPath(["Small IN100"]), + input_file=cxtest.GetBuildDirectory() + "/Data/Small_IN100/Slice_1.ang") + +cxtest.check_filter_result(cxor.ReadAngDataFilter, result) #------------------------------------------------------------------------------ # Rotate the Euler Reference Frame @@ -30,12 +68,7 @@ result = cxor.RotateEulerRefFrameFilter.execute(data_structure=data_structure, euler_angles_array_path=nx.DataPath(["Small IN100", "Scan Data", "EulerAngles"]), rotation_axis=[0,0,1,90]) -if len(result.errors) != 0: - print('Errors: {}', result.errors) - print('Warnings: {}', result.warnings) -else: - print("No errors running the RotateEulerRefFrameFilter") - +cxtest.check_filter_result(cxor.RotateEulerRefFrameFilter, result) #------------------------------------------------------------------------------ # Rotate the Sample Reference Frame 180@010 @@ -49,11 +82,8 @@ selected_image_geometry=nx.DataPath(["Small IN100"]), #rotation_matrix=[[1,0,0],[0,1,0],[0,0,1]] ) -if len(result.errors) != 0: - print('Errors: {}', result.errors) - print('Warnings: {}', result.warnings) -else: - print("No errors running the RotateEulerRefFrameFilter") +cxtest.check_filter_result(cx.RotateSampleRefFrameFilter, result) + #------------------------------------------------------------------------------ # Create a ThresholdSet to use in the MultiThreshold Objects filter @@ -75,12 +105,9 @@ result = nx.MultiThresholdObjects.execute(data_structure=data_structure, array_thresholds=threshold_set, created_data_path="Mask", - created_mask_type=nx.DataType.boolean) -if len(result.errors) != 0: - print('Errors: {}', result.errors) - print('Warnings: {}', result.warnings) -else: - print("No errors running the MultiThresholdObjects") + created_mask_type=cx.DataType.boolean) +cxtest.check_filter_result(cx.MultiThresholdObjects, result) + #------------------------------------------------------------------------------ # Generate the IPF Colors for the <001> direction @@ -94,28 +121,20 @@ reference_dir=[0,0,1], use_mask=True ) -if len(result.errors) != 0: - print('Errors: {}', result.errors) - print('Warnings: {}', result.warnings) -else: - print("No errors running the GenerateIPFColorsFilter") +cxtest.check_filter_result(cxor.GenerateIPFColorsFilter, result) + #------------------------------------------------------------------------------ # Write the IPF colors to a PNG file #------------------------------------------------------------------------------ -result = cxitk.ITKImageWriter.execute(data_structure=data_structure, file_name="/tmp/Small_IN100_IPF_Z.png", - image_array_path=nx.DataPath(["Small IN100", "Scan Data", "IPFColors"]), - image_geom_path=nx.DataPath(["Small IN100"]), +result = cxitk.ITKImageWriter.execute(data_structure=data_structure, + file_name=cxtest.GetTestTempDirectory() + "/Small_IN100_IPF_Z.png", + image_array_path=cx.DataPath(["Small IN100", "Scan Data", "IPFColors"]), + image_geom_path=cx.DataPath(["Small IN100"]), index_offset=0, plane=0) - -if len(result.errors) != 0: - print('Errors: {}', result.errors) - print('Warnings: {}', result.warnings) -else: - print("No errors running the ITKImageWriter") - +cxtest.check_filter_result(cxitk.ITKImageWriter, result) # #------------------------------------------------------------------------------ # # Show the IPFColors using MatPlotLib @@ -142,11 +161,8 @@ output_rgb_array_name="CI Color", selected_data_array_path=nx.DataPath(["Small IN100", "Scan Data", "Confidence Index"]), selected_preset=color_control_points) -if len(result.errors) != 0: - print('Errors: {}', result.errors) - print('Warnings: {}', result.warnings) -else: - print("No errors running the GenerateColorTableFilter") +cxtest.check_filter_result(cx.GenerateColorTableFilter, result) + #------------------------------------------------------------------------------ # Create a Pole Figure @@ -165,44 +181,21 @@ lambert_size=64, material_name_array_path=nx.DataPath(["Small IN100", "Phase Data", "MaterialName"]), num_colors=32, - output_path="small_in100_pole_figure", + output_path=cxtest.GetTestTempDirectory() + "/small_in100_pole_figure", save_as_image_geometry=True, title="Small IN100 Slice 1", use_mask=True, write_image_to_disk=True) -if len(result.errors) != 0: - print('Errors: {}', result.errors) - print('Warnings: {}', result.warnings) -else: - print("No errors running the WritePoleFigureFilter") +cxtest.check_filter_result(cxor.WritePoleFigureFilter, result) + #------------------------------------------------------------------------------ # Write the DataStructure to a .dream3d file #------------------------------------------------------------------------------ -output_file_path = "basic_ebsd_example.dream3d" -result = nx.WriteDREAM3DFilter.execute(data_structure=data_structure, + +output_file_path = cxtest.GetTestTempDirectory() + "/basic_ebsd_example.dream3d" +result = cx.WriteDREAM3DFilter.execute(data_structure=data_structure, export_file_path=output_file_path, write_xdmf_file=True) -if len(result.errors) != 0: - print('Errors: {}', result.errors) - print('Warnings: {}', result.warnings) -else: - print("No errors running the WriteDREAM3DFilter") - - - -#------------------------------------------------------------------------------ -# View with MatPlotLib -#------------------------------------------------------------------------------ -data_array = data_structure[nx.DataPath(["Small IN100 Pole Figure", "CellData", prefix + "Phase_1"])] -# Get the underlying DataStore object -data_store = data_array.store -npdata = data_store.npview().copy() -# Remove any dimension with '1' -npdata = np.squeeze(npdata, axis=0) - -plt.imshow(npdata) -plt.title("Small IN100 Pole Figure") -plt.axis('off') # to turn off axes -plt.show() +cxtest.check_filter_result(cx.WriteDREAM3DFilter, result) diff --git a/wrapping/python/examples/basic_numpy.py b/wrapping/python/examples/basic_numpy.py index 2a4f4f436f..33e0d061e6 100644 --- a/wrapping/python/examples/basic_numpy.py +++ b/wrapping/python/examples/basic_numpy.py @@ -1,4 +1,44 @@ -import simplnx as nx +""" +Important Note +============== + +This python file can be used as an example of how to execute a number of DREAM3D-NX +filters one after another, if you plan to use the codes below (and you are welcome to), +there are a few things that you, the developer, should take note of: + +Import Statements +----------------- + +You will most likely *NOT* need to include the following code: + + .. code:: python + + import complex_test_dirs as cxtest + +Filter Error Detection +---------------------- + +In each section of code a filter is created and executed immediately. This may or +may *not* be what you want to do. You can also preflight the filter to verify the +correctness of the filters before executing the filter **although** this is done +for you when the filter is executed. As such, you will want to check the 'result' +variable to see if there are any errors or warnings. If there **are** any then +you, as the developer, should act appropriately on the errors or warnings. +More specifically, this bit of code: + + .. code:: python + + cxtest.check_filter_result(cxor.ReadAngDataFilter, result) + +is used by the simplnx unit testing framework and should be replaced by your own +error checking code. You are welcome to look up the function definition and use +that. + +""" +import complex as cx +import complex_test_dirs as cxtest + + import numpy as np @@ -34,7 +74,8 @@ radians_data = np.radians(degrees_data) # Run a D3D filter to convert back to degrees -assert nx.ChangeAngleRepresentation.execute(data_structure, conversion_type=0, angles_array_path=array_path) +result = cx.ChangeAngleRepresentation.execute(data_structure, conversion_type=0, angles_array_path=array_path) +cxtest.check_filter_result(cx.ChangeAngleRepresentation, result) # compare the 2 arrays assert np.array_equal(npdata, radians_data) diff --git a/wrapping/python/examples/create_ensemble_info.py b/wrapping/python/examples/create_ensemble_info.py index 0ddc65dffc..52a955afb6 100644 --- a/wrapping/python/examples/create_ensemble_info.py +++ b/wrapping/python/examples/create_ensemble_info.py @@ -1,11 +1,53 @@ -# Import the DREAM3D Base library and Plugins -import simplnx as nx +""" +Important Note +============== + +This python file can be used as an example of how to execute a number of DREAM3D-NX +filters one after another, if you plan to use the codes below (and you are welcome to), +there are a few things that you, the developer, should take note of: + +Import Statements +----------------- + +You will most likely *NOT* need to include the following code: + + .. code:: python + + import complex_test_dirs as cxtest + +Filter Error Detection +---------------------- + +In each section of code a filter is created and executed immediately. This may or +may *not* be what you want to do. You can also preflight the filter to verify the +correctness of the filters before executing the filter **although** this is done +for you when the filter is executed. As such, you will want to check the 'result' +variable to see if there are any errors or warnings. If there **are** any then +you, as the developer, should act appropriately on the errors or warnings. +More specifically, this bit of code: + + .. code:: python + + cxtest.check_filter_result(cxor.ReadAngDataFilter, result) + +is used by the simplnx unit testing framework and should be replaced by your own +error checking code. You are welcome to look up the function definition and use +that. + +""" +import complex as cx import itkimageprocessing as cxitk import orientationanalysis as cxor +import complex_test_dirs as cxtest import numpy as np +#------------------------------------------------------------------------------ +# Print the various filesystem paths that are pregenerated for this machine. +#------------------------------------------------------------------------------ +cxtest.print_all_paths() + # Create a Data Structure data_structure = nx.DataStructure() @@ -21,9 +63,4 @@ phase_types_array_name="Primary", ensemble=ensemble_info_parameter ) -if len(result.errors) != 0: - print('Errors: {}', result.errors) - print('Warnings: {}', result.warnings) -else: - print("No errors running the filter") - +cxtest.check_filter_result(cxor.CreateEnsembleInfoFilter, result) diff --git a/wrapping/python/examples/generated_file_list.py b/wrapping/python/examples/generated_file_list.py index fcc3e1fe2a..ce701041e9 100644 --- a/wrapping/python/examples/generated_file_list.py +++ b/wrapping/python/examples/generated_file_list.py @@ -1,18 +1,61 @@ -# Import the DREAM3D Base library and Plugins -import simplnx as nx +""" +Important Note +============== + +This python file can be used as an example of how to execute a number of DREAM3D-NX +filters one after another, if you plan to use the codes below (and you are welcome to), +there are a few things that you, the developer, should take note of: + +Import Statements +----------------- + +You will most likely *NOT* need to include the following code: + + .. code:: python + + import complex_test_dirs as cxtest + +Filter Error Detection +---------------------- + +In each section of code a filter is created and executed immediately. This may or +may *not* be what you want to do. You can also preflight the filter to verify the +correctness of the filters before executing the filter **although** this is done +for you when the filter is executed. As such, you will want to check the 'result' +variable to see if there are any errors or warnings. If there **are** any then +you, as the developer, should act appropriately on the errors or warnings. +More specifically, this bit of code: + + .. code:: python + + cxtest.check_filter_result(cxor.ReadAngDataFilter, result) + +is used by the simplnx unit testing framework and should be replaced by your own +error checking code. You are welcome to look up the function definition and use +that. + +""" +import complex as cx import itkimageprocessing as cxitk import orientationanalysis as cxor +import complex_test_dirs as cxtest import numpy as np +#------------------------------------------------------------------------------ +# Print the various filesystem paths that are pre-generated for this machine. +#------------------------------------------------------------------------------ +cxtest.print_all_paths() + + # Create a Data Structure data_structure = nx.DataStructure() -generated_file_list_value = nx.GeneratedFileListParameter.ValueType() -generated_file_list_value.input_path = "Data/Porosity_Image" -generated_file_list_value.ordering = nx.GeneratedFileListParameter.Ordering.LowToHigh +generated_file_list_value = cx.GeneratedFileListParameter.ValueType() +generated_file_list_value.input_path = cxtest.GetBuildDirectory() + "/Data/Porosity_Image" +generated_file_list_value.ordering = cx.GeneratedFileListParameter.Ordering.LowToHigh generated_file_list_value.file_prefix = "slice_" generated_file_list_value.file_suffix = "" @@ -30,8 +73,4 @@ input_file_list_info=generated_file_list_value, origin=[0., 0., 0.], spacing=[1., 1.,1.]) -if len(result.errors) != 0: - print('Errors: {}', result.errors) - print('Warnings: {}', result.warnings) -else: - print("No errors running the filter") +cxtest.check_filter_result(cxitk.ITKImportImageStack, result) diff --git a/wrapping/python/examples/geometry_examples.py b/wrapping/python/examples/geometry_examples.py index 0783ff03d4..9f69e927eb 100644 --- a/wrapping/python/examples/geometry_examples.py +++ b/wrapping/python/examples/geometry_examples.py @@ -1,10 +1,53 @@ -import simplnx as nx +""" +Important Note +============== + +This python file can be used as an example of how to execute a number of DREAM3D-NX +filters one after another, if you plan to use the codes below (and you are welcome to), +there are a few things that you, the developer, should take note of: + +Import Statements +----------------- + +You will most likely *NOT* need to include the following code: + + .. code:: python + + import complex_test_dirs as cxtest + +Filter Error Detection +---------------------- + +In each section of code a filter is created and executed immediately. This may or +may *not* be what you want to do. You can also preflight the filter to verify the +correctness of the filters before executing the filter **although** this is done +for you when the filter is executed. As such, you will want to check the 'result' +variable to see if there are any errors or warnings. If there **are** any then +you, as the developer, should act appropriately on the errors or warnings. +More specifically, this bit of code: + + .. code:: python + + cxtest.check_filter_result(cxor.ReadAngDataFilter, result) + +is used by the simplnx unit testing framework and should be replaced by your own +error checking code. You are welcome to look up the function definition and use +that. + +""" +import complex as cx import itkimageprocessing as cxitk import orientationanalysis as cxor +import complex_test_dirs as cxtest import numpy as np +#------------------------------------------------------------------------------ +# Print the various filesystem paths that are pregenerated for this machine. +#------------------------------------------------------------------------------ +cxtest.print_all_paths() + """ In the code below we are using some data files that are found in the simplnx source code repository. It will up to the programmer to correctly set the paths @@ -22,11 +65,8 @@ geometry_type=0, # 0 = Image Geometry origin=[0.0, 0.0, 0.0], spacing=[1.0, 1.0, 1.0]) -if len(result.errors) != 0: - print('Errors: {}', result.errors) - print('Warnings: {}', result.warnings) -else: - print("No errors running the CreateGeometryFilter filter") +cxtest.check_filter_result(cx.CreateGeometryFilter, result) + data_object = data_structure["Image Geometry"] print(f'data_object: {type(data_object)}') @@ -46,11 +86,8 @@ result = create_array_filter.execute(data_structure=data_structure, component_count=1, data_format="", initialization_value="10", numeric_type=array_type, output_data_array=output_array_path) -if len(result.errors) != 0: - print('Errors: {}', result.errors) - print('Warnings: {}', result.warnings) -else: - print("No errors running the CreateDataArray filter") +cxtest.check_filter_result(cx.CreateDataArray, result) + # ------------------------------------------------------------------------------ # Lets try a Rectilinear Grid Geometry @@ -75,11 +112,8 @@ numeric_type=array_type, output_data_array=output_array_path, tuple_dimensions=tuple_dims) -if len(result.errors) != 0: - print('Errors: {}', result.errors) - print('Warnings: {}', result.warnings) -else: - print("No errors running the CreateDataArray filter") +cxtest.check_filter_result(cx.CreateDataArray, result) + x_coords = data_structure[output_array_path].npview() x_coords = np.squeeze(x_coords, axis=1) @@ -96,11 +130,8 @@ numeric_type=array_type, output_data_array=output_array_path, tuple_dimensions=tuple_dims) -if len(result.errors) != 0: - print('Errors: {}', result.errors) - print('Warnings: {}', result.warnings) -else: - print("No errors running the CreateDataArray filter") +cxtest.check_filter_result(cx.CreateDataArray, result) + y_coords = data_structure[output_array_path].npview() y_coords = np.squeeze(y_coords, axis=1) @@ -117,11 +148,8 @@ numeric_type=array_type, output_data_array=output_array_path, tuple_dimensions=tuple_dims) -if len(result.errors) != 0: - print('Errors: {}', result.errors) - print('Warnings: {}', result.warnings) -else: - print("No errors running the CreateDataArray filter") +cxtest.check_filter_result(cx.CreateDataArray, result) + z_coords = data_structure[output_array_path].npview() z_coords = np.squeeze(z_coords, axis=1) @@ -136,11 +164,8 @@ y_bounds=nx.DataPath("RectGridCoords/Y Coords"), z_bounds=nx.DataPath("RectGridCoords/Z Coords") ) -if len(result.errors) != 0: - print('Errors: {}', result.errors) - print('Warnings: {}', result.warnings) -else: - print("No errors running the CreateGeometryFilter filter") +cxtest.check_filter_result(cx.CreateGeometryFilter, result) + rect_grid_geom = data_structure["RectGrid Geometry"] x_cell_count = rect_grid_geom.num_x_cells @@ -161,15 +186,12 @@ tuple_dimensions=[[144]], output_data_array=array_path, initialization_value='0') -if len(result.errors) != 0: - print('Errors: {}', result.errors) - print('Warnings: {}', result.warnings) -else: - print("No errors running the CreateDataArray filter") +cxtest.check_filter_result(cx.CreateDataArray, result) + # Read the CSV file into the DataArray using the numpy view vertex_coords = data_structure[array_path].npview() -file_path = 'simplnx/test/Data/VertexCoordinates.csv' +file_path = cxtest.GetComplexSourceDir() + '/test/Data/VertexCoordinates.csv' vertex_coords[:] = np.loadtxt(file_path, delimiter=',', skiprows=1) array_path = nx.DataPath('Triangles') @@ -179,14 +201,11 @@ tuple_dimensions=[[242]], output_data_array=array_path, initialization_value='0') -if len(result.errors) != 0: - print('Errors: {}', result.errors) - print('Warnings: {}', result.warnings) -else: - print("No errors running the CreateDataArray filter") +cxtest.check_filter_result(cx.CreateDataArray, result) + # Read the CSV file into the DataArray using the numpy view triangles = data_structure[array_path].npview() -file_path = 'simplnx/test/Data/TriangleConnectivity.csv' +file_path = cxtest.GetComplexSourceDir() + '/test/Data/TriangleConnectivity.csv' triangles[:] = np.loadtxt(file_path, delimiter=',', skiprows=1) result = nx.CreateGeometryFilter.execute(data_structure=data_structure, @@ -199,11 +218,8 @@ vertex_list_name=nx.DataPath('Vertices'), triangle_list_name=nx.DataPath('Triangles') ) -if len(result.errors) != 0: - print('Errors: {}', result.errors) - print('Warnings: {}', result.warnings) -else: - print("No errors running the CreateGeometryFilter (Triangle) filter") +cxtest.check_filter_result(cx.CreateGeometryFilter, result) + # ------------------------------------------------------------------------------ # Lets try a Edge Geometry @@ -216,15 +232,12 @@ tuple_dimensions=[[144]], output_data_array=array_path, initialization_value='0') -if len(result.errors) != 0: - print('Errors: {}', result.errors) - print('Warnings: {}', result.warnings) -else: - print("No errors running the CreateDataArray filter") +cxtest.check_filter_result(cx.CreateDataArray, result) + # Read the CSV file into the DataArray using the numpy view vertex_coords = data_structure[array_path].npview() -file_path = 'simplnx/test/Data/VertexCoordinates.csv' +file_path = cxtest.GetComplexSourceDir() + '/test/Data/VertexCoordinates.csv' vertex_coords[:] = np.loadtxt(file_path, delimiter=',', skiprows=1) array_path = nx.DataPath('Edges') @@ -234,14 +247,11 @@ tuple_dimensions=[[264]], output_data_array=array_path, initialization_value='0') -if len(result.errors) != 0: - print('Errors: {}', result.errors) - print('Warnings: {}', result.warnings) -else: - print("No errors running the CreateDataArray filter") +cxtest.check_filter_result(cx.CreateDataArray, result) + # Read the CSV file into the DataArray using the numpy view -file_path = 'simplnx/test/Data/EdgeConnectivity.csv' +file_path = cxtest.GetComplexSourceDir() + '/test/Data/EdgeConnectivity.csv' edges_view = data_structure["Edges"].npview() edges_view[:] = np.loadtxt(file_path, delimiter=',', skiprows=1) @@ -254,18 +264,11 @@ vertex_list_name=nx.DataPath('Vertices'), edge_list_name=nx.DataPath('Edges') ) -if len(result.errors) != 0: - print('Errors: {}', result.errors) - print('Warnings: {}', result.warnings) -else: - print("No errors running the CreateGeometryFilter (Edge) filter") +cxtest.check_filter_result(cx.CreateGeometryFilter, result) +output_file_path = cxtest.GetTestTempDirectory() + "/geometry_examples.dream3d" +result = cx.WriteDREAM3DFilter.execute(data_structure=data_structure, export_file_path=output_file_path, + write_xdmf_file=True) +cxtest.check_filter_result(cx.WriteDREAM3DFilter, result) -output_file_path = "geometry_examples.dream3d" -result = nx.WriteDREAM3DFilter.execute(data_structure=data_structure, export_file_path=output_file_path, write_xdmf_file=True) -if len(result.errors) != 0: - print('Errors: {}', result.errors) - print('Warnings: {}', result.warnings) -else: - print("No errors running the WriteDREAM3DFilter filter") diff --git a/wrapping/python/examples/import_d3d.py b/wrapping/python/examples/import_d3d.py index fb0fa0b2ce..d68f0cbc5c 100644 --- a/wrapping/python/examples/import_d3d.py +++ b/wrapping/python/examples/import_d3d.py @@ -1,26 +1,75 @@ -import simplnx as nx +""" +Important Note +============== + +This python file can be used as an example of how to execute a number of DREAM3D-NX +filters one after another, if you plan to use the codes below (and you are welcome to), +there are a few things that you, the developer, should take note of: + +Import Statements +----------------- + +You will most likely *NOT* need to include the following code: + + .. code:: python + + import complex_test_dirs as cxtest + +Filter Error Detection +---------------------- + +In each section of code a filter is created and executed immediately. This may or +may *not* be what you want to do. You can also preflight the filter to verify the +correctness of the filters before executing the filter **although** this is done +for you when the filter is executed. As such, you will want to check the 'result' +variable to see if there are any errors or warnings. If there **are** any then +you, as the developer, should act appropriately on the errors or warnings. +More specifically, this bit of code: + + .. code:: python + + cxtest.check_filter_result(cxor.ReadAngDataFilter, result) + +is used by the simplnx unit testing framework and should be replaced by your own +error checking code. You are welcome to look up the function definition and use +that. + +""" +import complex as cx import itkimageprocessing as cxitk import orientationanalysis as cxor - +import complex_test_dirs as cxtest import numpy as np -import matplotlib.pyplot as plt +#------------------------------------------------------------------------------ +# Print the various filesystem paths that are pregenerated for this machine. +#------------------------------------------------------------------------------ +cxtest.print_all_paths() # Create the DataStructure object data_structure = nx.DataStructure() -import_data = nx.Dream3dImportParameter.ImportData() -import_data.file_path = "/private/tmp/basic_ebsd.dream3d" -import_data.data_paths = None +import_data = cx.Dream3dImportParameter.ImportData() +import_data.file_path = cxtest.GetTestTempDirectory() + "/basic_ebsd_example.dream3d" +import_data.data_paths = None # Use 'None' to import the entire file. + +print(f'{import_data.file_path}') + +result = cx.ReadDREAM3DFilter.execute(data_structure=data_structure, import_file_data=import_data) +cxtest.check_filter_result(cx.ReadDREAM3DFilter, result) + +#------------------------------------------------------------------------------ +# Print out the children of some of the Attribute Matrix groups +#------------------------------------------------------------------------------ +children = data_structure.get_children("Small IN100") +for child in children: + print(f'{child}') -result = nx.ReadDREAM3DFilter.execute(data_structure=data_structure, import_file_data=import_data) -if len(result.errors) != 0: - print('Errors: {}', result.errors) - print('Warnings: {}', result.warnings) -else: - print("No errors running the ReadDREAM3DFilter filter") +children = data_structure.get_children("Small IN100/Scan Data") +for child in children: + print(f'{child}') #------------------------------------------------------------------------------ # Get the underlying data from the DataStructure @@ -34,28 +83,9 @@ #------------------------------------------------------------------------------ # Write the DataStructure to a .dream3d file #------------------------------------------------------------------------------ -output_file_path = "/tmp/import_data.dream3d" -result = nx.WriteDREAM3DFilter.execute(data_structure=data_structure, +output_file_path = cxtest.GetTestTempDirectory() + "/import_data.dream3d" +result = cx.WriteDREAM3DFilter.execute(data_structure=data_structure, export_file_path=output_file_path, write_xdmf_file=True) -if len(result.errors) != 0: - print('Errors: {}', result.errors) - print('Warnings: {}', result.warnings) -else: - print("No errors running the WriteDREAM3DFilter") - - -#------------------------------------------------------------------------------ -# View with MatPlotLib -#------------------------------------------------------------------------------ -# Make a copy to that we can use MatPlotLib -npdata = data_structure[["Small IN100", "Scan Data", "Image Quality"]].npview().copy() - -# Remove any dimension with '1' for MatPlotLib? -npdata = np.squeeze(npdata, axis=0) -npdata = np.squeeze(npdata, axis=2) +cxtest.check_filter_result(cx.WriteDREAM3DFilter, result) -plt.imshow(npdata) -plt.title("Image Quality (Small IN100 from File)") -#plt.axis('off') # to turn off axes -plt.show() diff --git a/wrapping/python/examples/import_hdf5.py b/wrapping/python/examples/import_hdf5.py index 4aaa9b1b8b..f52c6d0d06 100644 --- a/wrapping/python/examples/import_hdf5.py +++ b/wrapping/python/examples/import_hdf5.py @@ -1,9 +1,53 @@ -import simplnx as nx +""" +Important Note +============== + +This python file can be used as an example of how to execute a number of DREAM3D-NX +filters one after another, if you plan to use the codes below (and you are welcome to), +there are a few things that you, the developer, should take note of: + +Import Statements +----------------- + +You will most likely *NOT* need to include the following code: + + .. code:: python + + import complex_test_dirs as cxtest + +Filter Error Detection +---------------------- + +In each section of code a filter is created and executed immediately. This may or +may *not* be what you want to do. You can also preflight the filter to verify the +correctness of the filters before executing the filter **although** this is done +for you when the filter is executed. As such, you will want to check the 'result' +variable to see if there are any errors or warnings. If there **are** any then +you, as the developer, should act appropriately on the errors or warnings. +More specifically, this bit of code: + + .. code:: python + + cxtest.check_filter_result(cxor.ReadAngDataFilter, result) + +is used by the simplnx unit testing framework and should be replaced by your own +error checking code. You are welcome to look up the function definition and use +that. + +""" +import complex as cx import itkimageprocessing as cxitk import orientationanalysis as cxor +import complex_test_dirs as cxtest import numpy as np +#------------------------------------------------------------------------------ +# Print the various filesystem paths that are pregenerated for this machine. +#------------------------------------------------------------------------------ +cxtest.print_all_paths() + + # Create the DataStructure object data_structure = nx.DataStructure() @@ -25,27 +69,22 @@ read_h5_ebsd_parameter=h5ebsdParameter ) -dataset1 = nx.ReadHDF5DatasetParameter.DatasetImportInfo() -dataset1.dataset_path = "/DataStructure/DataContainer/CellData/Confidence Index" -dataset1.tuple_dims = "117,201,189" +dataset1 = cx.ReadHDF5DatasetParameter.DatasetImportInfo() +dataset1.dataset_path = "/DataStructure/Small IN100/Scan Data/Confidence Index" +dataset1.tuple_dims = "1,201,189" dataset1.component_dims = "1" -dataset2 = nx.ReadHDF5DatasetParameter.DatasetImportInfo() -dataset2.dataset_path = "/DataStructure/DataContainer/CellData/EulerAngles" -dataset2.tuple_dims = "117,201,189" +dataset2 = cx.ReadHDF5DatasetParameter.DatasetImportInfo() +dataset2.dataset_path = "/DataStructure/Small IN100/Scan Data/EulerAngles" +dataset2.tuple_dims = "1,201,189" dataset2.component_dims = "3" -import_hdf5_param = nx.ReadHDF5DatasetParameter.ValueType() -import_hdf5_param.input_file = "Data/Output/Reconstruction/SmallIN100_Final.dream3d" +import_hdf5_param = cx.ReadHDF5DatasetParameter.ValueType() +import_hdf5_param.input_file = cxtest.GetTestTempDirectory() + "/basic_ebsd_example.dream3d" import_hdf5_param.datasets = [dataset1, dataset2] # import_hdf5_param.parent = nx.DataPath(["Imported Data"]) result = nx.ReadHDF5Dataset.execute(data_structure=data_structure, import_hd_f5_file=import_hdf5_param ) -if len(result.errors) != 0: - print('Errors: {}', result.errors) - print('Warnings: {}', result.warnings) -else: - print("No errors running the ReadHDF5DatasetParameter filter") - +cxtest.check_filter_result(cx.ReadHDF5Dataset, result) diff --git a/wrapping/python/examples/output_file.py b/wrapping/python/examples/output_file.py index 86104fa1cd..834bdde81d 100644 --- a/wrapping/python/examples/output_file.py +++ b/wrapping/python/examples/output_file.py @@ -1,11 +1,53 @@ -# Import the DREAM3D Base library and Plugins -import simplnx as nx +""" +Important Note +============== + +This python file can be used as an example of how to execute a number of DREAM3D-NX +filters one after another, if you plan to use the codes below (and you are welcome to), +there are a few things that you, the developer, should take note of: + +Import Statements +----------------- + +You will most likely *NOT* need to include the following code: + + .. code:: python + + import complex_test_dirs as cxtest + +Filter Error Detection +---------------------- + +In each section of code a filter is created and executed immediately. This may or +may *not* be what you want to do. You can also preflight the filter to verify the +correctness of the filters before executing the filter **although** this is done +for you when the filter is executed. As such, you will want to check the 'result' +variable to see if there are any errors or warnings. If there **are** any then +you, as the developer, should act appropriately on the errors or warnings. +More specifically, this bit of code: + + .. code:: python + + cxtest.check_filter_result(cxor.ReadAngDataFilter, result) + +is used by the simplnx unit testing framework and should be replaced by your own +error checking code. You are welcome to look up the function definition and use +that. + +""" +import complex as cx import itkimageprocessing as cxitk import orientationanalysis as cxor +import complex_test_dirs as cxtest import numpy as np +#------------------------------------------------------------------------------ +# Print the various filesystem paths that are pregenerated for this machine. +#------------------------------------------------------------------------------ +cxtest.print_all_paths() + # Let's get a data array created to have something to write. # Create a Data Structure @@ -19,22 +61,14 @@ create_array_filter = nx.CreateDataArray() result = create_array_filter.execute(data_structure=data_structure, component_count=1, data_format="", initialization_value="10", numeric_type=array_type, output_data_array=output_array_path, tuple_dimensions=tuple_dims) -if len(result.errors) != 0: - print('Errors: {}', result.errors) - print('Warnings: {}', result.warnings) -else: - print("No errors running the filter") +cxtest.check_filter_result(cx.CreateDataArray, result) + npdata = data_structure[output_array_path].npview() print(npdata) -output_file_path = "output_file_example.dream3d" -result = nx.WriteDREAM3DFilter.execute(data_structure=data_structure, +output_file_path = cxtest.GetTestTempDirectory() + "/output_file_example.dream3d" +result = cx.WriteDREAM3DFilter.execute(data_structure=data_structure, export_file_path=output_file_path, write_xdmf_file=True) -if len(result.errors) != 0: - print('Errors: {}', result.errors) - print('Warnings: {}', result.warnings) -else: - print("No errors running the filter") - +cxtest.check_filter_result(cx.WriteDREAM3DFilter, result) diff --git a/wrapping/python/examples/pipeline.py b/wrapping/python/examples/pipeline.py index ef7672d644..3a88f7fb98 100644 --- a/wrapping/python/examples/pipeline.py +++ b/wrapping/python/examples/pipeline.py @@ -1,16 +1,58 @@ -# Import the DREAM3D Base library and Plugins -import simplnx as nx +""" +Important Note +============== + +This python file can be used as an example of how to execute a number of DREAM3D-NX +filters one after another, if you plan to use the codes below (and you are welcome to), +there are a few things that you, the developer, should take note of: + +Import Statements +----------------- + +You will most likely *NOT* need to include the following code: + + .. code:: python + + import complex_test_dirs as cxtest + +Filter Error Detection +---------------------- + +In each section of code a filter is created and executed immediately. This may or +may *not* be what you want to do. You can also preflight the filter to verify the +correctness of the filters before executing the filter **although** this is done +for you when the filter is executed. As such, you will want to check the 'result' +variable to see if there are any errors or warnings. If there **are** any then +you, as the developer, should act appropriately on the errors or warnings. +More specifically, this bit of code: + + .. code:: python + + cxtest.check_filter_result(cxor.ReadAngDataFilter, result) + +is used by the simplnx unit testing framework and should be replaced by your own +error checking code. You are welcome to look up the function definition and use +that. + +""" +import complex as cx import itkimageprocessing as cxitk import orientationanalysis as cxor +import complex_test_dirs as cxtest import numpy as np -data_structure = nx.DataStructure() +#------------------------------------------------------------------------------ +# Print the various filesystem paths that are pregenerated for this machine. +#------------------------------------------------------------------------------ +cxtest.print_all_paths() + +data_structure = cx.DataStructure() -pipeline = nx.Pipeline().from_file("simplnx/src/Plugins/OrientationAnalysis/pipelines/EBSD Reconstruction/(01) Small IN100 Archive.d3dpipeline") +pipeline = cx.Pipeline().from_file(cxtest.GetComplexSourceDir() + '/src/Plugins/OrientationAnalysis/pipelines/EBSD Reconstruction/(01) Small IN100 Archive.d3dpipeline') -pipeline.to_file( "test pipeline", "/tmp/python_pipeline.d3dpipeline") +pipeline.to_file( "test pipeline", cxtest.GetTestTempDirectory() + "/python_pipeline.d3dpipeline") diff --git a/wrapping/python/examples/read_csv_file.py b/wrapping/python/examples/read_csv_file.py index b27e2225a4..0587327b72 100644 --- a/wrapping/python/examples/read_csv_file.py +++ b/wrapping/python/examples/read_csv_file.py @@ -1,14 +1,57 @@ -import simplnx as nx +""" +Important Note +============== + +This python file can be used as an example of how to execute a number of DREAM3D-NX +filters one after another, if you plan to use the codes below (and you are welcome to), +there are a few things that you, the developer, should take note of: + +Import Statements +----------------- + +You will most likely *NOT* need to include the following code: + + .. code:: python + + import complex_test_dirs as cxtest + +Filter Error Detection +---------------------- + +In each section of code a filter is created and executed immediately. This may or +may *not* be what you want to do. You can also preflight the filter to verify the +correctness of the filters before executing the filter **although** this is done +for you when the filter is executed. As such, you will want to check the 'result' +variable to see if there are any errors or warnings. If there **are** any then +you, as the developer, should act appropriately on the errors or warnings. +More specifically, this bit of code: + + .. code:: python + + cxtest.check_filter_result(cxor.ReadAngDataFilter, result) + +is used by the simplnx unit testing framework and should be replaced by your own +error checking code. You are welcome to look up the function definition and use +that. + +""" +import complex as cx import itkimageprocessing as cxitk import orientationanalysis as cxor +import complex_test_dirs as cxtest import numpy as np +#------------------------------------------------------------------------------ +# Print the various filesystem paths that are pregenerated for this machine. +#------------------------------------------------------------------------------ +cxtest.print_all_paths() + # Create the DataStructure object data_structure = nx.DataStructure() # This file has 7 columns to import -read_csv_data = nx.ReadCSVDataParameter() -read_csv_data.input_file_path = "wrapping/python/examples/test_csv_data.csv" +read_csv_data = cx.ReadCSVDataParameter() +read_csv_data.input_file_path = cxtest.GetComplexPythonSourceDir() + "/examples/test_csv_data.csv" read_csv_data.start_import_row = 2 read_csv_data.delimiters = [','] read_csv_data.custom_headers = [] @@ -29,8 +72,4 @@ # The ReadCSVData object with all member variables set. read_csv_data=read_csv_data # The ReadCSVData object with all member variables set. ) -if len(result.errors) != 0: - print('Errors: {}', result.errors) - print('Warnings: {}', result.warnings) -else: - print("No errors running the ReadCSVFileFilter filter") +cxtest.check_filter_result(cx.ReadCSVFileFilter, result) diff --git a/wrapping/python/examples/read_esprit_data.py b/wrapping/python/examples/read_esprit_data.py index 5596bba7f4..e43c9bd2af 100644 --- a/wrapping/python/examples/read_esprit_data.py +++ b/wrapping/python/examples/read_esprit_data.py @@ -1,5 +1,41 @@ -# Import the DREAM3D Base library and Plugins -import simplnx as nx +""" +Important Note +============== + +This python file can be used as an example of how to execute a number of DREAM3D-NX +filters one after another, if you plan to use the codes below (and you are welcome to), +there are a few things that you, the developer, should take note of: + +Import Statements +----------------- + +You will most likely *NOT* need to include the following code: + + .. code:: python + + import complex_test_dirs as cxtest + +Filter Error Detection +---------------------- + +In each section of code a filter is created and executed immediately. This may or +may *not* be what you want to do. You can also preflight the filter to verify the +correctness of the filters before executing the filter **although** this is done +for you when the filter is executed. As such, you will want to check the 'result' +variable to see if there are any errors or warnings. If there **are** any then +you, as the developer, should act appropriately on the errors or warnings. +More specifically, this bit of code: + + .. code:: python + + cxtest.check_filter_result(cxor.ReadAngDataFilter, result) + +is used by the simplnx unit testing framework and should be replaced by your own +error checking code. You are welcome to look up the function definition and use +that. + +""" +import complex as cx import itkimageprocessing as cxitk import orientationanalysis as cxor @@ -7,6 +43,10 @@ import numpy as np +#------------------------------------------------------------------------------ +# Print the various filesystem paths that are pregenerated for this machine. +#------------------------------------------------------------------------------ +cxtest.print_all_paths() # ------------------------------------------------------------------------------ @@ -30,14 +70,7 @@ selected_scan_names = param1, z_spacing = 1.0) -if len(result.errors) != 0: - print('Errors: {}', result.errors) - print('Warnings: {}', result.warnings) -else: - print("No errors running the ReadH5EspritDataFilter") - - - +cxtest.check_filter_result(cxor.ReadH5EspritDataFilter, result) #------------------------------------------------------------------------------ # Write the DataStructure to a .dream3d file @@ -46,10 +79,4 @@ result = nx.WriteDREAM3DFilter.execute(data_structure=data_structure, export_file_path=output_file_path, write_xdmf_file=True) -if len(result.errors) != 0: - print('Errors: {}', result.errors) - print('Warnings: {}', result.warnings) -else: - print("No errors running the WriteDREAM3DFilter") - -print(f'{output_file_path}') +cxtest.check_filter_result(cx.WriteDREAM3DFilter, result) diff --git a/wrapping/python/testing/anaconda_test.bat b/wrapping/python/testing/anaconda_test.bat new file mode 100644 index 0000000000..f6e8772b42 --- /dev/null +++ b/wrapping/python/testing/anaconda_test.bat @@ -0,0 +1,16 @@ +@echo off + +echo "complex_CONDA_EXECUTABLE: %complex_CONDA_EXECUTABLE%" +echo "complex_CONDA_ENV: %complex_CONDA_ENV%" +echo "PYTHON_TEST_FILE: %PYTHON_TEST_FILE%" +echo "PYTHONPATH: %PYTHONPATH%" + +CALL "%complex_CONDA_EXECUTABLE%" activate "%complex_CONDA_ENV%" + +echo "PATH: %PATH%" +echo "Where is Python: " +where python +echo "Python Version: " +python --version + +python "%PYTHON_TEST_FILE%" diff --git a/wrapping/python/testing/anaconda_test.sh b/wrapping/python/testing/anaconda_test.sh new file mode 100755 index 0000000000..7a32359e03 --- /dev/null +++ b/wrapping/python/testing/anaconda_test.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +# echo "complex_ANACONDA_DIR: $complex_ANACONDA_DIR" +# echo "complex_CONDA_ENV: $complex_CONDA_ENV" +echo "PYTHON_TEST_FILE: $PYTHON_TEST_FILE" +echo "PYTHONPATH: $PYTHONPATH" +echo "Python3_EXECUTABLE: $Python3_EXECUTABLE" + +# echo "Sourcing $complex_ANACONDA_DIR/etc/profile.d/conda.sh" +# source "$complex_ANACONDA_DIR"/etc/profile.d/conda.sh + +# echo "Activating Conda environment $complex_CONDA_ENV" +# conda activate "$complex_CONDA_ENV" + +echo "PATH: $PATH" +# echo "Where is Python: " `which python` +# echo "Where is Conda: " `which conda` +# PYTHONEXE=$complex_ANACONDA_DIR/envs/$complex_CONDA_ENV/bin/python +#PYTHONEXE=`which python` +#echo "Python Version: " `${PYTHONEXE} --version` + +${Python3_EXECUTABLE} "$PYTHON_TEST_FILE"