Teaching basic lab skills
for research computing

Solution to Data Checking Problem

I finally had a chance this morning to record my solution to the final exercise I set the learners from the Space Telescope Science Institute. It demonstrates how to build a little program in Python that checks the consistency of some experimental data; along the way, it uses file I/O, functions, assert statements, lists of lists, and on-the-fly unpacking. As always, feedback on the content and format would be greatly appreciated. (And if anyone would like to post their own solution, either as plain code or as a video, please let me know so that I can include it here.)

import sys


def get_reader(args):
    '''Select either standard input or a file to read from.'''
    if len(args) == 1:
        reader = sys.stdin
    elif len(args) == 2:
        reader = file(sys.argv[1], 'r')
        print >> sys.stderr, "Usage: check.py [filename]"
    return reader


def get_data(reader):
    '''Read a helmet test data file.  We expect the date on the first
    line, a title line second, and then one triple for each
    reader.readline() # should be the date
    reader.readline() # should be the title line
    # Each other line must be (degrees, seconds, brittleness) record
    data = []
    for line in reader:
        fields = line.split()
        assert len(fields) == 3, "Bad line: %s" % line
        deg = float(fields[0])
        sec = float(fields[1])
        brit = float(fields[2])
        record = [deg, sec, brit]
    return data


def report_error(left, right):
    '''Report inconsistent data.'''
    print left, 'is inconsistent with', right


def check(data):
    '''Check that records obey consistency rules.'''
    for record_1 in data:
        deg_1, sec_1, brit_1 = record_1

        for record_2 in data:
            deg_2, sec_2, brit_2 = record_2

            if (deg_1 == deg_2) and \
               (sec_1 > sec_2) and \
               (brit_1 < brit_2):                 report_error(record_1, record_2)             if (deg_1 > deg_2) and \
               (sec_1 == sec_2) and \
               (brit_1 < brit_2):
                report_error(record_1, record_2)


reader = get_reader(sys.argv)
data = get_data(reader)


Dialogue & Discussion

You can review our commenting policy here.