RatInABox-Lab / RatInABox

A python package for modelling locomotion in complex environments and spatially/velocity selective cell activity.
MIT License
172 stars 31 forks source link

Speed and place cells #96

Closed hsw28 closed 7 months ago

hsw28 commented 7 months ago

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!!

TomGeorge1234 commented 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:

It 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 :))

hsw28 commented 7 months ago

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!

TomGeorge1234 commented 7 months ago

Np at all. I'll leave it open for now and wait for questions

hsw28 commented 7 months ago

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!

TomGeorge1234 commented 7 months ago

not a stupid question!

Does this help?

hsw28 commented 7 months ago

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!!

hsw28 commented 7 months ago

Ok, a few other questions: Here are some plots of my agents movement (taken from real position data)

image image

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?

image

thank you again!

TomGeorge1234 commented 7 months ago

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
hsw28 commented 7 months ago

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

TomGeorge1234 commented 7 months ago

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:

c947f0d8-dd23-43ff-bc12-a598fe615fa4

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?

hsw28 commented 7 months ago

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!

TomGeorge1234 commented 7 months ago

How're you getting on? I'm thinking of closing this issue if theres no more questions for now but up to you

hsw28 commented 7 months ago

Doing great! I've built 4 models so far haha. Thank you! Feel free to close :)