Lecture 1b

  • backends
  • importing your own functions from a file
  • importlib.reload
  • Nans
  • Infs
  • Divide by zero
  • largest and smallest floats (their exponents)
  • the debugger pdb
  • Complex numbers

backends

In [1]:
%matplotlib
import numpy as np
# backend TkAgg is the default apparently
# this opens another window where the plotting is done!
Using matplotlib backend: TkAgg
In [2]:
import matplotlib.pyplot as plt
import matplotlib 
matplotlib.use('TkAgg')  # if you want to hard set the backend
# the plot buttons are very flacky, apparently  a common problem on macOS
# It's easier to get off the window and back on than to get a click to work
# double clicks sometimes work and single ones don't
In [3]:
plt.figure()
x = np.arange(0,10,0.1)
y= x**2
plt.plot(x,y,'ro')
Out[3]:
[<matplotlib.lines.Line2D at 0x7fb2a73707f0>]
In [1]:
#  restart the kernel and then try this
%matplotlib notebook
import numpy as np
import matplotlib.pyplot as plt
In [2]:
plt.figure()
x = np.arange(0,10,0.1)
y= x**2
plt.plot(x,y,'ro')
Out[2]:
[<matplotlib.lines.Line2D at 0x7f8db57284c0>]
In [ ]:
# the buttons work better in this backend
In [3]:
# lets add to the plot
plt.plot(x,np.sin(x),'b-')
Out[3]:
[<matplotlib.lines.Line2D at 0x7f8db681b370>]
In [1]:
#  restart the kernel and then this
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt

importing a function from a file

the file is called subs.py and contains the following:

import numpy as np

def simple_function(x):
    return np.sin(3*x)

The file is in the same directory as my notebook

In [2]:
import subs
In [3]:
x = np.arange(0,10,0.1)
z = subs.simple_function(x)
plt.plot(x,z)
Out[3]:
[<matplotlib.lines.Line2D at 0x7fe445dffd90>]

Reload

If you edit subs.py the function that you have loaded into python will not necessarily be updated. You can update it with importlib.reload

I notice a directory pycache and in it is a binary file called subs.cpython-38.pyc which is a compiled version of my subroutine. The subroutine is recompiled when I import the function again with reload().

As of 2021 autoreload seems not to work anymore.

In [6]:
from importlib import reload

now edit the file subs.py

In [7]:
reload(subs)
x = np.arange(0,2,0.01)
z = subs.simple_function(x)
plt.plot(x,z)
Out[7]:
[<matplotlib.lines.Line2D at 0x7fe446107ee0>]
In [ ]:
# the plot has changed!

Not numbers

In [5]:
np.log(-1) 
<ipython-input-5-05a3d8831400>:1: RuntimeWarning: invalid value encountered in log
  np.log(-1)
Out[5]:
nan
In [6]:
z = np.log(-1) 
<ipython-input-6-778aab7942b6>:1: RuntimeWarning: invalid value encountered in log
  z = np.log(-1)
In [7]:
?z
In [ ]:
np.isnan(z)

Nans propagate

You add a regular number to a nan and you get a nan.

If there are interactions between particles, this can make an entire particle based simulation crash.

In [8]:
z = np.log(-1)
w = z+1
print(w)  # you add a regular number to a nan and you get a nan
nan
<ipython-input-8-9265fd3589ce>:1: RuntimeWarning: invalid value encountered in log
  z = np.log(-1)
In [9]:
print(type(w))
<class 'numpy.float64'>

comparisons bewteen two nans

In [12]:
import numpy as np
w1 = np.sqrt(-1)
w2 = np.sqrt(-2)
if (w1 > w2):
    print("nan is bigger than nan")
    
if (w1 <= w2):
    print("nan is smaller or equal to nan")
    
if (w1 == w2):
    print("nan is equal to nan")
<ipython-input-12-c26bf7072cf2>:2: RuntimeWarning: invalid value encountered in sqrt
  w1 = np.sqrt(-1)
<ipython-input-12-c26bf7072cf2>:3: RuntimeWarning: invalid value encountered in sqrt
  w2 = np.sqrt(-2)

nothing was printed so comparisons give False when comparing two nans

In [14]:
print(w1>w2)
print(w1<=w2)
print(w1==w2)
False
False
False

Inf

In [15]:
np.exp(1000) 
#10**(-400)
<ipython-input-15-8271c75ed52a>:1: RuntimeWarning: overflow encountered in exp
  np.exp(1000)
Out[15]:
inf
In [16]:
type(np.exp(1000))
<ipython-input-16-3189a275acdf>:1: RuntimeWarning: overflow encountered in exp
  type(np.exp(1000))
Out[16]:
numpy.float64
In [17]:
z = np.exp(1000) 
np.isinf(z)
<ipython-input-17-bf4939641b2d>:1: RuntimeWarning: overflow encountered in exp
  z = np.exp(1000)
Out[17]:
True

largest number

In [18]:
for i in range(10,1000,10):
    print(10.0**i)
10000000000.0
1e+20
1e+30
1e+40
1e+50
1e+60
1e+70
1e+80
1e+90
1e+100
1e+110
1e+120
1e+130
1e+140
1e+150
1e+160
1e+170
1e+180
1e+190
1e+200
1e+210
1e+220
1e+230
1e+240
1e+250
1e+260
1e+270
1e+280
1e+290
1e+300
---------------------------------------------------------------------------
OverflowError                             Traceback (most recent call last)
<ipython-input-18-ac68b3330147> in <module>
      1 for i in range(10,1000,10):
----> 2     print(10.0**i)

OverflowError: (34, 'Result too large')

This is dependent on the number of digits available in the exponent for double precision floats

smallest number

In [19]:
for i in range(1,370,10):
    print (10**(-i))
0.1
1e-11
1e-21
1e-31
1e-41
1e-51
1e-61
1e-71
1e-81
1e-91
1e-101
1e-111
1e-121
1e-131
1e-141
1e-151
1e-161
1e-171
1e-181
1e-191
1e-201
1e-211
1e-221
1e-231
1e-241
1e-251
1e-261
1e-271
1e-281
1e-291
1e-301
1e-311
1e-321
0.0
0.0
0.0
0.0

divide by zero

In [20]:
ww = 1.0/0.0
---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
<ipython-input-20-156ef9731bc4> in <module>
----> 1 ww = 1.0/0.0

ZeroDivisionError: float division by zero
In [21]:
print(ww)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-21-ca16a8352e93> in <module>
----> 1 print(ww)

NameError: name 'ww' is not defined

Divide by zero crashes code

In [22]:
import pdb  # the debugger!
In [23]:
def add_to_life_universe_everything(x):
    answer = 42
    pdb.set_trace()
    answer += x
    
    return answer

add_to_life_universe_everything(12)
# to exit this type continue, you can type in variable names and 
# find out what they contain
> <ipython-input-23-9b4cd9c5e8a8>(4)add_to_life_universe_everything()
      2     answer = 42
      3     pdb.set_trace()
----> 4     answer += x
      5 
      6     return answer

ipdb> x
12
ipdb> answer
42
ipdb> continue
Out[23]:
54
In [24]:
z=1+2j
z
Out[24]:
(1+2j)
In [25]:
z?
In [26]:
c1 = complex(1,2)
print(c1)
(1+2j)
In [27]:
np.sqrt(c1)
Out[27]:
(1.272019649514069+0.7861513777574233j)
In [28]:
np.sqrt(-1 + 0j)
Out[28]:
1j
In [29]:
c1.imag
Out[29]:
2.0
In [30]:
c1.real
Out[30]:
1.0
In [ ]: