Skip to content

Commit

Permalink
Add check for `nodes_0_based'
Browse files Browse the repository at this point in the history
If not present, the NML is an older 1-based annotation, and each x, y, z
coordinate must be decremented by 1.
  • Loading branch information
Eroica committed Apr 16, 2019
1 parent ef20ed5 commit 51e4cb4
Show file tree
Hide file tree
Showing 4 changed files with 16 additions and 10 deletions.
9 changes: 5 additions & 4 deletions treeconvert/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,13 @@

input_file = Path(args.input_file)
with input_file.open() as f:
content = f.read()

nml = nml_to_dict(content, args.from_format == FileFormats.PYKNOSSOS_NML)
nml = nml_to_dict(f.read(), args.from_format == FileFormats.PYKNOSSOS_NML)

for i, thing in enumerate(nml['things']):
swc = nml_to_swc(nml['things'][i])
# <node_0_based /> is an empty tag whose existence determines
# whether the coordinates are 0-based. If the tag exists, its value
# in <parameters> will be '', otherwise its value is `False'.
swc = nml_to_swc(nml['things'][i], nml['parameters']['nodes_0_based'] == '')

if len(nml['things']) == 1:
output_file = f'{input_file.stem}.swc'
Expand Down
6 changes: 3 additions & 3 deletions treeconvert/conversion.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ def nml_to_dict(xml_str: str, is_pyknossos=False) -> dict:
raise ParseError(str(error))


def nml_to_swc(nml: dict) -> SwcData:
def nml_to_swc(nml: dict, is_zero_based=False) -> SwcData:
nodes = {node['id']: node for node in nml['nodes']}
targets = defaultdict(list, {
target: [edge['source'] for edge in list(edges)]
Expand All @@ -92,7 +92,7 @@ def nml_to_swc(nml: dict) -> SwcData:
first_node = set(nodes).pop()

swc = SwcData()
swc.append(Edge.from_nml_entry(nodes[first_node], -1))
swc.append(Edge.from_nml_entry(nodes[first_node], -1, is_zero_based))

next_nodes = deque([first_node])
visited = set()
Expand All @@ -105,5 +105,5 @@ def nml_to_swc(nml: dict) -> SwcData:
if neighbor in visited:
continue
next_nodes.append(neighbor)
swc.append(Edge.from_nml_entry(nodes[neighbor], node))
swc.append(Edge.from_nml_entry(nodes[neighbor], node, is_zero_based))
return swc
1 change: 1 addition & 0 deletions treeconvert/nml.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
declxml.string('.', attribute='path'),
declxml.integer('.', attribute='overlay')
], required=False),
declxml.string('nodes_0_based', required=False, default=False)
], required=False)

node_processor = declxml.dictionary('node', [
Expand Down
10 changes: 7 additions & 3 deletions treeconvert/swc.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,17 @@ def __str__(self):
return ' '.join(str(x) for x in vars(self).values())

@classmethod
def from_nml_entry(cls, node: dict, parent_id: int):
def from_nml_entry(cls, node: dict, parent_id: int, is_zero_based=False):
# You can dismiss "'IntEnum' object is not callable" because
# this call gets propagated to `StructureIdentifier_missing_'
# defined above.
structure_identifier = StructureIdentifier(node['comment'])
return Edge(node['id'], structure_identifier,
node['x'], node['y'], node['z'], node['radius'], parent_id)
if is_zero_based:
x, y, z = node['x'], node['y'], node['z']
else:
x, y, z = node['x'] - 1, node['y'] - 1, node['z'] - 1
return Edge(node['id'], structure_identifier, x, y, z, node['radius'],
parent_id)


class SwcData(collections.abc.MutableSequence):
Expand Down

0 comments on commit 51e4cb4

Please sign in to comment.