Lab I: Python Intro¶
Overview¶
What is Python?¶
Python is a high-level, interpreted programming language, which in recent years has become the leading tool for analysis and visualization of Astronomical data sets.
What is Anaconda?¶
Anaconda is a free-to-use software bundle that includes Python, Jupyter (a web-based interface to Python), plus many supporting packages. It is produced by Anaconda, Inc.
What is Jupyter?¶
Jupyter allows Python to be run from within a web-browser, via interactive documents known as notebooks. A notebook is built from a number of discrete fragments called cells; each cell may contain either textual narrative or Python code.
Installation¶
If you have not already done so, download and install Anaconda by following the appropriate instructions:
A First Notebook¶
With the Jupyter window open in your web browser, navigate to the
astro_310
folder that you created during the installation steps,
and make a fresh notebook by selecting Python 3 from the Notebook
section of the New drop-down menu. Then, click on the title of the
notebook and rename it from Untitled
to first-notebook
.
You’re going to use this notebook to explore Python’s basic functionality. A few points to bear in mind about notebooks:
To select a cell, click anywhere inside it.
To execute the currently-selected cell (i.e., pass its contents to Python for interpretation), press Shift+Enter (or Shift+Return) on your keyboard, or click the ▶ Run icon at the top of the notebook.
To execute all cells in the notebook, elect Cell→Run All from the menu at the top.
To insert a new cell below the currently-selected cell, click the ➕ icon at the top.
To delete the currently-selected cell, click the ✂ icon at the top.
To interrupt the execution of a cell, click the ⬛ icon at the top.
By default, newly created cells are interpreted as code. However, you can change them to text cells by clicking the Code drop-down menu at the top and selecting Markdown.
A further, important point to bear in mind about Python in general, is that indentation and capitalization are significant — if you get them wrong, then Python will complain!
Importing Modules¶
Modules are add-ons that extend Python’s basic functionality. To use them we need to import them. Cut and paste the following code into the first cell of your notebook:
# Lines like this, beginning with '#', are comments that are ignored
# by Python. It's a good idea to comment your code to make it clear
# what's going on
# Import the numpy module to provide numerical functionality
import numpy as np
# Import the matplotlib.pyplot module to provide plotting functionality
import matplotlib.pyplot as plt
# Tell matplotlib.pyplot to do inline plots
%matplotlib inline
Then, execute the cell (Shift+Enter or Shift+Return).
Variables¶
Variables are named locations where data can be stored. A variable has both a type (integer, float, list, etc.) and a value. In Python, types are ‘dynamic’ — they can change during program execution. This can be convenient, but it can also be a pitfall if you’re not aware. A variable name must start with a letter, it can’t contain any illegal symbols or spaces, and it can’t be one of the few words Python reserves. In a Jupyter notebook, when you type a word that Python reserves, it will change color.
Create a new cell in your notebook, and execute this code in it:
# Create an integer variable
x = 5
# Print it out and then print its type. print() is a built-in
# Python functions that prints out a value; type() is another
# built-in function that returns the type of a variable
print(x)
print(type(x))
# Create a float variable (for representing real numbers). Note the
# decimal point!
x = 5.
print(x)
print(type(x))
Numerical Operations¶
Numerical variables (integers, floats and complex numbers) support the four standard arithmetic operations (+, -, * and /) together with more-sophisticated functions. Try out the following code, executing each block in a separate cell:
# Addition with integers and floats (math on mixed types will
# convert integers to float)
myInteger = 2
myFloat = 2.
print(myInteger + 3)
print(myInteger + 3.)
print(myFloat + 3)
print(myFloat + 3.)
# Multiplication and division with integers and floats
print(myInteger*6)
print(myInteger/6) # Converts myInteger to float
print(myInteger//6) # Doesn't convert myInteger to float
print(myFloat*6)
print(myFloat/6)
# Some other math operators and functions
print(myFloat**2) # The ** operator raises to a power
print(np.exp(myFloat)) # Exponentiation (provided by numpy module)
print(np.log(myFloat)) # Natural logarithm (provided by numpy module)
print(np.log10(myFloat)) # Base-10 logarithm (provided by numpy module)
print(np.sin(myFloat)) # Sine (provided by numpy module)
print(np.sqrt(myFloat)) # Square root (provided by numpy module)
print(np.sqrt(-myFloat)) # This should produce a 'nan' (Not-a-Number)
# Create a complex variable
myComplex = complex(-1.,2.) # The complex() function returns a complex number
myComplex = -1. + 2.*1j # Same effect as previous command
print(myComplex)
print(type(myComplex))
print(np.sqrt(myComplex)) # The sqrt() function works as it should with complex numbers
Strings¶
Variables can store more than just numerical data. For instance, variables with the string type contain sequences of characters:
# Create a string
myString = 'This is my string' # Note quotes ''
print(myString)
print(type(myString))
print(len(myString)) # The len() function returns the length of a string
Strings support indexing operations using square brackets []
,
allowing individual characters of a string to be accessed by their
integer index. Indices start at 0
and run through to L-1
,
where L
is the length of the string:
# String indexing
print(myString[0]) # Print the first character (index 0)
print(myString[1]) # Print the second character (index 1)
L = len(myString)
print(myString[L-1]) # Print the last character
print(myString[-1]) # Easier way to print the last character
print(myString[-2]) # Print the second-to-last character
Square brackets can also be used to for slicing operations, where we access a sequence of characters within a string (known as a substring):
# String slicing
print(myString[5:10]) # Print characters with indices from 5 (inclusive) to 10 (exclusive)
print(myString[:10]) # Print charcters from the start to index 10 (exclusive)
print(myString[5:]) # Print characters from index 5 (inclusive) to the end
print(myString[:]) # Print all characters
Strings can be concatenated together using the +
operator:
# String concatenation
num = 7
numString = str(num) # The str() function converts a number to a string
anotherString = 'My lucky number is ' + numString
print(anotherString)
Lists & Tuples¶
Sometimes we want to store not just a single value in a variable, but a sequence of values. This is what lists are for:
# Create a list
myList = ['eggs', 'potatoes', 42, 180., 'bucky'] # Note square brackets []
print(myList)
print(type(myList))
print(len(myList)) # The len() function returns the length of a list
Lists can be indexed, sliced and concatenated the same way as strings:
# List indexing, slicing and concatenation
print(myList[1])
print(myList[-2])
print(myList[1:3])
print(myList[:3])
print(myList[3:])
anotherList = myList + [1+3*1j, 'eureka!']
print(anotherList)
You can modify lists by indexing or slicing on the left-hand side of an assignment:
# Modify a list using indexing and slicing
anotherList[0] = 'Ostrich eggs'
anotherList[4:6] = [-1, -2]
print(anotherList)
Tuples are like lists in almost all respects, but they are created using a slightly different syntax, and can’t be modified after creation:
# Create a tuple
myTuple = (0, 1, 2., 3., 'four', 'five') # Note parentheses ()
print(myTuple)
print(type(myTuple))
myTuple[0] = 'Nought' # Will cause an error
Arrays¶
Arrays are a type provided by the numpy
module. They are
similar to lists, but support multidimensional indexing. They can,
however, only contain numbers:
# Create an array
myArray = np.array([0, 1, 2, 3, 4, 5]) # The np.array() function creates an array from a list
print(myArray)
print(type(myArray))
print(type(myArray[0]))
print(myArray.shape) # The .shape operator returns the dimensions of an array
Unlike lists, arrays support array arithmetic where operations apply to each array element in turn:
# Array arithmetic
print(myArray*2)
print(myArray + myArray)
print(np.exp(myArray))
The numpy
module provides a variety of alternative ways to create
arrays:
# Alternative ways to create arrays
anotherArray = np.arange(0., 6., 1.5) # From 0 (inclusive) to 6 (exclusive) in steps of 1.5
print(anotherArray)
anotherArray = np.linspace(10., 20., 5) # From 10 to 20 (inclusive) with 5 values
print(anotherArray)
Dicts¶
Dicts (short for ‘dictionaries’) are Python’s most flexible type. They store a group of values, but indexed by a ‘key’ (a string) rather than an integer:
# Define a dict using a sequence of key-value pairs
myDict = {'width': 8.5, 'height': 11, 'shape':'rectangle'} # Note braces {}
print(myDict)
print(type(myDict))
# Print out keys and values (note that ordering is arbitrary)
print(myDict.keys())
print(myDict.values())
Dicts support indexing via their key:
# Dict indexing
print(myDict['width'])
print(myDict['shape'])
Loops¶
Often, we wish to iterate through the elements of an indexable type. We can do this using loops:
# Iterate through the elements of a list
for item in myList: # This sets the variable 'item' to each of the elements in turn
print(item)
# Do the same using indexing
for i in range(len(myList)): # The range() function returns a list of indices
print(i, myList[i])
# Iterate through the elements of a dict
for key, value in myDict.items():
print(key, value)
Plotting¶
As the final step of this lab, let’s use some functions from the
matplotlib
module to make a plot. First, let’s create data for the plot:
# Create plot data
x = np.linspace(0., 2.*np.pi, 25) # 0 to 2pi in 25 steps
y = np.sin(x)
Now create the plot plus all-important labels:
# Create a new figure
plt.figure()
# Plot y versus x
plt.plot(x, y, color='b', label='line') # Line plot
plt.scatter(x, y, color='r', label='scatter') # Scatter plot
# Add axis labels and annotation
plt.xlabel('x')
plt.ylabel('sin(x)')
plt.legend()