Skip to content

Commit

Permalink
Merge branch 'develop-0.9.3' of https://github.com/lneuhaus/pyrpl
Browse files Browse the repository at this point in the history
  • Loading branch information
leo10tt10 committed Jun 30, 2017
2 parents 8644cc4 + 2245332 commit bbcd312
Show file tree
Hide file tree
Showing 22 changed files with 166 additions and 93 deletions.
9 changes: 9 additions & 0 deletions pyrpl-0.9.3/setup.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[nosetests]
verbosity=3
nocapture=1
nologcapture=1
#logging-level=info # logging-level is set in config/nosetests_source.yml
with-coverage=1
cover-package=pyrpl
with-xunit=1
xunit-file=xunit.xml
24 changes: 12 additions & 12 deletions pyrpl/acquisition_module.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ def set_value(self, obj, val):
previous_state = obj.running_state
SelectProperty.set_value(self, obj, val)
if val == "running_single":
# acquire as fast as possible avg curves
# acquire as fast as possible trace_average curves
obj.setup()
elif val == "running_continuous":
if previous_state == 'stopped': # restart averaging...
Expand Down Expand Up @@ -283,12 +283,12 @@ class AcquisitionModule(Module):
public methods (All methods return immediately)
-----------------------------------------------
- single(): performs an asynchronous acquisition of avg curves.
- single(): performs an asynchronous acquisition of trace_average curves.
The function returns a promise of the result:
an object with a ready() function, and a get() function that
blocks until data is ready.
- continuous(): continuously acquires curves, and performs a
moving average over the avg last ones.
moving average over the trace_average last ones.
- pause(): stops the current acquisition without restarting the
averaging
- stop(): stops the current acquisition and restarts the averaging.
Expand All @@ -301,8 +301,8 @@ class AcquisitionModule(Module):
'paused', 'stopped'. Changing the flag actually performs the necessary
actions
- curve_name: name of the curve to create upon saving
- avg: number of averages in single (not to confuse with averaging per
point)
- trace_average: number of averages in single (not to confuse with
averaging per point)
- data_avg: array containing the current averaged curve
- current_avg: current number of averages
"""
Expand All @@ -327,12 +327,12 @@ class AcquisitionModule(Module):
# set future to run_continuous (irreversible) == call setup()
# - running_single/running_continuous -> pause/stop: pause acquisition

_gui_attributes = ['avg', 'curve_name']
_gui_attributes = ['trace_average', 'curve_name']

_setup_on_load = True # acquisition_modules need to be setup() once
# they are loaded
_signal_launcher = SignalLauncherAcquisitionModule
_setup_attributes = ['running_state', 'avg', 'curve_name']
_setup_attributes = ['running_state', 'trace_average', 'curve_name']
_run_future_cls = RunFuture
_curve_future_cls = CurveFuture

Expand All @@ -358,11 +358,11 @@ class AcquisitionModule(Module):
call of running_continuous.
""")

avg = IntProperty(doc="number of curves to average in single mode. In "
trace_average = IntProperty(doc="number of curves to average in single mode. In "
"continuous mode, a moving window average is "
"performed.",
default=1,
min=1)
default=1,
min=1)
curve_name = StringProperty(doc="name of the curve to save.")

def __init__(self, parent, name=None):
Expand Down Expand Up @@ -435,7 +435,7 @@ def curve(self, timeout=None):

def single_async(self):
"""
- Performs an asynchronous acquisition of avg curves.
- Performs an asynchronous acquisition of trace_average curves.
- If running_state is not stop, stops the current acquisition.
- Immediately returns a future object representing the curve.
- The curve can be retrieved by calling result(timeout) on the
Expand All @@ -459,7 +459,7 @@ def single(self, timeout=None):
def continuous(self):
"""
continuously acquires curves, and performs a moving
average over the avg last ones.
average over the trace_average last ones.
"""
self.running_state = 'running_continuous'
# return self._continuous_future
Expand Down
9 changes: 8 additions & 1 deletion pyrpl/async_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,14 @@ def sleep(delay):
timer = MainThreadTimer(new_delay * 1000)
timer.timeout.connect(loop.quit)
timer.start()
loop.exec_()
try:
loop.exec_()
except KeyboardInterrupt as e:
# try to recover from KeyboardInterrupt by finishing the current task
timer.setInterval(1)
timer.start()
loop.exec_()
raise e
# 2. For high-precision, manually process events 1-by-1 during the last ms
while default_timer() < end_time:
APP.processEvents()
1 change: 0 additions & 1 deletion pyrpl/hardware_modules/scope.py
Original file line number Diff line number Diff line change
Expand Up @@ -544,7 +544,6 @@ def _start_acquisition_rolling_mode(self):
self._trigger_source_register = 'off'
self._trigger_armed = True


def _rolling_mode_allowed(self):
"""
Only if duration larger than 0.1 s
Expand Down
3 changes: 2 additions & 1 deletion pyrpl/memory.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ def save(data, stream=None):
Dumper=ruamel.yaml.RoundTripDumper,
default_flow_style=False)
except:
logger.warning("ruamel.yaml could not be imported. Using yaml instead. Comments in config files will be lost.")
logger.debug("ruamel.yaml could not be imported. Using yaml instead. "
"Comments in config files will be lost.")
import yaml

