Sunday, March 3, 2013

Processing class assignments on paper (Part I)

One of my classes is really old-school. I give out exercises on paper. The nature of the class requires the students to write a lot of equations, and draw diagrams. These things are really hard to do electronically, unless every student would have an iPad (or other tablet). Collecting, and keeping the papers is a pain. In addition to the hassle of filing or returning them to the students, I also have to enter the scores into something electronic after grading.

So, I'm developing a system to produce worksheets for the students. The returned sheets can either be graded with pen on paper and then scanned for further processing, or the stack can be scanned into a PDF file, and graded on an iPad. I choose to use QR-Codes to mark the pages. Bar codes seem to be more reliable than deciphering text labels with OCR. In particular, QR-codes can be reliably detected regardless of position, and to a certain degree scale and rotation.

System Requirements

The solution is based on a number of open source packages and libraries. Installation is easy for UNIX systems. I produce the handouts on OS X or Linux, processing of the scanned papers runs on LINUX.
Fortunately, these systems make it easy to install the various packages. Windows users may have a chance with Cygwin/X to get this working.

Creating Worksheets

The worksheets are produced in LaTeX (with help of some PostScript). Fortunately, there are some neat packages, like pgffor, that enable loops and the use of arrays. Some helpful documents are listed here:
Basic conditional if-else structures can be achieved with conditional variables in TeX. http://handyfloss.net/2007.08/latex-programming-how-to-implement-conditionals/

