diff --git a/CHANGELOG.rst b/CHANGELOG.rst new file mode 100644 index 0000000..c0c5a35 --- /dev/null +++ b/CHANGELOG.rst @@ -0,0 +1,4 @@ +v1.0 +---- +- Generated setup files to install package. +- Bumped version to 1.0 as it's completely operational. diff --git a/README.rst b/README.rst index c898a22..f6887b6 100644 --- a/README.rst +++ b/README.rst @@ -5,7 +5,7 @@ pc2graph General Information ~~~~~~~~~~~~~~~~~~~ -This is a Python script that converts a numpy.ndarray containing a point cloud +This is a Python (2.7x) script that converts a numpy.ndarray containing a point cloud (x, y, z) into a NetworkX graph. The code also includes a function to extract shortest path information from a @@ -19,3 +19,27 @@ and Scientific Development (10.13039/501100003593) – Brazil (Process number 23 Any questions or suggestions, feel free to contact me using one of the following e-mails: matheus.boni.vicari@gmail.com or matheus.vicari.15@ucl.ac.uk + + +Installation +~~~~~~~~~~~~ + +To install this package use the command: + + .. code-block:: python + + python setup.py install + +or: + + .. code-block:: python + + pip install pc2graph + + + + + + + + diff --git a/data/batch/files.txt b/data/batch/files.txt index c283fb3..e361115 100644 --- a/data/batch/files.txt +++ b/data/batch/files.txt @@ -1 +1 @@ -../data/point_cloud_example.txt +../../data/point_cloud_example.txt diff --git a/data/test_gif/test.gif b/data/test_gif/test.gif new file mode 100644 index 0000000..7cd0e89 Binary files /dev/null and b/data/test_gif/test.gif differ diff --git a/doc/source.gif b/doc/path_creation_example.gif similarity index 100% rename from doc/source.gif rename to doc/path_creation_example.gif diff --git a/doc/dist.png b/doc/shortest_path_distance.png similarity index 100% rename from doc/dist.png rename to doc/shortest_path_distance.png diff --git a/pc2graph/__init__.py b/pc2graph/__init__.py new file mode 100644 index 0000000..555253c --- /dev/null +++ b/pc2graph/__init__.py @@ -0,0 +1,32 @@ +# Copyright (c) 2018-2019, Matheus Boni Vicari, pc2graph +# All rights reserved. +# +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +__author__ = "Matheus Boni Vicari" +__copyright__ = "Copyright 2018-2019" +__credits__ = ["Matheus Boni Vicari"] +__license__ = "GPL3" +__version__ = "1.0" +__maintainer__ = "Matheus Boni Vicari" +__email__ = "matheus.boni.vicari@gmail.com" +__status__ = "Development" + + +__all__ = ['downsampling', 'shortpath'] + +import downsampling +import shortpath + diff --git a/pc2graph/downsampling.py b/pc2graph/downsampling.py index b373590..b7d21d7 100644 --- a/pc2graph/downsampling.py +++ b/pc2graph/downsampling.py @@ -1,4 +1,4 @@ -# Copyright (c) 2017, Matheus Boni Vicari, TLSeparation Project +# Copyright (c) 2018-2019, Matheus Boni Vicari, pc2graph # All rights reserved. # # @@ -16,10 +16,10 @@ # along with this program. If not, see . __author__ = "Matheus Boni Vicari" -__copyright__ = "Copyright 2017" +__copyright__ = "Copyright 2018-2019" __credits__ = ["Matheus Boni Vicari"] __license__ = "GPL3" -__version__ = "0.1" +__version__ = "1.0" __maintainer__ = "Matheus Boni Vicari" __email__ = "matheus.boni.vicari@gmail.com" __status__ = "Development" diff --git a/pc2graph/example_plot_gif.py b/pc2graph/example_plot_gif.py deleted file mode 100644 index ae42dd5..0000000 --- a/pc2graph/example_plot_gif.py +++ /dev/null @@ -1,93 +0,0 @@ -# Copyright (c) 2017, Matheus Boni Vicari, TLSeparation Project -# All rights reserved. -# -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -__author__ = "Matheus Boni Vicari" -__copyright__ = "Copyright 2017" -__credits__ = ["Matheus Boni Vicari"] -__license__ = "GPL3" -__version__ = "0.1" -__maintainer__ = "Matheus Boni Vicari" -__email__ = "matheus.boni.vicari@gmail.com" -__status__ = "Development" - - -from downsampling import downsample_cloud -from shortpath import array_to_graph -import numpy as np -import glob -import os -import mayavi.mlab as mlab - - -if __name__ == '__main__': - - # Setting up where to save the data. - out_folder = '../data/test_gif/' - out_file = 'test' - layer_delay = 2 - - # Setting up parameters to generate the graph. - point_cloud = np.loadtxt('../data/point_cloud_example.txt') - downsample_dist = 0.05 - kpairs = 3 - knn = 100 - nbr_dist_threshold = downsample_dist * 1.5 - nbr_dist_threshold_step = 0.03 - downsample_cloud = downsample_cloud(point_cloud, downsample_dist) - - # Obtaining base id (lowest point in the cloud). - base_id = np.argmin(downsample_cloud[:, 2]) - - # Generating graph with option to return the step_register as True. - G, step_register = array_to_graph(downsample_cloud, base_id, kpairs, - knn, nbr_dist_threshold, - nbr_dist_threshold_step, - return_step=True) - - - # Starts the iterative plotting. This will require the Mayavi package. - iteration = 0 - mlab.figure(bgcolor=(1, 1, 1), fgcolor=(0, 0, 0)) - mlab.points3d(downsample_cloud[:, 0], downsample_cloud[:, 1], - downsample_cloud[:, 2], color=(0.3, 0.3, 0.3), mode='point') - for s in np.unique(step_register): - mask = step_register == s - mlab.points3d(downsample_cloud[mask, 0], downsample_cloud[mask, 1], - downsample_cloud[mask, 2], color=(1, 0, 0), mode='point') - mlab.savefig(out_folder + '%s.png' % iteration) - iteration += 1 - mlab.close() - - # Generating the list of step images to join in a gif later. - file_list = glob.glob('%s*.png' % out_folder) - file_list = [os.path.basename(f) for f in file_list] - list.sort(file_list, key=lambda x: int(os.path.basename(x).split('.png')[0])) - with open('%simage_list.txt' % out_folder, 'w') as file: - for item in file_list: - file.write("%s\n" % item) - - # Changing directory and using ImageMagik to join all images into a gif. - # Then, delets all unnecessary files.In the end, returns to initial - # directory. - cwd = os.getcwd() - os.chdir(out_folder) - os.system('convert -loop 0 -delay %s @image_list.txt %s.gif' % (layer_delay, out_file)) - os.remove('image_list.txt') - for f in file_list: - os.remove(f) - os.chdir(cwd) - \ No newline at end of file diff --git a/pc2graph/example_batch.py b/pc2graph/examples/example_batch.py similarity index 93% rename from pc2graph/example_batch.py rename to pc2graph/examples/example_batch.py index 0c7f10a..1a75dad 100644 --- a/pc2graph/example_batch.py +++ b/pc2graph/examples/example_batch.py @@ -1,4 +1,4 @@ -# Copyright (c) 2017, Matheus Boni Vicari, TLSeparation Project +# Copyright (c) 2018-2019, Matheus Boni Vicari, pc2graph # All rights reserved. # # @@ -16,10 +16,10 @@ # along with this program. If not, see . __author__ = "Matheus Boni Vicari" -__copyright__ = "Copyright 2017" +__copyright__ = "Copyright 2018-2019" __credits__ = ["Matheus Boni Vicari"] __license__ = "GPL3" -__version__ = "0.1" +__version__ = "1.0" __maintainer__ = "Matheus Boni Vicari" __email__ = "matheus.boni.vicari@gmail.com" __status__ = "Development" @@ -32,9 +32,9 @@ if __name__ == '__main__': - # Declaring list of files to process and output folder. - filelist = '../data/batch/files.txt' - out_folder = '../data/batch/' + # Declaring list of files to process and output directory. + filelist = '../../data/batch/files.txt' + out_dir = '../../data/batch/' # Declaring downsample size of 10 cm. downsample_size = 0.1 @@ -112,4 +112,4 @@ # Stacking all variables and exporting. out_cloud = np.hstack((upscale_cloud, upscale_distance.reshape(-1, 1), diff.reshape(-1, 1))) - np.savetxt('%s%s.txt' % (out_folder, fname), out_cloud, fmt='%1.3f') \ No newline at end of file + np.savetxt('%s%s.txt' % (out_dir, fname), out_cloud, fmt='%1.3f') diff --git a/pc2graph/examples/example_plot_gif.py b/pc2graph/examples/example_plot_gif.py new file mode 100644 index 0000000..daaa3a4 --- /dev/null +++ b/pc2graph/examples/example_plot_gif.py @@ -0,0 +1,99 @@ +# Copyright (c) 2018-2019, Matheus Boni Vicari, pc2graph +# All rights reserved. +# +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +__author__ = "Matheus Boni Vicari" +__copyright__ = "Copyright 2018-2019" +__credits__ = ["Matheus Boni Vicari"] +__license__ = "GPL3" +__version__ = "1.0" +__maintainer__ = "Matheus Boni Vicari" +__email__ = "matheus.boni.vicari@gmail.com" +__status__ = "Development" + +from downsampling import downsample_cloud +from shortpath import array_to_graph +import numpy as np +import glob +import os + + + + +if __name__ == '__main__': + + try: + import mayavi.mlab as mlab + + # Setting up where to save the data. + out_dir = '../../data/test_gif/' + out_file = 'test' + layer_delay = 2 + + # Setting up parameters to generate the graph. + point_cloud = np.loadtxt('../../data/point_cloud_example.txt') + downsample_dist = 0.05 + kpairs = 3 + knn = 100 + nbr_dist_threshold = downsample_dist * 1.5 + nbr_dist_threshold_step = 0.03 + downsample_cloud = downsample_cloud(point_cloud, downsample_dist) + + # Obtaining base id (lowest point in the cloud). + base_id = np.argmin(downsample_cloud[:, 2]) + + # Generating graph with option to return the step_register as True. + G, step_register = array_to_graph(downsample_cloud, base_id, kpairs, + knn, nbr_dist_threshold, + nbr_dist_threshold_step, + return_step=True) + + + # Starts the iterative plotting. This will require the Mayavi package. + iteration = 0 + mlab.figure(bgcolor=(1, 1, 1), fgcolor=(0, 0, 0)) + mlab.points3d(downsample_cloud[:, 0], downsample_cloud[:, 1], + downsample_cloud[:, 2], color=(0.3, 0.3, 0.3), mode='point') + for s in np.unique(step_register): + mask = step_register == s + mlab.points3d(downsample_cloud[mask, 0], downsample_cloud[mask, 1], + downsample_cloud[mask, 2], color=(1, 0, 0), mode='point') + mlab.savefig(out_dir + '%s.png' % iteration) + iteration += 1 + mlab.close() + + # Generating the list of step images to join in a gif later. + file_list = glob.glob('%s*.png' % out_dir) + file_list = [os.path.basename(f) for f in file_list] + list.sort(file_list, key=lambda x: int(os.path.basename(x).split('.png')[0])) + with open('%simage_list.txt' % out_dir, 'w') as file: + for item in file_list: + file.write("%s\n" % item) + + # Changing directory and using ImageMagik to join all images into a gif. + # Then, delets all unnecessary files.In the end, returns to initial + # directory. + cwd = os.getcwd() + os.chdir(out_dir) + os.system('convert -loop 0 -delay %s @image_list.txt %s.gif' % (layer_delay, out_file)) + os.remove('image_list.txt') + for f in file_list: + os.remove(f) + os.chdir(cwd) + + except: + print('Mayavi not installed, this example cannot run!') + \ No newline at end of file diff --git a/pc2graph/example_single.py b/pc2graph/examples/example_single.py similarity index 87% rename from pc2graph/example_single.py rename to pc2graph/examples/example_single.py index cb8d820..0adf33c 100644 --- a/pc2graph/example_single.py +++ b/pc2graph/examples/example_single.py @@ -1,4 +1,4 @@ -# Copyright (c) 2017, Matheus Boni Vicari, TLSeparation Project +# Copyright (c) 2018-2019, Matheus Boni Vicari, pc2graph # All rights reserved. # # @@ -16,10 +16,10 @@ # along with this program. If not, see . __author__ = "Matheus Boni Vicari" -__copyright__ = "Copyright 2017" +__copyright__ = "Copyright 2018-2019" __credits__ = ["Matheus Boni Vicari"] __license__ = "GPL3" -__version__ = "0.1" +__version__ = "1.0" __maintainer__ = "Matheus Boni Vicari" __email__ = "matheus.boni.vicari@gmail.com" __status__ = "Development" @@ -31,7 +31,7 @@ if __name__ == "__main__": # Loads point cloud into a numpy.ndarray (n_points x dimensions). - point_cloud = np.loadtxt('../data/point_cloud_example.txt') + point_cloud = np.loadtxt('../../data/point_cloud_example.txt') # Growth factor. Each point adds 3 new points to graph. kpairs = 3 @@ -64,4 +64,4 @@ # Preparing output point cloud. distance = np.asarray(distance).reshape(-1, 1) out_cloud = np.hstack((nodes, distance)) - np.savetxt('../data/output_point_cloud.txt', out_cloud, fmt='%1.3f') + np.savetxt('../../data/output_point_cloud.txt', out_cloud, fmt='%1.3f') diff --git a/pc2graph/shortpath.py b/pc2graph/shortpath.py index 6fa44d1..2474f2a 100644 --- a/pc2graph/shortpath.py +++ b/pc2graph/shortpath.py @@ -1,4 +1,4 @@ -# Copyright (c) 2017, Matheus Boni Vicari, TLSeparation Project +# Copyright (c) 2018-2019, Matheus Boni Vicari, pc2graph # All rights reserved. # # @@ -16,10 +16,10 @@ # along with this program. If not, see . __author__ = "Matheus Boni Vicari" -__copyright__ = "Copyright 2017" +__copyright__ = "Copyright 2018-2019" __credits__ = ["Matheus Boni Vicari"] __license__ = "GPL3" -__version__ = "0.1" +__version__ = "1.0" __maintainer__ = "Matheus Boni Vicari" __email__ = "matheus.boni.vicari@gmail.com" __status__ = "Development" diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..a787300 --- /dev/null +++ b/setup.py @@ -0,0 +1,57 @@ +# Copyright (c) 2017, Matheus Boni Vicari, pc2graph +# All rights reserved. +# +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + + +__author__ = "Matheus Boni Vicari" +__copyright__ = "Copyright 2018-2019, pc2graph" +__credits__ = ["Matheus Boni Vicari"] +__license__ = "GPL3" +__version__ = "1.0" +__maintainer__ = "Matheus Boni Vicari" +__email__ = "matheus.boni.vicari@gmail.com" +__status__ = "Development" + +from setuptools import setup, find_packages + + +def readme(): + with open('README.rst') as f: + return f.read() + +with open('requirements.txt') as f: + required = f.read().splitlines() + +setup( + name="pc2graph", + version="1.0", + author='Matheus Boni Vicari', + author_email='matheus.boni.vicari@gmail.com', + packages=find_packages(), + entry_points={ + }, + url='https://github.com/mattbv/pc2graph', + license='LICENSE.txt', + description='Generates a NetworkX graph from\ + 3D point clouds acquired using Terrestrial LiDAR\ + Scanners.', + long_description=readme(), + classifiers=['Programming Language :: Python', + 'Topic :: Scientific/Engineering'], + keywords='networkx graph shortest path TLS point cloud LiDAR', + install_requires=required, + # ... +)