Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor dendrogram #780

Merged
merged 6 commits into from
Nov 12, 2019
Merged

Refactor dendrogram #780

merged 6 commits into from
Nov 12, 2019

Conversation

asanin-epfl
Copy link
Contributor

Refactored dendrogram in order to add synapses to it later. Will be a separate PR.

Copy link
Collaborator

@mgeplf mgeplf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My (fast) first pass looks good, but I need to read it more carefully. Can you post an example of the output?

neurom/view/_dendrogram.py Outdated Show resolved Hide resolved

segments = neurom_section.points
segment_lengths = np.linalg.norm(
np.subtract(segments[:-1, COLS.XYZ], segments[1:, COLS.XYZ]), axis=1)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
np.subtract(segments[:-1, COLS.XYZ], segments[1:, COLS.XYZ]), axis=1)
np.diff(segments[:COLS.XYZ], axis=0)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wonder if we can use the segment_lengths statistic?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean to save it as a property? this.segments_lengths = segment_lengths? Currently I don't see any usage for it later.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean use the function that does this already neurom/fst/_neuritefunc.py, but called using get() instead of directly

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, ok. I will do the changes after all suggestions have been made.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately I couldn't reuse segments_lengths function because it is for neurites. I have sections. Please look neurom/fst/_neuritefunc.py#L204.

neurom/view/_dendrogram.py Outdated Show resolved Hide resolved
@asanin-epfl
Copy link
Contributor Author

Example outputs. You can see that dendrogram became wider. It's because I've added a horizontal padding. Probably I should remove it for backward compatibility. Also I put the leftmost section at (0, 0). This way no dendrogram is on negative X axis. This change I would insist to keep.

Before refactor:

denrogram_diam
denrogram_nodiam

After refactor:

refactored_denrogram_diam
refactored_denrogram_nodiam

@mgeplf
Copy link
Collaborator

mgeplf commented Nov 8, 2019

Cool, looks great.

Probably I should remove it for backward compatibility.
I think it's ok - we try and maintain backwards compat, but for diagrams it doesn't have to be exact, imo.

@asanin-epfl
Copy link
Contributor Author

Example output for the biological cell.

Before refactor:

denrogram_diam_bio
denrogram_nodiam_bio

After refactor:

refactored_denrogram_diam_bio
refactored_denrogram_nodiam_bio

neurom/view/_dendrogram.py Outdated Show resolved Hide resolved
if dendrogram_root is None:
dendrogram_root = self
dendrogram_root.processed_section_ids = []
if neurom_section.id in dendrogram_root.processed_section_ids:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please use an assert for these kind of checks.

Also, is this necessary? I'm not sure how a cycle would happen - without the check, the dendrogram_root param wouldn't be necessary, and I think the logic would look neater?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the previous version we had sys.setrecursionlimit(max_depth). I thought to replace this recursion limit with the cycles check. If the recursion limit didn't target cycles validation then I will remove my cycles check.

Copy link
Contributor Author

@asanin-epfl asanin-epfl Nov 11, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the only major issue left to discuss. I would be happy to remove the cycles check but it would be nice to have a guarantee that we can't receive a cycled Neurite tree. Otherwise we need this check. I don't know where else to put it because we need this check per dendrogram tree instance. So each dendrogram node needs an access to the dendrogram tree instance. dendrogram_root is this tree instance.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@wizmer Do we check that the loaded morphology does is not cycled? By the loaded morphology I mean neurom.load_neuron('morph.swc'). I don't see that we do it but I might overlooked it.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the structure of the file disallows cycles. For SWC, we don't support non-connected components, so I think that's where it wouldn't load properly. I can't remember for h5.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think the sys.setrecursionlimit(max_depth) was for validation, but probably because without it it would crash for neurites with too many descendents.

I just tried on SWC with the following file and NeuroM did not complain although it should have, scary:

    1 1  0  0 0 1. -1
    2 3  0  0 0 1.  1
    3 3  0  5 0 1.  2
    4 3 -5  5 0 0.  3
    5 3  6  5 0 0.  3
    6 2  0  0 0 1.  6  # <-- cyclic point
    7 2  0 -4 0 1.  6
    8 2  6 -4 0 0.  7
    9 2 -5 -4 0 0.  7

The mut_morphio branch already raises on this file so I don't know if it's worth an implementation.

if isinstance(neuron, Neurite):
return Dendrogram(neuron.root_node)
SomaSection = namedtuple('NeuromSection', ['id', 'type', 'children', 'points'])
soma_section = SomaSection(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there a way to do this with having a 'fake' soma section? I'm thinking that Dendrogram() could check the type, and then create the 'fake' data inline, instead of it being bundled into an object here, and basically decomposed in the __init__

neurom/view/_dendrogram.py Outdated Show resolved Hide resolved
neurom/view/_dendrogram.py Outdated Show resolved Hide resolved
neurom/view/view.py Show resolved Hide resolved
Copy link
Contributor

@wizmer wizmer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-run the notebook in tutorial/neurom_tutorial.ipynb so that it displays the new-style dendrogram.

)
if dendrogram_root is None:
dendrogram_root = self
dendrogram_root.processed_section_ids = []
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
dendrogram_root.processed_section_ids = []
self.processed_section_ids = []

to emphasize on the fact that the processed_section_ids you're setting is the one of the current object.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here I would keep dendrogram to emphasize that there is a tree head and self is this head now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dropped the cycles check because it is implemented in mut_morphio branch and the NeuroM core is a more appropriate place for this check.

neurom/view/dendrogram.py Outdated Show resolved Hide resolved
neurom/view/dendrogram.py Outdated Show resolved Hide resolved
if dendrogram_root is None:
dendrogram_root = self
dendrogram_root.processed_section_ids = []
if neurom_section.id in dendrogram_root.processed_section_ids:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think the sys.setrecursionlimit(max_depth) was for validation, but probably because without it it would crash for neurites with too many descendents.

I just tried on SWC with the following file and NeuroM did not complain although it should have, scary:

    1 1  0  0 0 1. -1
    2 3  0  0 0 1.  1
    3 3  0  5 0 1.  2
    4 3 -5  5 0 0.  3
    5 3  6  5 0 0.  3
    6 2  0  0 0 1.  6  # <-- cyclic point
    7 2  0 -4 0 1.  6
    8 2  6 -4 0 0.  7
    9 2 -5 -4 0 0.  7

The mut_morphio branch already raises on this file so I don't know if it's worth an implementation.

neurom/view/dendrogram.py Outdated Show resolved Hide resolved
@asanin-epfl
Copy link
Contributor Author

I removed the cycles check and fake SomaSection. @mgeplf and @wizmer please verify.

@asanin-epfl
Copy link
Contributor Author

Re-run the notebook in tutorial/neurom_tutorial.ipynb so that it displays the new-style dendrogram.

@wizmer I ran it and it worked fine. If you see a problem please say it directly.

@wizmer
Copy link
Contributor

wizmer commented Nov 12, 2019

It works, but the picture of the dendrogram cell #6 is the one from the old algo, so I just re-run this cell and update the notebook.

@asanin-epfl
Copy link
Contributor Author

It works, but the picture of the dendrogram cell #6 is the one from the old algo, so I just re-run this cell and update the notebook.

Thank you for the details. Fixed it. I reran the first two cells for imports + #6 cell.

@asanin-epfl asanin-epfl merged commit cb77caa into master Nov 12, 2019
@asanin-epfl asanin-epfl deleted the refactor-dendrogram branch November 12, 2019 16:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants