The working memory (a.k.a namespace)#

Manipulating variables#

Clicker question “cdcc” (Click me!)

The code below will print four numbers. Can you predict what will be printed?

c = 1
print(c)

d = c + 5
print(d)

print(c)
c = c + 8
print(c)

Keeping track of variables and their values#

How do you keep track of variables and their values? The kernel is the thing that executes your code. It also stores your namespace - all variables and code that you have executed so far and that are stored in your computer memory.

If you re-run your code cells out of order, it may be hard to know what’s in your namespace. In that case, you can clear and re-launch the kernel, to start from scratch, with a clean namespace. This will erase any variables stored in memory and reset python to its original state.

You can list the contents of your namespace with %whos:

%whos
Interactive namespace is empty.

Messing up and restoring the namespace#

The namespace contains not only all variables you’ve created and manipulated, but also all functions. It is therefore surprisingly easy to mess up you namespace. For instance, you can “overwrite” function names with variables in python.

Remember the print function? Let’s create a variable named print and assign a value to it:

print = 'no, never do this!'

Now let’s print the value of the print variable:

print(print)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[13], line 1
----> 1 print(print)

TypeError: 'str' object is not callable

That fails, as does

print(10)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[14], line 1
----> 1 print(10)

TypeError: 'str' object is not callable

That’s because in the namespace of the current notebook, we have overwritten the function print with a string variable of the same name.

Why is this happening? Let’s first inspect the namespace. This confirms that print is of type string now, and not a function.

type(print)
builtin_function_or_method
%whos
Interactive namespace is empty.

Clicker question “namespace”(Click me!)

What do you do now?

After restarting the kernel, we will see that the type of print is now “builtin_function_or_method”:

type(print)  # this will return "builtin_function_or_method"
builtin_function_or_method

Re-using and updating variables across cells#

Not that the order of execution matters, not order in which cells appear in the notebook!

Alice and Bob count mosquitoes. Alice, to store her count, creates a variable with name n_alice_mosquitoes and value 1 (she has counted only one mosquito so far).

n_alice_mosquitoes = 1  # create a new variable `n_alice_mosquitoes` and assign the value 1 to `n_alice_mosquitoes`
%whos
Variable             Type    Data/Info
--------------------------------------
n_alice_mosquitoes   int     1

Now she can perform a computation using n_alice_mosquitoes. For instance, Bob has counted 10 more mosquitoes - so we add 10 to her own count and store the result in a new variable, n_mosquitoes, for the total count:

Clicker question “mosquitoes 1” (Click me!)

What will be the value of n_mosquitoes after executing this code after having run the cell above?

n_mosquitoes = n_alice_mosquitoes + 10
print(n_mosquitoes)

What is going on here?

In the above expression, n_alice_mosquitoes + 10, python sees the variable name, n_alice_mosquitoes, and looks up it’s value, 1 This works since we have created and assigned a value to n_alice_mosquitoes in the previous cell.

Python then replaces the name n_alice_mosquitoes with the value 1 and performs the computation (it evaluates the expression).

n_alice_mosquitoes + 10 is evaluated as 1 + 10.

n_mosquitoes = n_alice_mosquitoes + 10 means that the result of the operation, the value 11, is saved in a new variable, with name n_mosquitoes.

Note that above we exploited that what you do in one cell transfers to the next:

  • we defined n_alice_mosquitoes in one cell

  • and used it in a computation in the next cell

Clicker question “mosquitoes 2” (Click me!)

What will be the value of n_mosquitoes after executing this code after having run the first and second cells above?

n_mosquitoes = n_tim_mosquitoes + 20
print(n_mosquitoes)

This will throw an error, as we cannot use a variable we have not defined before: Python does not know what n_tim_mosquitoes refers to!

The fact that we can re-use variables across cells allows us to successively build up our analysis code, cell by cell.

Spike detection with python#

  • Present data in code (individual voltage values, manipulate them and store the results) - variables

  • Compare variables (voltage to threshold) - boolean values

  • Perform different actions based on the value of a variable (only keep the position if the voltage exceeds the threshold) - if-else statements

  • Present and access data in a time series of voltage values - lists

  • Perform an action for each element in a sequence of values (inspect voltage values one-by-one) - for loops

  • Separate data and logic so we can use the same code for new recordings - functions

  • Apply this to multi data files

  • Plot and save the results