Skip to content

Commit

Permalink
Merge pull request #105 from eEcoLiDAR/bug-issue98-plyreadeof
Browse files Browse the repository at this point in the history
Bug issue98 plyreadeof
  • Loading branch information
cwmeijer committed Mar 28, 2018
2 parents f5d82cc + cc7bbc1 commit 292059a
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 44 deletions.
60 changes: 25 additions & 35 deletions laserchicken/read_ply.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,13 @@
import numpy as np
from dateutil import parser

def read(path, verbose=False):

def read(path):
"""
Read point cloud data from a ply file.
:param path: path to the ply file
:return: dictionary containing the point cloud data
"""
if not os.path.exists(path):
raise IOError('File not found: {}'.format(path))

Expand All @@ -16,28 +22,11 @@ def read(path, verbose=False):
if 'ply' not in first_line:
raise ValueError('Not a valid ply file: {}'.format(path))

index = read_header(ply)
result = {block['type']: read_block(block, ply) for block in index}
if verbose:
print('Header:')
print('-'*10)
for i, header_field in enumerate(index):
print(header_field)
print(index[i])
print
print('\nData:')
print('-'*10)
for data_field in result:
print(data_field)
print(result['%s' % data_field])

print('***************************')
print(result)

return result
index = _read_header(ply)
return {block['type']: _read_block(block, ply) for block in index}


def read_header(ply):
def _read_header(ply):
index = []
comments = []
line = ply.readline()
Expand All @@ -59,31 +48,32 @@ def read_header(ply):

line = ply.readline()

if len(comments) > 0:
for i, comment_line in enumerate(comments):
comments[i] = ast.literal_eval(comment_line)
if comments[i]['time']:
comments[i]['time'] = parser.parse(comments[i]['time'])
index.append({'type': 'log', 'log': (_read_log(comments))})
return index

index.append({'type': 'log', 'log': comments})

return index
def _read_log(comments):
log = ast.literal_eval(''.join(comments))
for i, entry in enumerate(log):
if 'time' in entry:
entry['time'] = parser.parse(entry['time'])
return log


def read_block(block, ply_body):
def _read_block(block, ply_body):
if block['type'] == 'log':
return block['log']
else:
properties, property_names = get_properties(block)
properties, property_names = _get_properties(block)
block_type = block['type']
number_of_elements = block['number_of_elements']

read_elements(ply_body, properties, property_names, block_type, number_of_elements)
_read_elements(ply_body, properties, property_names, block_type, number_of_elements)

return properties


def cast(value, value_type):
def _cast(value, value_type):
if value_type == 'float':
dtype = np.float32
elif value_type == 'double':
Expand All @@ -95,19 +85,19 @@ def cast(value, value_type):
return dtype(value)


def read_elements(ply_body, properties, property_names, block_type, number_of_elements):
def _read_elements(ply_body, properties, property_names, block_type, number_of_elements):
for i in range(number_of_elements):
line = ply_body.readline()
values = line.split(' ')
if len(values) != len(property_names):
raise ValueError('Error reading line {} of {} list.'.format(i, block_type))
for p, property_name in enumerate(property_names):
property_type = properties[property_name]['type']
value = cast(values[p], property_type)
value = _cast(values[p], property_type)
properties[property_name]['data'][i] = value


def get_properties(block):
def _get_properties(block):
properties = {}
property_names = []
for prop in block['properties']:
Expand Down
19 changes: 19 additions & 0 deletions laserchicken/test_read_ply.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,25 @@ def test_correctPointCloud(self):
offset = point_cloud['offset']['data'][0]
np.testing.assert_allclose(offset, 12.1)

def test_allLogEntriesContainAllColumns(self):
log = read(self.test_file_path)['log']

for entry in log:
for key in ['time', 'module', 'parameters', 'version']:
self.assertIn(key, entry)

def test_correctModulesLogged(self):
log = read(self.test_file_path)['log']

modules = [entry['module'] for entry in log]
self.assertListEqual(['load', 'filter'], modules)

def test_correctTimesLogged(self):
log = read(self.test_file_path)['log']

self.assertListEqual([2018, 1, 18, 16, 1, 0, 3, 18, -1], list(log[0]['time'].timetuple()))
self.assertListEqual([2018, 1, 18, 16, 3, 0, 3, 18, -1], list(log[1]['time'].timetuple()))

def setUp(self):
os.mkdir(self._test_dir)
shutil.copyfile(os.path.join(self._test_data_source, self._test_file_name), self.test_file_path)
Expand Down
2 changes: 1 addition & 1 deletion laserchicken/test_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def get_point_cloud():
@staticmethod
def get_header():
# This complex_test_header cloud and the complex_test_point should be in sync. Some tests depend on it.
comment = {"time": dt.datetime(2018, 1, 18, 16, 1, 0), "module": "filter"}
comment = {"time": str(dt.datetime(2018, 1, 18, 16, 1, 0)), "module": "filter"}
header = """ply
format ascii 1.0
comment [
Expand Down
23 changes: 17 additions & 6 deletions laserchicken/write_ply.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,24 @@ def _get_ordered_properties(elem_name, prop_list):


def _write_comment(pc, ply):
# TODO: Use json for this
log = pc.get(keys.provenance, [])
if any(log):
ply.write("comment [" + '\n')
for msg in log:
ply.write("comment " + str(msg) + '\n')
ply.write("comment ]" + '\n')
if not any(log):
return

head = 'comment [\n'
tail = 'comment ]\n'
formatted_entries = ','.join(['comment ' + _stringify(entry) + '\n' for entry in log])
ply.write(head + formatted_entries + tail)


def _stringify(entry):
copy = {}
for key, value in entry.items():
if key == 'time':
copy['time'] = str(value)
else:
copy[key] = value
return str(copy)


def _write_header_elements(pc, ply, element_name, get_num_elements=None):
Expand Down
6 changes: 4 additions & 2 deletions testdata/example.ply
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
ply
format ascii 1.0
comment {'time': '2018-01-18 16:01', 'module': 'load', 'parameters': [], 'version': '0.9.2'}
comment {'time': '2018-01-18 16:01', 'module': 'filter', 'parameters': [('z', 'gt', '1.5')], 'version': '0.9.2'}
comment [
comment {'time': '2018-01-18 16:01', 'module': 'load', 'parameters': [], 'version': '0.9.2'},
comment {'time': '2018-01-18 16:03', 'module': 'filter', 'parameters': [('z', 'gt', '1.5')], 'version': '0.9.2'}
comment ]
element vertex 3
property float x
property float y
Expand Down

0 comments on commit 292059a

Please sign in to comment.