|
From: <fer...@us...> - 2008-10-19 07:53:56
|
Revision: 6270
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6270&view=rev
Author: fer_perez
Date: 2008-10-19 07:53:47 +0000 (Sun, 19 Oct 2008)
Log Message:
-----------
Cleanup and updates to many examples.
Added new tool to create skeletons and solutions from a single source
script.
Modified Paths:
--------------
trunk/py4science/examples/bessel.py
trunk/py4science/examples/butter_filter.py
trunk/py4science/examples/fft_imdenoise.py
trunk/py4science/examples/filtilt_demo.py
trunk/py4science/examples/fitting.py
trunk/py4science/examples/montecarlo_pi.py
trunk/py4science/examples/qsort.py
trunk/py4science/examples/quad_newton.py
trunk/py4science/examples/recarray_demo.py
trunk/py4science/examples/trapezoid.py
Added Paths:
-----------
trunk/py4science/examples/mkskel.py
trunk/py4science/examples/skel/fortran_wrap/test_example.py
trunk/py4science/examples/skel/fortran_wrap/test_fib.py
Modified: trunk/py4science/examples/bessel.py
===================================================================
--- trunk/py4science/examples/bessel.py 2008-10-19 07:48:51 UTC (rev 6269)
+++ trunk/py4science/examples/bessel.py 2008-10-19 07:53:47 UTC (rev 6270)
@@ -1,45 +1,46 @@
#!/usr/bin/env python
"""Plot some Bessel functions of integer order, using Scipy and pylab"""
-import scipy.special
+from scipy import special
-import numpy as N
-import scipy as S
-import pylab as P
+import numpy as np
+import matplotlib.pyplot as plt
-# shorthand
-special = S.special
-
def jn_asym(n,x):
"""Asymptotic form of jn(x) for x>>n"""
+
+ #@ The asymptotic formula is:
+ #@ j_n(x) ~ sqrt(2.0/pi/x)*cos(x-(n*pi/2.0+pi/4.0))
- return S.sqrt(2.0/S.pi/x)*S.cos(x-(n*S.pi/2.0+S.pi/4.0))
+ return np.sqrt(2.0/np.pi/x)*np.cos(x-(n*np.pi/2.0+np.pi/4.0)) #@
# build a range of values to plot in
-x = N.linspace(0,30,400)
+x = np.linspace(0,30,400)
# Start by plotting the well-known j0 and j1
-P.figure()
-P.plot(x,special.j0(x),label='$J_0$')
-P.plot(x,special.j1(x),label='$J_1$')
+plt.figure()
+plt.plot(x,special.j0(x),label='$J_0$') #@
+plt.plot(x,special.j1(x),label='$J_1$') #@
# Show a higher-order Bessel function
n = 5
-P.plot(x,special.jn(n,x),label='$J_%s$' % n)
+plt.plot(x,special.jn(n,x),label='$J_%s$' % n)
# and compute its asymptotic form (valid for x>>n, where n is the order). We
-# must first find the valid range of x where at least x>n:
-x_asym = S.compress(x>n,x)
-P.plot(x_asym,jn_asym(n,x_asym),label='$J_%s$ (asymptotic)' % n)
+# must first find the valid range of x where at least x>n.
+#@ Find where x>n and evaluate the asymptotic relation only there
+x_asym = x[x>n] #@
+plt.plot(x_asym,jn_asym(n,x_asym),label='$J_%s$ (asymptotic)' % n) #@
# Finish off the plot
-P.legend()
-P.title('Bessel Functions')
+plt.legend()
+plt.title('Bessel Functions')
# horizontal line at 0 to show x-axis, but after the legend
-P.axhline(0)
+plt.axhline(0)
-# EXERCISE: redo the above, for the asymptotic range 0<x<<n. The asymptotic
-# form in this regime is
+# Extra credit: redo the above, for the asymptotic range 0<x<<n. The
+# asymptotic form in this regime is:
+#
# J(n,x) = (1/gamma(n+1))(x/2)^n
# Now, let's verify numerically the recursion relation
@@ -47,17 +48,25 @@
jn = special.jn # just a shorthand
# Be careful to check only for x!=0, to avoid divisions by zero
-xp = S.compress(x>0.0,x) # positive x
+#@ xp contains the positive values of x
+xp = x[x>0.0] #@
# construct both sides of the recursion relation, these should be equal
+#@ Define j_np1 to hold j_(n+1) evaluated at the points xp
j_np1 = jn(n+1,xp)
+#@ Define j_np1_rec to express j_(n+1) via a recursion relation, at points xp
j_np1_rec = (2.0*n/xp)*jn(n,xp)-jn(n-1,xp)
# Now make a nice error plot of the difference, in a new figure
-P.figure()
-P.semilogy(xp,abs(j_np1-j_np1_rec),'r+-')
-P.title('Error in recursion for $J_%s$' % n)
-P.grid()
+plt.figure()
+#@ We now plot the difference between the two formulas above. Note that to
+#@ properly display the errors, we want to use a logarithmic y scale. Search
+#@ the matplotlib docs for the proper calls.
+plt.semilogy(xp,abs(j_np1-j_np1_rec),'r+-') #@
+
+plt.title('Error in recursion for $J_%s$' % n)
+plt.grid()
+
# Don't forget a show() call at the end of the script
-P.show()
+plt.show()
Modified: trunk/py4science/examples/butter_filter.py
===================================================================
--- trunk/py4science/examples/butter_filter.py 2008-10-19 07:48:51 UTC (rev 6269)
+++ trunk/py4science/examples/butter_filter.py 2008-10-19 07:53:47 UTC (rev 6270)
@@ -1,13 +1,13 @@
-import numpy as n
+import numpy as np
import scipy.signal as signal
-from pylab import figure, show
+from matplotlib.pyplot import figure, show
dt = 0.01
-t = n.arange(0, 2, dt)
-s = n.sin(2*n.pi*t)
+t = np.arange(0, 2, dt)
+s = np.sin(2*np.pi*t)
# sine corrupted wih gaussian white noise
-sn = s + 0.1*n.random.randn(len(s)) # noisy sine
+sn = s + 0.1*np.random.randn(len(s)) # noisy sine
# the nyquist frequency 1/(2dt) is the maximum frequency in a sampled
# signal
Modified: trunk/py4science/examples/fft_imdenoise.py
===================================================================
--- trunk/py4science/examples/fft_imdenoise.py 2008-10-19 07:48:51 UTC (rev 6269)
+++ trunk/py4science/examples/fft_imdenoise.py 2008-10-19 07:53:47 UTC (rev 6270)
@@ -1,62 +1,86 @@
#!/usr/bin/env python
-"""Image denoising example using 2-dimensional FFT."""
+"""Simple image denoising example using 2-dimensional FFT."""
import sys
import numpy as np
from matplotlib import pyplot as plt
-def mag_phase(F):
- """Return magnitude and phase components of spectrum F."""
-
- return (np.absolute(F), np.angle(F))
-
def plot_spectrum(F, amplify=1000):
"""Normalise, amplify and plot an amplitude spectrum."""
- M, Phase = mag_phase(F)
- M *= amplify/M.max()
- M[M > 1] = 1
- print M.shape, M.dtype
- plt.imshow(M, plt.cm.Blues)
+ # Note: the problem here is that we have a spectrum whose histogram is
+ # *very* sharply peaked at small values. To get a meaningful display, a
+ # simple strategy to improve the display quality consists of simply
+ # amplifying the values in the array and then clipping.
+ # Compute the magnitude of the input F (call it mag). Then, rescale mag by
+ # amplify/maximum_of_mag. Numpy arrays can be scaled in-place with ARR *=
+ # number. For the max of an array, look for its max method.
+ mag = abs(F) #@
+ mag *= amplify/mag.max() #@
+
+ # Next, clip all values larger than one to one. You can set all elements
+ # of an array which satisfy a given condition with array indexing syntax:
+ # ARR[ARR<VALUE] = NEWVALUE, for example.
+ mag[mag > 1] = 1 #@
+ # Display: this one already works, if you did everything right with mag
+ plt.imshow(mag, plt.cm.Blues)
+
if __name__ == '__main__':
try:
# Read in original image, convert to floating point for further
# manipulation; imread returns a MxNx4 RGBA image. Since the image is
- # grayscale, just extrac the 1st channel
- im = plt.imread('data/moonlanding.png').astype(float)[:,:,0]
+ # grayscale, just extract the 1st channel
+ #@ Hints:
+ #@ - use plt.imread() to load the file
+ #@ - convert to a float array with the .astype() method
+ #@ - extract all rows, all columns, 0-th plane to get the first
+ #@ channel
+ #@ - the resulting array should have 2 dimensions only
+ im = plt.imread('data/moonlanding.png').astype(float)[:,:,0] #@
+ print "Image shape:",im.shape
except:
print "Could not open image."
sys.exit(-1)
# Compute the 2d FFT of the input image
- F = np.fft.fft2(im)
+ #@ Hint: Look for a 2-d FFT in np.fft.
+ #@ Note: call this variable 'F', which is the name we'll be using below.
+ F = np.fft.fft2(im) #@
- # Now, make a copy of the original spectrum and truncate coefficients.
+ # In the lines following, we'll make a copy of the original spectrum and
+ # truncate coefficients. NO immediate code is to be written right here.
+
+ # Define the fraction of coefficients (in each direction) we keep
keep_fraction = 0.1
# Call ff a copy of the original transform. Numpy arrays have a copy
# method for this purpose.
- ff = F.copy()
+ ff = F.copy() #@
- # Set r and c to be the number of rows and columns of the array.
- r,c = ff.shape
+ # Set r and c to be the number of rows and columns of the array.
+ #@ Hint: use the array's shape attribute.
+ r,c = ff.shape #@
# Set to zero all rows with indices between r*keep_fraction and
# r*(1-keep_fraction):
- ff[r*keep_fraction:r*(1-keep_fraction)] = 0
+ ff[r*keep_fraction:r*(1-keep_fraction)] = 0 #@
# Similarly with the columns:
- ff[:, c*keep_fraction:c*(1-keep_fraction)] = 0
+ ff[:, c*keep_fraction:c*(1-keep_fraction)] = 0 #@
# Reconstruct the denoised image from the filtered spectrum, keep only the
- # real part for display
- im_new = np.fft.ifft2(ff).real
-
+ # real part for display.
+ #@ Hint: There's an inverse 2d fft in the np.fft module as well (don't
+ #@ forget that you only want the real part).
+ #@ Call the result im_new,
+ im_new = np.fft.ifft2(ff).real #@
+
# Show the results
+ #@ The code below already works, if you did everything above right.
plt.figure()
plt.subplot(221)
@@ -75,9 +99,6 @@
plt.title('Reconstructed Image')
plt.imshow(im_new, plt.cm.gray)
- plt.savefig('fft_imdenoise.png', dpi=150)
- plt.savefig('fft_imdenoise.eps')
-
# Adjust the spacing between subplots for readability
plt.subplots_adjust(hspace=0.32)
plt.show()
Modified: trunk/py4science/examples/filtilt_demo.py
===================================================================
--- trunk/py4science/examples/filtilt_demo.py 2008-10-19 07:48:51 UTC (rev 6269)
+++ trunk/py4science/examples/filtilt_demo.py 2008-10-19 07:53:47 UTC (rev 6270)
@@ -7,10 +7,11 @@
order. The function also computes the initial filter parameters in
order to provide a more stable response (via lfilter_zi). The
following code has been tested with Python 2.4.4 and Scipy 0.5.1.
+"""
-"""
-from numpy import vstack, hstack, eye, ones, zeros, linalg, \
-newaxis, r_, flipud, convolve, matrix, array
+from numpy import (vstack, hstack, eye, ones, zeros, linalg,
+ newaxis, r_, flipud, convolve, matrix, array)
+
from scipy.signal import lfilter
def lfilter_zi(b,a):
@@ -38,19 +39,18 @@
return array(zi_return)
-
-
def filtfilt(b,a,x):
#For now only accepting 1d arrays
ntaps=max(len(a),len(b))
edge=ntaps*3
if x.ndim != 1:
- raise ValueError, "Filiflit is only accepting 1 dimension arrays."
+ raise ValueError("Filiflit is only accepting 1 dimension arrays.")
- #x must be bigger than edge
+ # x must be bigger than edge
if x.size < edge:
- raise ValueError, "Input vector needs to be bigger than 3 * max(len(a),len(b)."
+ e="Input vector needs to be bigger than 3 * max(len(a),len(b)."
+ raise ValueError(e)
if len(a) < ntaps:
a=r_[a,zeros(len(b)-len(a))]
Modified: trunk/py4science/examples/fitting.py
===================================================================
--- trunk/py4science/examples/fitting.py 2008-10-19 07:48:51 UTC (rev 6269)
+++ trunk/py4science/examples/fitting.py 2008-10-19 07:53:47 UTC (rev 6270)
@@ -7,10 +7,11 @@
from scipy.optimize import leastsq
from scipy.interpolate import splrep,splev
-import numpy as N
-import scipy as S
-import pylab as P
+import numpy as np
+import matplotlib as mpl
+import matplotlib.pyplot as plt
+
def func(pars):
a, alpha, k = pars
return a*exp(alpha*x_vals) + k
@@ -35,7 +36,7 @@
print 'Least-squares fit to the data'
print 'true', pars_true
print 'best', best
-print '|err|_l2 =',P.l2norm(pars_true-best)
+print '|err|_l2 =',np.linalg.norm(pars_true-best)
# scipy's splrep uses FITPACK's curfit (B-spline interpolation)
print
@@ -48,27 +49,27 @@
def plot_polyfit(x,y,n,fignum=None):
""" """
if fignum is None:
- fignum = P.figure().number
- P.plot(x,y,label='Data')
+ fignum = plt.figure().number
+ plt.plot(x,y,label='Data')
- fit_coefs = N.polyfit(x,y,n)
- fit_val = N.polyval(fit_coefs,x)
- P.plot(x,fit_val,label='Polynomial fit, $n=%d$' % n)
- P.legend()
+ fit_coefs = np.polyfit(x,y,n)
+ fit_val = np.polyval(fit_coefs,x)
+ plt.plot(x,fit_val,label='Polynomial fit, $n=%d$' % n)
+ plt.legend()
return fignum
# Now use pylab to plot
-P.figure()
-P.plot(x_vals,y_noisy,label='Noisy data')
-P.plot(x_vals,func(best),lw=2,label='Least-squares fit')
-P.legend()
-P.figure()
-P.plot(x_vals,y_noisy,label='Noisy data')
-P.plot(x_vals,smooth,lw=2,label='Spline-smoothing')
-P.legend()
+plt.figure()
+plt.plot(x_vals,y_noisy,label='Noisy data')
+plt.plot(x_vals,func(best),lw=2,label='Least-squares fit')
+plt.legend()
+plt.figure()
+plt.plot(x_vals,y_noisy,label='Noisy data')
+plt.plot(x_vals,smooth,lw=2,label='Spline-smoothing')
+plt.legend()
fignum = plot_polyfit(x_vals,y_noisy,1)
plot_polyfit(x_vals,y_noisy,2,fignum)
plot_polyfit(x_vals,y_noisy,3,fignum)
-P.show()
+plt.show()
Added: trunk/py4science/examples/mkskel.py
===================================================================
--- trunk/py4science/examples/mkskel.py (rev 0)
+++ trunk/py4science/examples/mkskel.py 2008-10-19 07:53:47 UTC (rev 6270)
@@ -0,0 +1,325 @@
+#!/usr/bin/env python
+"""Make skeletons out of Python scripts.
+
+Usage:
+
+ mkskel [--test] file1.py file2.py ....
+
+If --test is given, the test suite is run instead.
+
+For each input filename f.py, a pair of output files is generated, f_soln.py
+and f_skel.py.
+
+Source markup is very simple. The tests in the file show precisely how it
+works, but in summary:
+
+- Pure comment lines with the special marker (#@) are left in the skeleton
+ (only the marker is stripped, but they remain as valid comments). These are
+ typically used for hints.
+
+- Code lines terminated with the marker are:
+
+ - In the skeleton, replaced by a NotImplementedError call. Consecutive lines
+ are replaced by a single call.
+
+ - In the solution, kept as is but the marker is removed.
+"""
+
+from __future__ import with_statement
+
+#-----------------------------------------------------------------------------
+# Stdlib imports
+import os
+import re
+import shutil
+import sys
+
+# Third-party imports
+import nose
+
+# Constants
+MARKER = '#@'
+DEL_RE = re.compile(r'''^((\s*)(.*?))\s*%s\s*$''' % MARKER)
+HINT_RE = re.compile(r'''^(?P<space>\s*)%s\s+(?P<hint>.*)$''' % MARKER)
+
+
+#-----------------------------------------------------------------------------
+# Main code begins
+
+def src2soln(src):
+ """Remove markers from input source, leaving all else intact.
+
+ Inputs:
+ src : sequence of lines (file-like objects work out of the box)
+ """
+
+ out = []
+ addline = out.append
+ for line in src:
+ # Check for lines to delete and with hints
+ mdel = DEL_RE.match(line)
+ mhint = HINT_RE.match(line)
+
+ # All hints are unconditionally removed
+ if mhint is None:
+ if mdel:
+ # if marker is matched in code, strip it and leave the code
+ line = mdel.group(1)+'\n'
+ addline(line)
+
+ return ''.join(out)
+
+
+def src2skel(src):
+ """Remove markers from input source, replacing marked lines.
+
+ Marked lines are replaced with "raise NotImplementedError" calls that
+ summarize the total number of deleted lines.
+
+ Inputs:
+ src : sequence of lines (file-like objects work out of the box)
+ """
+
+ def flush_buffers(normal_lines,del_lines=0):
+ """Local function to reuse some common code"""
+
+ if state_cur == normal:
+ # add the normal lines
+ out.extend(normal_lines)
+ normal_lines[:] = []
+ else:
+ # Add the summary of 'raise' lines
+
+ # flush counter of code (disabled, we report static summary)
+ #msg = '1 line' if del_lines==1 else ('%s lines' % del_lines)
+ #exc = exc_tpl % msg
+ exc = exc_tpl
+
+ # Use the last value of 'space'
+ line = '%s%s' % (spaces[0],exc)
+ out.append(line)
+ del_lines = 0
+ spaces[:] = []
+
+ return del_lines
+
+ # used to report actual # of lines removed - disabled
+ #exc_tpl = "raise NotImplementedError('%s missing')\n"
+ exc_tpl = "raise NotImplementedError('insert missing code here')\n"
+
+ # states for state machine and other initialization
+ normal,delete = 0,1
+ state_cur = normal
+ del_lines = 0 # counter, in case we want to report # of deletions
+ spaces = []
+ normal_lines = []
+ out = []
+
+ # To remove multiple consecutive lines of input marked for deletion, we
+ # need a small state machine.
+ for line in src:
+ # Check for lines to delete and with hints
+ mdel = DEL_RE.match(line)
+ mhint = HINT_RE.match(line)
+
+ if mhint:
+ state_new = normal
+ hint = mhint.group('space')+'# ' + mhint.group('hint') +'\n'
+ normal_lines.append(hint)
+ else:
+ if mdel is None:
+ state_new = normal
+ normal_lines.append(line)
+ else:
+ state_new = delete
+ del_lines += 1
+ spaces.append(mdel.group(2))
+
+ # Flush output only when there's a change of state
+ if state_new != state_cur:
+ del_lines = flush_buffers(normal_lines,del_lines)
+
+ # Update state machine
+ state_cur = state_new
+
+ # Final buffer flush is unconditional
+ flush_buffers(normal_lines)
+
+ return ''.join(out)
+
+
+def transform_file(fpath,fname_skel,fname_soln):
+ """Run the cleanup routines for a given input, creating skel and soln.
+ """
+
+ # get the mode of the input so that we can create the output files with the
+ # same mode
+ fmode = os.stat(fpath).st_mode
+
+ with open(fpath) as infile:
+ # Generate the skeleton
+ skel = src2skel(infile)
+ with open(fname_skel,'w') as fskel:
+ fskel.write(skel)
+ os.chmod(fname_skel,fmode)
+
+ # Reset the input file pointer and generate the solution
+ infile.seek(0)
+ soln = src2soln(infile)
+ with open(fname_soln,'w') as fsoln:
+ fsoln.write(soln)
+ os.chmod(fname_soln,fmode)
+
+#-----------------------------------------------------------------------------
+# Main execution routines
+
+def copyforce(src,dest):
+ """Forceful file link/copy that overwrites destination files."""
+ try:
+ copy = os.link
+ except AttributeError:
+ copy = shutil.copy
+ if os.path.isfile(dest):
+ os.remove(dest)
+ copy(src,dest)
+
+
+def mvforce(src,dest):
+ """Forceful file copy that overwrites destination files."""
+ if os.path.isfile(dest):
+ os.remove(dest)
+ shutil.move(src,dest)
+
+
+def main(argv=None):
+ """Main entry point as a command line script for normal execution"""
+
+ if argv is None:
+ argv = sys.argv
+
+ # If there are subdirs called skel and soln, we populate them by moving the
+ # generated files there, otherwise they're left in the current dir.
+ skel_dir = 'skel'
+ soln_dir = 'soln'
+ has_skel_dir = os.path.isdir(skel_dir)
+ has_soln_dir = os.path.isdir(soln_dir)
+
+ # First, check that all files are present and abort immediately if any of
+ # them isn't there.
+ for fpath in argv[1:]:
+ if not os.path.isfile(fpath):
+ raise OSError("file %r not found" % fpath)
+
+ # If all files are there, then go ahead and process them unconditionally
+ for fpath in argv[1:]:
+ basename, ext = os.path.splitext(fpath)
+ fname_skel = basename + '_skel' + ext
+ fname_soln = basename + '_soln' + ext
+ transform_file(fpath,fname_skel,fname_soln)
+ # Move files over to final dirs if present
+ if has_skel_dir:
+ mvforce(fname_skel,os.path.join(skel_dir,fname_skel))
+ if has_soln_dir:
+ mvforce(fname_soln,os.path.join(soln_dir,fname_soln))
+
+#-----------------------------------------------------------------------------
+# Tests
+
+def str_match(s1,s2):
+ """Check that two strings are equal ignoring trailing whitespace."""
+ #print '***S1\n',s1,'\n***S2\n',s2 # dbg
+ nose.tools.assert_equal(s1.rstrip(),s2.rstrip())
+
+
+def test_simple():
+ src = """
+ first line
+ del line #@
+ second line
+ """
+ srclines = src.splitlines(True)
+
+ clean = """
+ first line
+ raise NotImplementedError('insert missing code here')
+ second line
+ """
+
+ cleaned = src2skel(srclines)
+ yield str_match,cleaned,clean
+
+ clean = """
+ first line
+ del line
+ second line
+ """
+ cleaned = src2soln(src.splitlines(True))
+ yield str_match,cleaned,clean
+
+
+def test_multi():
+ src = """
+ first line
+ #@ Hint: remember that
+ #@ idea we discussed before...
+ del line #@
+ del line2 #@
+ del line3 #@
+ second line:
+ del line4 #@
+ del line5 #@
+ third line
+
+ some indented code: #@
+ with more... #@
+ """
+ srclines = src.splitlines(True)
+
+ clean = """
+ first line
+ # Hint: remember that
+ # idea we discussed before...
+ raise NotImplementedError('insert missing code here')
+ second line:
+ raise NotImplementedError('insert missing code here')
+ third line
+
+ raise NotImplementedError('insert missing code here')
+ """
+ cleaned = src2skel(srclines)
+ yield str_match,cleaned,clean
+
+ clean = """
+ first line
+ del line
+ del line2
+ del line3
+ second line:
+ del line4
+ del line5
+ third line
+
+ some indented code:
+ with more...
+ """
+ cleaned = src2soln(srclines)
+ yield str_match,cleaned,clean
+
+
+@nose.tools.nottest
+def test():
+ """Simple self-contained test runner."""
+ nose.runmodule(__name__,exit=False,
+ argv=['--doctests',
+ #'-s',
+ #'--pdb-failures',
+ ])
+
+#-----------------------------------------------------------------------------
+# Execution from the command line.
+
+if __name__ == "__main__":
+ if '--test' in sys.argv:
+ test()
+ else:
+ main(sys.argv)
Property changes on: trunk/py4science/examples/mkskel.py
___________________________________________________________________
Added: svn:executable
+ *
Modified: trunk/py4science/examples/montecarlo_pi.py
===================================================================
--- trunk/py4science/examples/montecarlo_pi.py 2008-10-19 07:48:51 UTC (rev 6269)
+++ trunk/py4science/examples/montecarlo_pi.py 2008-10-19 07:53:47 UTC (rev 6270)
@@ -15,7 +15,7 @@
import math
import random
-import numpy as N
+import numpy as np
from scipy import weave
from scipy.weave import inline,converters
@@ -110,7 +110,7 @@
print 'pi - weave :',v2()
# make a simple 10x10 array
- a = N.arange(100)
+ a = np.arange(100)
a.shape = 10,10
# Print it using our printer
Modified: trunk/py4science/examples/qsort.py
===================================================================
--- trunk/py4science/examples/qsort.py 2008-10-19 07:48:51 UTC (rev 6269)
+++ trunk/py4science/examples/qsort.py 2008-10-19 07:53:47 UTC (rev 6270)
@@ -1,29 +1,60 @@
-"""
-Simple quicksort implementation.
+"""Simple quicksort implementation.
-See http://en.wikipedia.org/wiki/Quicksort for algorithm, pseudocode
-and C implementation for comparison
+From http://en.wikipedia.org/wiki/Quicksort we have this pseudocode (see also
+the C implementation for comparison).
+
+Note: what follows is NOT python code, it's meant to only illustrate the
+algorithm for you. Below you'll need to actually implement it in real Python.
+You may be surprised at how close a working Python implementation can be to
+this pseudocode.
+
+
+function quicksort(array)
+ var list less, greater
+ if length(array) <= 1
+ return array
+ select and remove a pivot value pivot from array
+ for each x in array
+ if x <= pivot then append x to less
+ else append x to greater
+ return concatenate(quicksort(less), pivot, quicksort(greater))
"""
def qsort(lst):
- """Return a sorted copy of the input list."""
+ """Return a sorted copy of the input list.
- if len(lst) <= 1:
- return lst
+ Input:
- # Select pivot and apply recursively
- pivot, rest = lst[0],lst[1:]
- less_than = [ lt for lt in rest if lt < pivot ]
- greater_equal = [ ge for ge in rest if ge >= pivot ]
-
- return qsort(less_than) + [pivot] + qsort(greater_equal)
+ lst : a list of elements which can be compared.
+ Examples:
+ >>> qsort([])
+ []
+
+ >>> qsort([3,2,5])
+ [2, 3, 5]
+ """
+
+ #@ Hint: remember that all recursive functions need an exit condition
+ if len(lst) <= 1: #@
+ return lst #@
+
+ #@ Select pivot and apply recursively
+ pivot, rest = lst[0],lst[1:] #@
+ less_than = [ lt for lt in rest if lt < pivot ] #@
+ greater_equal = [ ge for ge in rest if ge >= pivot ] #@
+
+ #@ Upon return, make sure to properly concatenate the output lists
+ return qsort(less_than) + [pivot] + qsort(greater_equal) #@
+
+
#-----------------------------------------------------------------------------
# Tests
#-----------------------------------------------------------------------------
import random
+import nose
import nose, nose.tools as nt
def test_sorted():
Modified: trunk/py4science/examples/quad_newton.py
===================================================================
--- trunk/py4science/examples/quad_newton.py 2008-10-19 07:48:51 UTC (rev 6269)
+++ trunk/py4science/examples/quad_newton.py 2008-10-19 07:53:47 UTC (rev 6270)
@@ -4,35 +4,35 @@
from math import sin
-import scipy, scipy.integrate, scipy.optimize
+from scipy.integrate import quad
+from scipy.optimize import newton
-quad = scipy.integrate.quad
-newton = scipy.optimize.newton
-
# test input function
def f(t):
- return t*(sin(t))**2
+ #@ f(t): t * sin^2(t)
+ return t*(sin(t))**2 #@
-# exact \int_0^t f(s) ds - u
def g(t):
+ "Exact form for g by integrating f(t)"
u = 0.25
return .25*(t**2-t*sin(2*t)+(sin(t))**2)-u
-# now let's construct g(t) via numerical integration
def gn(t):
+ "g(t) obtained by numerical integration"
u = 0.25
- return quad(f,0.0,t)[0] - u
+ #@ Hint: use quad, see its return value carefully.
+ return quad(f,0.0,t)[0] - u #@
# main
tguess = 10.0
print '"Exact" solution (knowing the analytical form of the integral)'
-t0 = newton(g,tguess,f)
+t0 = newton(g,tguess,f) #@
print "t0, g(t0) =",t0,g(t0)
print
print "Solution using the numerical integration technique"
-t1 = newton(gn,tguess,f)
+t1 = newton(gn,tguess,f) #@
print "t1, g(t1) =",t1,g(t1)
print
Modified: trunk/py4science/examples/recarray_demo.py
===================================================================
--- trunk/py4science/examples/recarray_demo.py 2008-10-19 07:48:51 UTC (rev 6269)
+++ trunk/py4science/examples/recarray_demo.py 2008-10-19 07:53:47 UTC (rev 6270)
@@ -1,67 +1,53 @@
"""
parse and load ge.csv into a record array
"""
-import time, datetime, csv
-import dateutil.parser
-import numpy
-if 0:
- # create a csv reader to parse the file
- fh = file('data/ge.csv')
- reader = csv.reader(fh)
- header = reader.next()
+import datetime
- # iterate over the remaining rows and convert the data to date
- # objects, ints, or floats as approriate
- rows = []
- for date, open, high, low, close, volume, adjclose in reader:
- date = dateutil.parser.parse(date).date()
- volume = int(volume)
- open, high, low, close, adjclose = map(float, (
- open, high, low, close, adjclose))
- rows.append((date, open, high, low, close, volume, adjclose))
+import numpy as np
- fh.close()
+import matplotlib
+from matplotlib import pyplot as plt
- # this is how you can use the function matplotlib.mlab.load to do the same
- #rows = load('data/ge.csv', skiprows=1, converters={0:datestr2num}, delimiter=',')
+# Disable latex support just in case, so we can rotate text
+matplotlib.rcParams['text.usetex'] = False
- r = numpy.rec.fromrecords(rows, names='date,open,high,low,close,volume,adjclose')
+# Load a data file into a record array using the matplotlib csv2rec utility
+r = matplotlib.mlab.csv2rec('data/ge.csv')
+r.sort() #sort by date, the first column
# compute the average approximate dollars traded over the last 10 days
# hint: closing price * volume trades approx equals dollars trades
recent = r[-10:]
-dollars = numpy.mean(recent.close * recent.volume)
-print '$%1.2fM'%(dollars/1e6)
+dollars = np.mean(recent.close * recent.volume)
+print 'Total traded over last 10 days: $%1.2fM'%(dollars/1e6)
-# plot the adjusted closing price vs time since 2003 - hint, you must
-# use date2num to convert the date to a float for mpl. Make two axes,
-# one for price and one for volume. Use a bar chart for volume
-import matplotlib
-matplotlib.rcParams['usetex'] = False
-from matplotlib.dates import date2num
-import pylab
-mask = r.date>datetime.date(2003,1,1)
-date = date2num(r.date[mask])
-price = r.adjclose[mask]
+# plot the adjusted closing price vs time since 2003. Make two axes, one for
+# price and one for volume. Use a bar chart for volume
+
+# Record arrays are like 'mini-spreadsheets'
+mask = r.date > datetime.date(2003,1,1)
+date = r.date[mask]
+price = r.adj_close[mask]
volume = r.volume[mask]
-fig = pylab.figure()
+# Plotting
+fig = plt.figure()
fig.subplots_adjust(hspace=0)
ax1 = fig.add_subplot(211)
-ax1.plot(date, price, '-');
-ax1.xaxis_date()
+ax1.plot(date, price, '-')
+
ax1.grid()
for label in ax1.get_xticklabels():
label.set_visible(False)
ax2 = fig.add_subplot(212, sharex=ax1)
ax2.bar(date, volume);
-ax2.xaxis_date()
+
ax2.grid()
for label in ax2.get_xticklabels():
label.set_rotation(30)
label.set_horizontalalignment('right')
-
-pylab.show()
+fig.autofmt_xdate()
+plt.show()
Added: trunk/py4science/examples/skel/fortran_wrap/test_example.py
===================================================================
--- trunk/py4science/examples/skel/fortran_wrap/test_example.py (rev 0)
+++ trunk/py4science/examples/skel/fortran_wrap/test_example.py 2008-10-19 07:53:47 UTC (rev 6270)
@@ -0,0 +1,9 @@
+import example
+import numpy
+
+x = numpy.arange(10.)
+
+yf = example.cumsum(x)
+yn = numpy.cumsum(x)
+
+numpy.testing.assert_array_almost_equal(yf, yn)
Added: trunk/py4science/examples/skel/fortran_wrap/test_fib.py
===================================================================
--- trunk/py4science/examples/skel/fortran_wrap/test_fib.py (rev 0)
+++ trunk/py4science/examples/skel/fortran_wrap/test_fib.py 2008-10-19 07:53:47 UTC (rev 6270)
@@ -0,0 +1,13 @@
+import numpy as N
+
+import example
+
+n = 10
+fn = example.fib(n)
+
+print 'Fibonacci numbers:'
+print fn
+
+# Check validity
+assert N.alltrue(fn[2:]== fn[1:-1]+fn[:-2]), "Fibonacci mismatch"
+
Modified: trunk/py4science/examples/trapezoid.py
===================================================================
--- trunk/py4science/examples/trapezoid.py 2008-10-19 07:48:51 UTC (rev 6269)
+++ trunk/py4science/examples/trapezoid.py 2008-10-19 07:53:47 UTC (rev 6270)
@@ -7,7 +7,8 @@
"""Simple trapezoid integrator for sequence-based innput.
Inputs:
- - x,y: arrays of the same length.
+ - x,y: arrays of the same length (and more than one element). If the two
+ inputs have different lengths, a ValueError exception is raised.
Output:
- The result of applying the trapezoid rule to the input, assuming that
@@ -15,14 +16,20 @@
Minimally modified from matplotlib.mlab."""
- # Sanity checks
- if len(x)!=len(y):
- raise ValueError('x and y must have the same length')
- if len(x)<2:
- raise ValueError('x and y must have > 1 element')
+ # Sanity checks.
+ #@
+ #@ Hint: if the two inputs have mismatched lengths or less than 2
+ #@ elements, we raise ValueError with an explanatory message.
+ if len(x) != len(y): #@
+ raise ValueError('x and y must have the same length') #@
+ if len(x) < 2: #@
+ raise ValueError('x and y must have > 1 element') #@
# Efficient application of trapezoid rule via numpy
- return 0.5*((x[1:]-x[:-1])*(y[1:]+y[:-1])).sum()
+ #@
+ #@ Hint: think of using numpy slicing to compute the moving difference in
+ #@ the basic trapezoid formula.
+ return 0.5*((x[1:]-x[:-1])*(y[1:]+y[:-1])).sum() #@
def trapzf(f,a,b,npts=100):
"""Simple trapezoid-based integrator.
@@ -39,15 +46,25 @@
Output:
- The value of the trapezoid-rule approximation to the integral."""
- # Generate an equally spaced grid to sample the function at
- x = np.linspace(a,b,npts)
+ #@ Hint: you will need to apply the function f to easch element of the
+ #@ vector x. What are several ways to do this? Can you profile them to see
+ #@ what differences in timings result for long vectors x?
+
+ # Generate an equally spaced grid to sample the function.
+ x = np.linspace(a,b,npts)#@
+
# For an equispaced grid, the x spacing can just be read off from the first
# two points and factored out of the summation.
- dx = x[1]-x[0]
+ dx = x[1]-x[0]#@
+
# Sample the input function at all values of x
- y = np.array(map(f,x))
+ #@
+ #@ Hint: you need to make an array out of the evaluations, and the python
+ #@ builtin 'map' function can come in handy.
+ y = np.array(map(f,x))#@
+
# Compute the trapezoid rule sum for the final result
- return 0.5*dx*(y[1:]+y[:-1]).sum()
+ return 0.5*dx*(y[1:]+y[:-1]).sum()#@
#-----------------------------------------------------------------------------
@@ -56,20 +73,25 @@
import nose, nose.tools as nt
import numpy.testing as nptest
+# A simple function for testing
def square(x): return x**2
def test_err():
+ """Test that mismatched inputs raise a ValueError exception."""
nt.assert_raises(ValueError,trapz,range(2),range(3))
def test_call():
+ "Test a direct call with equally spaced samples. "
x = np.linspace(0,1,100)
y = np.array(map(square,x))
nptest.assert_almost_equal(trapz(x,y),1./3,4)
def test_square():
+ "Test integrating the square() function."
nptest.assert_almost_equal(trapzf(square,0,1),1./3,4)
def test_square2():
+ "Another test integrating the square() function."
nptest.assert_almost_equal(trapzf(square,0,3,350),9.0,4)
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|