#!/usr/bin/env python
# LeCrunch
# Copyright (C) 2010 Anthony LaTorre
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
import os
import sys
import time
import socket
import struct
import h5py
from lecroy import LeCroyScope
from config import get_settings
def fetch(filename, events):
"""
Fetch and save waveform traces from the oscilloscope.
Args:
- filename: str
Filename to store traces in (in hdf5 format).
- events: int
Number of triggered events to save in `filename`.
"""
scope = LeCroyScope('scope01.hep.upenn.edu')
scope.connect()
# turn off the display
scope.send('display off')
scope.check_last_command()
# clear the output queue
scope.clear()
# get active channels
channels = scope.getchannels()
# get scope configuration
settings = get_settings(scope)
# get wave descriptors for each channel
# important to do this before queue is primed!
wavedesc = {}
for channel in channels:
wavedesc[channel] = scope.getwavedesc(channel)
# prime the output queue
for i in range(10):
scope.trigger()
for channel in channels:
scope.send('c%i:wf? dat1' % channel)
# open up the output file
f = h5py.File(filename, 'w')
# set scope configuration
for command, setting in settings.items():
f.attrs[command] = setting
dataset = {}
for channel in channels:
samples = wavedesc[channel]['wave_array_count']
chunks = (max(1,min(100, events//100)), samples)
dataset[channel] = f.create_dataset('channel%i' % channel,
(events, samples),
dtype=wavedesc[channel]['dtype'],
chunks=chunks,
compression='gzip')
for key, value in wavedesc[channel].items():
try:
dataset[channel].attrs[key] = value
except ValueError:
pass
# start a timer
time0 = time.time()
try:
for i in range(events):
print '\rSaving event: %i' % (i+1),
sys.stdout.flush()
try:
scope.trigger()
for channel in channels:
dataset[channel][i] = scope.getwaveform(channel,
wavedesc[channel])
except (socket.error, struct.error, RuntimeError, OverflowError):
print "\nFailed to receive waveform %i" % (i+1)
# clear the output queue
scope.clear()
# reprime the queue
for i in range(10):
scope.trigger()
for channel in channels:
scope.send('c%i:wf? dat1' % channel)
continue
print
except KeyboardInterrupt:
print
print 'Resizing datasets...'
for channel in channels:
dataset[channel].resize((i, wavedesc[channel]['wave_array_count']))
raise KeyboardInterrupt
finally:
f.close()
scope.clear()
scope.send('display on')
scope.check_last_command()
scope.close()
elapsed = time.time() - time0
print 'Completed %i events in %.3f seconds.' % (i+1, elapsed)
print 'Averaged %.5f seconds per acquisition.' % (elapsed/(i+1))
print "Wrote to file '%s'." % filename
if __name__ == '__main__':
import optparse
usage = "usage: %prog [-n] [-r]"
parser = optparse.OptionParser(usage, version="%prog 0.1.0")
parser.add_option("-n", type="int", dest="events",
help="number of events to store per run", default=1000)
parser.add_option("-r", type="int", dest="runs",
help="number of runs", default=1)
parser.add_option("--time", action="store_true", dest="time",
help="append time string to filename", default=False)
(options, args) = parser.parse_args()
if len(args) < 1:
sys.exit(parser.format_help())
if options.events < 1 or options.runs < 1:
sys.exit("Please specify a number >= 1 for number of events/runs")
if options.runs == 1 and not options.time:
fetch(args[0], options.events)
else:
import time
import string
for i in range(options.runs):
timestr = string.replace(time.asctime(time.localtime()), ' ', '-')
filename = args[0] + '_' + timestr + '.hdf5'
print '-' * 65
print 'Saving to file %s' % filename
print '-' * 65
try:
fetch(filename, options.events)
except KeyboardInterrupt:
break