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 CellRun 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()

Catching Up

If you fell behind in class, or are having difficulty with the cut-and-paste, then download a notebook containing the code for this lab from here.