Load LAS file into pcloud format

This commit is contained in:
Florent Guiotte 2019-03-05 19:16:53 +01:00
parent 4431d231de
commit 78c0d12d92
7 changed files with 161 additions and 3 deletions

74
idefix/io.py Normal file
View File

@ -0,0 +1,74 @@
#!/usr/bin/env python
# file io.py
# author Florent Guiotte <florent.guiotte@uhb.fr>
# version 0.0
# date 04 mars 2019
"""Abstract
doc.
"""
import logging
from pathlib import Path
import numpy as np
from numpy.lib import recfunctions as rfn
import laspy
log = logging.getLogger(__name__)
def load_las(fname):
'''Load a LAS file into idefix point cloud format.
Notes
-----
The empty fields from LAS format will be automatically stripped. The fields
typing are automatically determined.
Parameters
----------
fname : string, Path
Path to the LAS file to load.
Returns
-------
pcloud : recarray
Point cloud respecting structure::
[(spatial), (feature, [f1, f2, ..., fn])]
'''
fname = Path(fname)
if not fname.is_file():
msg = 'No such file: \'{}\''.format(fname)
log.error(msg)
raise IOError(msg)
log.info('Loading LAS file \'{}\'...'.format(fname))
infile = laspy.file.File(fname)
log.debug('Extract spatial data')
spatial = np.core.records.fromarrays([np.array((infile.x, infile.y, infile.z)).T],
dtype=[('spatial', np.float, 3)])
log.debug('Extract feature data')
feature_data, feature_dtype = [], []
for spec in infile.reader.point_format:
if spec.name in 'XYZ':
continue
att = infile.reader.get_dimension(spec.name)
if (att == 0).all():
log.info('Drop empty \'{}\' feature'.format(spec.name))
else:
log.info('Load \'{}\' feature'.format(spec.name))
feature_data.append(att)
feature_dtype.append((spec.name, att.dtype))
log.debug('Create feature recarray')
feature = np.core.records.fromarrays(feature_data, dtype=feature_dtype)
del feature_data, feature_dtype
log.debug('Concatenate pcloud')
pcloud = rfn.append_fields(spatial, 'feature', feature, usemask=False, asrecarray=True)
return pcloud

35
test/conftest.py Normal file
View File

@ -0,0 +1,35 @@
#!/usr/bin/env python
# file conftest.py
# author Florent Guiotte <florent.guiotte@uhb.fr>
# version 0.0
# date 04 mars 2019
"""Configuration script for PyTest.
Define in this script:
- Fixtures shared among tests
- Helpers functions for tests
- External plugins
- Hooks
"""
from distutils import dir_util
from pytest import fixture
import os
@fixture
def datadir(tmpdir, request):
'''
Fixture responsible for searching a folder with the same name of test
module and, if available, moving all contents to a temporary directory so
tests can use them freely.
from: https://stackoverflow.com/a/29631801
'''
filename = request.module.__file__
test_dir, _ = os.path.splitext(filename)
if os.path.isdir(test_dir):
dir_util.copy_tree(test_dir, str(tmpdir))
return tmpdir

41
test/test_io.py Normal file
View File

@ -0,0 +1,41 @@
#!/usr/bin/env python
# file test_io.py
# author Florent Guiotte <florent.guiotte@uhb.fr>
# version 0.0
# date 04 mars 2019
"""Idefix IO tests set.
doc.
"""
import pytest
import numpy as np
from idefix import io
@pytest.mark.parametrize('fname, exp_point_count, exp_field_count', [
# TODO: test different LAS version
# TODO: test LAS without field
('test.las', 58629, 3, ),
])
def test_load_las(datadir, fname, exp_point_count, exp_field_count):
fname = datadir.join(fname)
# Raise "No such file"
with pytest.raises(IOError) as e_info:
io.load_las('not_as_file.las')
# Open file without exception
try:
result = io.load_las(fname)
except IOError:
pytest.fail('IO error')
assert result.size == exp_point_count, "Return correct point count"
assert result['spatial'].shape[-1] == 3, "Return ndarray with spatial field"
assert (result['spatial'] == result.spatial).all(), "Quick access with records array"
assert len(result['feature'].dtype) == exp_field_count, "Return ndarray with attribute fields"
assert result.spatial.dtype == np.float, "Dtype of spatial is np.float"

BIN
test/test_io/test.las Normal file

Binary file not shown.

BIN
test/test_io/test.ply Normal file

Binary file not shown.

View File

@ -11,9 +11,12 @@ import numpy as np
import pytest
from idefix import utils
def test_first():
assert utils.first(1) == -1
assert utils.first(-4) == 4
@pytest.mark.parametrize("first_input,first_expected", [
(1, -1),
(-4, 4),
])
def test_first(first_input, first_expected):
assert utils.first(first_input) == first_expected
@pytest.fixture
def fix_data():
@ -23,3 +26,7 @@ def fix_data():
def test_bbox(fix_data):
res = np.array([fix_data.min(axis=0), fix_data.max(axis=0)])
assert (utils.bbox(fix_data) == res).all()
def test_read(datadir):
with open(datadir.join('first.txt')) as f:
assert f.read() == 'hullo\n'

View File

@ -0,0 +1 @@
hullo