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

Feature Draft/ Use PCA to visualize cell 'upwards' #379

Merged
merged 31 commits into from
Jun 24, 2024

Conversation

lej0hn
Copy link
Contributor

@lej0hn lej0hn commented Jun 3, 2024

  • Finds the first PCA
  • Finds rotations needed to bring it along z axis
  • Rotates the cell using same angles
  • Translates cell to origin
  • Visualizes axes and PCA axis (before and after rotation)

@sanjayankur31 sanjayankur31 self-requested a review June 3, 2024 11:35
@sanjayankur31
Copy link
Member

OK for me to take a peek?

@lej0hn
Copy link
Contributor Author

lej0hn commented Jun 3, 2024

Yes, go ahead!

@lej0hn
Copy link
Contributor Author

lej0hn commented Jun 3, 2024

The code is in different functions right now and I added the extra parameters just to be able to temporarily visualize the pca axis as well

@sanjayankur31
Copy link
Member

Cool, on my list, will hopefully have a look today/tomorrow 👍

@sanjayankur31 sanjayankur31 self-assigned this Jun 3, 2024
Copy link
Member

@sanjayankur31 sanjayankur31 left a comment

Choose a reason for hiding this comment

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

Looking very good! I think we're almost there. I've dropped a few minor comments.

I think the camera isn't still pointing to origin, and we're still slightly off---see the rotation bit:

Screencast.from.2024-06-04.12-25-47.webm

I'm not sure why this is given that youre axes are shown about the origin. Maybe the bounding box calculation is off by a bit, so the camera is slightly askew too?

