Closed hsw28 closed 7 months ago
Hi Hannah!
Yes, you're right. Out of the box PlaceCells
(as they stand) don't model down to that level of biological realism. The goal for RiaB is to provide a minimal set of tools from which this kind of stuff can be explored, so you're on the right path.
The lines of code which determine the PlaceCell
firing rates are located in the get_state()
method of PlaceCells
. You'll see that, by default, it's just a basic Gaussian and there's no Agent.velocity
dependence or theta dependence.
https://github.com/RatInABox-Lab/RatInABox/blob/16375e1d9d654a9b57b7a870aef5588ceb82e627/ratinabox/Neurons.py#L848-L893
So how could you model more these more realistic dependencies?
I see two options:
PlaceCells
: You could make a subclass called MyMoreRealisticPlaceCells(PlaceCells)
which inherits from PlaceCells
where you write your own get_state()
method which implements more complex theta or velocity dependence. PlaceCells
with other cells: You could create a cells which linearly "mix" PlaceCells
with, say, VelocityCells
using a class we call FeedForwardLayer
to make velocity-dependent-place cells. I did this for GridCells
in this demoIt depends what you're interested in. The first is probably more flexibility but the second is probably slightly easier. By the way, I once made a subclass of PlaceCells
which phase precess (here so you might be interested in checking that out too. Once you've decided I'm happy to help you out here if you have specific questions.
And, of course, once made you'd be welcome to contribute either of these two models to the repo so others can use them too, if you'd like :))
Got it, super helpful and thanks for the fast response! I will likely work on creating a class that makes place cell activity contingent on velocity-- I'll likely have some questions so would you prefer I leave this issue open for those or close it and open a new issue/discussion if need be? Thanks again!
Np at all. I'll leave it open for now and wait for questions
likely dumb question that it's easier just to ask:
in my class i am calling some attributes from Neurons/PlaceCells like so
def plot_rate_timeseries(self):
# This method acts as a wrapper to the parent class's plot_ratemap method
super(CombinedNeurons, self).plot_rate_timeseries()
def plot_rate_map(self):
# This method acts as a wrapper to the parent class's plot_ratemap method
super(CombinedNeurons, self).plot_rate_map()
But when it comes to plot_place_cell_centre I CANNOT find where that lives! If I try to call it as above:
def plot_place_cell_centre(self):
# This method acts as a wrapper to the parent class's plot_ratemap method
super(CombinedNeurons, self).plot_place_cell_centre()
I get the error: AttributeError: 'CombinedNeurons' object has no attribute 'plot_place_cell_centres'. I am assuming it doesnt live in the Neuron parent class but then where is it? Thanks!
not a stupid question!
Firstly (and probably the answer) is that the function is called plot_place_cell_locations()
(not ...._centre
). It's here:
https://github.com/RatInABox-Lab/RatInABox/blob/e5cc5e91833e0d2cb7a534911fedc8eb1df6d2b9/ratinabox/Neurons.py#L895
Secondly is that your CombinedNeurons
subclass should be a subclass of PlaceCells
(where this function lives) not (or at least not only) Neurons
Thirdly, unless you want to add extra things into these function you shouldn't need to write such basic wrappers like this. The subclasses "inherit" all methods from their parents by default so MySubClassInstance.a_method_defined_in_the_parent_class()
should work just fine without you duplicating each function like this.
Fourthly, the search bar at the top of GitHub is a pretty effective way to find things/functions. If not, go to Neurons.py
and poke around there for a while and you should find stuff.
Does this help?
great, thank you! my subclass is a subclass of PlaceCells, not just Neurons (sorry if I was unclear). I added the wrappers because I am calling the plotting functions (eg plot_rate_map) from a different main script.
I (of course) tried to search but was searching on plot_place_cell_centres-- it is described in your list of plotting functions (here: https://github.com/RatInABox-Lab/RatInABox/blob/080b4b895463735f5bc498e5773665d05d252275/demos/list_of_plotting_fuctions.md?plain=1#L108 ) which is where I must have pulled it from :)
Either way, all working now, so thank you!!
Ok, a few other questions: Here are some plots of my agents movement (taken from real position data)
And then here are the modelled place cell the centers seem to be relatively uniformly distributed despite that the agent is spending significantly more time on the perimeter of the arena. Also, why is there a stripe at the top with no centers, despite that the animal visited that area?
thank you again!
Oh sorry for the misnamed plot function. I've fixed that!
Yes, same as before, in RiaB PlaceCells
don't model this level of biological realism (this is a conscious choice to keep the toolkit simple). If you wanted you could definitely write your own code that sets PlaceCells.place_cell_centres
to be sampled from the motion heat map distribution (or something more complex) but, by default, cell centres are just scattered uniformly across the environment plus a bit of jitter so this aspect is totally expected.
As for the band at the top, I just looked into it and it seems like you have spotted a very subtle bug, thanks! It was essentially a fence-post error do with how positioned are sampled uniformly across the Environment
. I push a fix in version 1.11.4 which should mend things can you let me know. if you agree, update riab with
pip install -U ratinabox
great, thank you! if the place cells are scattered randomly across the environment, and can even be in locations where the animal has not travelled, what function does the agents position then have?
i was basing my modified class off of only creating place cells when the agent is travelling at a certain speed, but if the agents position does not matter for creating place cells, the speed will then also be irrelevant
The agent position determines the firing rate of the place cell...but not (by default) its receptive field.
I'm imagining your simulation looks a bit like this:
Env = Environment(params={'scale':0.4,'aspect':2.5})
Ag = Agent(Env)
#<---you probably imported a trajectory here...I'll use the inbuilt random motion model
PCs = PlaceCells(Ag, params={'n':80})
PCs.plot_place_cell_locations()
#The main simulation loop
while Ag.t < 60:
Ag.update()
PCs.update()
Two plotting functions may help here:
PlaceCells.plot_rate_maps()
show the receptive fields of the place cells. These are just Gaussian centres at a location which doesn't depend on the statistics of the Agent
.
PCs.plot_rate_map(chosen_neurons='10',shape=(5,2))
PlaceCells.plot_rate_timeseries()
shows the data created under the motion model.
So you see that PlaceCells
are just static Gaussians (there are more complex versions of place cells and other cell types entirely but these are the default I assume you're using), uniformly scattered across the environment. These Gaussians themselves don't depend on the position of the Agent
but the position of the Agent
maps through these Gaussians to determine the firing rate of each cell at each moment.
Now you totally could make the Gaussians depend on the Agent
position. You could extract the positions, create a density map, a sample positions from the density and re-set the place cell locations PlaceCells.place_cell_centres = my_new_centres
Or, alternatively, you could keep the Gaussians static but multiply them by a velocity-dependent term in your new cells get_state()
method. It would look something like:
... # the rest of your get_state function
fr = super().get_state(evaluate_at=evaluate_at, **kwargs)
fr *= self.Agent.velocity #or something more complex
Does this make sense?
Ok got it, so place cells where the animal never visits just wont ever be activated. That's good enough for me, I think! Thank you!
How're you getting on? I'm thinking of closing this issue if theres no more questions for now but up to you
Doing great! I've built 4 models so far haha. Thank you! Feel free to close :)
Hi, I am using ratinabox to model some place cell activity. As we know, place cells are really only active representations of the animals location when the animal is moving/during theta (of course they also activate during SWRs, etc, but those dont represent the current location). I would like to look at the code that "specifies" this property but I cant find it. Would you mind directing me to the right place? Many thanks!!