Skip to content

Commit fa92713

Browse files
authored
ENH: GeneratePythonFilter-Crashing fixed, Generation Fixed, headers split (#877)
Signed-off-by: Michael Jackson <[email protected]>
1 parent 1645a22 commit fa92713

File tree

6 files changed

+206
-32
lines changed

6 files changed

+206
-32
lines changed

src/Plugins/SimplnxCore/CMakeLists.txt

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,7 @@ set(PLUGIN_EXTRA_SOURCES
318318
"${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/CeilOperator.cpp"
319319
"${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/AvizoWriter.hpp"
320320
"${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/AvizoWriter.cpp"
321+
"${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/PythonPluginTemplateFile.hpp"
321322

322323
"${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/SurfaceNets/MMCellFlag.cpp"
323324
"${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/SurfaceNets/MMCellFlag.h"
@@ -348,11 +349,24 @@ source_group(TREE "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}" PREFIX ${PLU
348349
# the template file to use the contents of those files. This should allow easier
349350
# updating of those template files.
350351
file(READ "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/PythonFilterTemplate.py" PYTHON_FILTER_TEMPLATE)
352+
string(HEX ${PYTHON_FILTER_TEMPLATE} PYTHON_FILTER_TEMPLATE)
353+
string(REGEX REPLACE "([0-9a-f][0-9a-f])" "0x\\0," PYTHON_FILTER_TEMPLATE ${PYTHON_FILTER_TEMPLATE})
354+
string(APPEND PYTHON_FILTER_TEMPLATE "0x00")
355+
356+
351357
file(READ "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/PythonPluginInitTemplate.py" PYTHON_PLUGIN_INIT_TEMPLATE)
358+
string(HEX ${PYTHON_PLUGIN_INIT_TEMPLATE} PYTHON_PLUGIN_INIT_TEMPLATE)
359+
string(REGEX REPLACE "([0-9a-f][0-9a-f])" "0x\\0," PYTHON_PLUGIN_INIT_TEMPLATE ${PYTHON_PLUGIN_INIT_TEMPLATE})
360+
string(APPEND PYTHON_PLUGIN_INIT_TEMPLATE "0x00")
361+
352362
file(READ "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/PythonPluginTemplate.py" PYTHON_PLUGIN_TEMPLATE)
363+
string(HEX ${PYTHON_PLUGIN_TEMPLATE} PYTHON_PLUGIN_TEMPLATE)
364+
string(REGEX REPLACE "([0-9a-f][0-9a-f])" "0x\\0," PYTHON_PLUGIN_TEMPLATE ${PYTHON_PLUGIN_TEMPLATE})
365+
string(APPEND PYTHON_PLUGIN_TEMPLATE "0x00")
366+
353367

354-
configure_file("${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/PythonPluginTemplateFile.in.hpp"
355-
"${${PLUGIN_NAME}_BINARY_DIR}/utils/PythonPluginTemplateFile.hpp")
368+
cmpConfigureFileWithMD5Check(CONFIGURED_TEMPLATE_PATH "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/PythonPluginSourceTemplate.in.hpp"
369+
GENERATED_FILE_PATH "${${PLUGIN_NAME}_BINARY_DIR}/generated/${PLUGIN_NAME}/utils/PythonPluginSourceTemplate.hpp")
356370

357371
#------------------------------------------------------------------------------
358372
# If there are additional include directories that are needed for this plugin
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#pragma once
2+
3+
/**
4+
* This file is auto-generated during CMake time. Any changes made to the generated file
5+
* will be over written the next time CMake runs a configure.
6+
*/
7+
8+
#include <string>
9+
10+
namespace nx::core
11+
{
12+
13+
// clang-format off
14+
static const char k_PythonFilterTemplateCharArray[] = {@PYTHON_FILTER_TEMPLATE@};
15+
// clang-format on
16+
17+
inline const std::string PythonFilterTemplate()
18+
{
19+
return {k_PythonFilterTemplateCharArray};
20+
}
21+
22+
// clang-format off
23+
static const char k_PluginPythonFileCharArray[] = {@PYTHON_PLUGIN_TEMPLATE@};
24+
// clang-format on
25+
26+
inline const std::string PluginPythonFile()
27+
{
28+
return {k_PluginPythonFileCharArray};
29+
}
30+
31+
// clang-format off
32+
static const char k_PluginInitPythonFileCharArray[] = {@PYTHON_PLUGIN_INIT_TEMPLATE@};
33+
// clang-format on
34+
35+
inline const std::string PluginInitPythonFile()
36+
{
37+
return {k_PluginInitPythonFileCharArray};
38+
}
39+
40+
}; // namespace nx::core

src/Plugins/SimplnxCore/src/SimplnxCore/utils/PythonPluginTemplateFile.in.hpp renamed to src/Plugins/SimplnxCore/src/SimplnxCore/utils/PythonPluginTemplateFile.hpp

Lines changed: 33 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
#include "simplnx/Utilities/FilterUtilities.hpp"
66
#include "simplnx/Utilities/StringUtilities.hpp"
77

8+
#include "SimplnxCore/utils/PythonPluginSourceTemplate.hpp"
9+
810
#include <fmt/format.h>
911

1012
#include <filesystem>
@@ -16,9 +18,6 @@ namespace nx::core
1618
{
1719
inline const std::string k_FilterIncludeInsertToken = "# FILTER_INCLUDE_INSERT";
1820
inline const std::string k_FilterNameInsertToken = "# FILTER_NAME_INSERT";
19-
inline const std::string k_PythonFilterTemplate = R"(
20-
@PYTHON_FILTER_TEMPLATE@
21-
)";
2221

2322
/**
2423
*
@@ -29,7 +28,7 @@ inline const std::string k_PythonFilterTemplate = R"(
2928
*/
3029
inline std::string GeneratePythonFilter(const std::string& filterName, const std::string& humanName, const std::string& uuidString)
3130
{
32-
std::string content = k_PythonFilterTemplate;
31+
std::string content = PythonFilterTemplate();
3332

3433
content = StringUtilities::replace(content, "#PYTHON_FILTER_NAME#", filterName);
3534
content = StringUtilities::replace(content, "#PYTHON_FILTER_HUMAN_NAME#", humanName);
@@ -47,7 +46,13 @@ inline std::string GeneratePythonFilter(const std::string& filterName, const std
4746
inline Result<> InsertFilterNameInPluginFiles(const std::filesystem::path& pluginPath, const std::string& filterName)
4847
{
4948
Result<> result;
50-
std::string pluginName = pluginPath.stem().string();
49+
std::string pluginName = pluginPath.string();
50+
if(StringUtilities::ends_with(pluginName, "/"))
51+
{
52+
pluginName.pop_back();
53+
std::filesystem::path plugPath(pluginName);
54+
pluginName = plugPath.stem().string();
55+
}
5156

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

85-
std::string filterImportToken = fmt::format("from {0}.{1} import {1}\n", pluginName, filterName);
86-
content.insert(filterInsertPos, filterImportToken);
92+
std::string filterImportToken = fmt::format("from {0}.{1} import {1}\n", pluginName, filterName);
93+
content.insert(filterInsertPos, filterImportToken);
94+
}
8795
}
8896

8997
// Insert filter name
@@ -96,14 +104,17 @@ inline Result<> InsertFilterNameInPluginFiles(const std::filesystem::path& plugi
96104
"file. This plugin file must be manually updated to include the filter name ('{2}').",
97105
pluginFilePath.string(), k_FilterNameInsertToken, filterName)});
98106
}
99-
filterInsertPos -= 2; // Go back two characters to insert before the closing brace
100-
101-
std::string filterNameToken = filterName;
102-
if(pluginFilePath.filename() == "__init__.py")
107+
else
103108
{
104-
filterNameToken = fmt::format("'{}'", filterNameToken);
109+
filterInsertPos -= 2; // Go back two characters to insert before the closing brace
110+
111+
std::string filterNameToken = filterName;
112+
if(pluginFilePath.filename() == "__init__.py")
113+
{
114+
filterNameToken = fmt::format("'{}'", filterNameToken);
115+
}
116+
content.insert(filterInsertPos, "," + filterNameToken);
105117
}
106-
content.insert(filterInsertPos, "," + filterNameToken);
107118
}
108119

109120
std::ofstream out_file(pluginFilePath.string());
@@ -151,17 +162,19 @@ inline Result<> WritePythonFilterToPlugin(const std::filesystem::path& pluginPat
151162
*/
152163
inline Result<> WritePythonFiltersToPlugin(const std::filesystem::path& pluginPath, const std::string& filterNames)
153164
{
165+
Result<> result;
154166
auto filterNamesSplit = StringUtilities::split(filterNames, ',');
155167
for(const auto& filterName : filterNamesSplit)
156168
{
157-
auto result = nx::core::WritePythonFilterToPlugin(pluginPath, filterName);
158-
if(result.invalid())
169+
auto filterWriteResult = nx::core::WritePythonFilterToPlugin(pluginPath, filterName);
170+
if(filterWriteResult.invalid())
159171
{
160-
return result;
172+
return filterWriteResult;
161173
}
174+
result = MergeResults(result, filterWriteResult);
162175
}
163176

164-
return {};
177+
return result;
165178
}
166179

167180
/**
@@ -192,14 +205,6 @@ inline Result<> WritePythonFilterToFile(const std::filesystem::path& outputPath,
192205
return {};
193206
}
194207

195-
inline const std::string k_PluginPythonFile = R"(
196-
@PYTHON_PLUGIN_TEMPLATE@
197-
)";
198-
199-
inline const std::string k_PluginInitPythonFile = R"(
200-
@PYTHON_PLUGIN_INIT_TEMPLATE@
201-
)";
202-
203208
/**
204209
*
205210
* @param pluginName
@@ -211,7 +216,7 @@ inline const std::string k_PluginInitPythonFile = R"(
211216
*/
212217
inline std::string GeneratePythonPlugin(const std::string& pluginName, const std::string& pluginShortName, const std::string& pluginDescription, const std::string& pluginFilterList)
213218
{
214-
std::string content = k_PluginPythonFile;
219+
std::string content = PluginPythonFile();
215220

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

285290
content = StringUtilities::replace(content, "#PLUGIN_NAME#", pluginName);
286291
content = StringUtilities::replace(content, "#PLUGIN_UUID#", Uuid::GenerateV4().str());
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
2+
from typing import List
3+
4+
import simplnx as nx
5+
6+
import numpy as np
7+
8+
class NPSortArray:
9+
"""
10+
This section should contain the 'keys' that store each parameter. The value of the key should be snake_case. The name
11+
of the value should be ALL_CAPITOL_KEY
12+
"""
13+
INPUT_ARRAY_KEY = 'input_array_path'
14+
15+
def uuid(self) -> nx.Uuid:
16+
"""This returns the UUID of the filter. Each filter has a unique UUID value
17+
:return: The Filter's Uuid value
18+
:rtype: string
19+
"""
20+
return nx.Uuid('ae37de34-4ead-4202-9a49-6c222cbd88a8')
21+
22+
def human_name(self) -> str:
23+
"""This returns the name of the filter as a user of DREAM3DNX would see it
24+
:return: The filter's human name
25+
:rtype: string
26+
"""
27+
return 'Sort Data Array (Numpy)'
28+
29+
def class_name(self) -> str:
30+
"""The returns the name of the class that implements the filter
31+
:return: The name of the implementation class
32+
:rtype: string
33+
"""
34+
return 'NPSortArray'
35+
36+
def name(self) -> str:
37+
"""The returns the name of filter
38+
:return: The name of the filter
39+
:rtype: string
40+
"""
41+
return 'NPSortArray'
42+
43+
def default_tags(self) -> List[str]:
44+
"""This returns the default tags for this filter
45+
:return: The default tags for the filter
46+
:rtype: list
47+
"""
48+
return ['python']
49+
50+
def clone(self):
51+
"""Clones the filter
52+
:return: A new instance of the filter
53+
:rtype: NPSortArray
54+
"""
55+
return NPSortArray()
56+
57+
def parameters(self) -> nx.Parameters:
58+
"""This function defines the parameters that are needed by the filter. Parameters collect the values from the user
59+
or through a pipeline file.
60+
"""
61+
params = nx.Parameters()
62+
63+
params.insert(nx.ArraySelectionParameter(NPSortArray.INPUT_ARRAY_KEY, 'Input Data Array', 'The input array to sort.', nx.DataPath(), nx.get_all_data_types()))
64+
65+
return params
66+
67+
def preflight_impl(self, data_structure: nx.DataStructure, args: dict, message_handler: nx.IFilter.MessageHandler, should_cancel: nx.AtomicBoolProxy) -> nx.IFilter.PreflightResult:
68+
"""This method preflights the filter and should ensure that all inputs are sanity checked as best as possible. Array
69+
sizes can be checked if the arrays are actually know at preflight time. Some filters will not be able to report output
70+
array sizes during preflight (segmentation filters for example).
71+
:returns:
72+
:rtype: nx.IFilter.PreflightResult
73+
"""
74+
75+
# message_handler(nx.IFilter.Message(nx.IFilter.Message.Type.Info, f'Preflight: {value}'))
76+
return nx.IFilter.PreflightResult()
77+
78+
def execute_impl(self, data_structure: nx.DataStructure, args: dict, message_handler: nx.IFilter.MessageHandler, should_cancel: nx.AtomicBoolProxy) -> nx.IFilter.ExecuteResult:
79+
""" This method actually executes the filter algorithm and reports results.
80+
:returns:
81+
:rtype: nx.IFilter.ExecuteResult
82+
"""
83+
# Extract the DataPath from the arguments
84+
input_data_arr_path: nx.DataPath = args[NPSortArray.INPUT_ARRAY_KEY]
85+
# Use the DataPath to get a numpy view of the DataArray at that DataPath
86+
input_array_view = data_structure[input_data_arr_path].npview()
87+
88+
# Treat the view like a single dimensional array
89+
# The entire array is sorted from first element to last element.
90+
input_array_view = input_array_view.reshape(-1)
91+
92+
# Sort the actual Data Array in place
93+
input_array_view.sort()
94+
95+
return nx.Result()
96+
97+

wrapping/python/plugins/DataAnalysisToolkit/Plugin.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,16 @@
1+
2+
"""
3+
Insert documentation here.
4+
"""
5+
16
from DataAnalysisToolkit.CalculateHistogramFilter import CalculateHistogramFilter
27
from DataAnalysisToolkit.InterpolateGridDataFilter import InterpolateGridDataFilter
38
from DataAnalysisToolkit.CliReaderFilter import CliReaderFilter
49
from DataAnalysisToolkit.ContourDetectionFilter import ContourDetectionFilter
10+
from DataAnalysisToolkit.NPSortArray import NPSortArray
11+
12+
# FILTER_INCLUDE_INSERT
13+
514
import simplnx as nx
615

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

2332
def get_filters(self):
24-
return [CalculateHistogramFilter, InterpolateGridDataFilter, CliReaderFilter, ContourDetectionFilter]
33+
return [CalculateHistogramFilter,InterpolateGridDataFilter,CliReaderFilter,NPSortArray,ContourDetectionFilter] # FILTER_NAME_INSERT
34+
35+
Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
1+
12
from DataAnalysisToolkit.Plugin import DataAnalysisToolkit
3+
24
from DataAnalysisToolkit.CalculateHistogramFilter import CalculateHistogramFilter
35
from DataAnalysisToolkit.InterpolateGridDataFilter import InterpolateGridDataFilter
46
from DataAnalysisToolkit.CliReaderFilter import CliReaderFilter
57
from DataAnalysisToolkit.ContourDetectionFilter import ContourDetectionFilter
8+
from DataAnalysisToolkit.NPSortArray import NPSortArray
9+
10+
# FILTER_INCLUDE_INSERT
611

712
def get_plugin():
813
return DataAnalysisToolkit()
914

10-
__all__ = ['DataAnalysisToolkit', 'CalculateHistogramFilter', 'InterpolateGridDataFilter', 'CliReaderFilter', 'ContourDetectionFilter', 'get_plugin']
15+
__all__ = ['DataAnalysisToolkit','CalculateHistogramFilter', 'InterpolateGridDataFilter', 'CliReaderFilter', 'get_plugin', 'ContourDetectionFilter', 'NPSortArray'] # FILTER_NAME_INSERT
16+
17+

0 commit comments

Comments
 (0)