@@ -471,6 +486,50 @@ def plot_interactive_3D(

else:
cell = list(pop_id_vs_cell.values())[0]
#Get all segments' distal points
segment_points = []
Copy link
Member

Choose a reason for hiding this comment

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

I wonder if we can move this functionality into the plot_3D_cell_morphology function, and add an argument there to activate this transformation (instead of passing x_angle and y_angle pass: pcaify=True (with a better argument name, of course :))? I wonder because this is limited to the case where we're plotting a single cell, so it sort of fits better there. One should also be able to use this when using plot_3D_cell_morphology directly?

It'll also mean that the rotation + translation only happens once. At the moment, in the hay model, for example, it's happening multiple times---each time the mesh precision is dropped.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes this is the goal, this just allowed for visualization of the pca axes for debugging. However, besides not being able to visualize the pca axes after this change, I think there is another issue with the camera, as you noted above. So, the bounding box that's used to center the camera is taken in plot _interactive_3d , before the cell is translated to origin or rotated, so the bounding box and therefore the camera, is centered on the original cell's position. Since in this case we're translating the cell to the origin, maybe along with pcaify=True , we could set an extra argument in create_new_vispy_canvas that sets the view_center of the camera at the origin as well?

Copy link
Member

Choose a reason for hiding this comment

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

Yeh. So, if there's only one cell, we don't need to call create_new_vispy_canvas in plot_3D_interactive at all. I can't remember why I did it there. It doesn't seem necessary. We could conditionalise it there so that it's only called when there's more than one cell to be plotted, otherwise we let plot_3D_cell_morphology or plot_3D_schematic do it when it finds that current_canvas and current_view are None.

I just remembered that we also have the plot_3D_schematic function too, where it'll also be good to apply the PCA method so that the schematic is also upright. So perhaps we need to split out the PCA bits into a new method that takes a cell as argument and returns the "upright" cell? This could be called by both plot_3D_cell_morphology and plot_3D_schematic before they create the canvas and the meshes etc?

Yes, we could add another optional argument to create_new_vispy_canvas called view_center, which if provided will be used. If it isn't, we'll calculate the centre from view_min and view_max?

How does that sound?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah sound great. On it

@@ -769,6 +832,9 @@ def plot_3D_cell_morphology(
except Exception:
axon_segs = []

cell = rotate_cell(cell, x_angle, y_angle, 0, 'yxz', False, False)
cell = translate_cell_to_coords(cell, False, [0,0,0])
Copy link
Member

Choose a reason for hiding this comment

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

I assume the order of operations is important---would it be different if we:

  • first translated the cell to origin
  • did the pca
  • rotated the cell about the soma (origin)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

  • first translated the cell to origin
  • did the pca
    These two steps can be done in any order ,I believe, without any change because the PCA first translates the points so that their center is at the origin and then applies other computations.

But after that, the best way is in fact to translate and then rotate, now that I think of it, because the rotations and the angles are calculated based on the PCA axis, which starts at the origin. So to apply them succesfully to the cell, it should be close to the origin in order to have similar results.

@lej0hn
Copy link
Contributor Author

lej0hn commented Jun 5, 2024

I'm facing a problem with creating a new canvas in functions plot_3d_morphology and plot_3d_schematic . It seems that due to the recursion which occurs to reduce precision, the canvas created in those functions (which happens in case the canvas from plot_3d_interactive is none) , gets overwritten and can't be used

@lej0hn lej0hn marked this pull request as ready for review June 5, 2024 12:22
@sanjayankur31
Copy link
Member

Hrm---I think if one uses the plot_3D_morphology etc. functions directly instead of plot_intereactive_3D, we don't check for precision and reduce it etc. So we don't recurse 🤔

I'll try to take a look at your PR today, otherwise we can discuss it at the meeting tomorrow and see what to do.

@sanjayankur31 sanjayankur31 self-requested a review June 5, 2024 14:07
@lej0hn
Copy link
Contributor Author

lej0hn commented Jun 5, 2024

I didn't check for using them directly, so you are probably right at that. Perhaps it is a bit of a hustle, however, for the user, to call these functions directly instead of handling it through plot_interactive_3d?

@sanjayankur31
Copy link
Member

@sanjayankur31
Copy link
Member

  • give unique colours to axes for both themes

@lej0hn
Copy link
Contributor Author

lej0hn commented Jun 10, 2024

I am facing an issue with the rotation we discussed around the y axis. There was no problem getting the camera to look at the y axis and make the cell align to it, but I can not find a way to make the camera orbit around the y axis. The orbit function has only 2 arguments, elevation and azimuth which rotate it around the x and z axis respectively ( https://vispy.org/api/vispy.scene.cameras.turntable.html#vispy.scene.cameras.turntable.TurntableCamera.orbit). Also the XYZ shows the axis but doesn't use different colors. Any ideas?

@sanjayankur31
Copy link
Member

I am facing an issue with the rotation we discussed around the y axis. There was no problem getting the camera to look at the y axis and make the cell align to it, but I can not find a way to make the camera orbit around the y axis. The orbit function has only 2 arguments, elevation and azimuth which rotate it around the x and z axis respectively ( https://vispy.org/api/vispy.scene.cameras.turntable.html#vispy.scene.cameras.turntable.TurntableCamera.orbit).

Ah, yeh, I remember that. Let me look, maybe we can implement our own orbit function based on the original implementation?

Also the XYZ shows the axis but doesn't use different colors. Any ideas?

The XYZ from vispy, or our custom code? In the custom code, we set the colour to the "fg" for all lines, but we should be able to specify a colour per line there. You could define three colours for the XYZ axes for the light and dark themes in the VISPY_THEME dict and use them there?

See: https://vispy.org/api/vispy.scene.visuals.html#vispy.scene.visuals.Line for usage

PS: could you merge development into your branch again? I added coverage and made some linter fixes to make ruff happy.

@lej0hn
Copy link
Contributor Author

lej0hn commented Jun 10, 2024

I used XYZ from vispy and made it work, but the colors are all the same. The default is supposed to be different for each axis, and even when I specified colours it didn't work. So, I should drop it and change the custom way to have different colors?

I'll check as well if it's possible to create our own orbit function
However, having the camera point to the y axis does make the overall turntable camera a bit more rigid when a user wants to rotate it by hand as well for some reason. If you want to check that as well

@lej0hn
Copy link
Contributor Author

lej0hn commented Jun 11, 2024

Ready for review

Copy link
Member

@sanjayankur31 sanjayankur31 left a comment

Choose a reason for hiding this comment

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

Looks very good.

I was testing it with another pyramidal cell here:

https://github.com/sanjayankur31/Human-L2-3-Cortical-Microcircuit/blob/feat/neuroml/NeuroML2/HL23PYR.cell.nml

It's translated correctly, but the rotation doesn't look right. Do you want to try to see why? It's not quite "upright", but should be given the morphology? 🤔

Screencast.from.2024-06-11.16-45-08.webm

Here's another example from the Allen cell types database:

https://github.com/OpenSourceBrain/AllenInstituteNeuroML/blob/master/CellTypesDatabase/models/NeuroML2/Cell_329321704.cell.nml

Also not quite upright:

Screencast.from.2024-06-11.16-50-16.webm

Am I doing something wrong?

pyneuroml/plot/PlotMorphologyVispy.py Outdated Show resolved Hide resolved
pyneuroml/plot/PlotMorphologyVispy.py Outdated Show resolved Hide resolved
pyneuroml/plot/PlotMorphologyVispy.py Outdated Show resolved Hide resolved
pyneuroml/plot/PlotMorphologyVispy.py Outdated Show resolved Hide resolved
pyneuroml/plot/PlotMorphologyVispy.py Outdated Show resolved Hide resolved
pyneuroml/plot/PlotMorphologyVispy.py Outdated Show resolved Hide resolved

if isPCA:
cell = PCA_transformation(cell)
current_canvas = current_view = None
Copy link
Member

Choose a reason for hiding this comment

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

is this meant to be in the conditional? otherwise the canvas and view are always being cleared?

pyneuroml/plot/PlotMorphologyVispy.py Show resolved Hide resolved
"""
if title == "":
title = f"3D schematic of segment groups from {cell.id}"

if isPCA:
cell = PCA_transformation(cell)
Copy link
Member

Choose a reason for hiding this comment

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

do we need to clear the canvas here, and set the camera to origin etc?

@@ -745,6 +845,8 @@ def plot_3D_cell_morphology(
is used)

:type highlight_spec: dict
:param isPCA: bool that if True, transforms single Cell according to its PCA to make it look 'upwards'
:type isPCA: bool
Copy link
Member

Choose a reason for hiding this comment

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

probably worth adding the axes_pos argument here too, so that users can activate it when viewing single cells too (same for schematic figure)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

axes_pos argument doesn't exist in plot_interactive_3d either, should I add in every one of those?

Copy link
Member

Choose a reason for hiding this comment

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

Ah, yeh. We can think about whether we want to also expose this in the pynml-plotmorph command line tool later.

@sanjayankur31
Copy link
Member

One more thing---do check if the pre-commit hook is running for you. It should remove empty lines and trailing spaces etc.

Try running:

pre-commit install

in your virtual env, and then it should run on all changed files each time you commit.

@lej0hn
Copy link
Contributor Author

lej0hn commented Jun 11, 2024

Looks very good.

I was testing it with another pyramidal cell here:

https://github.com/sanjayankur31/Human-L2-3-Cortical-Microcircuit/blob/feat/neuroml/NeuroML2/HL23PYR.cell.nml

It's translated correctly, but the rotation doesn't look right. Do you want to try to see why? It's not quite "upright", but should be given the morphology? 🤔
Screencast.from.2024-06-11.16-45-08.webm

Here's another example from the Allen cell types database:

https://github.com/OpenSourceBrain/AllenInstituteNeuroML/blob/master/CellTypesDatabase/models/NeuroML2/Cell_329321704.cell.nml

Also not quite upright:
Screencast.from.2024-06-11.16-50-16.webm

Am I doing something wrong?

No, you were right, there was a missing '-' sign in the angles. But that reminds me, in the case of the first cell for example, do we wish to see it like this, or opposite?
Screenshot from 2024-06-11 19-58-30

@lej0hn
Copy link
Contributor Author

lej0hn commented Jun 11, 2024

One more thing---do check if the pre-commit hook is running for you. It should remove empty lines and trailing spaces etc.

Try running:

pre-commit install

in your virtual env, and then it should run on all changed files each time you commit.

I have already installed it

@sanjayankur31
Copy link
Member

No, you were right, there was a missing '-' sign in the angles. But that reminds me, in the case of the first cell for example, do we wish to see it like this, or opposite? Screenshot from 2024-06-11 19-58-30

This is the correct way---that long straight line is an artificial axon that the modellers have added there. The apical dendrites here are correctly going up.

I don't know how to generalise this mathematically though. We can't say "soma is always down", and we can't necessarily say "long dendrites always go up" because that may not be the case for all cells 🤔

Not sure how NeuroML-db have done it---I think they did it manually:

https://neuroml-db.org/gallery

@sanjayankur31
Copy link
Member

One more thing---do check if the pre-commit hook is running for you. It should remove empty lines and trailing spaces etc.
Try running:

pre-commit install

in your virtual env, and then it should run on all changed files each time you commit.

I have already installed it

Hrm, is it running when you commit? Check once, I thought I saw some trailing spaces that it should have removed.

@lej0hn
Copy link
Contributor Author

lej0hn commented Jun 11, 2024

No, you were right, there was a missing '-' sign in the angles. But that reminds me, in the case of the first cell for example, do we wish to see it like this, or opposite? Screenshot from 2024-06-11 19-58-30

This is the correct way---that long straight line is an artificial axon that the modellers have added there. The apical dendrites here are correctly going up.

I don't know how to generalise this mathematically though. We can't say "soma is always down", and we can't necessarily say "long dendrites always go up" because that may not be the case for all cells 🤔

Not sure how NeuroML-db have done it---I think they did it manually:

https://neuroml-db.org/gallery

Just by playing around with models I found that this condition works :
if the z angle of rotation < 0 then do z_angle += np,pi in order to rotate it 180 degrees. There probably are cases where it doesn't apply, but maybe it satisfies the majority of them

@sanjayankur31
Copy link
Member

Just by playing around with models I found that this condition works : if the z angle of rotation < 0 then do z_angle += np,pi in order to rotate it 180 degrees. There probably are cases where it doesn't apply, but maybe it satisfies the majority of them

Cool, let's go with that for now. Please do document it in the docstring I guess, just so users are aware that this is how we do it.

@sanjayankur31
Copy link
Member

@lej0hn : please do let me know when you want me to take another look at this one.

Copy link

Code Coverage

Package Line Rate Health
. 53%
analysis 37%
archive 72%
channelml 55%
lems 46%
neuron 31%
neuron.analysis 0%
plot 47%
povray 0%
sbml 91%
sedml 94%
swc 8%
tellurium 0%
tune 0%
utils 62%
xppaut 0%
Summary 37% (2784 / 7612)

@lej0hn
Copy link
Contributor Author

lej0hn commented Jun 12, 2024

Could you take another look?

@sanjayankur31
Copy link
Member

Sure, will try it today, but we've got a divisional meeting coming up so it may have to be tomorrow during our catch up :(

@sanjayankur31
Copy link
Member

@sanjayankur31 sanjayankur31 merged commit a2f6ba5 into NeuroML:development Jun 24, 2024
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: ✅ Done
Development

Successfully merging this pull request may close these issues.

2 participants