# see http://stackoverflow.com/questions/13518819/avoid-references-in-pyyaml
Expand Down
2 changes: 1 addition & 1 deletion pyrpl/software_modules/lockbox/gainoptimizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def setup_loop(self):
self.phase = 0
self.current_gain_factor = self.lockbox.final_stage.gain_factor

def loop(self):
def loop(self, a):
if not self.lockbox.is_locked_and_final(loglevel=0):
setattr(self.parent, self.name, None)
self._clear()
Expand Down
17 changes: 10 additions & 7 deletions pyrpl/software_modules/lockbox/input.py
Original file line number Diff line number Diff line change
Expand Up @@ -285,9 +285,9 @@ def sweep_acquire(self):
trigger_delay=0,
duration=1./self.lockbox.asg.frequency,
ch1_active=True,
ch2_active=False,
ch2_active=True,
average=True,
avg=1, # trace_average
trace_average=1,
running_state='stopped',
rolling_mode=False)
scope.save_state("autosweep")
Expand Down Expand Up @@ -524,11 +524,10 @@ def expected_signal(self, setpoint):
return setpoint_in_output_unit / output.dc_gain




class IqQuadratureFactorProperty(FloatProperty):
""" this is a direct link to quadrature_factor because we want to
benefit from its validate_and_normalize function"""
def set_value(self, instance, value):
# super(IqQuadratureFactorProperty, self).set_value(instance, value)
instance.iq.quadrature_factor = value
return value

Expand All @@ -543,9 +542,13 @@ def set_value(self, instance, val):
except:
val = [val, val] # preferentially choose second order filter
instance.iq.bandwidth = val
super(IqFilterProperty, self).set_value(instance, val)
super(IqFilterProperty, self).set_value(instance,
self.get_value(instance))
return val

def get_value(self, instance):
return instance.iq.bandwidth

def valid_frequencies(self, module):
# only allow the low-pass filter options (exclude negative high-pass options)
return [v for v in module.iq.__class__.bandwidth.valid_frequencies(module.iq) if v >= 0]
Expand All @@ -564,7 +567,7 @@ class InputIq(InputSignal):

@property
def acbandwidth(self):
return self.mod_freq / 100.0
return self.mod_freq / 128.0

# mod_freq = ProxyProperty("iq.frequency")
# mod_amp = ProxyProperty("iq.amplitude")
Expand Down
14 changes: 14 additions & 0 deletions pyrpl/software_modules/lockbox/lockbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,20 @@ def relock_function(lockbox, loop):
while not self._relock_until_locked_loop._ended: # wait for locks to terminate
sleep(1.0)

def lock_until_locked(self, **kwargs):
self.lock(**kwargs)
return self.relock_until_locked(**kwargs)

def sleep_while_locked(self, time_to_sleep):
t0 = time()
while time() < t0 + time_to_sleep: # doesnt quit loop during time_for_measurement
if self.is_locked_and_final(loglevel=0):
sleep(0.1)
else:
self._logger.error('Error during measurement - cavity unlocked. Aborting sleep...')
return False
return True