Another thing to point out is how to create LaTeX style files: There is a rather complicated, proper way to do it with documentation files (.dtx). However, for right now, I just put the preamble section of my LaTeX document, i.e. almost everything between \documentclass and \begin{document}, into a file names "worksheet.sty". However, there is one caveat: all \usepackage commands need to be replaced with \RequirePackage (more about that at http://tex.stackexchange.com/questions/19919/whats-the-difference-between-requirepackage-and-usepackage).

An interesting effect: the last page of the assignment already had the name of the next student. Apparently, the new header already became active for the last page. However, a tailing \newpage command forced the last page to be rendered, before the new header is set. Also, multiple new page commands don't create unwanted blank pages.

The following shows an excerpt of the style file:
\RequirePackage[letterpaper,margin=0.75in]{geometry}
\RequirePackage{graphicx}
\RequirePackage{amssymb}
\DeclareGraphicsRule{.tif}{png}{.png}{`convert #1 `dirname #1`/`basename #1 .tif`.png}
\RequirePackage{pstricks}
\RequirePackage{pst-barcode}
\RequirePackage{fancyhdr}
\RequirePackage{pgffor,pgfmath}
\pagestyle{fancy}

\newcommand{\hofilename}{XXX}
\newcommand{\hoclass}{ABC123}
\newcommand{\studentid}{A12345678}
\newcommand{\studentname}{John Doe}
\newcommand{\wsId}[1]{\renewcommand{\hoclass}{#1}}
\newcommand{\wsFile}[1]{\renewcommand{\hofilename}{#1}}
\renewcommand{\headrulewidth}{0.4pt}
\renewcommand{\footrulewidth}{0.4pt}

\setlength{\topmargin}{-1.7in}
\setlength{\headheight}{2.1in}
\setlength{\textheight}{8in}
\setlength{\footskip}{0.5in}

\fancyfoot[C]{%
  \foreach \val in {A, 0, 1, 2, 3, 4, X} {
    \val~\begin{pspicture}(0.7in,0.7in)
                \psbarcode{score=\val}{eclevel=M}{qrcode} \end{pspicture}
  }
}
\fancyfoot[L]{}
\fancyfoot[R]{}
\fancyhead[R]{\footnotesize Do not write over QR codes!}

%%\def\StudentsNames{{ "Smith, Fritz", "Jacobs, Lashonda", "Wu, Sarah" }}
%%\def\StudentsIds{ M12345678, 900123456, 900555123 }

\def\worksheets#1{%
  \foreach \id[count=\xi from 0] in \wsStudentIds {
    \renewcommand{\studentid}{\id}
    \newpage
    \fancyhead[C]{{\LARGE \hoclass:\ \@title}\\ \@date \\[1.5ex]%
        {\bf \pgfmathparse{\wsStudentNames[\xi]}\pgfmathresult}
    }
    \fancyhead[L]{%
        \begin{pspicture}(2in,2in)
          \psbarcode{c=\hoclass\&d=\@date\&f=\hofilename\&p=\thepage\&s=\studentid}{eclevel=M}{qrcode}
        \end{pspicture}
    }
    #1
    \newpage
  }
}
The two arrays, StudentNames and StudentIds should be defined in the main document, or in a separate file that will be included in each assignment.

An assignment would look something like this:

\documentclass[11pt]{article}
\usepackage{worksheet}

\wsId{CIS227}
\wsFile{CE02}

\title{Class Exercise 2}
\date{2013-01-24}

\input{students}

\def\handout{
  \noindent Prove the following tautologies by starting with the left side
  and finding a series of equivalent wff's that will convert the left
  side into the right side.
  \begin{enumerate}
    
  \item $(A \wedge B') \wedge C \leftrightarrow (A \wedge C) \wedge B'$
    \newpage
  \item $(A \vee B) \wedge (A \vee B') \leftrightarrow A$
    \newpage
  \item $A \vee ( B \wedge A') \leftrightarrow A \vee B $
    \newpage
  \item $(A \wedge B')' \vee B \leftrightarrow A' \vee B$
    \newpage
  \item $A \wedge (A \wedge B')' \leftrightarrow A \wedge B$
    \newpage  
  \end{enumerate}
}

\begin{document}
\worksheets{\handout}
\end{document}

Now, that I can produce these worksheets, I just need to develop the program that reads the scanned sheets and processes the grades.

Upgrading Python on Centos 6.3

In recent weeks I have become quite a fan of Python. Just like in many other cases, I learn to appreciate something once I have to use it. The attraction to Python is partly due to the sheer number of available libraries and packages. It seems like for virtually any task someone has already posted the 10-lines of python code to do it.

The majority of my computers run Centos 5.5 and Centos 6.3. Yes, there are some advantages in running Centos, and there are some good reasons not to upgrade a fine-tuned, running system. But Centos shows its conservative side with respect to the versions of its packages: Python 2.4.3 on Centos 5.5, and Python 2.6.6 on Centos 6.3.

Unfortunately, a number of software packages utilize Python, and many of them don't seem to be to friendly to the older versions. Even if most of my scripting would work on the older versions, those packages forced the upgrade.

The installation of newer versions is not that difficult. Fortunately, one can maintain several different version on the same system.

The blog http://toomuchdata.com/2012/06/25/how-to-install-python-2-7-3-on-centos-6-2/ describes how to download and install different versions quite nicely.

I choose /usr/local/Python-2.7.3 and /usr/local/Python-3.3.0 as the new locations. Fortunately, most of the work is done by running:
 
$ ./configure --prefix=/usr/local/Python-2.7.3
$ make
$ make install

Each Python installation has it's own directory for packages:
/usr/local/Python-2.7.3/lib/python2.7/site-packages/
That means one has to re-install all the packages that are needed. A significant advantage of separate installation directories is, of course, that different versions don't interfere with each other. Certain packages may not be compatible to all versions, either.

For users to select their Python version I created simple module files like this one:

#%Module1.0#####################################################################
##
proc ModulesHelp { } {
        global dotversion

        puts stderr "\tSelects Python 2.7.3"
        puts stderr "\n\tUse `python'."
        puts stderr "\n\t(PM 2013-02-15)\n"
}
module-whatis   "sets Python 2.7.3 as default interpreter
prepend-path    PATH    /usr/local/Python-2.7.3/bin/

All it takes is to set the PATH environment variable, though, there might be some other variables that should be defined.