annotate sitesurvey.py @ 31:c6c86dcb54ba

Add code to automate a sitesurvey (to some degree).
author Daniel O'Connor <darius@dons.net.au>
date Wed, 21 Sep 2011 15:00:24 +0930
parents
children 660a2997e720
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
31
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
1 #!/usr/bin/env python
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
2
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
3 # Copyright (c) 2011
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
4 # Daniel O'Connor <darius@dons.net.au>. All rights reserved.
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
5 #
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
6 # Redistribution and use in source and binary forms, with or without
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
7 # modification, are permitted provided that the following conditions
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
8 # are met:
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
9 # 1. Redistributions of source code must retain the above copyright
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
10 # notice, this list of conditions and the following disclaimer.
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
11 # 2. Redistributions in binary form must reproduce the above copyright
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
12 # notice, this list of conditions and the following disclaimer in the
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
13 # documentation and/or other materials provided with the distribution.
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
14 #
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
15 # THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
16 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
17 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
18 # ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
19 # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
20 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
21 # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
22 # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
23 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
24 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
25 # SUCH DAMAGE.
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
26 #
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
27
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
28 import calendar
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
29 import ConfigParser
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
30 import datetime
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
31 import exceptions
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
32 import numpy
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
33 import os
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
34 import scpi
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
35 import specan
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
36 import sys
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
37 import time
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
38
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
39 defaults = {}
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
40 confname = "sitesurvey.ini"
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
41 confpaths = [ ".", os.path.dirname(os.path.realpath(sys.argv[0]))]
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
42
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
43 class Experiment(object):
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
44 def __init__(self, conf, name):
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
45 if not conf.has_section(name):
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
46 raise exceptions.KeyError("No section for experiment " + name)
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
47
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
48 self.name = name
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
49 self.recurrence = None
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
50 self.opts = {}
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
51 for k, v in conf.items(name):
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
52 if k == "recurrence":
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
53 # In seconds
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
54 self.recurrence = int(v)
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
55 continue
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
56
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
57 try:
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
58 self.opts[k] = int(v)
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
59 except exceptions.ValueError, e:
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
60 try:
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
61 self.opts[k] = float(v)
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
62 except exceptions.ValueError, e:
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
63 self.opts[k] = v
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
64
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
65 if self.recurrence == None:
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
66 raise exceptions.KeyError("Mandatory parameter 'recurrence' is missing")
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
67 self.recurrence = datetime.timedelta(seconds = self.recurrence)
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
68
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
69 self.last_run = None
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
70
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
71 def __repr__(self):
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
72 return "<" + self.name + ">"
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
73
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
74 class CalFile(object):
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
75 def __init__(self, fname):
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
76 f = file(fname)
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
77 if f.readline().strip() != "Frequencies":
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
78 raise exceptions.SyntaxError("Format of cal file incorrect (frequencies header missing)")
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
79 freqs = numpy.fromstring(f.readline().strip(), sep = ',')
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
80 if f.readline().strip() != "Gain":
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
81 raise exceptions.SyntaxError("Format of cal file incorrect (gains header missing)")
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
82 gains = numpy.fromstring(f.readline().strip(), sep = ',')
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
83 if len(gains) != len(freqs):
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
84 raise exceptions.SyntaxError("Format of cal file incorrect (length of gain and freqs aren't equal)")
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
85
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
86 self.calfreqs = freqs
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
87 self.calgains = gains
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
88
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
89 def interp(self, freqs):
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
90 '''Interoplate the calibration over freqs and return an array'''
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
91 deltas = numpy.zeros(freqs.shape)
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
92
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
93 for i in range(len(freqs)):
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
94 if freqs[i] < self.calfreqs[0] or freqs[i] > self.calfreqs[-1]:
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
95 raise exceptions.SyntaxError("Frequency %.1f is out of range of calibration %f - %f" % (f, calfreqs[0], calfreqs[-1]))
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
96
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
97 # Find idx such that calfreqs[idx - 1] < freqs[i] <= calfreqs[idx]
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
98 idx = self.calfreqs.searchsorted(freqs[i])
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
99 sf = (freqs[i] - self.calfreqs[idx - 1]) / (self.calfreqs[idx] - self.calfreqs[idx - 1])
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
100 delta = ((self.calgains[idx] - self.calgains[idx - 1]) * sf) + self.calgains[idx]
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
101 deltas[i] = delta
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
102 return deltas
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
103
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
104
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
105 def getexpt(sequence):
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
106 '''Given a sequence return the experiment which should be run next and how long until it should start'''
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
107
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
108 now = datetime.datetime.utcnow()
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
109 #print "now is " + str(now)
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
110 soonestdly = None
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
111 soonestexp = None
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
112
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
113 for e in sequence:
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
114 #print "Looking at " + str(e)
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
115 # If an experiment has ever run do it now
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
116 if e.last_run == None:
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
117 return e, datetime.timedelta(0)
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
118
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
119 # Time until this experiment should be run
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
120 nextrun = e.last_run + e.recurrence
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
121 dly = nextrun - now
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
122 #print "Last run was at %s, nextrun at %s, rec = %s, dly = %s / %f" % (str(e.last_run), str(nextrun), str(e.recurrence), str(dly), dly.total_seconds())
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
123 # Haven't looked at an experiment yet or this one is sooner
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
124 if soonestdly == None or dly < soonestdly:
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
125 #print "sooner"
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
126 soonestdly = dly
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
127 soonestexp = e
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
128
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
129 if soonestdly < datetime.timedelta(0):
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
130 #print "Capping " + e.name + " to run now"
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
131 soonestdly = datetime.timedelta(0)
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
132
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
133 #print "Returning " + str(soonestexp)
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
134 return soonestexp, soonestdly
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
135
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
136 def getsweep(inst, conf):
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
137 print " Sending configuration"
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
138
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
139 for k in conf:
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
140 #time.sleep(0.3)
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
141 inst.setconf(k, conf[k])
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
142
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
143 # Otherwise the R&S doens't respond..
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
144 #time.sleep(0.3)
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
145 rconf = inst.dumpconf()
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
146 fstart = rconf['fstart']
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
147 fstop = rconf['fstop']
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
148 print " Configuration is " + str(rconf)
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
149
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
150 print " Fetching trace"
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
151 yaxis = inst.gettrace()
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
152 xaxis = numpy.arange(fstart, fstop, (fstop - fstart) / yaxis.shape[0])
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
153
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
154 return xaxis, yaxis, rconf
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
155
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
156 def savesweep(fname, exp, x, y):
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
157 f = open(fname, 'wb')
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
158 for k in exp:
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
159 f.write("%s %s\n" % (k.upper(), str(exp[k])))
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
160 f.write("XDATA ")
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
161 numpy.savetxt(f, [x], delimiter = ', ', fmt = '%.3f') # Produces a trailing \n
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
162 f.write("YDATA ")
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
163 numpy.savetxt(f, [y], delimiter = ', ', fmt = '%.3f')
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
164 del f
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
165
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
166 def total_seconds(td):
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
167 return (td.microseconds + (td.seconds + td.days * 24.0 * 3600.0) * 10.0**6) / 10.0**6
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
168
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
169 if __name__ == '__main__':
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
170 # Read in config file(s)
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
171 conf = ConfigParser.SafeConfigParser(defaults)
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
172 r = conf.read(map(lambda a: os.path.join(a, confname), confpaths))
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
173 if len(r) == 0:
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
174 print "Unable to find any configuration file(s)"
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
175 sys.exit(1)
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
176
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
177 if not conf.has_section('general'):
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
178 print "Configuration file doesn't have a 'general' section"
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
179 sys.exit(1)
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
180
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
181 if not conf.has_option('general', 'url'):
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
182 print "Configuration file doesn't have a 'url' option in the 'general' section"
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
183 sys.exit(1)
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
184
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
185 if not conf.has_option('general', 'type'):
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
186 print "Configuration file doesn't have a 'type' option in the 'general' section"
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
187 sys.exit(1)
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
188
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
189 if not conf.has_option('general', 'sequence'):
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
190 print "Configuration file doesn't have a 'sequence' option in the 'general' section"
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
191 sys.exit(1)
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
192
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
193 if not conf.has_option('general', 'fname'):
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
194 print "Configuration file doesn't have a 'fname' option in the 'general' section"
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
195 sys.exit(1)
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
196
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
197 if conf.has_option('general', 'ampcal'):
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
198 ampcal = CalFile(conf.get('general', 'ampcal'))
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
199 else:
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
200 ampcal = None
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
201
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
202 if conf.has_option('general', 'antcal'):
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
203 antcal = CalFile(conf.get('general', 'antcal'))
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
204 else:
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
205 antcal = None
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
206
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
207
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
208 sequence = []
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
209 seqnames = conf.get('general', 'sequence').split()
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
210 for e in seqnames:
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
211 sequence.append(Experiment(conf, e))
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
212
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
213 url = conf.get('general', 'url')
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
214 insttype = conf.get('general', 'type')
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
215 fnamefmt = conf.get('general', 'fname')
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
216
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
217 # Connect to the instrument
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
218 print "Connecting to " + url
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
219 con = scpi.instURL(url)
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
220 con.write("*IDN?")
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
221 idn = con.read()
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
222 print "Instrument is a " + idn
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
223
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
224 # Get class for this instrument & instantiate it
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
225 inst = specan.getInst(insttype)(con)
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
226
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
227 while True:
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
228 # Find the next experiment to run
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
229 exp, dly = getexpt(sequence)
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
230
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
231 # Sleep if necessary
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
232 dly = total_seconds(dly)
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
233 if dly > 1:
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
234 print "Sleeping for %.1f seconds" % (dly)
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
235 time.sleep(dly)
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
236
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
237 # Run it
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
238 print "--> Running experiment " + str(exp)
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
239 freqs, power, opts = getsweep(inst, exp.opts)
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
240
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
241 # Adjust power based on amplifier and antenna calibration
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
242 if ampcal != None:
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
243 adj = ampcal.interp(freqs)
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
244 power = power - adj
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
245
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
246 if antcal != None:
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
247 adj = antcal.interp(freqs)
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
248 power = power - adj
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
249
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
250 # Update last run time
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
251 exp.last_run = datetime.datetime.utcnow()
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
252
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
253 # Add some informative params
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
254 tsepoch = calendar.timegm(exp.last_run.utctimetuple())
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
255
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
256 extras = { 'timestamp' : exp.last_run,
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
257 'timestamp_hex' : '%08x' % (tsepoch),
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
258 'timestamp_dec' : '%d' % (tsepoch),
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
259 'tag' : exp.name,
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
260 }
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
261 opts = dict(opts.items() + extras.items())
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
262 fname = fnamefmt % opts
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
263
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
264 # Save data
c6c86dcb54ba Add code to automate a sitesurvey (to some degree).
Daniel O'Connor <darius@dons.net.au>
parents:
diff changeset
265 savesweep(fname, opts, freqs, power)