Revision: 6276
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6276&view=rev
Author: fer_perez
Date: 2008-10-19 09:11:30 +0000 (Sun, 19 Oct 2008)
Log Message:
-----------
Workbook updates.
Modified Paths:
--------------
trunk/py4science/workbook/bessel.tex
trunk/py4science/workbook/fft_imdenoise.tex
trunk/py4science/workbook/qsort.tex
trunk/py4science/workbook/quad_newton.tex
trunk/py4science/workbook/trapezoid.tex
trunk/py4science/workbook/update_problems.py
trunk/py4science/workbook/wallis_pi.tex
Added Paths:
-----------
trunk/py4science/examples/mkprob.py
Removed Paths:
-------------
trunk/py4science/examples/mkskel.py
Copied: trunk/py4science/examples/mkprob.py (from rev 6270,
trunk/py4science/examples/mkskel.py)
===================================================================
--- trunk/py4science/examples/mkprob.py (rev 0)
+++ trunk/py4science/examples/mkprob.py 2008-10-19 09:11:30 UTC (rev 6276)
@@ -0,0 +1,325 @@
+#!/usr/bin/env python
+"""Make skeletons out of Python scripts.
+
+Usage:
+
+ mkprob.py [--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
+
+
[EMAIL PROTECTED]
+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/mkprob.py
___________________________________________________________________
Added: svn:executable
+ *
Added: svn:mergeinfo
+
Deleted: trunk/py4science/examples/mkskel.py
===================================================================
--- trunk/py4science/examples/mkskel.py 2008-10-19 09:04:27 UTC (rev 6275)
+++ trunk/py4science/examples/mkskel.py 2008-10-19 09:11:30 UTC (rev 6276)
@@ -1,325 +0,0 @@
-#!/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
-
-
[EMAIL PROTECTED]
-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)
Modified: trunk/py4science/workbook/bessel.tex
===================================================================
--- trunk/py4science/workbook/bessel.tex 2008-10-19 09:04:27 UTC (rev
6275)
+++ trunk/py4science/workbook/bessel.tex 2008-10-19 09:11:30 UTC (rev
6276)
@@ -1,6 +1,10 @@
\section{Bessel functions}
\label{sec:bessel}
+\textbf{Illustrates}: Special functions library, array manipulations
+to check recursion relation.
+
+
In this exercise, you will verify a few simple relations involving the Bessel
functions of the first kind. The important relations to keep in mind are the
asymptotic form of $J_n(x)$ for $x>>n$:
Modified: trunk/py4science/workbook/fft_imdenoise.tex
===================================================================
--- trunk/py4science/workbook/fft_imdenoise.tex 2008-10-19 09:04:27 UTC (rev
6275)
+++ trunk/py4science/workbook/fft_imdenoise.tex 2008-10-19 09:11:30 UTC (rev
6276)
@@ -1,6 +1,9 @@
\section{FFT Image Denoising}
\label{sec:fft_imdenoise}
+\textbf{Illustrates}: 2-d image denoising, use of the scipy FFT library,
+array manipulations, image plotting.
+
Convolution of an input with with a linear filter in the termporal or spatial
domain is equivalent to multiplication by the fourier transforms of the input
and the filter in the spectral domain. This provides a conceptually simple way
Modified: trunk/py4science/workbook/qsort.tex
===================================================================
--- trunk/py4science/workbook/qsort.tex 2008-10-19 09:04:27 UTC (rev 6275)
+++ trunk/py4science/workbook/qsort.tex 2008-10-19 09:11:30 UTC (rev 6276)
@@ -1,6 +1,7 @@
-
\section{Sorting quickly with QuickSort }
+\textbf{Illustrates}: lists, recursion.
+
Quicksort is one of the best known, and probably the simplest, fast
algorithm for sorting $n$ items. It is fast in the sense that it
requires on average $\mathcal{O}(n\log n)$ comparisons instead of
Modified: trunk/py4science/workbook/quad_newton.tex
===================================================================
--- trunk/py4science/workbook/quad_newton.tex 2008-10-19 09:04:27 UTC (rev
6275)
+++ trunk/py4science/workbook/quad_newton.tex 2008-10-19 09:11:30 UTC (rev
6276)
@@ -1,6 +1,9 @@
\section{Newton's method}
\label{sec:quad_newton}
+\textbf{Illustrates:} functions as first class objects, use of the
+scipy libraries.
+
Consider the problem of solving for $t$ in
\begin{equation}
\int_{o}^{t}f(s)ds=u
Modified: trunk/py4science/workbook/trapezoid.tex
===================================================================
--- trunk/py4science/workbook/trapezoid.tex 2008-10-19 09:04:27 UTC (rev
6275)
+++ trunk/py4science/workbook/trapezoid.tex 2008-10-19 09:11:30 UTC (rev
6276)
@@ -1,6 +1,9 @@
\section{Trapezoidal rule}
\label{sec:trapezoid}
+\textbf{Illustrates}: basic array slicing, functions as first class
+objects.
+
In this exercise, you are tasked with implementing the simple trapezoid
rule formula for numerical integration. If we want to compute the
definite integral \begin{equation}
Modified: trunk/py4science/workbook/update_problems.py
===================================================================
--- trunk/py4science/workbook/update_problems.py 2008-10-19 09:04:27 UTC
(rev 6275)
+++ trunk/py4science/workbook/update_problems.py 2008-10-19 09:11:30 UTC
(rev 6276)
@@ -10,10 +10,11 @@
from IPython.genutils import target_outdated
# Constants
-SRC_DIR = '../examples'
-UPDATE = './mkskel.py'
-PROBLEMS_DIR = 'problems'
+SRC_DIR = '../examples' # source dir for the examples
+UPDATE = './mkprob.py' # executable to make problems (in SRC_DIR)
+PROBLEMS_DIR = 'problems' # directory for problem output (in this dir)
+
if __name__ == '__main__':
problems = [f for f in os.listdir(PROBLEMS_DIR) if f.endswith('.py')]
Modified: trunk/py4science/workbook/wallis_pi.tex
===================================================================
--- trunk/py4science/workbook/wallis_pi.tex 2008-10-19 09:04:27 UTC (rev
6275)
+++ trunk/py4science/workbook/wallis_pi.tex 2008-10-19 09:11:30 UTC (rev
6276)
@@ -1,6 +1,7 @@
-
\section{Wallis' slow road to $\pi$}
+\textbf{Illustrates}: arbitrary size integers, simple function definitions.
+
Wallis' formula is an infinite product that converges (slowly) to
$\pi$:\begin{equation}
\pi=\prod_{i=1}^{\infty}\frac{4i^{2}}{4i^{2}-1}.\end{equation}
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Matplotlib-checkins mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/matplotlib-checkins