Add read txt
This commit is contained in:
parent
a75d7088c4
commit
f62dcc9552
75
idefix/io.py
75
idefix/io.py
@ -26,7 +26,7 @@ def load_las(fname):
|
|||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
fname : string, Path
|
fname : str, Path
|
||||||
Path to the LAS file to load.
|
Path to the LAS file to load.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
@ -43,7 +43,12 @@ def load_las(fname):
|
|||||||
raise IOError(msg)
|
raise IOError(msg)
|
||||||
|
|
||||||
log.info('Loading LAS file \'{}\'...'.format(fname))
|
log.info('Loading LAS file \'{}\'...'.format(fname))
|
||||||
infile = laspy.file.File(fname)
|
try:
|
||||||
|
infile = laspy.file.File(fname)
|
||||||
|
except Exception as e:
|
||||||
|
msg = 'Laspy exception while opening file \'{}\': {}'.format(fname, e)
|
||||||
|
log.error(msg)
|
||||||
|
raise IOError(msg)
|
||||||
|
|
||||||
log.debug('Extract spatial data')
|
log.debug('Extract spatial data')
|
||||||
spatial = np.core.records.fromarrays([np.array((infile.x, infile.y, infile.z)).T],
|
spatial = np.core.records.fromarrays([np.array((infile.x, infile.y, infile.z)).T],
|
||||||
@ -72,3 +77,69 @@ def load_las(fname):
|
|||||||
return pcloud
|
return pcloud
|
||||||
|
|
||||||
|
|
||||||
|
def load_txt(fname, header, delimiter=' '):
|
||||||
|
'''Load a text file into idefix point cloud format.
|
||||||
|
|
||||||
|
Read point cloud from text files (CSV like).
|
||||||
|
|
||||||
|
Notes
|
||||||
|
-----
|
||||||
|
This reader needs the column header corresponding to the point cloud. There
|
||||||
|
has to be `x`, `y` and `z` columns in the header.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
fname : str, Path
|
||||||
|
Path to the text file to load.
|
||||||
|
header : array
|
||||||
|
Names of the columns contained in the text point cloud file.
|
||||||
|
delimiter : str, optional
|
||||||
|
String used to separate values. The default is whitespace.
|
||||||
|
|
||||||
|
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 TXT file \'{}\'...'.format(fname))
|
||||||
|
try:
|
||||||
|
log.debug('Loading the first lines of \'{}\'...'.format(fname))
|
||||||
|
insight_txt = np.loadtxt(fname, delimiter=delimiter, max_rows=2)
|
||||||
|
except Exception as e:
|
||||||
|
msg = 'Numpy exception while opening file \'{}\': {}'.format(fname, e)
|
||||||
|
log.error(msg)
|
||||||
|
raise IOError(msg)
|
||||||
|
|
||||||
|
# Compare header length and column count
|
||||||
|
if insight_txt.shape[-1] != len(header):
|
||||||
|
msg = 'Mismatch between header and file columns, count {} and count {}'.format(insight_txt.shape[-1], len(header))
|
||||||
|
log.error(msg)
|
||||||
|
raise IOError(msg)
|
||||||
|
|
||||||
|
dtype = [(x, np.float) for x in header]
|
||||||
|
raw_txt = np.loadtxt(fname, delimiter=delimiter, dtype=dtype)
|
||||||
|
|
||||||
|
log.debug('Extract spatial data')
|
||||||
|
spatial = np.core.records.fromarrays([np.array([raw_txt[x] for x in ('x', 'y', 'z')]).T],
|
||||||
|
dtype=[('spatial', np.float, 3)])
|
||||||
|
|
||||||
|
log.debug('Extract feature data')
|
||||||
|
header_c = header.copy()
|
||||||
|
for i in ('x', 'y', 'z'):
|
||||||
|
header_c.remove(i)
|
||||||
|
|
||||||
|
log.debug('Create feature recarray')
|
||||||
|
feature = raw_txt[header_c]
|
||||||
|
|
||||||
|
log.debug('Concatenate pcloud')
|
||||||
|
pcloud = rfn.append_fields(spatial, 'feature', feature, usemask=False, asrecarray=True)
|
||||||
|
|
||||||
|
return pcloud
|
||||||
|
|||||||
@ -16,6 +16,7 @@ from idefix import io
|
|||||||
# TODO: test different LAS version
|
# TODO: test different LAS version
|
||||||
# TODO: test LAS without field
|
# TODO: test LAS without field
|
||||||
('test.las', 58629, 3, ),
|
('test.las', 58629, 3, ),
|
||||||
|
#('test.laz', 58629, 3, ),
|
||||||
])
|
])
|
||||||
def test_load_las(datadir, fname, exp_point_count, exp_field_count):
|
def test_load_las(datadir, fname, exp_point_count, exp_field_count):
|
||||||
fname = datadir.join(fname)
|
fname = datadir.join(fname)
|
||||||
@ -28,7 +29,42 @@ def test_load_las(datadir, fname, exp_point_count, exp_field_count):
|
|||||||
try:
|
try:
|
||||||
result = io.load_las(fname)
|
result = io.load_las(fname)
|
||||||
except IOError:
|
except IOError:
|
||||||
pytest.fail('IO error')
|
pytest.fail('Opening legit file without exception')
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('fname, head, separator, exp_point_count, exp_field_count', [
|
||||||
|
# TODO: test different LAS version
|
||||||
|
# TODO: test LAS without field
|
||||||
|
('test.txt', ['x', 'y', 'z', 'class', 'intensity'], ',', 58629, 2, ),
|
||||||
|
('test_b.txt', ['x', 'y', 'z', 'class', 'intensity'], ' ', 58629, 2, ),
|
||||||
|
#('test.laz', 58629, 3, ),
|
||||||
|
])
|
||||||
|
def test_load_txt(datadir, fname, head, separator, exp_point_count, exp_field_count):
|
||||||
|
fname = datadir.join(fname)
|
||||||
|
|
||||||
|
# Raise "No such file"
|
||||||
|
with pytest.raises(IOError) as e_info:
|
||||||
|
io.load_txt('not_as_file.txt', head)
|
||||||
|
|
||||||
|
# Raise "Header and file mismatch"
|
||||||
|
with pytest.raises(IOError) as e_info:
|
||||||
|
io.load_txt(fname, header=['x'])
|
||||||
|
|
||||||
|
|
||||||
|
# Open file without exception
|
||||||
|
try:
|
||||||
|
result = io.load_txt(fname, head, separator)
|
||||||
|
except IOError:
|
||||||
|
pytest.fail('Opening legit file without exception')
|
||||||
|
|
||||||
assert result.size == exp_point_count, "Return correct point count"
|
assert result.size == exp_point_count, "Return correct point count"
|
||||||
|
|
||||||
|
|||||||
BIN
test/test_io/test.laz
Normal file
BIN
test/test_io/test.laz
Normal file
Binary file not shown.
58629
test/test_io/test.txt
Normal file
58629
test/test_io/test.txt
Normal file
File diff suppressed because it is too large
Load Diff
58629
test/test_io/test_b.txt
Normal file
58629
test/test_io/test_b.txt
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user