Skip to content

Commit

Permalink
Create CTest unit tests to run the Python example files.
Browse files Browse the repository at this point in the history
Signed-off-by: Michael Jackson <[email protected]>
  • Loading branch information
imikejackson committed Nov 29, 2023
1 parent a06a6d5 commit 97e33d4
Show file tree
Hide file tree
Showing 44 changed files with 943 additions and 210 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ jobs:
sudo apt-get -y install ninja-build
- name: Install Sphinx
run: |
sudo pip install sphinx myst-parser sphinx-markdown-tables sphinx_rtd_theme
sudo pip install sphinx myst-parser sphinx-markdown-tables sphinx_rtd_theme numpy
- name: Setup NuGet Credentials
shell: bash
run: |
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ jobs:
brew install ninja
- name: Install Sphinx
run: |
sudo pip3 install sphinx myst-parser sphinx-markdown-tables sphinx_rtd_theme
sudo pip3 install sphinx myst-parser sphinx-markdown-tables sphinx_rtd_theme numpy
- name: Setup NuGet Credentials
shell: bash
run: |
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ jobs:
-source "https://nuget.pkg.github.com/BlueQuartzSoftware/index.json"
- name: Install Sphinx
run: |
pip install sphinx myst-parser sphinx-markdown-tables sphinx_rtd_theme
pip install sphinx myst-parser sphinx-markdown-tables sphinx_rtd_theme numpy
- name: Configure
run: |
cmake --preset ci-windows-${{matrix.toolset}} ${{github.workspace}} -T ${{matrix.toolset}}
Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ option(COMPLEX_ENABLE_INSTALL "Enables COMPLEX install rules" ON)
file(TO_CMAKE_PATH "${CMAKE_COMMAND}" CMAKE_COMMAND_NORM)

project(complex
VERSION 1.2.0
VERSION 1.2.1
DESCRIPTION "SIMPL Redesign"
HOMEPAGE_URL "https://github.com/BlueQuartzSoftware/complex"
LANGUAGES CXX
Expand Down
4 changes: 4 additions & 0 deletions CMakePresets.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@
"type": "BOOL",
"value": "ON"
},
"COMPLEX_ENABLE_PYTHON_TESTS": {
"type": "BOOL",
"value": "ON"
},
"COMPLEX_EMBED_PYTHON": {
"type": "BOOL",
"value": "OFF"
Expand Down
83 changes: 83 additions & 0 deletions cmake/Utility.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -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})

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}"
)
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}"
)
endif()
else()
add_test(NAME ${ARGS_NAME}
COMMAND ${PYTHON_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}"
"${complex_PYTHON_TEST_ENV}"
)
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
"$<TARGET_FILE_DIR:complex>"
)

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()
2 changes: 1 addition & 1 deletion conda/meta.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{% set name = "complex" %}
{% set version = "1.2.0" %}
{% set version = "1.2.1" %}

package:
name: {{ name|lower }}
Expand Down
2 changes: 1 addition & 1 deletion conda/recipe.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
context:
version: "1.2.0"
version: "1.2.1"
name: complex

package:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,8 @@ IFilter::PreflightResult CreateDataArray::preflightImpl(const DataStructure& dat
if(!useDims)
{
return MakePreflightErrorResult(
-78602, "The DataArray to be created is not within an AttributeMatrix, so the dimensions cannot be determined implicitly. Check Set Tuple Dimensions to set the dimensions");
-78602, fmt::format("The DataArray to be created '{}'is not within an AttributeMatrix, so the dimensions cannot be determined implicitly. Check Set Tuple Dimensions to set the dimensions",
dataArrayPath.toString()));
}
else
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,8 @@ IFilter::PreflightResult ReadTextDataArrayFilter::preflightImpl(const DataStruct
if(!useDims)
{
return MakePreflightErrorResult(
-77602, "The DataArray to be created is not within an AttributeMatrix, so the dimensions cannot be determined implicitly. Check Set Tuple Dimensions to set the dimensions");
-78602, fmt::format("The DataArray to be created '{}'is not within an AttributeMatrix, so the dimensions cannot be determined implicitly. Check Set Tuple Dimensions to set the dimensions",
arrayPath.toString()));
}
else
{
Expand Down
108 changes: 107 additions & 1 deletion src/Plugins/ComplexCore/wrapping/python/complexpy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
#include "ComplexCore/ComplexCoreFilterBinding.hpp"

#include <ComplexCore/ComplexCorePlugin.hpp>

#include <complex/DataStructure/AttributeMatrix.hpp>
#include <complex/DataStructure/DataArray.hpp>
#include <complex/DataStructure/DataGroup.hpp>
Expand Down Expand Up @@ -80,6 +79,7 @@
#include <complex/Pipeline/AbstractPipelineNode.hpp>
#include <complex/Pipeline/Pipeline.hpp>
#include <complex/Pipeline/PipelineFilter.hpp>
#include <complex/Utilities/DataGroupUtilities.hpp>

#include <fmt/ranges.h>

Expand Down Expand Up @@ -504,12 +504,118 @@ PYBIND11_MODULE(complex, mod)

dataObject.def_property_readonly("id", &DataObject::getId);
dataObject.def_property_readonly("name", &DataObject::getName);
dataObject.def_property_readonly("type", &DataObject::getDataObjectType);

dataStructure.def(py::init<>());
dataStructure.def("__getitem__", py::overload_cast<const DataPath&>(&DataStructure::getSharedData));
dataStructure.def("__getitem__", [](DataStructure& self, const std::string& path) {
auto pathConversionResult = DataPath::FromString(path);
if(!pathConversionResult)
{
return std::shared_ptr<DataObject>(nullptr);
}
return self.getSharedData(pathConversionResult.value());
});
dataStructure.def_property_readonly("size", &DataStructure::getSize);
dataStructure.def("__len__", &DataStructure::getSize);
dataStructure.def("remove", py::overload_cast<const DataPath&>(&DataStructure::removeData));
dataStructure.def("remove", [](DataStructure& self, const std::string& path) {
auto pathConversionResult = DataPath::FromString(path);
if(!pathConversionResult)
{
return false;
}
return self.removeData(pathConversionResult.value());
});
dataStructure.def("hierarchy_to_str", [](DataStructure& self) {
std::stringstream ss;
self.exportHierarchyAsText(ss);
return ss.str();
});
dataStructure.def("hierarchy_to_graphviz", [](DataStructure& self) {
std::stringstream ss;
self.exportHierarchyAsGraphViz(ss);
return ss.str();
});
dataStructure.def("get_children", [](DataStructure& self, complex::DataPath& parentPath) {
if(parentPath.empty())
{
std::vector<DataPath> outputPaths;
for(const auto* object : self.getTopLevelData())
{
auto topLevelPath = DataPath::FromString(object->getDataPaths()[0].getTargetName()).value();
outputPaths.push_back(topLevelPath);
}
return outputPaths;
}
else
{
auto result = complex::GetAllChildDataPaths(self, parentPath);
if(result)
{
return result.value();
}
return std::vector<DataPath>{};
}
});
dataStructure.def("get_children", [](DataStructure& self, const std::string& parentPath) {
if(parentPath.empty())
{
std::vector<DataPath> outputPaths;
for(const auto* object : self.getTopLevelData())
{
auto topLevelPath = DataPath::FromString(object->getDataPaths()[0].getTargetName()).value();
outputPaths.push_back(topLevelPath);
}
return outputPaths;
}
else
{
auto pathConversionResult = DataPath::FromString(parentPath);
if(!pathConversionResult)
{
return std::vector<DataPath>{};
}

auto result = complex::GetAllChildDataPaths(self, pathConversionResult.value());
if(result)
{
return result.value();
}
return std::vector<DataPath>{};
}
});

auto dataObjectType = py::enum_<DataObject::Type>(dataObject, "DataObjectType");
dataObjectType.value("DataObject", DataObject::Type::DataObject);
dataObjectType.value("DynamicListArray", DataObject::Type::DynamicListArray);
dataObjectType.value("ScalarData", DataObject::Type::ScalarData);
dataObjectType.value("BaseGroup", DataObject::Type::BaseGroup);
dataObjectType.value("AttributeMatrix", DataObject::Type::AttributeMatrix);
dataObjectType.value("DataGroup", DataObject::Type::DataGroup);
dataObjectType.value("IDataArray", DataObject::Type::IDataArray);
dataObjectType.value("DataArray", DataObject::Type::DataArray);
dataObjectType.value("IGeometry", DataObject::Type::IGeometry);
dataObjectType.value("IGridGeometry", DataObject::Type::IGridGeometry);
dataObjectType.value("RectGridGeom", DataObject::Type::RectGridGeom);
dataObjectType.value("ImageGeom", DataObject::Type::ImageGeom);
dataObjectType.value("INodeGeometry0D", DataObject::Type::INodeGeometry0D);
dataObjectType.value("VertexGeom", DataObject::Type::VertexGeom);
dataObjectType.value("INodeGeometry1D", DataObject::Type::INodeGeometry1D);
dataObjectType.value("EdgeGeom", DataObject::Type::EdgeGeom);
dataObjectType.value("INodeGeometry2D", DataObject::Type::INodeGeometry2D);
dataObjectType.value("QuadGeom", DataObject::Type::QuadGeom);
dataObjectType.value("TriangleGeom", DataObject::Type::TriangleGeom);
dataObjectType.value("INodeGeometry3D", DataObject::Type::INodeGeometry3D);
dataObjectType.value("HexahedralGeom", DataObject::Type::HexahedralGeom);
dataObjectType.value("TetrahedralGeom", DataObject::Type::TetrahedralGeom);
dataObjectType.value("INeighborList", DataObject::Type::INeighborList);
dataObjectType.value("NeighborList", DataObject::Type::NeighborList);
dataObjectType.value("StringArray", DataObject::Type::StringArray);
dataObjectType.value("AbstractMontage", DataObject::Type::AbstractMontage);
dataObjectType.value("GridMontage", DataObject::Type::GridMontage);
dataObjectType.value("Unknown", DataObject::Type::Unknown);
dataObjectType.value("Any", DataObject::Type::Any);

py::class_<BaseGroup, DataObject, std::shared_ptr<BaseGroup>> baseGroup(mod, "BaseGroup");
baseGroup.def("contains", py::overload_cast<const std::string&>(&BaseGroup::contains, py::const_));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ Parameters ReadH5EspritDataFilter::parameters() const
Parameters params;
// Create the parameter descriptors that are needed for this filter
params.insertSeparator(Parameters::Separator{"Input Parameters"});
params.insert(std::make_unique<OEMEbsdScanSelectionParameter>(k_SelectedScanNames_Key, "Scan Names", "The name of the scan in the .h5 file. EDAX can store multiple scans in a single file",
params.insert(std::make_unique<OEMEbsdScanSelectionParameter>(k_SelectedScanNames_Key, "Scan Names", "The name of the scan in the .h5 file. Esprit can store multiple scans in a single file",
OEMEbsdScanSelectionParameter::ValueType{},
/* OEMEbsdScanSelectionParameter::AllowedManufacturers{EbsdLib::OEM::Bruker, EbsdLib::OEM::DREAM3D},*/
OEMEbsdScanSelectionParameter::EbsdReaderType::Esprit, OEMEbsdScanSelectionParameter::ExtensionsType{".h5", ".hdf5"}));
Expand Down Expand Up @@ -134,7 +134,10 @@ IFilter::PreflightResult ReadH5EspritDataFilter::preflightImpl(const DataStructu
const std::vector<usize> tupleDims = {dims[2], dims[1], dims[0]};
{
CreateImageGeometryAction::SpacingType spacing = {static_cast<float32>(reader->getXStep()), static_cast<float32>(reader->getYStep()), pZSpacingValue};

for(float& value : spacing)
{
value = (value == 0.0f ? 1.0f : value);
}
auto createDataGroupAction = std::make_unique<CreateImageGeometryAction>(pImageGeometryNameValue, dims, pOriginValue, spacing, pCellAttributeMatrixNameValue);
resultOutputActions.value().appendAction(std::move(createDataGroupAction));
}
Expand Down
Loading

0 comments on commit 97e33d4

Please sign in to comment.