Skip to main content

Posts

Showing posts from 2015

Paths in Python

How do you get your Python interpreter to find modules that are not located in your current working directory? The answer is … you tell it where to look. When you type something like from my_module import my_function Python searches a collection of directories (i.e., folders) on your computer. If the directory containing <my_module.py> is not in this collection, you will receive an ImportError . This can be frustrating if you know the file exists, and even more so if you know where it exists. In this post, we will take a brief look at how to add paths to the collection of directories searched by Python. Paths A path is essentially a set of directions to a file: /Users/username/modules/my_module.py [Mac OS X, Linux] C:\modules\my_module.py [Windows] It tells your operating system how to navigate from a fixed starting point — the “root directory” / in Unix-based systems, or C:\ in Windows — through a collection of folders to the de

Speeding Up Python — Part 2: Optimization

The goal of this post and its predecessor is to provide some tools and tips for improving the performance of Python programs. In the previous post , we examined profiling tools — sophisticated stopwatches for timing programs as they execute. In this post, we will use these tools to demonstrate some general principles that make Python programs run faster. Remember: If your program already runs fast enough, you do not need to worry about profiling and optimization. Faster is not always better, especially if you end up with code that is difficult to read, modify, or maintain. Overview We can summarize our principles for optimizing performance as follows: Debug first. Never attempt to optimize a program that does not work. Focus on bottlenecks. Find out what takes the most time, and work on that. Look for algorithmic improvements. A different theoretical approach might speed up your program by orders of magnitude. Use library functions. The routines in NumPy, SciPy,

Speeding Up Python — Part 1: Profiling

When people argue about programming languages, a common critique of Python is, “It’s slow.” This is occasionally followed by, “A program written in C will run a thousand times faster.” Such generalization carry little weight. Python is often fast enough, and a well-written Python program can run significantly faster than a poorly-written C program. Plus, Moore’s Law implies that computers today are over a thousand times faster than those of 15 years ago: You can do with Python today what was only possible with a highly optimized, compiled program in 2000. It is also important to consider development time. Suppose a C program takes a week to write and debug and 1 minute to run, and an equivalent Python program takes a day to write and debug and 1000 minutes (about a day) to run. The “slow” Python program will finish running five days earlier than the “fast” C program! If you already know Python and don’t know any C, then the time difference will be even greater. In short, you nee

Lists, Comprehensions, and Generators

In A Student’s Guide to Python for Physical Modeling , we emphasized NumPy arrays and paid less attention to Python lists. The reason is simple: In most scientific computing applications, NumPy arrays store data more efficiently and speed up mathematical calculations, sometimes a thousandfold. However, there are some applications where a Python list is the better choice. There are also times when the choice between a list and an array has little or no effect on performance. In such cases a list can make your code easier to read and understand, and that is always a good thing. In this post, I will describe Python lists and explain a special Python construct for creating lists called a list comprehension . I will also describe a similar construct called a generator expression . Lists A list is an ordered collection of items. You may have made a “To Do” list this morning or a grocery list for a recent trip to the store. In computer science, a list is a data structure that sup

Function Arguments: *args and **kwargs

In Python, functions can have positional arguments and named arguments . In this post, I will describe both types and explain how to use special syntax to simplify repetitive function calls with nearly the same arguments. This extends the discussion in section 5.1.3 of A Student’s Guide to Python for Physical Modeling . First, let’s look at np.savetxt , which has a straightforward declaration: $ import matplotlib.pyplot as plt $ from mpl_toolkits.mplot3d import Axes3D $ np.savetxt? Signature: np.savetxt( fname, X, fmt='%.18e', delimiter=' ', newline='\n', header='', footer='', comments='# ') Docstring: Save an array to a text file. We see the function has two required arguments, followed by several optional arguments with default values. Next, let’s look at something more exotic: $ Axes3D.plot_surface? Signature: Axes3D.plot_surface(X, Y, Z, *args, **kwargs) Docstring: Create a surface plot. The f

Illuminating Surface Plots

Matplotlib provides functions for visualizing three-dimensional data sets. One useful tool is a surface plot. A surface plot is a two-dimensional projection of a three-dimensional object. Much like a sketch artist, Python uses techniques like perspective and shading to give the illusion of a three-dimensional object in space. In this post, I describe how you can control the lighting of a surface plot. Surface Plots First, let’s look at some of the options available with the default three-dimensional plotting tools. This script will create a surface plot of a Bessel function. Its ripples will emphasize the effects of lighting later. import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D # Import 3D plotting tools. from scipy.special import jn # Import Bessel function. # Define grid of points. points = np.linspace(-10, 10, 51) X, Y = np.meshgrid(points, points) R = np.sqrt(X**2 + Y**2) Z = jn(0,R) # Create 3D surface plo

Displaying Plots Inside Loops

In the early stages of some programming projects, I often like to explore the problem visually: to run a series of simulations with different values of the input parameters and create a series of graphs in order to gain some intuition about the problem. A convenient approach is to embed some plotting commands in a loop. For example, suppose I want to see what the first ten Bessel functions look like. It seems that the following script should do what I want: import numpy as np import matplotlib.pyplot as plt from scipy.special import jn # Import Bessel function. r = np.linspace(0,20,101) for n in range(10): plt.plot(r, jn(n,r)) # Draw nth Bessel function. plt.title("Bessel function J[%d](r)." % n) input("Press <Enter> to continue.") # Wait for user input to continue. plt.cla() # Clear axes for next plot. However, when I run the script, all I see is an empty plot window,

Raising a Figure Window to the Foreground

This post describes a utility function that will raise a plot window to the foreground of your screen. The function will only work with the Qt graphics backend, so I will start with a brief overview of graphics backends. If you just want to use the function as a black box, you can do the following: Set the Graphics Backend to “Qt” in the Spyder preferences menu. Copy this function into your working directory. Graphics Backends You may have have written a script to produce precisely the data you need, but a lot of processing is required to transform these numbers into a figure. You need to create a plot window, draw a figure inside of it, and manage all of the attributes that control a figure’s appearance: title, axis labels, line widths, colors, tick marks, etc. All of this happens in the background when you type a command like plt.plot(x,y) . A graphics backend is the software that Python uses to physically draw a figure on your computer screen. If you have already import

Interpolation

“I have experimental data for absorption (dependent variable) measured at various wavelengths (independent variable). Now I want estimates of the absorption at other values in the same range.” This is an interpolation problem. We wish to obtain the value of a dependent value at point for which we did not sample the independent value. Interpolation is a mathematical procedure for filling in the gaps between available values. SciPy provides a module for interpolation based on the FITPACK library of FORTRAN functions. (Thus, it is fast and reliable.) A Simple Example To gain access to the interpolation functions, import the module: import scipy.interpolate Or, simply import the function we need for our one-dimensional problem: from scipy.interpolate import interp1d Suppose that each column of an array expData contains a (wavelength, absorption) pair. We can use interp1d to create a function-like object for interpolation from this data set: F = interp1d(expData[:,0], ex