Skip to content

Commit

Permalink
General PR Patch (#138)
Browse files Browse the repository at this point in the history
* FIX: got rid of cloudtocloud away from publication

* FIX:catch up with main

* ADD-WIP: unsure about this commit, leftover mods

* FIX-ADD: no more distances in csv export, added distances export option as separate

* ADD: extra commodity for automatic added bool toggles

* MILESTONE-ADD: new category results with import/export/inspect results + load cloud fix

* FIX: convert pickle to JSON serialization

* FIX: missing import

* FIX: correct exception RML message
  • Loading branch information
9and3 authored Nov 18, 2024
1 parent af2f956 commit 5cb47e3
Show file tree
Hide file tree
Showing 40 changed files with 970 additions and 62 deletions.
Binary file added assets/icon_pool/icon_export_ply.xcf
Binary file not shown.
Binary file added assets/icon_pool/icon_export_serialization.xcf
Binary file not shown.
Binary file added assets/icon_pool/icon_export_serialization_v2.xcf
Binary file not shown.
Binary file added assets/icon_pool/icon_import_serialization_v1.xcf
Binary file not shown.
Binary file added assets/icon_pool/icon_inspect_results.xcf
Binary file not shown.
Binary file added assets/icon_pool/icon_results.xcf
Binary file not shown.
Binary file added assets/icon_pool/normal_v1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion deps/eigen
Submodule eigen updated from 7ad7c1 to 8b4efc
2 changes: 1 addition & 1 deletion deps/pybind11
Submodule pybind11 updated 74 files
+23 −0 .github/workflows/ci.yml
+1 −1 .github/workflows/pip.yml
+8 −8 .pre-commit-config.yaml
+3 −0 CMakeLists.txt
+391 −0 docs/advanced/deadlock.md
+8 −1 docs/advanced/misc.rst
+2 −1 docs/upgrade.rst
+21 −4 include/pybind11/cast.h
+15 −0 include/pybind11/conduit/README.txt
+111 −0 include/pybind11/conduit/pybind11_conduit_v1.h
+88 −0 include/pybind11/conduit/pybind11_platform_abi_id.h
+72 −0 include/pybind11/conduit/wrap_include_python_h.h
+54 −11 include/pybind11/detail/class.h
+35 −70 include/pybind11/detail/common.h
+2 −3 include/pybind11/detail/descr.h
+1 −1 include/pybind11/detail/init.h
+6 −65 include/pybind11/detail/internals.h
+6 −13 include/pybind11/detail/type_caster_base.h
+3 −3 include/pybind11/eigen/tensor.h
+4 −4 include/pybind11/eval.h
+2 −0 include/pybind11/gil_safe_call_once.h
+59 −29 include/pybind11/pybind11.h
+29 −7 include/pybind11/pytypes.h
+38 −2 include/pybind11/stl_bind.h
+6 −0 tests/CMakeLists.txt
+4 −3 tests/conftest.py
+1 −0 tests/env.py
+21 −48 tests/exo_planet_c_api.cpp
+9 −1 tests/extra_python_package/test_files.py
+5 −0 tests/pybind11_tests.cpp
+21 −0 tests/pybind11_tests.h
+7 −6 tests/requirements.txt
+171 −0 tests/test_buffers.cpp
+164 −0 tests/test_buffers.py
+2 −2 tests/test_call_policies.cpp
+7 −0 tests/test_call_policies.py
+1 −1 tests/test_callbacks.cpp
+2 −0 tests/test_callbacks.py
+16 −0 tests/test_class.cpp
+37 −1 tests/test_class.py
+11 −5 tests/test_cmake_build/CMakeLists.txt
+4 −0 tests/test_copy_move.py
+5 −1 tests/test_cpp_conduit.py
+2 −0 tests/test_custom_type_casters.py
+2 −2 tests/test_custom_type_setup.py
+3 −0 tests/test_eigen_matrix.py
+3 −0 tests/test_eigen_tensor.py
+5 −3 tests/test_embed/CMakeLists.txt
+63 −0 tests/test_enum.py
+1 −1 tests/test_eval.py
+4 −1 tests/test_exceptions.py
+13 −0 tests/test_factory_constructors.py
+16 −0 tests/test_gil_scoped.py
+6 −0 tests/test_iostream.py
+1 −21 tests/test_kwargs_and_defaults.cpp
+3 −1 tests/test_kwargs_and_defaults.py
+1 −1 tests/test_methods_and_attributes.cpp
+14 −1 tests/test_methods_and_attributes.py
+5 −2 tests/test_modules.py
+15 −9 tests/test_multiple_inheritance.py
+2 −1 tests/test_numpy_array.py
+4 −1 tests/test_opaque_types.py
+6 −0 tests/test_operator_overloading.py
+18 −1 tests/test_pickling.py
+12 −0 tests/test_pytypes.cpp
+12 −1 tests/test_pytypes.py
+39 −10 tests/test_sequences_and_iterators.py
+12 −0 tests/test_smart_ptr.py
+2 −0 tests/test_stl.py
+19 −0 tests/test_stl_binders.py
+2 −1 tests/test_type_caster_pyobject_ptr.cpp
+7 −2 tests/test_virtual_functions.py
+4 −1 tools/setup_global.py.in
+2 −0 tools/setup_main.py.in
8 changes: 8 additions & 0 deletions doc/gh_DFExportCloudToFile.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.. image:: ../src/gh/components/DF_export_cloud_to_file/icon.png
:align: left
:width: 40px

``DFExportCloudToFile`` component
=================================

.. ghcomponent_to_rst:: ../src/gh/components/DF_export_cloud_to_file
8 changes: 8 additions & 0 deletions doc/gh_DFExportResults.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.. image:: ../src/gh/components/DF_export_results/icon.png
:align: left
:width: 40px

``DFExportResults`` component
=============================

.. ghcomponent_to_rst:: ../src/gh/components/DF_export_results
8 changes: 8 additions & 0 deletions doc/gh_DFImportResults.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.. image:: ../src/gh/components/DF_import_results/icon.png
:align: left
:width: 40px

``DFImportResults`` component
=============================

.. ghcomponent_to_rst:: ../src/gh/components/DF_import_results
8 changes: 8 additions & 0 deletions doc/gh_DFInspectResults.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.. image:: ../src/gh/components/DF_inspect_results/icon.png
:align: left
:width: 40px

``DFInspectResults`` component
==============================

.. ghcomponent_to_rst:: ../src/gh/components/DF_inspect_results
16 changes: 15 additions & 1 deletion doc/gh_components.rst
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,16 @@ DF has a Grasshopper_ plugin with a set of components that allows the user to in
- .. image:: ../src/gh/components/DF_cloud_voxel_downsample/icon.png
- `gh_DFCloudVoxelDownsample <gh_DFCloudVoxelDownsample.html>`_

* - .. image:: ../src/gh/components/DF_export_cloud_to_file/icon.png
- `DFExportCloudToFile <gh_DFExportCloudToFile.html>`_
- .. image:: ../src/gh/components/DF_export_results/icon.png
- `DFExportResults <gh_DFExportResults.html>`_

* - .. image:: ../src/gh/components/DF_import_results/icon.png
- `DFImportResults <gh_DFImportResults.html>`_
- .. image:: ../src/gh/components/DF_inspect_results/icon.png
- `DFInspectResults <gh_DFInspectResults.html>`_


.. toctree::
:maxdepth: 1
Expand Down Expand Up @@ -113,4 +123,8 @@ DF has a Grasshopper_ plugin with a set of components that allows the user to in
gh_DFColorizeCloud
gh_DFBrepToCloud
gh_DFRemoveStatisticalOutliers
gh_DFMergeAssemblies
gh_DFMergeAssemblies
gh_DFExportCloudToFile
gh_DFExportResults
gh_DFImportResults
gh_DFInspectResults
9 changes: 6 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,13 @@ module = "pefile"
ignore_missing_imports = true

[[tool.mypy.overrides]]
module = "diffCheck"
ignore_undefined_attributes = true

module = "df_geometries"
disable_error_code = "annotation-unchecked"
check_untyped_defs = false

[[tool.mypy.overrides]]
module = "src.gh.diffCheck.diffCheck.df_geometries"
disable_error_code = "annotation-unchecked"

[tool.ruff]
exclude = [
Expand Down
9 changes: 9 additions & 0 deletions src/diffCheck/IOManager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,15 @@ namespace diffCheck::io
return mesh;
}

void WritePLYPointCloud(const std::shared_ptr<diffCheck::geometry::DFPointCloud> &pointCloud, const std::string &filename)
{
auto open3dPointCloud = pointCloud->Cvt2O3DPointCloud();
open3d::io::WritePointCloudToPLY(
filename,
*open3dPointCloud,
open3d::io::WritePointCloudOption());
}

std::string GetTestDataDir()
{
// for github action conviniency
Expand Down
7 changes: 7 additions & 0 deletions src/diffCheck/IOManager.hh
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@ namespace diffCheck::io
*/
std::shared_ptr<diffCheck::geometry::DFMesh> ReadPLYMeshFromFile(const std::string &filename);

/**
* @brief Write a point cloud to a file as a PLY
*
* @param pointCloud the point cloud to write
* @param filename the path to the file with the extension
*/
void WritePLYPointCloud(const std::shared_ptr<diffCheck::geometry::DFPointCloud> &pointCloud, const std::string &filename);

//////////////////////////////////////////////////////////////////////////
// IO for test suite and tests data
Expand Down
6 changes: 6 additions & 0 deletions src/diffCheck/geometry/DFPointCloud.cc
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,12 @@ namespace diffCheck::geometry
this->Normals = cloud->Normals;
}

void DFPointCloud::SaveToPLY(const std::string &path)
{
auto cloud_ptr = std::make_shared<DFPointCloud>(this->Points, this->Colors, this->Normals);
diffCheck::io::WritePLYPointCloud(cloud_ptr, path);
}

std::vector<double> DFPointCloud::ComputeDistance(std::shared_ptr<geometry::DFPointCloud> target)
{
std::vector<double> errors;
Expand Down
7 changes: 7 additions & 0 deletions src/diffCheck/geometry/DFPointCloud.hh
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,13 @@ namespace diffCheck::geometry
*/
void LoadFromPLY(const std::string &path);

/**
* @brief Save a point cloud to a file as a PLY
*
* @param filename the path to the file with the extension
*/
void SaveToPLY(const std::string &path);

public: ///< Distance calculations
/**
* @brief Compute the distance between two point clouds.
Expand Down
2 changes: 2 additions & 0 deletions src/diffCheckBindings.cc
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ PYBIND11_MODULE(diffcheck_bindings, m) {
py::arg("nb_neighbors"), py::arg("std_ratio"))

.def("load_from_PLY", &diffCheck::geometry::DFPointCloud::LoadFromPLY)
.def("save_to_PLY", &diffCheck::geometry::DFPointCloud::SaveToPLY)

.def("add_points", &diffCheck::geometry::DFPointCloud::AddPoints)

.def("get_tight_bounding_box", &diffCheck::geometry::DFPointCloud::GetTightBoundingBox)
Expand Down
146 changes: 126 additions & 20 deletions src/gh/components/DF_csv_exporter/code.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,45 @@
#! python3

import System
import csv
import os
import typing

from ghpythonlib.componentbase import executingcomponent as component
import Grasshopper as gh

from diffCheck.df_error_estimation import DFInvalidData
import csv
import os
from diffCheck.df_error_estimation import DFInvalidData, DFVizResults


def add_bool_toggle(self,
nickname: str,
indx: int,
X_param_coord: float,
Y_param_coord: float,
X_offset: int=87
) -> None:
"""
Adds a boolean toggle to the component input
:param nickname: the nickname of the value list
:param indx: the index of the input parameter
:param X_param_coord: the x coordinate of the input parameter
:param Y_param_coord: the y coordinate of the input parameter
:param X_offset: the offset of the value list from the input parameter
"""
param = ghenv.Component.Params.Input[indx] # noqa: F821
if param.SourceCount == 0:
toggle = gh.Kernel.Special.GH_BooleanToggle()
toggle.NickName = nickname
toggle.Description = "Toggle the value to use with DFVizSettings"
toggle.CreateAttributes()
toggle.Attributes.Pivot = System.Drawing.PointF(
X_param_coord - (toggle.Attributes.Bounds.Width) - X_offset,
Y_param_coord - (toggle.Attributes.Bounds.Height / 2 + 0.1)
)
toggle.Attributes.ExpireLayout()
gh.Instances.ActiveCanvas.Document.AddObject(toggle, False)
ghenv.Component.Params.Input[indx].AddSource(toggle) # noqa: F821


class DFCsvExporter(component):
Expand All @@ -14,7 +48,28 @@ def __init__(self):
self.prefix = ""
self.counter = 0

def _get_id(self, idx, i_result):
ghenv.Component.ExpireSolution(True) # noqa: F821
ghenv.Component.Attributes.PerformLayout() # noqa: F821
params = getattr(ghenv.Component.Params, "Input") # noqa: F821
for j in range(len(params)):
Y_cord = params[j].Attributes.InputGrip.Y + 1
X_cord = params[j].Attributes.Pivot.X + 10
input_indx = j
if "i_export_seperate_files" == params[j].NickName:
add_bool_toggle(
ghenv.Component, # noqa: F821
"export_asfiles",
input_indx, X_cord, Y_cord)
if "i_export_distances" == params[j].NickName:
add_bool_toggle(
ghenv.Component, # noqa: F821
"export_dist",
input_indx, X_cord, Y_cord)

def _get_id(self,
idx: int,
i_result: DFVizResults
) -> str:
""" Get the ID of the element """
counter = 0

Expand All @@ -34,15 +89,18 @@ def _get_id(self, idx, i_result):
return f"{idx_b}--{idx_j}--{idx_f}"
counter += 1

def _write_csv(self, file_path, rows):
""" Write the CSV file """
with open(file_path, mode='w', newline='') as file:
writer = csv.writer(file)
writer.writerow([f"{self.prefix} id", "distances", "min_deviation", "max_deviation", "std_deviation", "rmse", "mean"])
writer.writerows(rows)
def _prepare_row(self,
idx: int,
i_result: DFVizResults
) -> typing.Dict:
"""
Convert the results contained in the DFVizResults object to a dict to be written in the CSV file
def _prepare_row(self, idx, i_result):
""" Prepare a row for the CSV file """
:param idx: Index of the element
:param i_result: DFVizResults object containing all the values
:return: Dict of values containng as keys the header and as items the values to be written in the CSV file
"""
if i_result.sanity_check[idx].value != DFInvalidData.VALID.value:
invalid_type = i_result.sanity_check[idx].name
return [self._get_id(idx, i_result), invalid_type, invalid_type, invalid_type, invalid_type, invalid_type, invalid_type]
Expand All @@ -53,16 +111,57 @@ def _prepare_row(self, idx, i_result):
std_dev = round(i_result.distances_sd_deviation[idx], 4)
rmse = round(i_result.distances_rmse[idx], 4)
mean = round(i_result.distances_mean[idx], 4)
distances_str = ";".join(map(str, distances))
return [self._get_id(idx, i_result), distances_str, min_dev, max_dev, std_dev, rmse, mean]

row: typing.Dict = {
f"{self.prefix} id": self._get_id(idx, i_result),
"distances": distances,
"min_deviation": min_dev,
"max_deviation": max_dev,
"std_deviation": std_dev,
"rmse": rmse,
"mean": mean
}
return row

def _write_csv(self,
csv_path: str,
rows: typing.List[typing.Dict],
is_writing_only_distances: bool = False
) -> None:
"""
Write the CSV file
:param csv_path: Path of the CSV file
:param rows: Dict of values to be written in the CSV file
:param is_writing_only_distances: Flag to check if to write ONLY distances or the whole analysis
:return: None
"""
with open(csv_path, mode='w', newline='') as file:
writer = csv.writer(file, quoting=csv.QUOTE_MINIMAL)
if is_writing_only_distances:
writer.writerow(list(rows[0].keys())[:2]) # header
element_id = [row[f"{self.prefix} id"] for row in rows]
dist_rows = [row["distances"] for row in rows]
for idx, dist_row in enumerate(dist_rows):
for dist in dist_row:
writer.writerow([element_id[idx], dist])
else:
rows = [{k: v for k, v in row.items() if k != "distances"} for row in rows] # no distances
writer.writerow(list(rows[0].keys())) # header
writer.writerows([list(row.values()) for row in rows])

def RunScript(self,
i_dump: bool,
i_export_dir: str,
i_file_name: str,
i_export_seperate_files: bool,
i_export_distances: bool,
i_result):

csv_analysis_path: str = None
csv_distances_path: str = None

if i_dump:
os.makedirs(i_export_dir, exist_ok=True)

Expand All @@ -75,10 +174,17 @@ def RunScript(self,

if i_export_seperate_files:
for idx in range(len(i_result.source)):
element_id = self._get_id( idx, i_result)
file_path = os.path.join(i_export_dir, f"{i_file_name}_{self.prefix}_{element_id}.csv")
self._write_csv(file_path, [self._prepare_row(idx, i_result)])
element_id = self._get_id(idx, i_result)
csv_analysis_path = os.path.join(i_export_dir, f"{i_file_name}_{self.prefix}_{element_id}.csv")
rows = [self._prepare_row(idx, i_result)]
self._write_csv(csv_analysis_path, rows)
if i_export_distances:
csv_distances_path = os.path.join(i_export_dir, f"{i_file_name}_{self.prefix}_{element_id}_distances.csv")
self._write_csv(csv_distances_path, rows, is_writing_only_distances=True)
else:
file_path = os.path.join(i_export_dir, f"{i_file_name}.csv")
rows = [self._prepare_row(idx, i_result) for idx in range(len(i_result.source))]
self._write_csv(file_path, rows)
csv_analysis_path = os.path.join(i_export_dir, f"{i_file_name}.csv")
merged_rows = [self._prepare_row(idx, i_result) for idx in range(len(i_result.source))]
self._write_csv(csv_analysis_path, merged_rows)
if i_export_distances:
csv_distances_path = os.path.join(i_export_dir, f"{i_file_name}_distances.csv")
self._write_csv(csv_distances_path, merged_rows, is_writing_only_distances=True)
12 changes: 12 additions & 0 deletions src/gh/components/DF_csv_exporter/metadata.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,18 @@
"sourceCount": 0,
"typeHintID": "bool"
},
{
"name": "i_export_distances",
"nickname": "i_export_distances",
"description": "Whether to export the calculated error distances for each point of the analysed point cloud.",
"optional": true,
"allowTreeAccess": true,
"showTypeHints": true,
"scriptParamAccess": "item",
"wireDisplay": "default",
"sourceCount": 0,
"typeHintID": "bool"
},
{
"name": "i_result",
"nickname": "i_result",
Expand Down
Loading

0 comments on commit 5cb47e3

Please sign in to comment.