svr-roughness 0.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 HAM Lab, Iowa State University
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,139 @@
1
+ Metadata-Version: 2.4
2
+ Name: svr-roughness
3
+ Version: 0.3.0
4
+ Summary: Surface roughness metrics from scanner point clouds
5
+ Author: Sullivan Hart, HAM Lab, Iowa State University
6
+ License: MIT License
7
+
8
+ Copyright (c) 2026 HAM Lab, Iowa State University
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+ Keywords: roughness,point-cloud,ply,surface-metrology
28
+ Classifier: Development Status :: 4 - Beta
29
+ Classifier: Intended Audience :: Science/Research
30
+ Classifier: Programming Language :: Python :: 3
31
+ Classifier: Programming Language :: Python :: 3 :: Only
32
+ Classifier: Topic :: Scientific/Engineering
33
+ Requires-Python: >=3.10
34
+ Description-Content-Type: text/markdown
35
+ License-File: LICENSE
36
+ Requires-Dist: numpy>=1.24
37
+ Requires-Dist: opencv-python-headless>=4.8
38
+ Requires-Dist: scipy>=1.10
39
+ Dynamic: license-file
40
+
41
+ # svr-roughness
42
+
43
+ `svr-roughness` is a reusable Python library for SurfInspect-compatible surface
44
+ roughness analysis from industrial scan outputs. Use `svr_roughness` as the
45
+ consistent Python import name.
46
+
47
+ The core API is file-type agnostic: roughness is computed from an `Nx3` NumPy-like XYZ point array in millimeters. Svr is calculated from signed distances to a smoothed, triangulated reference surface and a KD-tree variogram modeled on SurfInspect. The regular grid remains available for Sa/Sq and visualization. Reference mesh resolution and smoothing default to 0.30 mm, matching the supplied SurfInspect A2 reference closely. At most 10,000 variogram points are used by default to bound memory on industrial scans; set `max_svr_points` higher when full point coverage is required.
48
+
49
+ ```python
50
+ config = RoughnessConfig(
51
+ mesh_resolution_mm=0.30,
52
+ mesh_smoothing_mm=0.30,
53
+ svr_points=10,
54
+ svr_span_mm=0.50,
55
+ )
56
+ ```
57
+
58
+ ## Install
59
+
60
+ From this repository:
61
+
62
+ ```bash
63
+ python -m pip install ./svr-roughness
64
+ ```
65
+
66
+ For deployment from inside `SurfaceRoughnessPi`:
67
+
68
+ ```bash
69
+ python -m pip install ../svr-roughness
70
+ ```
71
+
72
+ ## Python API
73
+
74
+ Use `analyze_points()` when your scanner or upstream software already gives you XYZ points:
75
+
76
+ ```python
77
+ import numpy as np
78
+ from svr_roughness import analyze_points
79
+
80
+ points_xyz_mm = np.asarray(points) # shape (N, 3), columns x/y/z, units mm
81
+ result = analyze_points(points_xyz_mm, grid_mm=0.30, short_cutoff_mm=0.6, long_cutoff_mm=8.0)
82
+
83
+ print(result.sa_um, result.sq_um, result.svr_um)
84
+ ```
85
+
86
+ Use `analyze_file()` as a convenience adapter for supported files:
87
+
88
+ ```python
89
+ from svr_roughness import RoughnessConfig, analyze_file
90
+
91
+ config = RoughnessConfig(grid_mm=0.30, short_cutoff_mm=0.6, long_cutoff_mm=8.0)
92
+ result = analyze_file("scan.ply", config=config)
93
+ ```
94
+
95
+ Supported file loaders (all are converted to an `Nx3` NumPy array):
96
+
97
+ - ASCII and binary little-endian `.ply` point clouds
98
+ - ASCII and binary `.pcd` point clouds
99
+ - ASCII and binary `.stl` mesh vertices
100
+ - `.obj` vertex meshes
101
+ - comma-, tab-, or whitespace-delimited `.csv`, `.tsv`, `.xyz`, and `.txt`
102
+ - `.npy` and `.npz` NumPy arrays
103
+
104
+ STL files are converted to their unique mesh vertices before analysis. For production mesh metrology, prefer scanner point clouds or add controlled surface sampling before calling `analyze_points()`.
105
+
106
+ ## Result Output
107
+
108
+ ```python
109
+ result.save_grid_npz("output/roughness/latest_grid.npz")
110
+ result.save_metrics_json("output/roughness/latest_metrics.json")
111
+ ```
112
+
113
+ `save_metrics_json()` writes:
114
+
115
+ - `sa_um`
116
+ - `sq_um`
117
+ - `svr_um`
118
+ - point counts, grid dimensions, grid coverage, and filter cutoffs
119
+
120
+ `save_grid_npz()` writes:
121
+
122
+ - `grid_raw`
123
+ - `grid_filled`
124
+ - `grid_filtered`
125
+ - `valid_raw`
126
+ - `valid_filled`
127
+ - `grid_origin`
128
+ - plane basis arrays
129
+
130
+ ## Command line
131
+
132
+ The package also includes a no-code command for scanner integrations:
133
+
134
+ ```bash
135
+ svr-roughness scan.ply --grid-mm 0.30 --metrics-out metrics.json --grid-out grid.npz
136
+ ```
137
+
138
+ Coordinates are assumed to be millimeters, and metrics are reported in
139
+ micrometers. Unit conversion should happen before calling the library.
@@ -0,0 +1,99 @@
1
+ # svr-roughness
2
+
3
+ `svr-roughness` is a reusable Python library for SurfInspect-compatible surface
4
+ roughness analysis from industrial scan outputs. Use `svr_roughness` as the
5
+ consistent Python import name.
6
+
7
+ The core API is file-type agnostic: roughness is computed from an `Nx3` NumPy-like XYZ point array in millimeters. Svr is calculated from signed distances to a smoothed, triangulated reference surface and a KD-tree variogram modeled on SurfInspect. The regular grid remains available for Sa/Sq and visualization. Reference mesh resolution and smoothing default to 0.30 mm, matching the supplied SurfInspect A2 reference closely. At most 10,000 variogram points are used by default to bound memory on industrial scans; set `max_svr_points` higher when full point coverage is required.
8
+
9
+ ```python
10
+ config = RoughnessConfig(
11
+ mesh_resolution_mm=0.30,
12
+ mesh_smoothing_mm=0.30,
13
+ svr_points=10,
14
+ svr_span_mm=0.50,
15
+ )
16
+ ```
17
+
18
+ ## Install
19
+
20
+ From this repository:
21
+
22
+ ```bash
23
+ python -m pip install ./svr-roughness
24
+ ```
25
+
26
+ For deployment from inside `SurfaceRoughnessPi`:
27
+
28
+ ```bash
29
+ python -m pip install ../svr-roughness
30
+ ```
31
+
32
+ ## Python API
33
+
34
+ Use `analyze_points()` when your scanner or upstream software already gives you XYZ points:
35
+
36
+ ```python
37
+ import numpy as np
38
+ from svr_roughness import analyze_points
39
+
40
+ points_xyz_mm = np.asarray(points) # shape (N, 3), columns x/y/z, units mm
41
+ result = analyze_points(points_xyz_mm, grid_mm=0.30, short_cutoff_mm=0.6, long_cutoff_mm=8.0)
42
+
43
+ print(result.sa_um, result.sq_um, result.svr_um)
44
+ ```
45
+
46
+ Use `analyze_file()` as a convenience adapter for supported files:
47
+
48
+ ```python
49
+ from svr_roughness import RoughnessConfig, analyze_file
50
+
51
+ config = RoughnessConfig(grid_mm=0.30, short_cutoff_mm=0.6, long_cutoff_mm=8.0)
52
+ result = analyze_file("scan.ply", config=config)
53
+ ```
54
+
55
+ Supported file loaders (all are converted to an `Nx3` NumPy array):
56
+
57
+ - ASCII and binary little-endian `.ply` point clouds
58
+ - ASCII and binary `.pcd` point clouds
59
+ - ASCII and binary `.stl` mesh vertices
60
+ - `.obj` vertex meshes
61
+ - comma-, tab-, or whitespace-delimited `.csv`, `.tsv`, `.xyz`, and `.txt`
62
+ - `.npy` and `.npz` NumPy arrays
63
+
64
+ STL files are converted to their unique mesh vertices before analysis. For production mesh metrology, prefer scanner point clouds or add controlled surface sampling before calling `analyze_points()`.
65
+
66
+ ## Result Output
67
+
68
+ ```python
69
+ result.save_grid_npz("output/roughness/latest_grid.npz")
70
+ result.save_metrics_json("output/roughness/latest_metrics.json")
71
+ ```
72
+
73
+ `save_metrics_json()` writes:
74
+
75
+ - `sa_um`
76
+ - `sq_um`
77
+ - `svr_um`
78
+ - point counts, grid dimensions, grid coverage, and filter cutoffs
79
+
80
+ `save_grid_npz()` writes:
81
+
82
+ - `grid_raw`
83
+ - `grid_filled`
84
+ - `grid_filtered`
85
+ - `valid_raw`
86
+ - `valid_filled`
87
+ - `grid_origin`
88
+ - plane basis arrays
89
+
90
+ ## Command line
91
+
92
+ The package also includes a no-code command for scanner integrations:
93
+
94
+ ```bash
95
+ svr-roughness scan.ply --grid-mm 0.30 --metrics-out metrics.json --grid-out grid.npz
96
+ ```
97
+
98
+ Coordinates are assumed to be millimeters, and metrics are reported in
99
+ micrometers. Unit conversion should happen before calling the library.
@@ -0,0 +1,38 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "svr-roughness"
7
+ version = "0.3.0"
8
+ description = "Surface roughness metrics from scanner point clouds"
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = { file = "LICENSE" }
12
+ authors = [
13
+ { name = "Sullivan Hart" },
14
+ { name = "HAM Lab, Iowa State University" }
15
+ ]
16
+ dependencies = [
17
+ "numpy>=1.24",
18
+ "opencv-python-headless>=4.8",
19
+ "scipy>=1.10"
20
+ ]
21
+ keywords = ["roughness", "point-cloud", "ply", "surface-metrology"]
22
+ classifiers = [
23
+ "Development Status :: 4 - Beta",
24
+ "Intended Audience :: Science/Research",
25
+ "Programming Language :: Python :: 3",
26
+ "Programming Language :: Python :: 3 :: Only",
27
+ "Topic :: Scientific/Engineering"
28
+ ]
29
+
30
+ [project.scripts]
31
+ svr-roughness = "svr_roughness.__main__:main"
32
+
33
+
34
+ [tool.setuptools.packages.find]
35
+ where = ["src"]
36
+
37
+ [tool.setuptools.package-data]
38
+ svr_roughness = ["py.typed"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,35 @@
1
+ """Surface roughness analysis for scanner point clouds."""
2
+
3
+ from .analyze import (
4
+ analyze_file,
5
+ analyze_ply,
6
+ analyze_points,
7
+ compute_roughness,
8
+ compute_roughness_from_ply,
9
+ )
10
+ from .config import RoughnessConfig
11
+ from .io import load_ascii_ply, load_delimited, load_obj, load_pcd, load_ply, load_points, load_stl_vertices
12
+ from .result import PlaneFit, RoughnessGrid, RoughnessResult, format_report
13
+ from ._algorithm import svr_map, svr_surface
14
+
15
+ __all__ = [
16
+ "PlaneFit",
17
+ "RoughnessConfig",
18
+ "RoughnessGrid",
19
+ "RoughnessResult",
20
+ "analyze_file",
21
+ "analyze_ply",
22
+ "analyze_points",
23
+ "compute_roughness",
24
+ "compute_roughness_from_ply",
25
+ "format_report",
26
+ "load_ascii_ply",
27
+ "load_delimited",
28
+ "load_obj",
29
+ "load_pcd",
30
+ "load_ply",
31
+ "load_points",
32
+ "load_stl_vertices",
33
+ "svr_map",
34
+ "svr_surface",
35
+ ]
@@ -0,0 +1,37 @@
1
+ from __future__ import annotations
2
+
3
+ import argparse
4
+ from pathlib import Path
5
+
6
+ from .analyze import analyze_file
7
+ from .config import RoughnessConfig
8
+ from .result import format_report
9
+
10
+
11
+ def main() -> None:
12
+ parser = argparse.ArgumentParser(description="Calculate surface roughness from a point-cloud file.")
13
+ parser.add_argument("input", type=Path, help="Input PLY, PCD, STL, OBJ, CSV, XYZ, TXT, TSV, NPY, or NPZ file")
14
+ parser.add_argument("--grid-mm", type=float, default=0.30)
15
+ parser.add_argument("--short-cutoff-mm", type=float, default=0.0)
16
+ parser.add_argument("--long-cutoff-mm", type=float, default=0.0)
17
+ parser.add_argument("--metrics-out", type=Path)
18
+ parser.add_argument("--grid-out", type=Path)
19
+ args = parser.parse_args()
20
+
21
+ result = analyze_file(
22
+ args.input,
23
+ RoughnessConfig(
24
+ grid_mm=args.grid_mm,
25
+ short_cutoff_mm=args.short_cutoff_mm,
26
+ long_cutoff_mm=args.long_cutoff_mm,
27
+ ),
28
+ )
29
+ print(format_report(result))
30
+ if args.metrics_out:
31
+ result.save_metrics_json(args.metrics_out)
32
+ if args.grid_out:
33
+ result.save_grid_npz(args.grid_out)
34
+
35
+
36
+ if __name__ == "__main__":
37
+ main()