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
[MRG] Add function to visualize connectivity weights #339
Conversation
Codecov Report
@@ Coverage Diff @@
## master #339 +/- ##
==========================================
+ Coverage 89.80% 91.06% +1.25%
==========================================
Files 13 13
Lines 2462 2540 +78
==========================================
+ Hits 2211 2313 +102
+ Misses 251 227 -24
Continue to review full report at Codecov.
|
hnn_core/viz.py
Outdated
net : Instance of Network object | ||
The Network object | ||
conn_idx : int | ||
Index of _Connectivity object to be visualized |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could we avoid talking about _Connectivity
since it's a private object? You can just say net.connectivity
. It's just a dict for most users
hnn_core/viz.py
Outdated
# Identical calculation used in Cell.par_connect_from_src() | ||
dx = src_pos[0] - target_pos[0] | ||
dy = src_pos[1] - target_pos[1] | ||
d = np.sqrt(dx**2 + dy**2) | ||
|
||
weight = nc_dict['A_weight'] * \ | ||
np.exp(-(d**2) / (nc_dict['lamtha']**2)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use a private function that is used by both?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe @rythorpe has more thoughts here. But it's a bit odd that the weight
computation is done at the cell level. I think it's more a network property. One potential direction is to have _parconnect_from_src
the following signature:
_parconnect_from_src(gid_presyn, postsyn, weight, delay, threshold)
that is pre-compute nc.weight
and nc.delay
in NetworkBuilder
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe @rythorpe has more thoughts here. But it's a bit odd that the
weight
computation is done at the cell level. I think it's more a network property. One potential direction is to have_parconnect_from_src
the following signature:_parconnect_from_src(gid_presyn, postsyn, weight, delay, threshold)that is pre-compute
nc.weight
andnc.delay
inNetworkBuilder
Did this get resolved yet? I'm just getting caught up and am unclear whether this issue is still a WIP. cc @jasmainak @ntolley
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this was a more general comment I made. Probably only tangentially related to the PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a good point though and I agree with you. We should be mindful of this moving forward!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missed this comment, this seems like a reasonable short term solution. But I think Ryan's point on separating cell/network functions requires some more thought.
hnn_core/viz.py
Outdated
# Identical calculation used in Cell.par_connect_from_src() | ||
dx = src_pos[0] - target_pos[0] | ||
dy = src_pos[1] - target_pos[1] | ||
d = np.sqrt(dx**2 + dy**2) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
try to avoid single letter variable names, hard to grep and replace
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, this is copied directly from cell.py
so it can be changed with a common function. Any preference for where that function would live? It could just be moved out of the class and remain in cell.py
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah I think that sounds reasonable to me
hnn_core/viz.py
Outdated
@@ -569,13 +569,87 @@ def plot_cell_morphology(cell, ax, show=True): | |||
return ax | |||
|
|||
|
|||
def plot_connectivity_weights(net, conn_idx, ax=None, show=True): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we still have the plot_connectivity_matrix
function? Shouldn't it be absorbed into this one?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I was realizing it is pretty superfluous while writing this. I'll add a flag that skips the weight computation and just plots black/white squares.
Then this can be renamed plot_connectivity_matrix
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you might want to ignore this comment now since I understand the situation better now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this function is still relevant after getting the cell-specific
plotting function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Honestly I am still leaning towards my previous comment in this thread. While the weight visualization here is obviously not as intuitive as cell-specific plotting, it seems weird not to include the functionality.
I'm planning to remove the "black and white" matrix function, and rename this function to plot_connectivity_matrix
. Then I can set a show_weights=False
flag for the default behavior.
I don't understand the grid structure @ntolley . Could you explain more? Should the x/y axis be physical distance of the cells so people can relate it to the |
Looks very promising by the way. Apologies for so many comments, it just reflects my excitement :) |
This not possible if you want to visualize all connection weights. The gids are arranged like so:
If you consider matrix entries at (1,1), (1,2), (1,3), (1,4) sure that direction involves increasing distances and you will see a gaussian decay. But at the next entry (1,5) the distance is equivalent to (1,2). What you're probably envisioning is defining a single gid as the reference, and then plotting the weights with respect to that. In that case the axes could correspond to physical distances, and the plot would appear as a bivariate gaussian distribution. |
@jasmainak what do you think about an additional plot_gid_connectivity(net, conn_idx, gid) ? |
indeed, I get it now. Yeah, I guess we'll need two different functions. Perhaps call it it's a bit odd to use indices (as opposed to the name of the cell population) for this, but let's make this work first and then we can think of nicer solutions |
Indeces are definitely awkward at the moment, but I was thinking this will be a lot cleaner after implementing that "pick" method we had discussed. Something like: con_indeces = net.pick_connectivity(src_type='L2_pyramidal', target_type='L2_basket', ...)
for con_idx in con_indeces:
plot_connectivity_matrix(net, con_idx) This way we don't have to overwhelm the viz function with a bunch of methods filtering for desired gids. |
indeed that seems like the way to go! |
Most recent commits move the gaussian connection calculations into separate functions. Will add the function to visualize weights with respect to a specific gid soon. |
Co-authored-by: Mainak Jas <jasmainak@users.noreply.github.com>
Fantastic, love it! Didn't realize our cells were not in a perfect grid ... |
diff looks clean as such. Any test to update? |
hnn_core/viz.py
Outdated
def plot_cell_connectivity(net, conn_idx, src_gid, ax=None, show=True): | ||
"""Plot synaptic weight of connections from a src_gid. | ||
|
||
Parameters | ||
---------- | ||
net : Instance of Network object | ||
The Network object | ||
conn_idx : int | ||
Index of connection to be visualized | ||
from `net.connectivity` | ||
src_gid : int | ||
Each cell in a network is uniquely identified by it's "global ID": GID. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm in doubt what this function does. Could you be more explicit about the first two arguments? I don't understand which int's to enter. Loving the output though!!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Definitely will add a better docstring. conn_idx
is awkward to work with at the moment as it is really just the index of the connection you'd like to visualize in net.connectivity[conn_idx]
. Unfortunately the alternative of passing the _Connectivity
object directly isn't much better.
I think this awkwardness will be resolved when I implement a utility function discussed with @jasmainak. It will look like
net.pick_connectivity(src_type='L5_pyramidal', receptor='ampa',...)
and return the indeces of all connections that match the provided arguments.
from .network import Network | ||
from .cell import _get_gaussian_connection |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
don't nest this if possible ... not sure if you have a circular import issue
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just checked, unfortunately the nesting is required here as well.
@@ -24,6 +24,8 @@ Changelog | |||
|
|||
- Add probability argument to :func:`~hnn_core.Network.add_connection`. Connectivity patterns can also be visualized with :func:`~hnn_core.viz.plot_connectivity_matrix`, by `Nick Tolley`_ in `#318 <https://github.com/jonescompneurolab/hnn-core/pull/318>`_ | |||
|
|||
- Add function to visualize connections originating from individual cells :func:`~hnn_core.viz.plot_cell_connectivity`, by `Nick Tolley`_ in `#339 <https://github.com/jonescompneurolab/hnn-core/pull/339>`_ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add to api.rst
?
hnn_core/viz.py
Outdated
# Gather positions of all gids in target_type. | ||
x_pos = [target_type_pos[idx][0] for idx in range(len(target_type_pos))] | ||
y_pos = [target_type_pos[idx][1] for idx in range(len(target_type_pos))] | ||
ax.scatter(x_pos, y_pos, color='k', zorder=-1, s=4) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just a thought, should we make this a little greyish to that people are not confused that the size stands for something ... it was not apparent to me because the red dot was different size, then there were the black dots and then there was the connectivitiy dots all different sizes. Maybe you can also think of changing the symbol of the src_gid
dot from circle to square or something. Sorry, I know this is a bit bikeshedding at this point ...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good suggestions. I think to be more explicit, I'll do a red square for src_gid
, and black x
's for the non-connected cells.
Merged, thanks @ntolley ! Connectivity API gets better and better. What's next?! |
This has been on the to-do for awhile. I've added a function to visualize the connectivity weights so that the gaussian decay with distance is visible. Since gids are arranged in a grid, it produces some interesting repeating patterns:
I still need to add some quick smoke tests, but I am satisfied with the current implementation of the function and definitely ready for some reviews.