Skip to content

Commit

Permalink
ENH: GeneratePythonFilter-Crashing fixed, Generation Fixed, headers s…
Browse files Browse the repository at this point in the history
…plit (#877)

Signed-off-by: Michael Jackson <[email protected]>
  • Loading branch information
imikejackson authored Mar 5, 2024
1 parent 1645a22 commit fa92713
Show file tree
Hide file tree
Showing 6 changed files with 206 additions and 32 deletions.
18 changes: 16 additions & 2 deletions src/Plugins/SimplnxCore/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,7 @@ set(PLUGIN_EXTRA_SOURCES
"${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/CeilOperator.cpp"
"${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/AvizoWriter.hpp"
"${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/AvizoWriter.cpp"
"${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/PythonPluginTemplateFile.hpp"

"${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/SurfaceNets/MMCellFlag.cpp"
"${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/SurfaceNets/MMCellFlag.h"
Expand Down Expand Up @@ -348,11 +349,24 @@ source_group(TREE "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}" PREFIX ${PLU
# the template file to use the contents of those files. This should allow easier
# updating of those template files.
file(READ "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/PythonFilterTemplate.py" PYTHON_FILTER_TEMPLATE)
string(HEX ${PYTHON_FILTER_TEMPLATE} PYTHON_FILTER_TEMPLATE)
string(REGEX REPLACE "([0-9a-f][0-9a-f])" "0x\\0," PYTHON_FILTER_TEMPLATE ${PYTHON_FILTER_TEMPLATE})
string(APPEND PYTHON_FILTER_TEMPLATE "0x00")


file(READ "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/PythonPluginInitTemplate.py" PYTHON_PLUGIN_INIT_TEMPLATE)
string(HEX ${PYTHON_PLUGIN_INIT_TEMPLATE} PYTHON_PLUGIN_INIT_TEMPLATE)
string(REGEX REPLACE "([0-9a-f][0-9a-f])" "0x\\0," PYTHON_PLUGIN_INIT_TEMPLATE ${PYTHON_PLUGIN_INIT_TEMPLATE})
string(APPEND PYTHON_PLUGIN_INIT_TEMPLATE "0x00")

file(READ "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/PythonPluginTemplate.py" PYTHON_PLUGIN_TEMPLATE)
string(HEX ${PYTHON_PLUGIN_TEMPLATE} PYTHON_PLUGIN_TEMPLATE)
string(REGEX REPLACE "([0-9a-f][0-9a-f])" "0x\\0," PYTHON_PLUGIN_TEMPLATE ${PYTHON_PLUGIN_TEMPLATE})
string(APPEND PYTHON_PLUGIN_TEMPLATE "0x00")


configure_file("${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/PythonPluginTemplateFile.in.hpp"
"${${PLUGIN_NAME}_BINARY_DIR}/utils/PythonPluginTemplateFile.hpp")
cmpConfigureFileWithMD5Check(CONFIGURED_TEMPLATE_PATH "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/PythonPluginSourceTemplate.in.hpp"
GENERATED_FILE_PATH "${${PLUGIN_NAME}_BINARY_DIR}/generated/${PLUGIN_NAME}/utils/PythonPluginSourceTemplate.hpp")

#------------------------------------------------------------------------------
# If there are additional include directories that are needed for this plugin
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#pragma once

/**
* This file is auto-generated during CMake time. Any changes made to the generated file
* will be over written the next time CMake runs a configure.
*/

#include <string>

namespace nx::core
{

// clang-format off
static const char k_PythonFilterTemplateCharArray[] = {@PYTHON_FILTER_TEMPLATE@};
// clang-format on

inline const std::string PythonFilterTemplate()
{
return {k_PythonFilterTemplateCharArray};
}

// clang-format off
static const char k_PluginPythonFileCharArray[] = {@PYTHON_PLUGIN_TEMPLATE@};
// clang-format on

inline const std::string PluginPythonFile()
{
return {k_PluginPythonFileCharArray};
}

// clang-format off
static const char k_PluginInitPythonFileCharArray[] = {@PYTHON_PLUGIN_INIT_TEMPLATE@};
// clang-format on

inline const std::string PluginInitPythonFile()
{
return {k_PluginInitPythonFileCharArray};
}

}; // namespace nx::core
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include "simplnx/Utilities/FilterUtilities.hpp"
#include "simplnx/Utilities/StringUtilities.hpp"

#include "SimplnxCore/utils/PythonPluginSourceTemplate.hpp"

#include <fmt/format.h>

#include <filesystem>
Expand All @@ -16,9 +18,6 @@ namespace nx::core
{
inline const std::string k_FilterIncludeInsertToken = "# FILTER_INCLUDE_INSERT";
inline const std::string k_FilterNameInsertToken = "# FILTER_NAME_INSERT";
inline const std::string k_PythonFilterTemplate = R"(
@PYTHON_FILTER_TEMPLATE@
)";

/**
*
Expand All @@ -29,7 +28,7 @@ inline const std::string k_PythonFilterTemplate = R"(
*/
inline std::string GeneratePythonFilter(const std::string& filterName, const std::string& humanName, const std::string& uuidString)
{
std::string content = k_PythonFilterTemplate;
std::string content = PythonFilterTemplate();

content = StringUtilities::replace(content, "#PYTHON_FILTER_NAME#", filterName);
content = StringUtilities::replace(content, "#PYTHON_FILTER_HUMAN_NAME#", humanName);
Expand All @@ -47,7 +46,13 @@ inline std::string GeneratePythonFilter(const std::string& filterName, const std
inline Result<> InsertFilterNameInPluginFiles(const std::filesystem::path& pluginPath, const std::string& filterName)
{
Result<> result;
std::string pluginName = pluginPath.stem().string();
std::string pluginName = pluginPath.string();
if(StringUtilities::ends_with(pluginName, "/"))
{
pluginName.pop_back();
std::filesystem::path plugPath(pluginName);
pluginName = plugPath.stem().string();
}

fs::path pluginPyPath = pluginPath / "Plugin.py";
if(!fs::exists(pluginPyPath))
Expand Down Expand Up @@ -80,10 +85,13 @@ inline Result<> InsertFilterNameInPluginFiles(const std::filesystem::path& plugi
"file. This plugin file must be manually updated to include the filter import statement.",
pluginFilePath.string(), k_FilterNameInsertToken)});
}
filterInsertPos--; // Go back one character to insert before the newline
else
{
filterInsertPos--; // Go back one character to insert before the newline

std::string filterImportToken = fmt::format("from {0}.{1} import {1}\n", pluginName, filterName);
content.insert(filterInsertPos, filterImportToken);
std::string filterImportToken = fmt::format("from {0}.{1} import {1}\n", pluginName, filterName);
content.insert(filterInsertPos, filterImportToken);
}
}

// Insert filter name
Expand All @@ -96,14 +104,17 @@ inline Result<> InsertFilterNameInPluginFiles(const std::filesystem::path& plugi
"file. This plugin file must be manually updated to include the filter name ('{2}').",
pluginFilePath.string(), k_FilterNameInsertToken, filterName)});
}
filterInsertPos -= 2; // Go back two characters to insert before the closing brace

