py4dgeo 1.0.0__cp314-cp314t-win_amd64.whl

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.
py4dgeo/util.py ADDED
@@ -0,0 +1,348 @@
1
+ import argparse
2
+ import collections
3
+ import logging
4
+ import numpy as np
5
+ import os
6
+ import platform
7
+ import psutil
8
+ import pooch
9
+ import requests
10
+ import sys
11
+ import warnings
12
+ import xdg
13
+
14
+ from importlib import metadata
15
+
16
+ import _py4dgeo
17
+
18
+ # The current data archive URL
19
+ TEST_DATA_ARCHIVE = "doi:10.5281/zenodo.18378272/"
20
+ PY4DGEO_REQUEST_HEADERS = {
21
+ "User-Agent": "py4dgeo (https://github.com/3dgeo-heidelberg/py4dgeo)"
22
+ }
23
+
24
+ # Read the version from package metadata
25
+ __version__ = metadata.version(__package__)
26
+
27
+
28
+ class Py4DGeoError(Exception):
29
+ def __init__(self, msg, loggername="py4dgeo"):
30
+ # Initialize the base class
31
+ super().__init__(msg)
32
+
33
+ # Also write the message to the error stream
34
+ logger = logging.getLogger(loggername)
35
+ logger.error(self)
36
+
37
+
38
+ def get_test_data_dir():
39
+ return pooch.os_cache("py4dgeo")
40
+
41
+
42
+ def download_test_data(path=None, filename=None):
43
+ """Download the test data"""
44
+
45
+ # Get the target path
46
+ if path is None:
47
+ path = get_test_data_dir()
48
+
49
+ # Create a pooch instance
50
+ p = pooch.create(path=path, base_url=TEST_DATA_ARCHIVE)
51
+ p.load_registry_from_doi()
52
+
53
+ # Decide which files to download, defaulting to all
54
+ files_to_download = (
55
+ [filename] if filename else ["usage_data.zip", "synthetic.zip", "pbm3c2.zip"]
56
+ )
57
+
58
+ # Download the files
59
+ for archive in files_to_download:
60
+ p.fetch(
61
+ archive,
62
+ downloader=pooch.DOIDownloader(
63
+ headers=PY4DGEO_REQUEST_HEADERS, timeout=(3, None)
64
+ ),
65
+ processor=pooch.Unzip(extract_dir="extracted"),
66
+ )
67
+
68
+ return path
69
+
70
+
71
+ def find_file(filename, fatal=True):
72
+ """Find a file of given name on the file system.
73
+
74
+ This function is intended to use in tests and demo applications
75
+ to locate data files without resorting to absolute paths. You may
76
+ use it for your code as well.
77
+
78
+ It looks in the following locations:
79
+
80
+ * If an absolute filename is given, it is used
81
+ * Check whether the given relative path exists with respect to the current working directory
82
+ * Check whether the given relative path exists with respect to the specified XDG data directory (e.g. through the environment variable :code:`XDG_DATA_DIRS`).
83
+ * Check whether the given relative path exists in downloaded test data.
84
+ * If still not found, attempt to download test data and search again.
85
+
86
+ :param filename:
87
+ The (relative) filename to search for
88
+ :type filename: str
89
+ :param fatal:
90
+ Whether not finding the file should be a fatal error
91
+ :type fatal: bool
92
+ :return: An absolute filename
93
+ """
94
+
95
+ def search_candidates(filename):
96
+ """Search for the file in candidate locations, return path if found."""
97
+ # If the path is absolute, check it directly
98
+ if os.path.isabs(filename):
99
+ if os.path.exists(filename):
100
+ return filename
101
+ return None
102
+
103
+ # Gather a list of candidate paths for relative path
104
+ candidates = []
105
+
106
+ # Use the current working directory
107
+ candidates.append(os.path.join(os.getcwd(), filename))
108
+
109
+ data_dir = get_test_data_dir()
110
+ candidates.append(os.path.join(data_dir, filename))
111
+ if os.path.isdir(data_dir):
112
+ for root, _, files in os.walk(data_dir):
113
+ if filename in files:
114
+ candidates.append(os.path.join(root, filename))
115
+
116
+ # Use the XDG data directories
117
+ if platform.system() in ["Linux", "Darwin"]:
118
+ for xdg_dir in xdg.xdg_data_dirs():
119
+ candidates.append(os.path.join(xdg_dir, filename))
120
+
121
+ # Iterate through the list to check for file existence
122
+ for candidate in candidates:
123
+ if os.path.exists(candidate):
124
+ return candidate
125
+
126
+ return None
127
+
128
+ # First attempt to find the file
129
+ result = search_candidates(filename)
130
+ if result:
131
+ return result
132
+
133
+ # File not found - try downloading test data
134
+ try:
135
+ download_test_data()
136
+ except Exception:
137
+ # Download failed, continue to error handling
138
+ pass
139
+
140
+ # Search again after download
141
+ result = search_candidates(filename)
142
+ if result:
143
+ return result
144
+
145
+ # Still not found
146
+ if fatal:
147
+ data_dir = get_test_data_dir()
148
+ candidates = [
149
+ os.path.join(os.getcwd(), filename),
150
+ os.path.join(data_dir, filename),
151
+ ]
152
+ if platform.system() in ["Linux", "Darwin"]:
153
+ for xdg_dir in xdg.xdg_data_dirs():
154
+ candidates.append(os.path.join(xdg_dir, filename))
155
+ raise FileNotFoundError(
156
+ f"Cannot locate file {filename}. Tried the following locations: {', '.join(candidates)}"
157
+ )
158
+
159
+ return filename
160
+
161
+
162
+ class MemoryPolicy(_py4dgeo.MemoryPolicy):
163
+ """A descriptor for py4dgeo's memory usage policy
164
+
165
+ This can be used to describe the memory usage policy that py4dgeo
166
+ should follow. The implementation of py4dgeo checks the currently
167
+ set policy whenever it would make a memory allocation of the same order
168
+ of magnitude as the input pointcloud or the set of corepoints.
169
+ To globally set the policy, use :func:`~py4dgeo.set_memory_policy`.
170
+
171
+ Currently the following policies are available:
172
+
173
+ * :code:`STRICT`: py4dgeo is not allowed to do additional memory allocations.
174
+ If such an allocation would be required, an error is thrown.
175
+ * :code:`MINIMAL`: py4dgeo is allowed to do additional memory allocations if
176
+ and only if they are necessary for a seemless operation of the library.
177
+ * :code:`COREPOINTS`: py4dgeo is allowed to do additional memory allocations
178
+ as part of performance trade-off considerations (e.g. precompute vs. recompute),
179
+ but only if the allocation is on the order of the number of corepoints.
180
+ This is the default behaviour of py4dgeo.
181
+ * :code:`RELAXED`: py4dgeo is allowed to do additional memory allocations as
182
+ part of performance trade-off considerations (e.g. precompute vs. recompute).
183
+ """
184
+
185
+ pass
186
+
187
+
188
+ # The global storage for the memory policy
189
+ _policy = MemoryPolicy.COREPOINTS
190
+
191
+
192
+ def set_memory_policy(policy: MemoryPolicy):
193
+ """Globally set py4dgeo's memory policy
194
+
195
+ For details about the memory policy, see :class:`~py4dgeo.MemoryPolicy`.
196
+ Use this once before performing any operations. Changing the memory policy
197
+ in the middle of the computation results in undefined behaviour.
198
+
199
+ :param policy: The policy value to globally set
200
+ :type policy: MemoryPolicy
201
+ """
202
+ global _policy
203
+ _policy = policy
204
+
205
+
206
+ def get_memory_policy():
207
+ """Access the globally set memory policy"""
208
+ return _policy
209
+
210
+
211
+ def memory_policy_is_minimum(policy: MemoryPolicy):
212
+ """Whether or not the globally set memory policy is at least the given one
213
+
214
+ :param policy: The policy value to compare against
215
+ :type policy: MemoryPolicy
216
+ :returns: Whether the globally set policy is at least the given one
217
+ :rtype: bool
218
+ """
219
+ return policy <= get_memory_policy()
220
+
221
+
222
+ def make_contiguous(arr: np.ndarray):
223
+ """Make a numpy array contiguous
224
+
225
+ This is a no-op if the array is already contiguous and makes
226
+ a copy if it is not. It checks py4dgeo's memory policy before copying.
227
+
228
+ :param arr: The numpy array
229
+ :type arr: np.ndarray
230
+ """
231
+
232
+ if arr.flags["C_CONTIGUOUS"]:
233
+ return arr
234
+
235
+ if not memory_policy_is_minimum(MemoryPolicy.MINIMAL):
236
+ raise Py4DGeoError(
237
+ "Using non-contiguous memory layouts requires at least the MINIMAL memory policy"
238
+ )
239
+
240
+ return np.copy(arr, order="C")
241
+
242
+
243
+ def _as_dtype(arr, dtype, policy_check):
244
+ if np.issubdtype(arr.dtype, dtype):
245
+ return arr
246
+
247
+ if policy_check and not memory_policy_is_minimum(MemoryPolicy.MINIMAL):
248
+ raise Py4DGeoError(
249
+ f"py4dgeo expected an input of type {np.dtype(dtype).name}, but got {np.dtype(arr.dtype).name}. Current memory policy forbids automatic cast."
250
+ )
251
+
252
+ return np.asarray(arr, dtype=dtype)
253
+
254
+
255
+ def as_double_precision(arr: np.ndarray, policy_check=True):
256
+ """Ensure that a numpy array is double precision
257
+
258
+ This is a no-op if the array is already double precision and makes a copy
259
+ if it is not. It checks py4dgeo's memory policy before copying.
260
+
261
+ :param arr: The numpy array
262
+ :type arr: np.ndarray
263
+ """
264
+ return _as_dtype(arr, np.float64, policy_check)
265
+
266
+
267
+ def set_num_threads(num_threads: int):
268
+ """Set the number of threads to use in py4dgeo
269
+
270
+ :param num_threads: The number of threads to use
271
+ "type num_threads: int
272
+ """
273
+
274
+ env_threads = os.environ.get("OMP_NUM_THREADS")
275
+ if env_threads:
276
+ try:
277
+ env_threads_int = int(env_threads)
278
+ if env_threads_int != num_threads:
279
+ warnings.warn(
280
+ f"OMP_NUM_THREADS environment variable is set to {env_threads_int}, but set_num_threads({num_threads}) was called. The environment variable may override this setting."
281
+ )
282
+ except ValueError:
283
+ raise Py4DGeoError(f"Invalid value for OMP_NUM_THREADS: '{env_threads}'")
284
+ try:
285
+ _py4dgeo.omp_set_num_threads(num_threads)
286
+ except AttributeError:
287
+ # The C++ library was built without OpenMP!
288
+ if num_threads != 1:
289
+ raise Py4DGeoError("py4dgeo was built without threading support!")
290
+
291
+
292
+ def get_num_threads():
293
+ """Get the number of threads currently used by py4dgeo
294
+
295
+ :return: The number of threads
296
+ :rtype: int
297
+ """
298
+
299
+ try:
300
+ return _py4dgeo.omp_get_max_threads()
301
+ except AttributeError:
302
+ # The C++ library was built without OpenMP!
303
+ return 1
304
+
305
+
306
+ def append_file_extension(filename, extension):
307
+ """Append a file extension if and only if the original filename has none"""
308
+
309
+ _, ext = os.path.splitext(filename)
310
+ if ext == "":
311
+ return f"{filename}.{extension}"
312
+ else:
313
+ return filename
314
+
315
+
316
+ def is_iterable(obj):
317
+ """Whether the object is an iterable (excluding a string)"""
318
+ return isinstance(obj, collections.abc.Iterable) and not isinstance(obj, str)
319
+
320
+
321
+ def initialize_openmp_defaults():
322
+ """Set OpenMP environment variables for optimal performance on Windows with llvm OpenMP"""
323
+
324
+ # Only apply when using Windows
325
+ if platform.system() != "Windows":
326
+ return
327
+
328
+ # Only set if the user has not already
329
+ if "OMP_NUM_THREADS" not in os.environ:
330
+ num_cores = psutil.cpu_count(logical=False)
331
+ os.environ["OMP_NUM_THREADS"] = str(num_cores)
332
+
333
+
334
+ def copy_test_data_entrypoint():
335
+ """A command line entry point to download test data"""
336
+
337
+ parser = argparse.ArgumentParser(description="Download py4dgeo test data")
338
+
339
+ parser.add_argument(
340
+ "path",
341
+ nargs="?",
342
+ default=os.getcwd(),
343
+ help="Target directory for test data (default: current working directory)",
344
+ )
345
+
346
+ args = parser.parse_args()
347
+
348
+ download_test_data(path=args.path)
@@ -0,0 +1,2 @@
1
+ Version: 1.12.0
2
+ Arguments: ['C:\\Users\\runneradmin\\AppData\\Local\\Temp\\cibw-run-qpltyhx6\\cp314t-win_amd64\\build\\venv\\Scripts\\delvewheel', 'repair', '-v', '-w', 'C:\\Users\\runneradmin\\AppData\\Local\\Temp\\cibw-run-qpltyhx6\\cp314t-win_amd64\\repaired_wheel', 'C:\\Users\\runneradmin\\AppData\\Local\\Temp\\cibw-run-qpltyhx6\\cp314t-win_amd64\\built_wheel\\py4dgeo-1.0.0-cp314-cp314t-win_amd64.whl']
@@ -0,0 +1,212 @@
1
+ Metadata-Version: 2.4
2
+ Name: py4dgeo
3
+ Version: 1.0.0
4
+ Summary: Library for change detection in 4D point cloud data
5
+ Keywords: point-cloud,change-detection,4D,geospatial,lidar
6
+ Maintainer-Email: Dominic Kempf <ssc@iwr.uni-heidelberg.de>
7
+ License-Expression: MIT
8
+ License-File: LICENSE.md
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Programming Language :: C++
11
+ Classifier: Operating System :: OS Independent
12
+ Classifier: Topic :: Scientific/Engineering :: GIS
13
+ Classifier: Intended Audience :: Science/Research
14
+ Project-URL: homepage, https://github.com/3dgeo-heidelberg/py4dgeo/
15
+ Project-URL: documentation, https://py4dgeo.readthedocs.io/
16
+ Project-URL: repository, https://github.com/3dgeo-heidelberg/py4dgeo/
17
+ Requires-Python: >=3.9
18
+ Requires-Dist: dateparser
19
+ Requires-Dist: laspy[lazrs]<3.0,>=2.0
20
+ Requires-Dist: matplotlib
21
+ Requires-Dist: numpy
22
+ Requires-Dist: pooch
23
+ Requires-Dist: requests
24
+ Requires-Dist: seaborn
25
+ Requires-Dist: scikit-learn
26
+ Requires-Dist: xdg
27
+ Requires-Dist: psutil
28
+ Description-Content-Type: text/markdown
29
+
30
+ # Welcome to py4dgeo
31
+
32
+ <img src="https://github.com/3dgeo-heidelberg/py4dgeo/blob/main/py4dgeo_logo.png?raw=true" alt="logo" style="width:500px;"/>
33
+
34
+
35
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
36
+ [![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/3dgeo-heidelberg/py4dgeo/ci.yml?branch=main)](https://github.com/3dgeo-heidelberg/py4dgeo/actions/workflows/ci.yml)
37
+ [![PyPI Release](https://img.shields.io/pypi/v/py4dgeo.svg)](https://pypi.org/project/py4dgeo)
38
+ [![Documentation Status](https://readthedocs.org/projects/py4dgeo/badge/)](https://py4dgeo.readthedocs.io/)
39
+ [![codecov](https://codecov.io/gh/3dgeo-heidelberg/py4dgeo/branch/main/graph/badge.svg)](https://codecov.io/gh/3dgeo-heidelberg/py4dgeo)
40
+
41
+ `py4dgeo` is a `C++` library with `Python` bindings for change analysis in multitemporal and 4D point clouds.
42
+
43
+ Topographic 3D/4D point clouds are omnipresent in geosciences, environmental, ecological and archaeological sciences, robotics, and many more fields and applications. Technology to capture such data using laser scanning and photogrammetric techniques have evolved into standard tools. Dense time series of topographic point clouds are becoming increasing available and require tools for automatic analysis. Moreover, methods considering the full 4D (3D space + time) data are being developed in research and need to be made available in an accessible way with flexible integration into existent workflows.
44
+
45
+ The **main objective** of `py4dgeo` is to bundle and provide different methods of 3D/4D change analysis in a dedicated, comprehensive Python library.
46
+ `py4dgeo` is designed as an international open source project that can be integrated into almost any 3D and GIS software in the geodata domain supporting Python, e.g. as plugins.
47
+
48
+ `py4dgeo` is under *ongoing active development*.
49
+ Below, you find a list of [provided methods](#methods-provided-by-py4dgeo).
50
+
51
+
52
+ ## ๐Ÿ”จ Methods provided by py4dgeo
53
+
54
+ * **M3C2 algorithm** ([Lague et al., 2013](#-literature)) for bitemporal point cloud distance computation.
55
+
56
+ * **M3C2-EP** (M3C2-EP; [Winiwarter et al., 2021](#-literature)) for statistical signal-noise separation in change analysis through error propagation.
57
+
58
+ * **4D objects-by-change** (4D-OBC; [Anders et al., 2021](#-literature)) for time series-based extraction of surface activities.
59
+
60
+ * **Correspondence-driven plane-based M3C2** ([Zahs et al., 2022](#-literature)) for lower uncertainty in 3D topographic change quantification *[under active development]*.
61
+
62
+ * **Point cloud registration using standard ICP** by calculating and applying affine transformations to point clouds using a standard ICP implementations.
63
+
64
+ * **Point cloud registration with automatic determination of stable areas** ([Yang et al., 2022](https://doi.org/10.1515/jag-2022-0031)) for multitemporal change detection.
65
+
66
+ ## ๐ŸŽฎ Examples
67
+
68
+ ### Demo notebooks using methods provided by py4dgeo
69
+ | | |
70
+ |--------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------|
71
+ | [![Example 1](img/m3c2_change_analysis_thumbnail.png)](https://nbviewer.org/github/3dgeo-heidelberg/py4dgeo/blob/24fe2b105c1f05bc30dab02b16960ba09c3b0f0b/demo/m3c2-change_analysis.ipynb) | [![Example 2](img/m3c2ep_change_analysis_thumbnail.png)](https://nbviewer.org/github/3dgeo-heidelberg/py4dgeo/blob/24fe2b105c1f05bc30dab02b16960ba09c3b0f0b/demo/m3c2ep_change_analysis.ipynb) |
72
+ | [![Example 3](img/4dobc_extraction_thumbnail.png)](https://nbviewer.org/github/3dgeo-heidelberg/py4dgeo/blob/24fe2b105c1f05bc30dab02b16960ba09c3b0f0b/demo/4dobc-change_analysis.ipynb) | [![Example 4](img/kmeans_clustering_thumbnail.png)](https://nbviewer.org/github/3dgeo-heidelberg/py4dgeo/blob/24fe2b105c1f05bc30dab02b16960ba09c3b0f0b/demo/kmeans_clustering_of_time_series.ipynb) |
73
+ | [![Example 5](img/pca_thumbnail.png)](https://nbviewer.org/github/3dgeo-heidelberg/py4dgeo/blob/24fe2b105c1f05bc30dab02b16960ba09c3b0f0b/demo/principal_component_analysis_of_time_series.ipynb) | [![Example 6](img/pbm3c2_thumbnail.png)](https://nbviewer.org/github/3dgeo-heidelberg/py4dgeo/blob/24fe2b105c1f05bc30dab02b16960ba09c3b0f0b/jupyter/pbm3c2.ipynb) |
74
+ | [![Example 7](img/standard_icp_thumbnail.png)](https://nbviewer.org/github/3dgeo-heidelberg/py4dgeo/blob/24fe2b105c1f05bc30dab02b16960ba09c3b0f0b/demo/registration_standard_ICP.ipynb) |
75
+
76
+
77
+ ## ๐Ÿ’ป Installation
78
+
79
+ ### Prerequisites
80
+
81
+ Using py4dgeo requires the following software installed:
82
+
83
+ * 64-bit Python `>= 3.9` (32-bit installations might cause trouble during installation of dependencies)
84
+
85
+ In order to build the package from source, the following tools are also needed.
86
+
87
+ * A C++17-compliant compiler
88
+ * Doxygen (optional, documentation building is skipped if missing)
89
+
90
+ ### Installing py4dgeo
91
+
92
+ The preferred way of installing `py4dgeo` is using `pip`.
93
+
94
+ ### Installing the release version using pip
95
+
96
+ `py4dgeo` can be installed using `pip` to obtain the [current release](https://pypi.org/project/py4dgeo/):
97
+
98
+ ```
99
+ python -m pip install py4dgeo
100
+ ```
101
+
102
+ ### Building from source using pip
103
+
104
+ The following sequence of commands is used to build `py4dgeo` from source:
105
+
106
+ ```
107
+ git clone --recursive https://github.com/3dgeo-heidelberg/py4dgeo.git
108
+ cd py4dgeo
109
+ python -m pip install -v --editable .
110
+ ```
111
+
112
+ The `--editable` flag allows you to change the Python sources of `py4dgeo` without
113
+ reinstalling the package. The `-v` flag enables verbose output which gives you
114
+ detailed information about the compilation process that you should include into
115
+ potential bug reports. To recompile the C++ source, please run `pip install` again.
116
+ In order to enable multi-threading on builds from source, your compiler toolchain
117
+ needs to support `OpenMP`.
118
+
119
+ If you want to contribute to the library's development you should also install
120
+ its additional Python dependencies for testing and documentation building:
121
+
122
+ ```
123
+ python -m pip install -r requirements-dev.txt
124
+ ```
125
+
126
+ ### ๐ŸชŸ Windows-specific Notes
127
+ py4dgeo works on Windows, but optimal performance is typically achieved on Linux.
128
+
129
+ If you want to experiment with performance on your system, you can tune OpenMP using environment variables such as ```OMP_NUM_THREADS```, ```OMP_PROC_BIND```, and ```OMP_PLACES```.
130
+
131
+ The best settings depend on your system, so there is no single recommended configuration.
132
+
133
+ ### Setting up py4dgeo using Docker
134
+
135
+ Additionally, `py4dgeo` provides a Docker image that allows to explore
136
+ the library using JupyterLab. The image can be locally built and run with
137
+ the following commands:
138
+
139
+ ```
140
+ docker build -t py4dgeo:latest .
141
+ docker run -t -p 8888:8888 py4dgeo:latest
142
+ ```
143
+
144
+ ## ๐Ÿ Documentation of software usage
145
+
146
+ As a starting point, please have a look to the [Jupyter Notebooks](jupyter) available in the repository and find the `py4dgeo` documentation [on readthedocs](https://py4dgeo.readthedocs.io/en/latest/intro.html).
147
+
148
+ ## ๐ŸŒ Published test data
149
+
150
+ <!-- TODO: integrate example notebooks for these use cases and data -->
151
+
152
+ If you are looking for data to test different methods, consider the following open data publications:
153
+
154
+ ### Hourly TLS point clouds of a sandy beach
155
+
156
+ <a href="https://doi.org/10.1038/s41597-022-01291-9" target="_blank"><img src="https://github.com/3dgeo-heidelberg/py4dgeo/blob/main/doc/img/data_vos_2022_kijkduin.png?raw=true" alt="" width="450" /></a>
157
+ <br>
158
+ Vos et al. (2022): [https://doi.org/10.1038/s41597-022-01291-9](https://doi.org/10.1038/s41597-022-01291-9).
159
+
160
+
161
+ ### By-weekly TLS point clouds of an Alpine rock glacier
162
+
163
+ <a href="https://doi.org/10.11588/data/TGSVUI" target="_blank"><img src="https://github.com/3dgeo-heidelberg/py4dgeo/blob/main/doc/img/data_zahs_2022_ahk_2019_tls.png?raw=true" alt="" width="450" /></a>
164
+ <br>
165
+ Zahs et al. (2022): [https://doi.org/10.11588/data/TGSVUI](https://doi.org/10.11588/data/TGSVUI).
166
+
167
+
168
+
169
+
170
+ ## ๐Ÿ“‘ Citation
171
+ Please cite py4dgeo when using it in your research and reference the appropriate release version.
172
+
173
+ <!-- TODO: All releases of py4dgeo are listed on Zenodo where you will find the citation information including DOI. -->
174
+
175
+ ```
176
+ article{py4dgeo,
177
+ author = {py4dgeo Development Core Team}
178
+ title = {py4dgeo: library for change analysis in 4D point clouds},
179
+ journal = {},
180
+ year = {2022},
181
+ number = {},
182
+ volume = {},
183
+ doi = {},
184
+ url = {https://github.com/3dgeo-heidelberg/py4dgeo},
185
+ }
186
+ ```
187
+
188
+ ## ๐Ÿ’Ÿ Funding / Acknowledgements
189
+ The initial software development was supported by the [**Scientific Software Center (SSC)**](https://ssc.iwr.uni-heidelberg.de/) in the Open Call 2021. The scientific software project is further supported by the research projects [**CharAct4D**](https://www.uni-heidelberg.de/charact4d) and [**AImon5.0**](https://www.uni-heidelberg.de/aimon).
190
+
191
+ ## ๐Ÿ”” Contact / Bugs / Feature Requests
192
+
193
+ You think you have found a bug or have specific request for a new feature? Please open a new issue in the online code repository on Github. Also for general questions please use the issue system.
194
+
195
+ Scientific requests can be directed to the [3DGeo Research Group Heidelberg](https://uni-heidelberg.de/3dgeo) and its respective members.
196
+
197
+ ## ๐Ÿ“„ How to contribute
198
+
199
+ We welcome contributions of new methods and usage demonstrations!
200
+ Please see the full guidelines in our [CONTRIBUTING.md](./CONTRIBUTING.md) for details on how to get started.
201
+
202
+ ## ๐Ÿ“œ License
203
+
204
+ See [LICENSE.md](LICENSE.md).
205
+
206
+
207
+ ## ๐Ÿ“š Related literature
208
+
209
+ * Anders, K., Winiwarter, L., Mara, H., Lindenbergh, R., Vos, S.E. & Hรถfle, B. (2021): Fully automatic spatiotemporal segmentation of 3D LiDAR time series for the extraction of natural surface changes. ISPRS Journal of Photogrammetry and Remote Sensing, 173, pp. 297-308. DOI: [10.1016/j.isprsjprs.2021.01.015](https://doi.org/10.1016/j.isprsjprs.2021.01.015).
210
+ * Lague, D., Brodu, N., & Leroux, J. (2013). Accurate 3D comparison of complex topography with terrestrial laser scanner: Application to the Rangitikei canyon (N-Z). ISPRS Journal of Photogrammetry and Remote Sensing, 82, pp. 10-26. DOI: [10.1016/j.isprsjprs.2013.04.009](https://doi.org/10.1016/j.isprsjprs.2013.04.009).
211
+ * Winiwarter, L., Anders, K., Hรถfle, B. (2021): M3C2-EP: Pushing the limits of 3D topographic point cloud change detection by error propagation. ISPRS Journal of Photogrammetry and Remote Sensing, 178, pp. 240โ€“258. DOI: [10.1016/j.isprsjprs.2021.06.011](https://doi.org/10.1016/j.isprsjprs.2021.06.011).
212
+ * Zahs, V., Winiwarter, L., Anders, K., Williams, J.G., Rutzinger, M. & Hรถfle, B. (2022): Correspondence-driven plane-based M3C2 for lower uncertainty in 3D topographic change quantification. ISPRS Journal of Photogrammetry and Remote Sensing, 183, pp. 541-559. DOI: [10.1016/j.isprsjprs.2021.11.018](https://doi.org/10.1016/j.isprsjprs.2021.11.018).
@@ -0,0 +1,22 @@
1
+ _py4dgeo.cp314t-win_amd64.pyd,sha256=iITsIHNbQxoN_LOpU4EVWHJxvJ_1bDIJvSRQIeYqp2Q,941568
2
+ py4dgeo/cloudcompare.py,sha256=Bit7dXXW0-EO8Aa55aLxspLdTtzlKgvjBfKxpOd-5Uk,1109
3
+ py4dgeo/epoch.py,sha256=y-DR19Lcyc9fpvw33i3WKy6U16DnIvrdcK05xpV3lFw,31587
4
+ py4dgeo/fallback.py,sha256=5fL4OK8MIA7IMdgneRAVpmk8BWY_6ppYXIdtSvBMyDo,5240
5
+ py4dgeo/logger.py,sha256=JOvLQpgQ2cNQ1SfvX9Ym9VqmBeom7OUz3V54e1EEP3Y,2470
6
+ py4dgeo/m3c2.py,sha256=v7JNkAKt-GVnomnfwAYiXPEztOoWAn7soBAAmzJWo1s,8449
7
+ py4dgeo/m3c2ep.py,sha256=Xjwbjc8fIFFiEX6ulcVtZCt8MXnH_o5G7_HUmhIDlDw,29242
8
+ py4dgeo/pbm3c2.py,sha256=-wmYetC9QPmHloYHIPCA5a8EwuVxIjONxvWrkiRKR3Q,26247
9
+ py4dgeo/py4dgeo_python.cpp,sha256=v_qlpI_wFCr0aNW72whMUYg3yVPQ6mks6v9ctr9gOg0,30607
10
+ py4dgeo/registration.py,sha256=aUdEas772buy31PVv-hA5Y3v-jGnnGeJB8Bo56eV4zg,17640
11
+ py4dgeo/segmentation.py,sha256=au3EWQHE9aCQb0grSIqKVZ9nTZniPXinVd-1ZZyswqo,55193
12
+ py4dgeo/UpdateableZipFile.py,sha256=aZVdQgAc_M-EWFDIEVukgrYQUtEb5fRoRMCVxZqpggc,2770
13
+ py4dgeo/util.py,sha256=8ly8Kxo-1710xH80_J_xWHwqxJrVTELILmR8IzAq_pY,11280
14
+ py4dgeo/__init__.py,sha256=E6XT0ZFCx_zUseRG4fu7ZmbzuguG6ykFniaEwBrYksw,1188
15
+ py4dgeo-1.0.0.data/platlib/libomp-a12116ba72d1d6820407cf30be23da04.dll,sha256=oSEWunLR1oIEB88wviPaBM551ruKcaXucXWcWh-qbxw,768000
16
+ py4dgeo-1.0.0.data/platlib/msvcp140-a4c2229bdc2a2a630acdc095b4d86008.dll,sha256=pMIim9wqKmMKzcCVtNhgCOXD47x3cxdDVPPaT1vrnN4,575056
17
+ py4dgeo-1.0.0.dist-info/DELVEWHEEL,sha256=7SCERVRsLj-5I4sioGmxyZGApnghT_E9DcEtwhMUdY8,410
18
+ py4dgeo-1.0.0.dist-info/entry_points.txt,sha256=S8EHFVRD4deFJ_N6ZWst9v_ukH5lGnZY-f8NHjYoIfk,83
19
+ py4dgeo-1.0.0.dist-info/METADATA,sha256=48UU9RFNnjwI-WlLV9Ng7gWO8mo9O9R-w-1rwhSmNNc,12320
20
+ py4dgeo-1.0.0.dist-info/RECORD,,
21
+ py4dgeo-1.0.0.dist-info/WHEEL,sha256=Wp6T4xrwRfJfFoFG_idqZkQJxYyHg92Cyiw2fzTnaZY,107
22
+ py4dgeo-1.0.0.dist-info/licenses/LICENSE.md,sha256=Rza103klOvpFdEr8ed20dZErIT6Tm998uX2ai29wDl8,1028
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: scikit-build-core 0.11.6
3
+ Root-Is-Purelib: false
4
+ Tag: cp314-cp314t-win_amd64
5
+
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ copy_py4dgeo_test_data = py4dgeo.util:copy_test_data_entrypoint
3
+
@@ -0,0 +1,5 @@
1
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
2
+
3
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
4
+
5
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.