def is_locked(self, input=None, loglevel=logging.INFO):
""" returns True if locked, else False. Also updates an internal
dict that contains information about the current error signals. The
Expand Down
13 changes: 10 additions & 3 deletions pyrpl/software_modules/lockbox/models/fabryperot.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from .. import *
from .interferometer import Interferometer

from ....errors import TimeoutError

class Lorentz(object):
""" base class for Lorentzian-like signals"""
Expand Down Expand Up @@ -206,7 +206,14 @@ def sweep_acquire_zoom(self, threshold, input2=None):
curves = scope.curve_async()
self.lockbox._sweep() # start sweep only after arming the scope
# give some extra (10x) timeout time in case the trigger is missed
curve1, curve2 = curves.await_result(timeout=10./self.lockbox.asg.frequency+scope.duration)
try:
curve1, curve2 = curves.await_result(timeout=100./self.lockbox.asg.frequency+scope.duration)
except TimeoutError:
# scope is blocked
self._logger.warning("Signal %s could not be calibrated because no trigger was detected while "
"sweeping the cavity before the expiration of a timeout of %.1e s!",
self.name, 100./self.lockbox.asg.frequency+scope.duration)
return None, None, None
times = scope.times
self.calibration_data._asg_phase = self.lockbox.asg.scopetriggerphase
return curve1, curve2, times
Expand Down Expand Up @@ -258,7 +265,7 @@ def get_threshold_theoretical(self, curve):
self.calibration_data.get_stats_from_curve(curve)
eta = max(0.0, min(self.lockbox.eta, 1.0))
self.calibration_data.min = (1.0-eta) * self.calibration_data.max
threshold = self.expected_signal(0.5*self.lockbox._unit_in_setpoint_unit('bandwidth'))
threshold = self.expected_signal(1.0*self.lockbox._unit_in_setpoint_unit('bandwidth'))
self.calibration_data.setup_attributes = calibration_params
return threshold

Expand Down
4 changes: 3 additions & 1 deletion pyrpl/software_modules/lockbox/stage.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ class StageOutput(LockboxModule):
_widget_class = StageOutputWidget
lock_on = BoolIgnoreProperty(default=False, call_setup=True)
reset_offset = BoolProperty(default=False, call_setup=True)
offset = FloatProperty(default=0, min=-1., max=1., call_setup=True)
offset = FloatProperty(default=0, min=-1., max=1.,
increment=1e-4,
call_setup=True)

def _setup(self):
# forward changes to parent module
Expand Down
2 changes: 1 addition & 1 deletion pyrpl/software_modules/loop.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ def __init__(self, *args, **kwargs):

def plotappend(self, *args, **kwargs):
if self.plot:
if hasattr(self, 'plotter'):
if self.plotter is not None:
setattr(self.parent, self.plotter, (args, kwargs))
else:
try:
Expand Down
18 changes: 9 additions & 9 deletions pyrpl/software_modules/network_analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ def _scan_finished(self):
# in case the user wants to move on with running_continuous mode
self.current_point = 0
self._module.running_state = "paused"
self.current_avg = min(self.current_avg + 1, self._module.avg)
self.current_avg = min(self.current_avg + 1, self._module.trace_average)

def _set_run_continuous(self):
self._run_continuous = True
Expand Down Expand Up @@ -293,12 +293,12 @@ class NetworkAnalyzer(AcquisitionModule, SignalModule):
"logscale",
"infer_open_loop_tf"]
_setup_attributes = _gui_attributes + ['running_state']
avg = IntProperty(doc="number of curves to average in single mode. In "
"continuous mode, a decaying average with a "
"characteristic memory of 'avg' curves is "
"performed.",
default=10,
min=1)
trace_average = IntProperty(doc="number of curves to average in single mode. In "
"continuous mode, a decaying average with a "
"characteristic memory of 'trace_average' "
"curves is performed.",
default=10,
min=1)
input = InputSelectProperty(default='networkanalyzer',
call_setup=True,
ignore_errors=True)
Expand Down Expand Up @@ -506,12 +506,12 @@ def _get_point(self, index):
y /= tf
return y, amp

def take_ringdown(self, frequency, rbw=1000, points=1000, avg=1):
def take_ringdown(self, frequency, rbw=1000, points=1000, trace_average=1):
self.start_freq = frequency
self.stop_freq = frequency
self.rbw = rbw
self.points = points
self.avg = avg
self.trace_average = trace_average
curve = self.single_async()
sleep(0.1)
self.iq.output_direct = "off"
Expand Down
2 changes: 1 addition & 1 deletion pyrpl/software_modules/software_pid.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ class SoftwarePidController(Module):
plot = BoolProperty(default=True)
plotter = Plotter(legend='error (red, V) and output (green, V)') # plotting window
running = RunningProperty(default=False)
_setup_attributes = ['p', 'i', 'd', 'setpoint', 'reset_ival_on_restart',
_setup_attributes = ['input', 'output', 'p', 'i', 'd', 'setpoint', 'reset_ival_on_restart',
'interval', 'plot', 'running']
_gui_attributes = _setup_attributes + ["plotter"]

Expand Down
17 changes: 11 additions & 6 deletions pyrpl/test/test_hardware_modules/test_na_iir.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ def test_iirsimple_na_generator(self):
stop_freq=1e6,
points=301,
rbw=[500, 500],
avg=1,
average_per_point=1,
trace_average=1,
amplitude=0.005,
input=iir,
output_direct='off',
Expand Down Expand Up @@ -139,12 +140,13 @@ def test_iircomplicated_na_generator(self):
stop_freq=50e3,
points=2001,
rbw=[500, 500],
avg=1,
average_per_point=1,
trace_average=1,
amplitude=0.05,
input=iir,
output_direct='off',
logscale=True)
error_threshold = 0.05 # [0.01, 0.03] works if avg=10 in naset
error_threshold = 0.05 # [0.01, 0.03] works if average_per_point=10 in naset
params.append((z, p, g, loops, naset, "low_sampling", error_threshold,
['final', 'continuous']))

Expand All @@ -157,7 +159,8 @@ def test_iircomplicated_na_generator(self):
stop_freq=10e6,
points=1001,
rbw=[500, 500],
avg=1,
average_per_point=1,
trace_average=1,
amplitude=0.05,
input=iir,
output_direct='off',
Expand Down Expand Up @@ -186,7 +189,8 @@ def test_iircomplicated_na_generator(self):
stop_freq=50e3,
points=2501,
rbw=[1000, 1000],
avg=5,
average_per_point=5,
trace_average=1,
amplitude=0.02,
input=iir,
output_direct='off',
Expand All @@ -205,7 +209,8 @@ def test_iircomplicated_na_generator(self):
stop_freq=500e3,
points=301,
rbw=1000,
avg=1,
average_per_point=1,
trace_average=1,
amplitude=0.01,
input='iir',
output_direct='off',
Expand Down
Loading

0 comments on commit bbcd312

Please sign in to comment.