std::string filterNameToken = filterName;
if(pluginFilePath.filename() == "__init__.py")
else
{
filterNameToken = fmt::format("'{}'", filterNameToken);
filterInsertPos -= 2; // Go back two characters to insert before the closing brace

std::string filterNameToken = filterName;
if(pluginFilePath.filename() == "__init__.py")
{
filterNameToken = fmt::format("'{}'", filterNameToken);
}
content.insert(filterInsertPos, "," + filterNameToken);
}
content.insert(filterInsertPos, "," + filterNameToken);
}

std::ofstream out_file(pluginFilePath.string());
Expand Down Expand Up @@ -151,17 +162,19 @@ inline Result<> WritePythonFilterToPlugin(const std::filesystem::path& pluginPat
*/
inline Result<> WritePythonFiltersToPlugin(const std::filesystem::path& pluginPath, const std::string& filterNames)
{
Result<> result;
auto filterNamesSplit = StringUtilities::split(filterNames, ',');
for(const auto& filterName : filterNamesSplit)
{
auto result = nx::core::WritePythonFilterToPlugin(pluginPath, filterName);
if(result.invalid())
auto filterWriteResult = nx::core::WritePythonFilterToPlugin(pluginPath, filterName);
if(filterWriteResult.invalid())
{
return result;
return filterWriteResult;
}
result = MergeResults(result, filterWriteResult);
}

return {};
return result;
}

/**
Expand Down Expand Up @@ -192,14 +205,6 @@ inline Result<> WritePythonFilterToFile(const std::filesystem::path& outputPath,
return {};
}

inline const std::string k_PluginPythonFile = R"(
@PYTHON_PLUGIN_TEMPLATE@
)";

inline const std::string k_PluginInitPythonFile = R"(
@PYTHON_PLUGIN_INIT_TEMPLATE@
)";

/**
*
* @param pluginName
Expand All @@ -211,7 +216,7 @@ inline const std::string k_PluginInitPythonFile = R"(
*/
inline std::string GeneratePythonPlugin(const std::string& pluginName, const std::string& pluginShortName, const std::string& pluginDescription, const std::string& pluginFilterList)
{
std::string content = k_PluginPythonFile;
std::string content = PluginPythonFile();

content = StringUtilities::replace(content, "#PLUGIN_NAME#", pluginName);
content = StringUtilities::replace(content, "#PLUGIN_UUID#", Uuid::GenerateV4().str());
Expand Down Expand Up @@ -280,7 +285,7 @@ inline Result<> WritePythonPluginFiles(const std::filesystem::path& outputDirect
{
return MakeErrorResult(-74100, fmt::format("Error creating and opening output file at path: {}", initTempFile.tempFilePath().string()));
}
std::string content = k_PluginInitPythonFile;
std::string content = PluginInitPythonFile();

content = StringUtilities::replace(content, "#PLUGIN_NAME#", pluginName);
content = StringUtilities::replace(content, "#PLUGIN_UUID#", Uuid::GenerateV4().str());
Expand Down
97 changes: 97 additions & 0 deletions wrapping/python/plugins/DataAnalysisToolkit/NPSortArray.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@

from typing import List

import simplnx as nx

import numpy as np

class NPSortArray:
"""
This section should contain the 'keys' that store each parameter. The value of the key should be snake_case. The name
of the value should be ALL_CAPITOL_KEY
"""
INPUT_ARRAY_KEY = 'input_array_path'

def uuid(self) -> nx.Uuid:
"""This returns the UUID of the filter. Each filter has a unique UUID value
:return: The Filter's Uuid value
:rtype: string
"""
return nx.Uuid('ae37de34-4ead-4202-9a49-6c222cbd88a8')

def human_name(self) -> str:
"""This returns the name of the filter as a user of DREAM3DNX would see it
:return: The filter's human name
:rtype: string
"""
return 'Sort Data Array (Numpy)'

def class_name(self) -> str:
"""The returns the name of the class that implements the filter
:return: The name of the implementation class
:rtype: string
"""
return 'NPSortArray'

def name(self) -> str:
"""The returns the name of filter
:return: The name of the filter
:rtype: string
"""
return 'NPSortArray'

def default_tags(self) -> List[str]:
"""This returns the default tags for this filter
:return: The default tags for the filter
:rtype: list
"""
return ['python']

def clone(self):
"""Clones the filter
:return: A new instance of the filter
:rtype: NPSortArray
"""
return NPSortArray()

def parameters(self) -> nx.Parameters:
"""This function defines the parameters that are needed by the filter. Parameters collect the values from the user
or through a pipeline file.
"""
params = nx.Parameters()

params.insert(nx.ArraySelectionParameter(NPSortArray.INPUT_ARRAY_KEY, 'Input Data Array', 'The input array to sort.', nx.DataPath(), nx.get_all_data_types()))

return params

def preflight_impl(self, data_structure: nx.DataStructure, args: dict, message_handler: nx.IFilter.MessageHandler, should_cancel: nx.AtomicBoolProxy) -> nx.IFilter.PreflightResult:
"""This method preflights the filter and should ensure that all inputs are sanity checked as best as possible. Array
sizes can be checked if the arrays are actually know at preflight time. Some filters will not be able to report output
array sizes during preflight (segmentation filters for example).
:returns:
:rtype: nx.IFilter.PreflightResult
"""

# message_handler(nx.IFilter.Message(nx.IFilter.Message.Type.Info, f'Preflight: {value}'))
return nx.IFilter.PreflightResult()

def execute_impl(self, data_structure: nx.DataStructure, args: dict, message_handler: nx.IFilter.MessageHandler, should_cancel: nx.AtomicBoolProxy) -> nx.IFilter.ExecuteResult:
""" This method actually executes the filter algorithm and reports results.
:returns:
:rtype: nx.IFilter.ExecuteResult
"""
# Extract the DataPath from the arguments
input_data_arr_path: nx.DataPath = args[NPSortArray.INPUT_ARRAY_KEY]
# Use the DataPath to get a numpy view of the DataArray at that DataPath
input_array_view = data_structure[input_data_arr_path].npview()

# Treat the view like a single dimensional array
# The entire array is sorted from first element to last element.
input_array_view = input_array_view.reshape(-1)

# Sort the actual Data Array in place
input_array_view.sort()

return nx.Result()


13 changes: 12 additions & 1 deletion wrapping/python/plugins/DataAnalysisToolkit/Plugin.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@

"""
Insert documentation here.
"""

from DataAnalysisToolkit.CalculateHistogramFilter import CalculateHistogramFilter
from DataAnalysisToolkit.InterpolateGridDataFilter import InterpolateGridDataFilter
from DataAnalysisToolkit.CliReaderFilter import CliReaderFilter
from DataAnalysisToolkit.ContourDetectionFilter import ContourDetectionFilter
from DataAnalysisToolkit.NPSortArray import NPSortArray

# FILTER_INCLUDE_INSERT

import simplnx as nx

class DataAnalysisToolkit:
Expand All @@ -21,4 +30,6 @@ def vendor(self) -> str:
return 'BlueQuartz Software'

def get_filters(self):
return [CalculateHistogramFilter, InterpolateGridDataFilter, CliReaderFilter, ContourDetectionFilter]
return [CalculateHistogramFilter,InterpolateGridDataFilter,CliReaderFilter,NPSortArray,ContourDetectionFilter] # FILTER_NAME_INSERT


9 changes: 8 additions & 1 deletion wrapping/python/plugins/DataAnalysisToolkit/__init__.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@

from DataAnalysisToolkit.Plugin import DataAnalysisToolkit

from DataAnalysisToolkit.CalculateHistogramFilter import CalculateHistogramFilter
from DataAnalysisToolkit.InterpolateGridDataFilter import InterpolateGridDataFilter
from DataAnalysisToolkit.CliReaderFilter import CliReaderFilter
from DataAnalysisToolkit.ContourDetectionFilter import ContourDetectionFilter
from DataAnalysisToolkit.NPSortArray import NPSortArray

# FILTER_INCLUDE_INSERT

def get_plugin():
return DataAnalysisToolkit()

__all__ = ['DataAnalysisToolkit', 'CalculateHistogramFilter', 'InterpolateGridDataFilter', 'CliReaderFilter', 'ContourDetectionFilter', 'get_plugin']
__all__ = ['DataAnalysisToolkit','CalculateHistogramFilter', 'InterpolateGridDataFilter', 'CliReaderFilter', 'get_plugin', 'ContourDetectionFilter', 'NPSortArray'] # FILTER_NAME_INSERT


0 comments on commit fa92713

Please sign in to comment.