From f3567ec50ae6ea6563ee6d5cf1d51b38bd0640dd Mon Sep 17 00:00:00 2001
From: Giulio Ungaretti <giulioungaretti@me.com>
Date: Sun, 5 Mar 2017 22:51:49 +0100
Subject: [PATCH 01/36] remove metaclass

---
 qcodes/instrument/base.py      | 1 +
 qcodes/instrument/metaclass.py | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/qcodes/instrument/base.py b/qcodes/instrument/base.py
index 0a2ac8a4299..db7dfa0c269 100644
--- a/qcodes/instrument/base.py
+++ b/qcodes/instrument/base.py
@@ -95,6 +95,7 @@ def __init__(self, name, server_name=None, **kwargs):
         self._meta_attrs = ['name']
 
         self._no_proxy_methods = {'__getstate__'}
+        self.record_instance(self)
 
     def get_idn(self):
         """
diff --git a/qcodes/instrument/metaclass.py b/qcodes/instrument/metaclass.py
index 641028ab8df..2d5ceca65d7 100644
--- a/qcodes/instrument/metaclass.py
+++ b/qcodes/instrument/metaclass.py
@@ -40,6 +40,6 @@ def __call__(cls, *args, server_name=None, **kwargs):
 
         # for RemoteInstrument, we want to record this instance with the
         # class that it proxies, not with RemoteInstrument itself
-        cls.record_instance(instrument)
+        # cls.record_instance(instrument)
 
         return instrument

From ff7b8799891e7edd052a457d9bc603c551e81ee3 Mon Sep 17 00:00:00 2001
From: Giulio Ungaretti <giulioungaretti@me.com>
Date: Mon, 6 Mar 2017 00:21:34 +0100
Subject: [PATCH 02/36] first step in removing the metaclass

---
 qcodes/instrument/base.py       | 1 -
 qcodes/instrument/metaclass.py  | 7 ++++---
 qcodes/tests/test_instrument.py | 8 ++++++++
 3 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/qcodes/instrument/base.py b/qcodes/instrument/base.py
index db7dfa0c269..c131f7b9663 100644
--- a/qcodes/instrument/base.py
+++ b/qcodes/instrument/base.py
@@ -220,7 +220,6 @@ def record_instance(cls, instance):
         """
         wr = weakref.ref(instance)
         name = instance.name
-
         # First insert this instrument in the record of *all* instruments
         # making sure its name is unique
         existing_wr = cls._all_instruments.get(name)
diff --git a/qcodes/instrument/metaclass.py b/qcodes/instrument/metaclass.py
index 2d5ceca65d7..3e4593a29d2 100644
--- a/qcodes/instrument/metaclass.py
+++ b/qcodes/instrument/metaclass.py
@@ -35,11 +35,12 @@ def __call__(cls, *args, server_name=None, **kwargs):
         else:
             warnings.warn('Multiprocessing is in beta, use at own risk',
                           UserWarning)
+
             instrument = RemoteInstrument(*args, instrument_class=cls,
                                           server_name=server_name, **kwargs)
 
-        # for RemoteInstrument, we want to record this instance with the
-        # class that it proxies, not with RemoteInstrument itself
-        # cls.record_instance(instrument)
+            # for RemoteInstrument, we want to record this instance with the
+            # class that it proxies, not with RemoteInstrument itself
+            cls.record_instance(instrument)
 
         return instrument
diff --git a/qcodes/tests/test_instrument.py b/qcodes/tests/test_instrument.py
index 434f0ae1148..8dc5703de62 100644
--- a/qcodes/tests/test_instrument.py
+++ b/qcodes/tests/test_instrument.py
@@ -1,6 +1,7 @@
 """
 Test suite for  instument.*
 """
+import gc
 from datetime import datetime, timedelta
 from unittest import TestCase
 import time
@@ -211,6 +212,13 @@ def test_creation_failure(self):
         name = 'gatesFailing2'
         with self.assertRaises(ValueError):
             GatesBadDelayValue(model=self.model, name=name, server_name=None)
+        # gc is confused by the context manager we just used
+        # we want to make sure the ojbect we just tried to create
+        # but it threw an exception is properly gc'ed. Which
+        # is what happens wihtout the context manager AND
+        # it's how the __del__ method is supposed to work.
+
+        gc.collect()
 
         # this instrument should not be in the instance list
         with self.assertRaises(KeyError):

From 0676d7aaa62332aff2c94e162efd8ff4a52062e3 Mon Sep 17 00:00:00 2001
From: Giulio Ungaretti <giulioungaretti@me.com>
Date: Mon, 6 Mar 2017 12:01:33 +0100
Subject: [PATCH 03/36] fix: Remove background

---
 qcodes/__init__.py        |   2 +-
 qcodes/loops.py           | 144 ++-------------------
 qcodes/tests/test_loop.py | 265 +-------------------------------------
 3 files changed, 13 insertions(+), 398 deletions(-)

diff --git a/qcodes/__init__.py b/qcodes/__init__.py
index 859bcaf45dd..4243cf3c2cb 100644
--- a/qcodes/__init__.py
+++ b/qcodes/__init__.py
@@ -40,7 +40,7 @@
     from qcodes.widgets.widgets import show_subprocess_widget
 
 from qcodes.station import Station
-from qcodes.loops import get_bg, halt_bg, Loop
+from qcodes.loops import Loop
 from qcodes.measure import Measure
 from qcodes.actions import Task, Wait, BreakIf
 
diff --git a/qcodes/loops.py b/qcodes/loops.py
index ebec726a46c..5c13f553728 100644
--- a/qcodes/loops.py
+++ b/qcodes/loops.py
@@ -48,18 +48,15 @@
 
 from datetime import datetime
 import logging
-import multiprocessing as mp
 import time
 import numpy as np
 import warnings
 
-from qcodes import config
 from qcodes.station import Station
 from qcodes.data.data_set import new_data, DataMode
 from qcodes.data.data_array import DataArray
 from qcodes.data.manager import get_data_manager
 from qcodes.utils.helpers import wait_secs, full_class, tprint
-from qcodes.process.qcodes_process import QcodesProcess
 from qcodes.utils.metadata import Metadatable
 
 from .actions import (_actions_snapshot, Task, Wait, _Measure, _Nest,
@@ -67,71 +64,7 @@
 
 
 log = logging.getLogger(__name__)
-# Switches off multiprocessing by default, cant' be altered after module
-USE_MP = config.core.legacy_mp
-MP_NAME = 'Measurement'
-
-
-def get_bg(return_first=False):
-    """
-    Find the active background measurement process, if any
-    returns None otherwise.
-
-    Todo:
-        RuntimeError message is really hard to understand.
-    Args:
-        return_first(bool): if there are multiple loops running return the
-                            first anyway.
-    Raises:
-        RuntimeError: if multiple loops are active and return_first is False.
-    Returns:
-        Union[loop, None]: active loop or none if no loops are active
-    """
-    processes = mp.active_children()
-    loops = [p for p in processes if getattr(p, 'name', '') == MP_NAME]
-
-    if len(loops) > 1 and not return_first:
-        raise RuntimeError('Oops, multiple loops are running???')
-
-    if loops:
-        return loops[0]
-
-    # if we got here, there shouldn't be a loop running. Make sure the
-    # data manager, if there is one, agrees!
-    _clear_data_manager()
-    return None
-
-
-def halt_bg(timeout=5, traceback=True):
-    """
-    Stop the active background measurement process, if any.
-
-    Args:
-        timeout (int): seconds to wait for a clean exit before forcibly
-         terminating.
-
-        traceback (bool):  whether to print a traceback at the point of
-         interrupt, for debugging purposes.
-    """
-    loop = get_bg(return_first=True)
-    if not loop:
-        print('No loop running')
-        return
-
-    if traceback:
-        signal_ = ActiveLoop.HALT_DEBUG
-    else:
-        signal_ = ActiveLoop.HALT
-
-    loop.signal_queue.put(signal_)
-    loop.join(timeout)
-
-    if loop.is_alive():
-        loop.terminate()
-        loop.join(timeout/2)
-        print('Background loop did not respond to halt signal, terminated')
-
-    _clear_data_manager()
+USE_MP=False
 
 
 def _clear_data_manager():
@@ -139,13 +72,6 @@ def _clear_data_manager():
     if dm and dm.ask('get_measuring'):
         dm.ask('finalize_data')
 
-# TODO(giulioungaretti) remove dead code
-# def measure(*actions):
-#     # measure has been moved into Station
-#     # TODO - for all-at-once parameters we want to be able to
-#     # store the output into a DataSet without making a Loop.
-#     pass
-
 
 class Loop(Metadatable):
     """
@@ -314,7 +240,7 @@ def run_temp(self, *args, **kwargs):
         shortcut to run a loop in the foreground as a temporary dataset
         using the default measurement set
         """
-        return self.run(*args, background=False, quiet=True,
+        return self.run(*args, quiet=True,
                         data_manager=False, location=False, **kwargs)
 
     def then(self, *actions, overwrite=False):
@@ -426,22 +352,13 @@ def __init__(self, sweep_values, delay, *actions, then_actions=(),
         self.bg_min_delay = bg_min_delay
         self.data_set = None
 
-        # compile now, but don't save the results
-        # just used for preemptive error checking
-        # if we saved the results, we wouldn't capture nesting
-        # nor would we be able to reuse an ActiveLoop multiple times
-        # within one outer Loop.
-        # TODO: this doesn't work, because _Measure needs the data_set,
-        # which doesn't exist yet - do we want to make a special "dry run"
-        # mode, or is it sufficient to let errors wait until .run()?
-        # self._compile_actions(actions)
-
         # if the first action is another loop, it changes how delays
         # happen - the outer delay happens *after* the inner var gets
         # set to its initial value
         self._nest_first = hasattr(actions[0], 'containers')
 
         # for sending halt signals to the loop
+        import multiprocessing as mp
         self.signal_queue = mp.Queue()
 
         self._monitor = None  # TODO: how to specify this?
@@ -754,18 +671,16 @@ def run_temp(self, **kwargs):
         especially for use in composite parameters that need to run a Loop
         as part of their get method
         """
-        return self.run(background=False, quiet=True,
-                        data_manager=False, location=False, **kwargs)
+        return self.run(quiet=True, data_manager=USE_MP, location=False,
+                **kwargs)
 
-    def run(self, background=USE_MP, use_threads=False, quiet=False,
+    def run(self, use_threads=False, quiet=False,
             data_manager=USE_MP, station=None, progress_interval=False,
             *args, **kwargs):
         """
         Execute this loop.
 
         Args:
-            background: (default False) run this sweep in a separate process
-                so we can have live plotting and other analysis in the main process
             use_threads: (default False): whenever there are multiple `get` calls
                 back-to-back, execute them in separate threads so they run in
                 parallel (as long as they don't block each other)
@@ -803,21 +718,8 @@ def run(self, background=USE_MP, use_threads=False, quiet=False,
         if progress_interval is not False:
             self.progress_interval = progress_interval
 
-        prev_loop = get_bg()
-        if prev_loop:
-            if not quiet:
-                print('Waiting for the previous background Loop to finish...',
-                      flush=True)
-            prev_loop.join()
-
         data_set = self.get_data_set(data_manager, *args, **kwargs)
 
-        if background and not getattr(data_set, 'data_manager', None):
-            warnings.warn(
-                'With background=True you must also set data_manager=True '
-                'or you will not be able to sync your DataSet.',
-                UserWarning)
-
         self.set_common_attrs(data_set=data_set, use_threads=use_threads,
                               signal_queue=self.signal_queue)
 
@@ -831,47 +733,17 @@ def run(self, background=USE_MP, use_threads=False, quiet=False,
         ts = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
         data_set.add_metadata({'loop': {
             'ts_start': ts,
-            'background': background,
             'use_threads': use_threads,
             'use_data_manager': (data_manager is not False)
         }})
 
         data_set.save_metadata()
 
-        if prev_loop and not quiet:
-            print('...done. Starting ' + (data_set.location or 'new loop'),
-                  flush=True)
-
         try:
-            if background:
-                warnings.warn("Multiprocessing is in beta, use at own risk",
-                              UserWarning)
-                p = QcodesProcess(target=self._run_wrapper, name=MP_NAME)
-                p.is_sweep = True
-                p.signal_queue = self.signal_queue
-                p.start()
-                self.process = p
-
-                # now that the data_set we created has been put in the loop
-                # process, this copy turns into a reader
-                # if you're not using a DataManager, it just stays local
-                # and sync() reads from disk
-                if self.data_set.mode == DataMode.PUSH_TO_SERVER:
-                    self.data_set.mode = DataMode.PULL_FROM_SERVER
-                self.data_set.sync()
-            else:
-                if hasattr(self, 'process'):
-                    # in case this ActiveLoop was run before in the background
-                    del self.process
-
-                self._run_wrapper()
-
-                if self.data_set.mode != DataMode.LOCAL:
-                    self.data_set.sync()
-
+            self._run_wrapper()
             ds = self.data_set
-
         finally:
+
             if not quiet:
                 print(repr(self.data_set))
                 print(datetime.now().strftime('started at %Y-%m-%d %H:%M:%S'))
diff --git a/qcodes/tests/test_loop.py b/qcodes/tests/test_loop.py
index fff3414ba82..a50aeb356f4 100644
--- a/qcodes/tests/test_loop.py
+++ b/qcodes/tests/test_loop.py
@@ -1,262 +1,17 @@
 from datetime import datetime
-import logging
-import multiprocessing as mp
-import numpy as np
 import time
 from unittest import TestCase
 from unittest.mock import patch
 
-from qcodes.loops import (Loop, MP_NAME, get_bg, halt_bg, ActiveLoop,
-                          _DebugInterrupt)
+from qcodes.loops import Loop, ActiveLoop, _DebugInterrupt
 from qcodes.actions import Task, Wait, BreakIf
 from qcodes.station import Station
-from qcodes.data.io import DiskIO
 from qcodes.data.data_array import DataArray
-from qcodes.data.manager import get_data_manager
-from qcodes.instrument.mock import ArrayGetter
-from qcodes.instrument.parameter import Parameter, ManualParameter
-from qcodes.process.helpers import kill_processes
-from qcodes.process.qcodes_process import QcodesProcess
+from qcodes.instrument.parameter import ManualParameter
 from qcodes.utils.validators import Numbers
 from qcodes.utils.helpers import LogCapture
 
-from .instrument_mocks import (AMockModel, MockGates, MockSource, MockMeter,
-                               MultiGetter)
-
-
-class TestMockInstLoop(TestCase):
-    def setUp(self):
-        get_data_manager().restart(force=True)
-        kill_processes()
-        # TODO: figure out what's leaving DataManager in a weird state
-        # and fix it
-        get_data_manager().restart(force=True)
-        time.sleep(0.1)
-
-        self.model = AMockModel()
-
-        self.gates = MockGates(model=self.model, server_name='')
-        self.source = MockSource(model=self.model, server_name='')
-        self.meter = MockMeter(model=self.model, server_name='')
-        self.location = '_loop_test_'
-        self.location2 = '_loop_test2_'
-        self.io = DiskIO('.')
-
-        c1 = self.gates.chan1
-        self.loop = Loop(c1[1:5:1], 0.001).each(c1)
-        self.loop_progress = Loop(c1[1:5:1], 0.001,
-                                  progress_interval=1).each(c1)
-
-        self.assertFalse(self.io.list(self.location))
-        self.assertFalse(self.io.list(self.location2))
-
-    def tearDown(self):
-        for instrument in [self.gates, self.source, self.meter]:
-            instrument.close()
-
-        get_data_manager().close()
-        self.model.close()
-
-        self.io.remove_all(self.location)
-        self.io.remove_all(self.location2)
-
-    def check_empty_data(self, data):
-        expected = repr([float('nan')] * 4)
-        self.assertEqual(repr(data.gates_chan1.tolist()), expected)
-        self.assertEqual(repr(data.gates_chan1_set.tolist()), expected)
-
-    def check_loop_data(self, data):
-        self.assertEqual(data.gates_chan1.tolist(), [1, 2, 3, 4])
-        self.assertEqual(data.gates_chan1_set.tolist(), [1, 2, 3, 4])
-
-        self.assertTrue(self.io.list(self.location))
-
-    def test_background_and_datamanager(self):
-        # make sure that an unpicklable instrument can indeed run in a loop
-        # because the instrument itself is in a server
-
-        # TODO: if we don't save the dataset (location=False) then we can't
-        # sync it when we're done. Should fix that - for now that just means
-        # you can only do in-memory loops if you set data_manager=False
-        # TODO: this is the one place we don't do quiet=True - test that we
-        # really print stuff?
-        data = self.loop.run(location=self.location, background=True, data_manager=True)
-        self.check_empty_data(data)
-
-        # wait for process to finish (ensures that this was run in the bg,
-        # because otherwise there *is* no loop.process)
-        self.loop.process.join()
-
-        data.sync()
-        self.check_loop_data(data)
-
-    def test_local_instrument(self):
-        # a local instrument should work in a foreground loop, but
-        # not in a background loop (should give a RuntimeError)
-        self.gates.close()  # so we don't have two gates with same name
-        gates_local = MockGates(model=self.model, server_name=None)
-        self.gates = gates_local
-        c1 = gates_local.chan1
-        loop_local = Loop(c1[1:5:1], 0.001).each(c1)
-
-        # if spawn, pickle will happen
-        if mp.get_start_method() == "spawn":
-            with self.assertRaises(RuntimeError):
-                loop_local.run(location=self.location,
-                               quiet=True,
-                               background=True)
-        # allow for *nix
-        # TODO(giulioungaretti) see what happens ?
-        # what is the expected beavhiour ?
-        # The RunimError will never be raised here, as the forkmethod
-        # won't try to pickle anything at all.
-        else:
-            logging.error("this should not be allowed, but for now we let it be")
-            loop_local.run(location=self.location, quiet=True)
-
-        data = loop_local.run(location=self.location2, background=False,
-                              quiet=True)
-        self.check_loop_data(data)
-
-    def test_background_no_datamanager(self):
-        # We don't support syncing data from a background process
-        # if not using a datamanager. See warning in ActiveLoop.run()
-        # So we expect the data to be empty even after running.
-        data = self.loop.run(location=self.location,
-                             background=True,
-                             data_manager=False,
-                             quiet=True)
-        self.check_empty_data(data)
-
-        self.loop.process.join()
-
-        data.sync()
-        self.check_empty_data(data)
-
-    def test_foreground_and_datamanager(self):
-        data = self.loop.run(location=self.location, background=False,
-                             quiet=True)
-        self.assertFalse(hasattr(self.loop, 'process'))
-
-        self.check_loop_data(data)
-
-    def test_foreground_no_datamanager_progress(self):
-        data = self.loop_progress.run(location=self.location, background=False,
-                                      data_manager=False, quiet=True)
-        self.assertFalse(hasattr(self.loop, 'process'))
-
-        self.check_loop_data(data)
-
-    @patch('qcodes.loops.tprint')
-    def test_progress_calls(self, tprint_mock):
-        data = self.loop_progress.run(location=self.location, background=False,
-                                      data_manager=False, quiet=True)
-        self.assertFalse(hasattr(self.loop, 'process'))
-
-        self.check_loop_data(data)
-        expected_calls = len(self.loop_progress.sweep_values) + 1
-        self.assertEqual(tprint_mock.call_count, expected_calls)
-
-        # now run again with no progress interval and check that we get no
-        # additional calls
-        data = self.loop_progress.run(location=False, background=False,
-                                      data_manager=False, quiet=True,
-                                      progress_interval=None)
-        self.assertFalse(hasattr(self.loop, 'process'))
-
-        self.check_loop_data(data)
-        self.assertEqual(tprint_mock.call_count, expected_calls)
-
-    def test_foreground_no_datamanager(self):
-        data = self.loop.run(location=self.location, background=False,
-                             data_manager=False, quiet=True)
-        self.assertFalse(hasattr(self.loop, 'process'))
-
-        self.check_loop_data(data)
-
-    def test_enqueue(self):
-        c1 = self.gates.chan1
-        loop = Loop(c1[1:5:1], 0.01).each(c1)
-        data1 = loop.run(location=self.location,
-                         quiet=True,
-                         background=True,
-                         data_manager=True)
-
-        # second running of the loop should be enqueued, blocks until
-        # the first one finishes.
-        # TODO: check what it prints?
-        data2 = loop.run(location=self.location2,
-                         quiet=True,
-                         background=True,
-                         data_manager=True)
-
-        data1.sync()
-        data2.sync()
-        self.assertEqual(data1.gates_chan1.tolist(), [1, 2, 3, 4])
-        for v in data2.gates_chan1:
-            self.assertTrue(np.isnan(v))
-
-        loop.process.join()
-        data2.sync()
-        self.assertEqual(data2.gates_chan1.tolist(), [1, 2, 3, 4])
-
-        # and while we're here, check that running a loop in the
-        # foreground *after* the background clears its .process
-        self.assertTrue(hasattr(loop, 'process'))
-        loop.run_temp()
-        self.assertFalse(hasattr(loop, 'process'))
-
-    def test_sync_no_overwrite(self):
-        # Test fix for 380, this tests that the setpoints are not incorrectly
-        # overwritten by data_set.sync() for this to happen with the original code
-        # the delay must be larger than the write period otherwise sync is a no opt.
-
-        loop = Loop(self.gates.chan1.sweep(0, 1, 1), delay=0.1).each(ArrayGetter(self.meter.amplitude,
-                                                                                 self.gates.chan2[0:1:1], 0.000001))
-        data = loop.get_data_set(name='testsweep', write_period=0.01)
-        _ = loop.with_bg_task(data.sync).run()
-        assert not np.isnan(data.chan2_set).any()
-
-def sleeper(t):
-    time.sleep(t)
-
-
-class TestBG(TestCase):
-    def test_get_halt(self):
-        kill_processes()
-        self.assertIsNone(get_bg())
-
-        p1 = QcodesProcess(name=MP_NAME, target=sleeper, args=(10, ))
-        p1.start()
-        p2 = QcodesProcess(name=MP_NAME, target=sleeper, args=(10, ))
-        p2.start()
-        p1.signal_queue = p2.signal_queue = mp.Queue()
-        qcodes_processes = [p for p in mp.active_children()
-                            if isinstance(p, QcodesProcess)]
-        self.assertEqual(len(qcodes_processes), 2, mp.active_children())
-
-        with self.assertRaises(RuntimeError):
-            get_bg()
-        bg1 = get_bg(return_first=True)
-        self.assertIn(bg1, [p1, p2])
-
-        halt_bg(timeout=0.05)
-        bg2 = get_bg()
-        self.assertIn(bg2, [p1, p2])
-        # is this robust? requires that active_children always returns the same
-        # order, even if it's not the order you started processes in
-        self.assertNotEqual(bg1, bg2)
-
-        self.assertEqual(len(mp.active_children()), 1)
-
-        halt_bg(timeout=0.05)
-        self.assertIsNone(get_bg())
-
-        self.assertEqual(len(mp.active_children()), 0)
-
-        # TODO - test that we print "no loops running"?
-        # at least this shows that it won't raise an error
-        halt_bg()
+from .instrument_mocks import MultiGetter
 
 
 class FakeMonitor:
@@ -279,9 +34,6 @@ def setUpClass(cls):
         cls.p3 = ManualParameter('p3', vals=Numbers(-10, 10))
         Station().set_measurement(cls.p2, cls.p3)
 
-    def setUp(self):
-        kill_processes()
-
     def test_nesting(self):
         loop = Loop(self.p1[1:3:1], 0.001).loop(
             self.p2[3:5:1], 0.001).loop(
@@ -402,15 +154,7 @@ def test_tasks_waits(self):
             self.p2)
         delay_array = []
         loop._monitor = FakeMonitor(delay_array)
-
-        # give it a "process" as if it was run in the bg before,
-        # check that this gets cleared
-        loop.process = 'TDD'
-
         data = loop.run_temp()
-
-        self.assertFalse(hasattr(loop, 'process'))
-
         self.assertEqual(data.p1_set.tolist(), [1, 2])
         self.assertEqual(data.p2_2.tolist(), [-1, -1])
         self.assertEqual(data.p2_4.tolist(), [1, 1])
@@ -690,7 +434,6 @@ def g():
                 'default_measurement': [p2snap, p3snap]
             },
             'loop': {
-                'background': False,
                 'use_threads': False,
                 'use_data_manager': False,
                 '__class__': 'qcodes.loops.ActiveLoop',
@@ -781,7 +524,7 @@ def test_halt(self):
             # need to use explicit loop.run rather than run_temp
             # so we can avoid providing location=False twice, which
             # is an error.
-            loop.run(background=False, data_manager=False, quiet=True)
+            loop.run(data_manager=False, quiet=True)
 
         self.check_data(data)
 

From 700e150a7ffde2613906e4a2d92e8e0a6e09555c Mon Sep 17 00:00:00 2001
From: Giulio Ungaretti <giulioungaretti@me.com>
Date: Mon, 6 Mar 2017 12:38:47 +0100
Subject: [PATCH 04/36] fix: remove alt-docs about monitor

---
 qcodes/loops.py           |  8 --------
 qcodes/tests/test_loop.py | 34 ----------------------------------
 2 files changed, 42 deletions(-)

diff --git a/qcodes/loops.py b/qcodes/loops.py
index 5c13f553728..86898cc204a 100644
--- a/qcodes/loops.py
+++ b/qcodes/loops.py
@@ -361,8 +361,6 @@ def __init__(self, sweep_values, delay, *actions, then_actions=(),
         import multiprocessing as mp
         self.signal_queue = mp.Queue()
 
-        self._monitor = None  # TODO: how to specify this?
-
     def then(self, *actions, overwrite=False):
         """
         Attach actions to be performed after the loop completes.
@@ -913,12 +911,6 @@ def _wait(self, delay):
         if delay:
             finish_clock = time.perf_counter() + delay
 
-            if self._monitor:
-                # TODO - perhpas pass self._check_signal in here
-                # so that we can halt within monitor.call if it
-                # lasts a very long time?
-                self._monitor.call(finish_by=finish_clock)
-
             while True:
                 self._check_signal()
                 t = wait_secs(finish_clock)
diff --git a/qcodes/tests/test_loop.py b/qcodes/tests/test_loop.py
index a50aeb356f4..0c44557b17f 100644
--- a/qcodes/tests/test_loop.py
+++ b/qcodes/tests/test_loop.py
@@ -14,18 +14,6 @@
 from .instrument_mocks import MultiGetter
 
 
-class FakeMonitor:
-    '''
-    when attached to an ActiveLoop as _monitor, records how long
-    the monitor was given to measure
-    '''
-    def __init__(self, delay_array):
-        self.delay_array = delay_array
-
-    def call(self, finish_by=None):
-        self.delay_array.append(finish_by - time.perf_counter())
-
-
 class TestLoop(TestCase):
     @classmethod
     def setUpClass(cls):
@@ -143,28 +131,6 @@ def test_func(*args, **kwargs):
 
         self.assertEqual(data.p2.tolist(), [2])
 
-    def test_tasks_waits(self):
-        delay0 = 0.01
-        delay1 = 0.03
-        loop = Loop(self.p1[1:3:1], delay0).each(
-            Task(self.p2.set, -1),
-            Wait(delay1),
-            self.p2,
-            Task(self.p2.set, 1),
-            self.p2)
-        delay_array = []
-        loop._monitor = FakeMonitor(delay_array)
-        data = loop.run_temp()
-        self.assertEqual(data.p1_set.tolist(), [1, 2])
-        self.assertEqual(data.p2_2.tolist(), [-1, -1])
-        self.assertEqual(data.p2_4.tolist(), [1, 1])
-
-        self.assertEqual(len(delay_array), 4)
-        for i, delay in enumerate(delay_array):
-            target = delay1 if i % 2 else delay0
-            self.assertLessEqual(delay, target)
-            self.assertGreater(delay, target - 0.001)
-
     @patch('time.sleep')
     def test_delay0(self, sleep_mock):
         self.p2.set(3)

From 01e066ecb518e0a2cb080c7c601b65593cc6afa2 Mon Sep 17 00:00:00 2001
From: Giulio Ungaretti <giulioungaretti@me.com>
Date: Mon, 6 Mar 2017 13:19:27 +0100
Subject: [PATCH 05/36] remove signal queue

---
 qcodes/loops.py           | 203 ++++++++++++++++----------------------
 qcodes/tests/test_loop.py |  60 +++--------
 2 files changed, 98 insertions(+), 165 deletions(-)

diff --git a/qcodes/loops.py b/qcodes/loops.py
index 86898cc204a..c20ce7430f3 100644
--- a/qcodes/loops.py
+++ b/qcodes/loops.py
@@ -330,12 +330,6 @@ class ActiveLoop(Metadatable):
     The *ActiveLoop* determines what *DataArray*\s it will need to hold the data
     it collects, and it creates a *DataSet* holding these *DataArray*\s
     """
-    # constants for signal_queue
-    HALT = 'HALT LOOP'
-    HALT_DEBUG = 'HALT AND DEBUG'
-
-    # maximum sleep time (secs) between checking the signal_queue for a HALT
-    signal_period = 1
 
     def __init__(self, sweep_values, delay, *actions, then_actions=(),
                  station=None, progress_interval=None, bg_task=None,
@@ -357,10 +351,6 @@ def __init__(self, sweep_values, delay, *actions, then_actions=(),
         # set to its initial value
         self._nest_first = hasattr(actions[0], 'containers')
 
-        # for sending halt signals to the loop
-        import multiprocessing as mp
-        self.signal_queue = mp.Queue()
-
     def then(self, *actions, overwrite=False):
         """
         Attach actions to be performed after the loop completes.
@@ -582,7 +572,7 @@ def _default_setpoints(self, shape):
 
         return sp
 
-    def set_common_attrs(self, data_set, use_threads, signal_queue):
+    def set_common_attrs(self, data_set, use_threads):
         """
         set a couple of common attributes that the main and nested loops
         all need to have:
@@ -590,21 +580,10 @@ def set_common_attrs(self, data_set, use_threads, signal_queue):
         - a queue for communicating with the main process
         """
         self.data_set = data_set
-        self.signal_queue = signal_queue
         self.use_threads = use_threads
         for action in self.actions:
             if hasattr(action, 'set_common_attrs'):
-                action.set_common_attrs(data_set, use_threads, signal_queue)
-
-    def _check_signal(self):
-        while not self.signal_queue.empty():
-            signal_ = self.signal_queue.get()
-            if signal_ == self.HALT:
-                raise _QuietInterrupt('sweep was halted')
-            elif signal_ == self.HALT_DEBUG:
-                raise _DebugInterrupt('sweep was halted')
-            else:
-                raise ValueError('unknown signal', signal_)
+                action.set_common_attrs(data_set, use_threads)
 
     def get_data_set(self, data_manager=USE_MP, *args, **kwargs):
         """
@@ -718,8 +697,7 @@ def run(self, use_threads=False, quiet=False,
 
         data_set = self.get_data_set(data_manager, *args, **kwargs)
 
-        self.set_common_attrs(data_set=data_set, use_threads=use_threads,
-                              signal_queue=self.signal_queue)
+        self.set_common_attrs(data_set=data_set, use_threads=use_threads)
 
         station = station or self.station or Station.default
         if station:
@@ -785,17 +763,16 @@ def _compile_one(self, action, new_action_indices):
             return action
 
     def _run_wrapper(self, *args, **kwargs):
-        try:
-            self._run_loop(*args, **kwargs)
-        except _QuietInterrupt:
-            pass
-        finally:
-            if hasattr(self, 'data_set'):
-                # somehow this does not show up in the data_set returned by
-                # run(), but it is saved to the metadata
-                ts = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
-                self.data_set.add_metadata({'loop': {'ts_end': ts}})
-                self.data_set.finalize()
+        # try:
+        self._run_loop(*args, **kwargs)
+        # finally:
+        if hasattr(self, 'data_set'):
+            # TODO (giulioungaretti) WTF?
+            # somehow this does not show up in the data_set returned by
+            # run(), but it is saved to the metadata
+            ts = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
+            self.data_set.add_metadata({'loop': {'ts_end': ts}})
+            self.data_set.finalize()
 
     def _run_loop(self, first_delay=0, action_indices=(),
                   loop_indices=(), current_values=(),
@@ -824,77 +801,74 @@ def _run_loop(self, first_delay=0, action_indices=(),
 
         self.last_task_failed = False
 
-        for i, value in enumerate(self.sweep_values):
-            if self.progress_interval is not None:
-                tprint('loop %s: %d/%d (%.1f [s])' % (
-                    self.sweep_values.name, i, imax, time.time() - t0),
-                    dt=self.progress_interval, tag='outerloop')
-
-            set_val = self.sweep_values.set(value)
-
-            new_indices = loop_indices + (i,)
-            new_values = current_values + (value,)
-            data_to_store = {}
-
-            if hasattr(self.sweep_values, "parameters"):
-                set_name = self.data_set.action_id_map[action_indices]
-                if hasattr(self.sweep_values, 'aggregate'):
-                    value = self.sweep_values.aggregate(*set_val)
-                self.data_set.store(new_indices, {set_name: value})
-                for j, val in enumerate(set_val):
-                    set_index = action_indices + (j+1, )
-                    set_name = (self.data_set.action_id_map[set_index])
-                    data_to_store[set_name] = val
-            else:
-                set_name = self.data_set.action_id_map[action_indices]
-                data_to_store[set_name] = value
-
-            self.data_set.store(new_indices, data_to_store)
-
-            if not self._nest_first:
-                # only wait the delay time if an inner loop will not inherit it
-                self._wait(delay)
-
-            try:
-                for f in callables:
-                    f(first_delay=delay,
-                      loop_indices=new_indices,
-                      current_values=new_values)
-
-                    # after the first action, no delay is inherited
-                    delay = 0
-            except _QcodesBreak:
-                break
-
-            # after the first setpoint, delay reverts to the loop delay
-            delay = self.delay
-
-            # now check for a background task and execute it if it's
-            # been long enough since the last time
-            # don't let exceptions in the background task interrupt
-            # the loop
-            # if the background task fails twice consecutively, stop
-            # executing it
-            if self.bg_task is not None:
-                t = time.time()
-                if t - last_task >= self.bg_min_delay:
-                    try:
-                        self.bg_task()
-                    except Exception:
-                        if self.last_task_failed:
-                            self.bg_task = None
-                        self.last_task_failed = True
-                        log.exception("Failed to execute bg task")
-
-                    last_task = t
-
-        if self.progress_interval is not None:
-            # final progress note: set dt=-1 so it *always* prints
-            tprint('loop %s DONE: %d/%d (%.1f [s])' % (
-
-                   self.sweep_values.name, i + 1, imax, time.time() - t0),
-                   dt=-1, tag='outerloop')
+        try:
+            for i, value in enumerate(self.sweep_values):
+                if self.progress_interval is not None:
+                    tprint('loop %s: %d/%d (%.1f [s])' % (
+                        self.sweep_values.name, i, imax, time.time() - t0),
+                        dt=self.progress_interval, tag='outerloop')
+
+                set_val = self.sweep_values.set(value)
+
+                new_indices = loop_indices + (i,)
+                new_values = current_values + (value,)
+                data_to_store = {}
+
+                if hasattr(self.sweep_values, "parameters"):
+                    set_name = self.data_set.action_id_map[action_indices]
+                    if hasattr(self.sweep_values, 'aggregate'):
+                        value = self.sweep_values.aggregate(*set_val)
+                    self.data_set.store(new_indices, {set_name: value})
+                    for j, val in enumerate(set_val):
+                        set_index = action_indices + (j+1, )
+                        set_name = (self.data_set.action_id_map[set_index])
+                        data_to_store[set_name] = val
+                else:
+                    set_name = self.data_set.action_id_map[action_indices]
+                    data_to_store[set_name] = value
+
+                self.data_set.store(new_indices, data_to_store)
+
+                if not self._nest_first:
+                    # only wait the delay time if an inner loop will not inherit it
+                    self._wait(delay)
+
+                try:
+                    for f in callables:
+                        f(first_delay=delay,
+                          loop_indices=new_indices,
+                          current_values=new_values)
+
+                        # after the first action, no delay is inherited
+                        delay = 0
+                except _QcodesBreak:
+                    break
 
+                # after the first setpoint, delay reverts to the loop delay
+                delay = self.delay
+
+                # now check for a background task and execute it if it's
+                # been long enough since the last time
+                # don't let exceptions in the background task interrupt
+                # the loop
+                # if the background task fails twice consecutively, stop
+                # executing it
+                if self.bg_task is not None:
+                    t = time.time()
+                    if t - last_task >= self.bg_min_delay:
+                        try:
+                            self.bg_task()
+                        except Exception:
+                            if self.last_task_failed:
+                                self.bg_task = None
+                            self.last_task_failed = True
+                            log.exception("Failed to execute bg task")
+
+                        last_task = t
+
+        except Interrupt:
+            log.debug("Stopping loop cleanly")
+            return
         # run the background task one last time to catch the last setpoint(s)
         if self.bg_task is not None:
             self.bg_task()
@@ -910,20 +884,9 @@ def _run_loop(self, first_delay=0, action_indices=(),
     def _wait(self, delay):
         if delay:
             finish_clock = time.perf_counter() + delay
-
-            while True:
-                self._check_signal()
-                t = wait_secs(finish_clock)
-                time.sleep(min(t, self.signal_period))
-                if t <= self.signal_period:
-                    break
-        else:
-            self._check_signal()
-
-
-class _QuietInterrupt(Exception):
-    pass
+            t = wait_secs(finish_clock)
+            time.sleep(t)
 
 
-class _DebugInterrupt(Exception):
+class Interrupt(Exception):
     pass
diff --git a/qcodes/tests/test_loop.py b/qcodes/tests/test_loop.py
index 0c44557b17f..cbe082bc7ff 100644
--- a/qcodes/tests/test_loop.py
+++ b/qcodes/tests/test_loop.py
@@ -1,9 +1,10 @@
 from datetime import datetime
 import time
 from unittest import TestCase
+import numpy as np
 from unittest.mock import patch
 
-from qcodes.loops import Loop, ActiveLoop, _DebugInterrupt
+from qcodes.loops import Loop, Interrupt
 from qcodes.actions import Task, Wait, BreakIf
 from qcodes.station import Station
 from qcodes.data.data_array import DataArray
@@ -450,70 +451,39 @@ def g():
 
 
 class AbortingGetter(ManualParameter):
-    '''
-    A manual parameter that can only be measured a couple of times
+    """
+    A manual parameter that can only be measured n times
     before it aborts the loop that's measuring it.
-
-    You have to attach the queue after construction with set_queue
-    so you can grab it from the loop that uses the parameter.
-    '''
+    """
     def __init__(self, *args, count=1, msg=None, **kwargs):
         self._count = self._initial_count = count
-        self.msg = msg
         # also need a _signal_queue, but that has to be added later
         super().__init__(*args, **kwargs)
 
     def get(self):
         self._count -= 1
         if self._count <= 0:
-            self._signal_queue.put(self.msg)
+            raise Interrupt
         return super().get()
 
-    def set_queue(self, queue):
-        self._signal_queue = queue
-
     def reset(self):
         self._count = self._initial_count
 
 
-class TestSignal(TestCase):
+class Test_halt(TestCase):
     def test_halt(self):
-        p1 = AbortingGetter('p1', count=2, vals=Numbers(-10, 10),
-                            msg=ActiveLoop.HALT_DEBUG)
-        loop = Loop(p1[1:6:1], 0.005).each(p1)
+        abort_after = 3
+        self.res = list(np.arange(0, abort_after-1, 1.))
+        [self.res.append(float('nan')) for i in range(0, abort_after-1)]
+
+        p1 = AbortingGetter('p1', count=abort_after, vals=Numbers(-10, 10))
+        loop = Loop(p1.sweep(0, abort_after, 1), 0.005).each(p1)
         # we want to test what's in data, so get it ahead of time
         # because loop.run will not return.
         data = loop.get_data_set(location=False)
-        p1.set_queue(loop.signal_queue)
-
-        with self.assertRaises(_DebugInterrupt):
-            # need to use explicit loop.run rather than run_temp
-            # so we can avoid providing location=False twice, which
-            # is an error.
-            loop.run(data_manager=False, quiet=True)
-
-        self.check_data(data)
 
-    def test_halt_quiet(self):
-        p1 = AbortingGetter('p1', count=2, vals=Numbers(-10, 10),
-                            msg=ActiveLoop.HALT)
-        loop = Loop(p1[1:6:1], 0.005).each(p1)
-        p1.set_queue(loop.signal_queue)
-
-        # does not raise, just quits, but the data set looks the same
-        # as in test_halt
-        data = loop.run_temp()
-        self.check_data(data)
-
-    def check_data(self, data):
-        nan = float('nan')
-        self.assertEqual(data.p1.tolist()[:2], [1, 2])
-        # when NaN is involved, I'll just compare reprs, because NaN!=NaN
-        self.assertEqual(repr(data.p1.tolist()[-2:]), repr([nan, nan]))
-        # because of the way the waits work out, we can get an extra
-        # point measured before the interrupt is registered. But the
-        # test would be valid either way.
-        self.assertIn(repr(data.p1[2]), (repr(nan), repr(3), repr(3.0)))
+        loop.run(data_manager=False, quiet=True)
+        self.assertEqual(repr(data.p1.tolist()), repr(self.res))
 
 
 class TestMetaData(TestCase):

From 5bf22e3b38ddadec23461767492fea0d835e5acb Mon Sep 17 00:00:00 2001
From: Giulio Ungaretti <giulioungaretti@me.com>
Date: Mon, 6 Mar 2017 14:08:56 +0100
Subject: [PATCH 06/36] fix: More backgroudn removal

---
 qcodes/measure.py                  | 7 ++-----
 qcodes/tests/test_hdf5formatter.py | 4 ++--
 qcodes/tests/test_measure.py       | 1 -
 3 files changed, 4 insertions(+), 8 deletions(-)

diff --git a/qcodes/measure.py b/qcodes/measure.py
index 17063fd38c4..782e07bc223 100644
--- a/qcodes/measure.py
+++ b/qcodes/measure.py
@@ -71,9 +71,6 @@ def run(self, use_threads=False, quiet=False, data_manager=USE_MP,
             a DataSet object containing the results of the measurement
         """
 
-        # background is not configurable, would be weird to run this in the bg
-        background = False
-
         data_set = self._dummyLoop.get_data_set(data_manager=data_manager,
                                                 **kwargs)
 
@@ -83,7 +80,7 @@ def run(self, use_threads=False, quiet=False, data_manager=USE_MP,
         data_set.location = False
 
         # run the measurement as if it were a Loop
-        self._dummyLoop.run(background=background, use_threads=use_threads,
+        self._dummyLoop.run(use_threads=use_threads,
                             station=station, quiet=True)
 
         # look for arrays that are unnecessarily nested, and un-nest them
@@ -128,7 +125,7 @@ def run(self, use_threads=False, quiet=False, data_manager=USE_MP,
         # puts in a 'loop' section that we need to replace with 'measurement'
         # but we use the info from 'loop' to ensure consistency and avoid
         # duplication.
-        LOOP_SNAPSHOT_KEYS = ['background', 'ts_start', 'ts_end',
+        LOOP_SNAPSHOT_KEYS = ['ts_start', 'ts_end',
                               'use_data_manager', 'use_threads']
         data_set.add_metadata({'measurement': {
             k: data_set.metadata['loop'][k] for k in LOOP_SNAPSHOT_KEYS
diff --git a/qcodes/tests/test_hdf5formatter.py b/qcodes/tests/test_hdf5formatter.py
index d1506998f18..4f759f1d8bf 100644
--- a/qcodes/tests/test_hdf5formatter.py
+++ b/qcodes/tests/test_hdf5formatter.py
@@ -137,7 +137,7 @@ def test_loop_writing(self):
         loop = Loop(MockPar.x[-100:100:20]).each(MockPar.skewed_parabola)
         data1 = loop.run(name='MockLoop_hdf5_test',
                          formatter=self.formatter,
-                         background=False, data_manager=False)
+                         data_manager=False)
         data2 = DataSet(location=data1.location, formatter=self.formatter)
         data2.read()
         for key in data2.arrays.keys():
@@ -159,7 +159,7 @@ def test_loop_writing_2D(self):
             MockPar.y[-50:50:10]).each(MockPar.skewed_parabola)
         data1 = loop.run(name='MockLoop_hdf5_test',
                          formatter=self.formatter,
-                         background=False, data_manager=False)
+                         data_manager=False)
         data2 = DataSet(location=data1.location, formatter=self.formatter)
         data2.read()
         for key in data2.arrays.keys():
diff --git a/qcodes/tests/test_measure.py b/qcodes/tests/test_measure.py
index 71d3c45d4c4..8563c34559e 100644
--- a/qcodes/tests/test_measure.py
+++ b/qcodes/tests/test_measure.py
@@ -25,7 +25,6 @@ def test_simple_scalar(self):
         meta = data.metadata['measurement']
         self.assertEqual(meta['__class__'], 'qcodes.measure.Measure')
         self.assertEqual(len(meta['actions']), 1)
-        self.assertFalse(meta['background'])
         self.assertFalse(meta['use_data_manager'])
         self.assertFalse(meta['use_threads'])
 

From f320b5d6cabfdfa3e5bbf5ccb48c750048d77009 Mon Sep 17 00:00:00 2001
From: Giulio Ungaretti <giulioungaretti@me.com>
Date: Mon, 6 Mar 2017 15:24:41 +0100
Subject: [PATCH 07/36] remove data_manager stuff

---
 qcodes/__init__.py                 |   2 +-
 qcodes/data/data_set.py            | 290 +++--------------------------
 qcodes/loops.py                    |  42 +----
 qcodes/measure.py                  |  14 +-
 qcodes/tests/test_data.py          | 140 +-------------
 qcodes/tests/test_format.py        |   4 +-
 qcodes/tests/test_hdf5formatter.py |   6 +-
 qcodes/tests/test_loop.py          |   4 +-
 qcodes/tests/test_measure.py       |   1 -
 9 files changed, 55 insertions(+), 448 deletions(-)

diff --git a/qcodes/__init__.py b/qcodes/__init__.py
index 4243cf3c2cb..b1b2644ccd9 100644
--- a/qcodes/__init__.py
+++ b/qcodes/__init__.py
@@ -45,7 +45,7 @@
 from qcodes.actions import Task, Wait, BreakIf
 
 from qcodes.data.manager import get_data_manager
-from qcodes.data.data_set import DataMode, DataSet, new_data, load_data
+from qcodes.data.data_set import DataSet, new_data, load_data
 from qcodes.data.location import FormatLocation
 from qcodes.data.data_array import DataArray
 from qcodes.data.format import Formatter
diff --git a/qcodes/data/data_set.py b/qcodes/data/data_set.py
index 98b3fa60c3a..d5407807b5d 100644
--- a/qcodes/data/data_set.py
+++ b/qcodes/data/data_set.py
@@ -1,35 +1,19 @@
 """DataSet class and factory functions."""
 
-from enum import Enum
 import time
 import logging
 from traceback import format_exc
 from copy import deepcopy
 from collections import OrderedDict
 
-from .manager import get_data_manager, NoData
 from .gnuplot_format import GNUPlotFormat
 from .io import DiskIO
 from .location import FormatLocation
 from qcodes.utils.helpers import DelegateAttributes, full_class, deep_update
 
 
-class DataMode(Enum):
-
-    """Server connection modes supported by a DataSet."""
-
-    LOCAL = 1
-    PUSH_TO_SERVER = 2
-    PULL_FROM_SERVER = 3
-
-
-SERVER_MODES = set((DataMode.PULL_FROM_SERVER, DataMode.PUSH_TO_SERVER))
-
-
 def new_data(location=None, loc_record=None, name=None, overwrite=False,
-             io=None, data_manager=False, mode=DataMode.LOCAL, **kwargs):
-    # NOTE(giulioungaretti): leave this docstrings as it is, because
-    # documenting the types is silly in this case.
+             io=None, **kwargs):
     """
     Create a new DataSet.
 
@@ -61,24 +45,6 @@ def new_data(location=None, loc_record=None, name=None, overwrite=False,
             says the root data directory is the current working directory, ie
             where you started the python session.
 
-        data_manager (Optional[bool]): use a manager for the
-            ``DataServer`` that offloads storage and syncing of this Defaults
-            to  ``False`` i.e. this ``DataSet`` will store itself without extra
-            processes. Set to ``True`` to use the default from
-            ``get_data_manager()``.
-
-        mode (DataMode, optional): connection type to the ``DataServer``.
-
-            - ``DataMode.LOCAL``: this DataSet doesn't communicate across
-              processes.
-            - ``DataMode.PUSH_TO_SERVER``: no local copy of data, just pushes
-              each measurement to a ``DataServer``.
-            - ``DataMode.PULL_FROM_SERVER``: pulls changes from the
-              ``DataServer`` on calling ``self.sync()``. Reverts to local if
-              and when it stops being the live measurement.
-
-            Default ``DataMode.LOCAL``.
-
         arrays (Optional[List[qcodes.DataArray]): arrays to add to the DataSet.
                 Can be added later with ``self.add_array(array)``.
 
@@ -86,11 +52,8 @@ def new_data(location=None, loc_record=None, name=None, overwrite=False,
             write (and read) with. Default ``DataSet.default_formatter`` which
             is initially ``GNUPlotFormat()``.
 
-        write_period (float or None, optional): Only if ``mode=LOCAL``, seconds
-            between saves to disk. If not ``LOCAL``, the ``DataServer`` handles
-            this and generally writes more often. Use None to disable writing
-            from calls to ``self.store``. Default 5.
-
+        write_period (float or None, optional):seconds
+            between saves to disk.
     Returns:
         A new ``DataSet`` object ready for storing new data in.
     """
@@ -111,23 +74,13 @@ def new_data(location=None, loc_record=None, name=None, overwrite=False,
     if location and (not overwrite) and io.list(location):
         raise FileExistsError('"' + location + '" already has data')
 
-    if data_manager is True:
-        data_manager = get_data_manager()
-    else:
-        if mode != DataMode.LOCAL:
-            raise ValueError('DataSets without a data_manager must be local')
+    return DataSet(location=location, io=io, **kwargs)
 
-    return DataSet(location=location, io=io, data_manager=data_manager,
-                   mode=mode, **kwargs)
 
-
-def load_data(location=None, data_manager=None, formatter=None, io=None):
+def load_data(location=None, formatter=None, io=None):
     """
     Load an existing DataSet.
 
-    The resulting ``DataSet.mode`` is determined automatically from location:
-    PULL_FROM_SERVER if this is the live DataSet, otherwise LOCAL
-
     Args:
         location (str, optional): the location to load from. Default is the
             current live DataSet.
@@ -135,13 +88,6 @@ def load_data(location=None, data_manager=None, formatter=None, io=None):
             combination of io + location. the default ``DiskIO`` sets the base
             directory, which this location is a relative path inside.
 
-        data_manager (DataManager or False, optional): manager for the
-            ``DataServer`` that offloads storage and syncing of this
-            ``DataSet``. Usually omitted (default None) to use the default
-            from ``get_data_manager()``. If ``False``, this ``DataSet`` will
-            store itself. ``load_data`` will not start a DataManager but may
-            query an existing one to determine (and pull) the live data.
-
         formatter (Formatter, optional): sets the file format/structure to
             read with. Default ``DataSet.default_formatter`` which
             is initially ``GNUPlotFormat()``.
@@ -154,39 +100,14 @@ def load_data(location=None, data_manager=None, formatter=None, io=None):
     Returns:
         A new ``DataSet`` object loaded with pre-existing data.
     """
-    if data_manager is None:
-        data_manager = get_data_manager(only_existing=True)
-
-    if location is None:
-        if not data_manager:
-            raise RuntimeError('Live data requested but DataManager does '
-                               'not exist or was requested not to be used')
-
-        return _get_live_data(data_manager)
-
-    elif location is False:
+    if location is False:
         raise ValueError('location=False means a temporary DataSet, '
                          'which is incompatible with load_data')
 
-    elif (data_manager and
-            location == data_manager.ask('get_data', 'location')):
-        return _get_live_data(data_manager)
-
-    else:
-        data = DataSet(location=location, formatter=formatter, io=io,
-                       mode=DataMode.LOCAL)
-        data.read_metadata()
-        data.read()
-        return data
-
-
-def _get_live_data(data_manager):
-    live_data = data_manager.ask('get_data')
-    if live_data is None or isinstance(live_data, NoData):
-        raise RuntimeError('DataManager has no live data')
-
-    live_data.mode = DataMode.PULL_FROM_SERVER
-    return live_data
+    data = DataSet(location=location, formatter=formatter, io=io)
+    data.read_metadata()
+    data.read()
+    return data
 
 
 class DataSet(DelegateAttributes):
@@ -212,24 +133,6 @@ class DataSet(DelegateAttributes):
             says the root data directory is the current working directory, ie
             where you started the python session.
 
-        data_manager (Optional[bool]): use a manager for the
-            ``DataServer`` that offloads storage and syncing of this Defaults
-            to  ``False`` i.e. this ``DataSet`` will store itself without extra
-            processes.  Set to ``True`` to use the default from
-            ``get_data_manager()``.
-
-        mode (DataMode, optional): connection type to the ``DataServer``.
-
-            - ``DataMode.LOCAL``: this DataSet doesn't communicate across
-              processes.
-            - ``DataMode.PUSH_TO_SERVER``: no local copy of data, just pushes
-              each measurement to a ``DataServer``.
-            - ``DataMode.PULL_FROM_SERVER``: pulls changes from the
-              ``DataServer`` on calling ``self.sync()``. Reverts to local if
-              and when it stops being the live measurement.
-
-            Default to ``DataMode.LOCAL``.
-
         arrays (Optional[List[qcodes.DataArray]): arrays to add to the DataSet.
                 Can be added later with ``self.add_array(array)``.
 
@@ -265,8 +168,8 @@ class DataSet(DelegateAttributes):
 
     background_functions = OrderedDict()
 
-    def __init__(self, location=None, mode=DataMode.LOCAL, arrays=None,
-                 data_manager=False, formatter=None, io=None, write_period=5):
+    def __init__(self, location=None, arrays=None, formatter=None, io=None,
+                 write_period=5):
         if location is False or isinstance(location, str):
             self.location = location
         else:
@@ -289,92 +192,10 @@ def __init__(self, location=None, mode=DataMode.LOCAL, arrays=None,
             for array in arrays:
                 self.add_array(array)
 
-        if data_manager is True and mode in SERVER_MODES:
-            data_manager = get_data_manager()
-
-        if mode == DataMode.LOCAL:
-            self._init_local()
-        elif mode == DataMode.PUSH_TO_SERVER:
-            self._init_push_to_server(data_manager)
-        elif mode == DataMode.PULL_FROM_SERVER:
-            self._init_live(data_manager)
-        else:
-            raise ValueError('unrecognized DataSet mode', mode)
-
-    def _init_local(self):
-        self.mode = DataMode.LOCAL
-
         if self.arrays:
             for array in self.arrays.values():
                 array.init_data()
 
-    def _init_push_to_server(self, data_manager):
-        self.mode = DataMode.PUSH_TO_SERVER
-
-        # If some code was not available when data_manager was started,
-        # we can't unpickle it on the other end.
-        # So we'll try, then restart if this error occurs, then try again.
-        #
-        # This still has a pitfall, if code has been *changed* since
-        # starting the server, it will still have the old version and
-        # everything will look fine but it won't have the new behavior.
-        # If the user does that, they need to manually restart the server,
-        # using:
-        #     data_manager.restart()
-        try:
-            data_manager.ask('new_data', self)
-        except AttributeError:
-            data_manager.restart()
-            data_manager.ask('new_data', self)
-
-        # need to set data_manager *after* sending to data_manager because
-        # we can't (and shouldn't) send data_manager itself through a queue
-        self.data_manager = data_manager
-
-    def init_on_server(self):
-        """
-        Configure this DataSet as the DataServer copy.
-
-        Should be run only by the DataServer itself.
-        """
-        if not self.arrays:
-            raise RuntimeError('A server-side DataSet needs DataArrays.')
-
-        self._init_local()
-
-    def _init_live(self, data_manager):
-        self.mode = DataMode.PULL_FROM_SERVER
-        self.data_manager = data_manager
-        with data_manager.query_lock:
-            if self.is_on_server:
-                live_obj = data_manager.ask('get_data')
-                self.arrays = live_obj.arrays
-            else:
-                self._init_local()
-
-    @property
-    def is_live_mode(self):
-        """
-        Indicate whether this DataSet thinks it is live in the DataServer.
-
-        Does not actually talk to the DataServer or sync with it.
-        """
-        return self.mode in SERVER_MODES and self.data_manager and True
-
-    @property
-    def is_on_server(self):
-        """
-        Check whether this DataSet is actually live in the DataServer.
-
-        If it thought it was but isn't, convert it to mode=LOCAL
-        """
-        if not self.is_live_mode or self.location is False:
-            return False
-
-        with self.data_manager.query_lock:
-            live_location = self.data_manager.ask('get_data', 'location')
-            return self.location == live_location
-
     def sync(self):
         """
         Synchronize this DataSet with the DataServer or storage.
@@ -391,39 +212,9 @@ def sync(self):
         # changed (and I guess throw an error if both did? Would be cool if we
         # could find a robust and intuitive way to make modifications to the
         # version on the DataServer from the main copy)
-        if not self.is_live_mode:
-            # LOCAL DataSet - no need to sync just use local data
-            return False
-            # TODO - for remote live plotting, maybe set some timestamp
-            # threshold and call it static after it's been dormant a long time?
-            # I'm thinking like a minute, or ten? Maybe it's configurable?
-
-        with self.data_manager.query_lock:
-            if self.is_on_server:
-                synced_indices = {
-                    array_id: array.get_synced_index()
-                    for array_id, array in self.arrays.items()
-                }
-
-                changes = self.data_manager.ask('get_changes', synced_indices)
-
-                for array_id, array_changes in changes.items():
-                    self.arrays[array_id].apply_changes(**array_changes)
-
-                measuring = self.data_manager.ask('get_measuring')
-                if not measuring:
-                    # we must have *just* stopped measuring
-                    # but the DataSet is still on the server,
-                    # so we got the data, and don't need to read.
-                    self.mode = DataMode.LOCAL
-                    return False
-                return True
-            else:
-                # this DataSet *thought* it was on the server, but it wasn't,
-                # so we haven't synced yet and need to read from storage
-                self.mode = DataMode.LOCAL
-                self.read()
-                return False
+
+        # LOCAL DataSet - no need to sync just use local data
+        return False
 
     def fraction_complete(self):
         """
@@ -582,9 +373,6 @@ def store(self, loop_indices, ids_values):
         """
         Insert data into one or more of our DataArrays.
 
-        If in ``PUSH_TO_SERVER`` mode, this is where we do that!
-        Otherwise we also periodically trigger a write to storage.
-
         Args:
             loop_indices (tuple): the indices within whatever loops we are
                 inside. May have fewer dimensions than some of the arrays
@@ -594,23 +382,13 @@ def store(self, loop_indices, ids_values):
                 array_ids, and values are single numbers or entire slices
                 to insert into that array.
          """
-        if self.mode == DataMode.PUSH_TO_SERVER:
-            # Defers to the copy on the dataserver to call this identical
-            # function
-            self.data_manager.write('store_data', loop_indices, ids_values)
-        elif self.mode == DataMode.LOCAL:
-            # You will always end up in this block, either in the copy
-            # on the server (if you hit the if statement above) or else here
-            for array_id, value in ids_values.items():
-                self.arrays[array_id][loop_indices] = value
-            self.last_store = time.time()
-            if (self.write_period is not None and
-                    time.time() > self.last_write + self.write_period):
-                self.write()
-                self.last_write = time.time()
-        else:  # in PULL_FROM_SERVER mode; store() isn't legal
-            raise RuntimeError('This object is pulling from a DataServer, '
-                               'so data insertion is not allowed.')
+        for array_id, value in ids_values.items():
+            self.arrays[array_id][loop_indices] = value
+        self.last_store = time.time()
+        if (self.write_period is not None and
+                time.time() > self.last_write + self.write_period):
+            self.write()
+            self.last_write = time.time()
 
     def default_parameter_name(self, paramname='amplitude'):
         """ Return name of default parameter for plotting
@@ -692,10 +470,6 @@ def write(self, write_metadata=False):
         Args:
             write_metadata (bool): write the metadata to disk
         """
-        if self.mode != DataMode.LOCAL:
-            raise RuntimeError('This object is connected to a DataServer, '
-                               'which handles writing automatically.')
-
         if self.location is False:
             return
 
@@ -783,20 +557,11 @@ def finalize(self):
         Also closes the data file(s), if the ``Formatter`` we're using
         supports that.
         """
-        if self.mode == DataMode.PUSH_TO_SERVER:
-            # Just like .store, if this DataSet is on the DataServer,
-            # we defer to the copy there and execute this same method.
-            self.data_manager.ask('finalize_data')
-        elif self.mode == DataMode.LOCAL:
-            # You will always end up in this block, either in the copy
-            # on the server (if you hit the if statement above) or else here
-            self.write()
+        self.write()
+
+        if hasattr(self.formatter, 'close_file'):
+            self.formatter.close_file(self)
 
-            if hasattr(self.formatter, 'close_file'):
-                self.formatter.close_file(self)
-        else:
-            raise RuntimeError('This mode does not allow finalizing',
-                               self.mode)
         self.save_metadata()
 
     def snapshot(self, update=False):
@@ -833,8 +598,7 @@ def __repr__(self):
         """Rich information about the DataSet and contained arrays."""
         out = type(self).__name__ + ':'
 
-        attrs = [['mode', self.mode],
-                 ['location', repr(self.location)]]
+        attrs = [['location', repr(self.location)]]
         attr_template = '\n   {:8} = {}'
         for var, val in attrs:
             out += attr_template.format(var, val)
diff --git a/qcodes/loops.py b/qcodes/loops.py
index c20ce7430f3..f00a35b6aa6 100644
--- a/qcodes/loops.py
+++ b/qcodes/loops.py
@@ -50,12 +50,10 @@
 import logging
 import time
 import numpy as np
-import warnings
 
 from qcodes.station import Station
-from qcodes.data.data_set import new_data, DataMode
+from qcodes.data.data_set import new_data
 from qcodes.data.data_array import DataArray
-from qcodes.data.manager import get_data_manager
 from qcodes.utils.helpers import wait_secs, full_class, tprint
 from qcodes.utils.metadata import Metadatable
 
@@ -64,13 +62,6 @@
 
 
 log = logging.getLogger(__name__)
-USE_MP=False
-
-
-def _clear_data_manager():
-    dm = get_data_manager(only_existing=True)
-    if dm and dm.ask('get_measuring'):
-        dm.ask('finalize_data')
 
 
 class Loop(Metadatable):
@@ -240,8 +231,7 @@ def run_temp(self, *args, **kwargs):
         shortcut to run a loop in the foreground as a temporary dataset
         using the default measurement set
         """
-        return self.run(*args, quiet=True,
-                        data_manager=False, location=False, **kwargs)
+        return self.run(*args, quiet=True, location=False, **kwargs)
 
     def then(self, *actions, overwrite=False):
         """
@@ -585,7 +575,7 @@ def set_common_attrs(self, data_set, use_threads):
             if hasattr(action, 'set_common_attrs'):
                 action.set_common_attrs(data_set, use_threads)
 
-    def get_data_set(self, data_manager=USE_MP, *args, **kwargs):
+    def get_data_set(self, *args, **kwargs):
         """
         Return the data set for this loop.
 
@@ -618,22 +608,12 @@ def get_data_set(self, data_manager=USE_MP, *args, **kwargs):
             a DataSet object that we can use to plot
         """
         if self.data_set is None:
-            if data_manager is False:
-                data_mode = DataMode.LOCAL
-            else:
-                warnings.warn("Multiprocessing is in beta, use at own risk",
-                              UserWarning)
-                data_mode = DataMode.PUSH_TO_SERVER
-
-            data_set = new_data(arrays=self.containers(), mode=data_mode,
-                                data_manager=data_manager, *args, **kwargs)
-
+            data_set = new_data(arrays=self.containers(), *args, **kwargs)
             self.data_set = data_set
 
         else:
             has_args = len(kwargs) or len(args)
-            uses_data_manager = (self.data_set.mode != DataMode.LOCAL)
-            if has_args or (uses_data_manager != data_manager):
+            if has_args:
                 raise RuntimeError(
                     'The DataSet for this loop already exists. '
                     'You can only provide DataSet attributes, such as '
@@ -648,12 +628,10 @@ def run_temp(self, **kwargs):
         especially for use in composite parameters that need to run a Loop
         as part of their get method
         """
-        return self.run(quiet=True, data_manager=USE_MP, location=False,
-                **kwargs)
+        return self.run(quiet=True, location=False, **kwargs)
 
-    def run(self, use_threads=False, quiet=False,
-            data_manager=USE_MP, station=None, progress_interval=False,
-            *args, **kwargs):
+    def run(self, use_threads=False, quiet=False, station=None,
+            progress_interval=False, *args, **kwargs):
         """
         Execute this loop.
 
@@ -662,7 +640,6 @@ def run(self, use_threads=False, quiet=False,
                 back-to-back, execute them in separate threads so they run in
                 parallel (as long as they don't block each other)
             quiet: (default False): set True to not print anything except errors
-            data_manager: set to True to use a DataManager. Default to False.
             station: a Station instance for snapshots (omit to use a previously
                 provided Station, or the default Station)
             progress_interval (default None): show progress of the loop every x
@@ -695,7 +672,7 @@ def run(self, use_threads=False, quiet=False,
         if progress_interval is not False:
             self.progress_interval = progress_interval
 
-        data_set = self.get_data_set(data_manager, *args, **kwargs)
+        data_set = self.get_data_set(*args, **kwargs)
 
         self.set_common_attrs(data_set=data_set, use_threads=use_threads)
 
@@ -710,7 +687,6 @@ def run(self, use_threads=False, quiet=False,
         data_set.add_metadata({'loop': {
             'ts_start': ts,
             'use_threads': use_threads,
-            'use_data_manager': (data_manager is not False)
         }})
 
         data_set.save_metadata()
diff --git a/qcodes/measure.py b/qcodes/measure.py
index 782e07bc223..74443d3b587 100644
--- a/qcodes/measure.py
+++ b/qcodes/measure.py
@@ -1,7 +1,7 @@
 from datetime import datetime
 
 from qcodes.instrument.parameter import ManualParameter
-from qcodes.loops import Loop, USE_MP
+from qcodes.loops import Loop
 from qcodes.actions import _actions_snapshot
 from qcodes.utils.helpers import full_class
 from qcodes.utils.metadata import Metadatable
@@ -29,11 +29,9 @@ def run_temp(self, **kwargs):
         """
         Wrapper to run this measurement as a temporary data set
         """
-        return self.run(quiet=True, data_manager=False, location=False,
-                        **kwargs)
+        return self.run(quiet=True, location=False, **kwargs)
 
-    def run(self, use_threads=False, quiet=False, data_manager=USE_MP,
-            station=None, **kwargs):
+    def run(self, use_threads=False, quiet=False, station=None, **kwargs):
         """
         Run the actions in this measurement and return their data as a DataSet
 
@@ -71,8 +69,7 @@ def run(self, use_threads=False, quiet=False, data_manager=USE_MP,
             a DataSet object containing the results of the measurement
         """
 
-        data_set = self._dummyLoop.get_data_set(data_manager=data_manager,
-                                                **kwargs)
+        data_set = self._dummyLoop.get_data_set(**kwargs)
 
         # set the DataSet to local for now so we don't save it, since
         # we're going to massage it afterward
@@ -125,8 +122,7 @@ def run(self, use_threads=False, quiet=False, data_manager=USE_MP,
         # puts in a 'loop' section that we need to replace with 'measurement'
         # but we use the info from 'loop' to ensure consistency and avoid
         # duplication.
-        LOOP_SNAPSHOT_KEYS = ['ts_start', 'ts_end',
-                              'use_data_manager', 'use_threads']
+        LOOP_SNAPSHOT_KEYS = ['ts_start', 'ts_end', 'use_threads']
         data_set.add_metadata({'measurement': {
             k: data_set.metadata['loop'][k] for k in LOOP_SNAPSHOT_KEYS
         }})
diff --git a/qcodes/tests/test_data.py b/qcodes/tests/test_data.py
index adfc19688e3..ccd7af58181 100644
--- a/qcodes/tests/test_data.py
+++ b/qcodes/tests/test_data.py
@@ -8,7 +8,7 @@
 from qcodes.data.data_array import DataArray
 from qcodes.data.manager import get_data_manager, NoData
 from qcodes.data.io import DiskIO
-from qcodes.data.data_set import load_data, new_data, DataMode, DataSet
+from qcodes.data.data_set import load_data, new_data, DataSet
 from qcodes.process.helpers import kill_processes
 from qcodes.utils.helpers import LogCapture
 from qcodes import active_children
@@ -287,19 +287,6 @@ class TestLoadData(TestCase):
     def setUp(self):
         kill_processes()
 
-    def test_no_live_data(self):
-        # live data with no DataManager at all
-        with self.assertRaises(RuntimeError):
-            load_data()
-        self.assertEqual(len(active_children()), 0)
-
-        # now make a DataManager and try again
-        get_data_manager()
-        self.assertEqual(len(active_children()), 1)
-        # same result but different code path
-        with self.assertRaises(RuntimeError):
-            load_data()
-
     def test_no_saved_data(self):
         with self.assertRaises(IOError):
             load_data('_no/such/file_')
@@ -308,34 +295,11 @@ def test_load_false(self):
         with self.assertRaises(ValueError):
             load_data(False)
 
-    def test_get_live(self):
-        loc = 'live from New York!'
-
-        class MockLive:
-            pass
-
-        live_data = MockLive()
-
-        dm = MockDataManager()
-        dm.location = loc
-        dm.live_data = live_data
-
-        data = load_data(data_manager=dm, location=loc)
-        self.assertEqual(data, live_data)
-
-        for nd in (None, NoData()):
-            dm.live_data = nd
-            with self.assertRaises(RuntimeError):
-                load_data(data_manager=dm, location=loc)
-            with self.assertRaises(RuntimeError):
-                load_data(data_manager=dm)
-
     def test_get_read(self):
         dm = MockDataManager()
         dm.location = 'somewhere else'
 
-        data = load_data(formatter=MockFormatter(), data_manager=dm,
-                         location='here!')
+        data = load_data(formatter=MockFormatter(), location='here!')
         self.assertEqual(data.has_read_data, True)
         self.assertEqual(data.has_read_metadata, True)
 
@@ -393,16 +357,11 @@ def test_overwrite(self):
         io = MatchIO([1])
 
         with self.assertRaises(FileExistsError):
-            new_data(location='somewhere', io=io, data_manager=False)
+            new_data(location='somewhere', io=io)
 
-        data = new_data(location='somewhere', io=io, overwrite=True,
-                        data_manager=False)
+        data = new_data(location='somewhere', io=io, overwrite=True,)
         self.assertEqual(data.location, 'somewhere')
 
-    def test_mode_error(self):
-        with self.assertRaises(ValueError):
-            new_data(mode=DataMode.PUSH_TO_SERVER, data_manager=False)
-
     def test_location_functions(self):
         def my_location(io, record):
             return 'data/{}'.format((record or {}).get('name') or 'LOOP!')
@@ -413,14 +372,12 @@ def my_location2(io, record):
 
         DataSet.location_provider = my_location
 
-        self.assertEqual(new_data(data_manager=False).location, 'data/LOOP!')
-        self.assertEqual(new_data(data_manager=False, name='cheese').location,
-                         'data/cheese')
+        self.assertEqual(new_data().location, 'data/LOOP!')
+        self.assertEqual(new_data(name='cheese').location, 'data/cheese')
 
-        data = new_data(data_manager=False, location=my_location2)
+        data = new_data(location=my_location2)
         self.assertEqual(data.location, 'data/loop?/folder')
-        data = new_data(data_manager=False, location=my_location2,
-                        name='iceCream')
+        data = new_data(location=my_location2, name='iceCream')
         self.assertEqual(data.location, 'data/iceCream/folder')
 
 
@@ -437,87 +394,6 @@ def test_constructor_errors(self):
         with self.assertRaises(ValueError):
             DataSet(location=42)
 
-        # OK to have location=False, but wrong mode
-        with self.assertRaises(ValueError):
-            DataSet(location=False, mode='happy')
-
-    @patch('qcodes.data.data_set.get_data_manager')
-    def test_from_server(self, gdm_mock):
-        mock_dm = MockDataManager()
-        gdm_mock.return_value = mock_dm
-        mock_dm.location = 'Mars'
-        mock_dm.live_data = MockLive()
-
-        # wrong location or False location - converts to local
-        data = DataSet(location='Jupiter', data_manager=True, mode=DataMode.PULL_FROM_SERVER)
-        self.assertEqual(data.mode, DataMode.LOCAL)
-
-        data = DataSet(location=False,  data_manager=True, mode=DataMode.PULL_FROM_SERVER)
-        self.assertEqual(data.mode, DataMode.LOCAL)
-
-        # location matching server - stays in server mode
-        data = DataSet(location='Mars',  data_manager=True, mode=DataMode.PULL_FROM_SERVER,
-                       formatter=MockFormatter())
-        self.assertEqual(data.mode, DataMode.PULL_FROM_SERVER)
-        self.assertEqual(data.arrays, MockLive.arrays)
-
-        # cannot write except in LOCAL mode
-        with self.assertRaises(RuntimeError):
-            data.write()
-
-        # cannot finalize in PULL_FROM_SERVER mode
-        with self.assertRaises(RuntimeError):
-            data.finalize()
-
-        # now test when the server says it's not there anymore
-        mock_dm.location = 'Saturn'
-        data.sync()
-        self.assertEqual(data.mode, DataMode.LOCAL)
-        self.assertEqual(data.has_read_data, True)
-
-        # now it's LOCAL so we *can* write.
-        data.write()
-        self.assertEqual(data.has_written_data, True)
-
-        # location=False: write, read and sync are noops.
-        data.has_read_data = False
-        data.has_written_data = False
-        data.location = False
-        data.write()
-        data.read()
-        data.sync()
-        self.assertEqual(data.has_read_data, False)
-        self.assertEqual(data.has_written_data, False)
-
-    @patch('qcodes.data.data_set.get_data_manager')
-    def test_to_server(self, gdm_mock):
-        mock_dm = MockDataManager()
-        mock_dm.needs_restart = True
-        gdm_mock.return_value = mock_dm
-
-        data = DataSet(location='Venus', data_manager=True, mode=DataMode.PUSH_TO_SERVER)
-        self.assertEqual(mock_dm.needs_restart, False, data)
-        self.assertEqual(mock_dm.data_set, data)
-        self.assertEqual(data.data_manager, mock_dm)
-        self.assertEqual(data.mode, DataMode.PUSH_TO_SERVER)
-
-        # cannot write except in LOCAL mode
-        with self.assertRaises(RuntimeError):
-            data.write()
-
-        # now do what the DataServer does with this DataSet: init_on_server
-        # fails until there is an array
-        with self.assertRaises(RuntimeError):
-            data.init_on_server()
-
-        data.add_array(MockArray())
-        data.init_on_server()
-        self.assertEqual(data.noise.ready, True)
-
-        # we can only add a given array_id once
-        with self.assertRaises(ValueError):
-            data.add_array(MockArray())
-
     def test_write_copy(self):
         data = DataSet1D(location=False)
         mockbase = os.path.abspath('some_folder')
diff --git a/qcodes/tests/test_format.py b/qcodes/tests/test_format.py
index d20b75ebd5f..c9a635ae316 100644
--- a/qcodes/tests/test_format.py
+++ b/qcodes/tests/test_format.py
@@ -333,8 +333,8 @@ def test_incremental_write(self):
             # we wrote to a second location without the stars, so we can read
             # back in and make sure that we get the right last_saved_index
             # for the amount of data we've read.
-            reread_data = load_data(location=location2, data_manager=False,
-                                    formatter=formatter, io=data.io)
+            reread_data = load_data(location=location2, formatter=formatter,
+                                    io=data.io)
             self.assertEqual(repr(reread_data.x_set.tolist()),
                              repr(data.x_set.tolist()))
             self.assertEqual(repr(reread_data.y.tolist()),
diff --git a/qcodes/tests/test_hdf5formatter.py b/qcodes/tests/test_hdf5formatter.py
index 4f759f1d8bf..ac813edc3cf 100644
--- a/qcodes/tests/test_hdf5formatter.py
+++ b/qcodes/tests/test_hdf5formatter.py
@@ -136,8 +136,7 @@ def test_loop_writing(self):
         # # added to station to test snapshot at a later stage
         loop = Loop(MockPar.x[-100:100:20]).each(MockPar.skewed_parabola)
         data1 = loop.run(name='MockLoop_hdf5_test',
-                         formatter=self.formatter,
-                         data_manager=False)
+                         formatter=self.formatter)
         data2 = DataSet(location=data1.location, formatter=self.formatter)
         data2.read()
         for key in data2.arrays.keys():
@@ -158,8 +157,7 @@ def test_loop_writing_2D(self):
         loop = Loop(MockPar.x[-100:100:20]).loop(
             MockPar.y[-50:50:10]).each(MockPar.skewed_parabola)
         data1 = loop.run(name='MockLoop_hdf5_test',
-                         formatter=self.formatter,
-                         data_manager=False)
+                         formatter=self.formatter)
         data2 = DataSet(location=data1.location, formatter=self.formatter)
         data2.read()
         for key in data2.arrays.keys():
diff --git a/qcodes/tests/test_loop.py b/qcodes/tests/test_loop.py
index cbe082bc7ff..ae76594936a 100644
--- a/qcodes/tests/test_loop.py
+++ b/qcodes/tests/test_loop.py
@@ -83,7 +83,6 @@ def test_repr(self):
         active_loop = loop
         data = active_loop.run_temp()
         expected = ('DataSet:\n'
-                    '   mode     = DataMode.LOCAL\n'
                     '   location = False\n'
                     '   <Type>   | <array_id> | <array.name> | <array.shape>\n'
                     '   Setpoint | p1_set     | p1           | (2,)\n'
@@ -402,7 +401,6 @@ def g():
             },
             'loop': {
                 'use_threads': False,
-                'use_data_manager': False,
                 '__class__': 'qcodes.loops.ActiveLoop',
                 'sweep_values': {
                     'parameter': p1snap,
@@ -482,7 +480,7 @@ def test_halt(self):
         # because loop.run will not return.
         data = loop.get_data_set(location=False)
 
-        loop.run(data_manager=False, quiet=True)
+        loop.run(quiet=True)
         self.assertEqual(repr(data.p1.tolist()), repr(self.res))
 
 
diff --git a/qcodes/tests/test_measure.py b/qcodes/tests/test_measure.py
index 8563c34559e..28e8953887b 100644
--- a/qcodes/tests/test_measure.py
+++ b/qcodes/tests/test_measure.py
@@ -25,7 +25,6 @@ def test_simple_scalar(self):
         meta = data.metadata['measurement']
         self.assertEqual(meta['__class__'], 'qcodes.measure.Measure')
         self.assertEqual(len(meta['actions']), 1)
-        self.assertFalse(meta['use_data_manager'])
         self.assertFalse(meta['use_threads'])
 
         ts_start = datetime.strptime(meta['ts_start'], '%Y-%m-%d %H:%M:%S')

From 496783d9e72effe4b8176ae39bac5f7b9746961e Mon Sep 17 00:00:00 2001
From: Giulio Ungaretti <giulioungaretti@me.com>
Date: Mon, 6 Mar 2017 16:03:06 +0100
Subject: [PATCH 08/36] feature: Remove tests, yolo

---
 qcodes/tests/test_instrument.py | 963 +-------------------------------
 1 file changed, 2 insertions(+), 961 deletions(-)

diff --git a/qcodes/tests/test_instrument.py b/qcodes/tests/test_instrument.py
index 8dc5703de62..d4a94c92832 100644
--- a/qcodes/tests/test_instrument.py
+++ b/qcodes/tests/test_instrument.py
@@ -1,968 +1,9 @@
 """
 Test suite for  instument.*
 """
-import gc
-from datetime import datetime, timedelta
 from unittest import TestCase
-import time
 
-from qcodes.instrument.base import Instrument
-from qcodes.instrument.mock import MockInstrument
-from qcodes.instrument.parameter import ManualParameter
-from qcodes.instrument.server import get_instrument_server_manager
-
-from qcodes.utils.validators import Numbers, Ints, Strings, MultiType, Enum
-from qcodes.utils.command import NoCommandError
-from qcodes.utils.helpers import LogCapture
-from qcodes.process.helpers import kill_processes
-
-from .instrument_mocks import (AMockModel, MockInstTester,
-                               MockGates, MockSource, MockMeter,
-                               DummyInstrument)
-from .common import strip_qc
-
-
-class GatesBadDelayType(MockGates):
-
-    def __init__(self, *args, **kwargs):
-        super().__init__(*args, **kwargs)
-        self.add_parameter('chan0bad', get_cmd='c0?',
-                           set_cmd=self.slow_neg_set,
-                           get_parser=float,
-                           vals=Numbers(-10, 10), step=0.2,
-                           delay=0.01,
-                           max_delay='forever')
-
-
-class GatesBadDelayValue(MockGates):
-
-    def __init__(self, *args, **kwargs):
-        super().__init__(*args, **kwargs)
-        self.add_parameter('chan0bad', get_cmd='c0?',
-                           set_cmd=self.slow_neg_set,
-                           get_parser=float,
-                           vals=Numbers(-10, 10), step=0.2,
-                           delay=0.05,
-                           max_delay=0.03)
-
-
-class TestInstrument(TestCase):
-
-    @classmethod
-    def setUpClass(cls):
-        cls.model = AMockModel()
-
-        cls.gates = MockGates(model=cls.model, server_name='')
-        cls.source = MockSource(model=cls.model, server_name='')
-        cls.meter = MockMeter(
-            model=cls.model, keep_history=False, server_name='')
-
-    def setUp(self):
-        # reset the model state via the gates function
-        self.gates.reset()
-
-        # then reset each instrument's state, so we can avoid the time to
-        # completely reinstantiate with every test case
-        for inst in (self.gates, self.source, self.meter):
-            inst.restart()
-        self.init_ts = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
-
-    @classmethod
-    def tearDownClass(cls):
-        try:
-            cls.model.close()
-            for instrument in [cls.gates, cls.source, cls.meter]:
-                instrument.close()
-                # do it twice - should not error, though the second is
-                # irrelevant
-                instrument.close()
-        except:
-            pass
-
-        # TODO: when an error occurs during constructing an instrument,
-        # we don't have the instrument but its server doesn't know to stop.
-        # should figure out a way to remove it. (I thought I had but it
-        # doesn't seem to have worked...)
-        # for test_mock_instrument_errors
-        kill_processes()
-
-    def test_unpicklable(self):
-        self.assertEqual(self.gates.add5(6), 11)
-        # compare docstrings to make sure we're really calling add5
-        # on the server, and seeing its docstring
-        self.assertIn('The class copy of this should not get run',
-                      MockInstTester.add5.__doc__)
-        self.assertIn('not the same function as the original method',
-                      self.gates.add5.__doc__)
-
-    def test_slow_set(self):
-        # at least for now, need a local instrument to test logging
-        gatesLocal = MockGates(model=self.model, server_name=None,
-                               name='gateslocal')
-        for param, logcount in (('chan0slow', 2), ('chan0slow2', 2),
-                                ('chan0slow3', 0), ('chan0slow4', 1),
-                                ('chan0slow5', 0)):
-            gatesLocal.chan0.set(-0.5)
-
-            with LogCapture() as logs:
-                if param in ('chan0slow', 'chan0slow2', 'chan0slow3'):
-                    # these are the stepped parameters
-                    gatesLocal.set(param, 0.5)
-                else:
-                    # these are the non-stepped parameters that
-                    # still have delays
-                    gatesLocal.set(param, -1)
-                    gatesLocal.set(param, 1)
-
-            loglines = logs.value.split('\n')[:-1]
-            # TODO: occasional extra negative delays here
-            self.assertEqual(len(loglines), logcount, (param, logs.value))
-            for line in loglines:
-                self.assertTrue(line.startswith('negative delay'), line)
-
-    def test_max_delay_errors(self):
-        with self.assertRaises(TypeError):
-            # add_parameter works remotely with string commands, but
-            # function commands are not going to be picklable, since they
-            # need to talk to the hardware, so these need to be included
-            # from the beginning when the instrument is created on the
-            # server.
-            GatesBadDelayType(model=self.model, name='gatesBDT')
-
-        with self.assertRaises(ValueError):
-            GatesBadDelayValue(model=self.model, name='gatesBDV')
-
-    def check_ts(self, ts_str):
-        now = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
-        self.assertTrue(self.init_ts <= ts_str <= now)
-
-    def test_instances(self):
-        instruments = [self.gates, self.source, self.meter]
-        for instrument in instruments:
-            for other_instrument in instruments:
-                instances = instrument.instances()
-                # check that each instrument is in only its own
-                # instances list
-                # also test type checking in find_instrument,
-                # but we need to use find_component so it executes
-                # on the server
-                if other_instrument is instrument:
-                    self.assertIn(instrument, instances)
-
-                    name2 = other_instrument.find_component(
-                        instrument.name + '.name',
-                        other_instrument._instrument_class)
-                    self.assertEqual(name2, instrument.name)
-                else:
-                    self.assertNotIn(other_instrument, instances)
-
-                    with self.assertRaises(TypeError):
-                        other_instrument.find_component(
-                            instrument.name + '.name',
-                            other_instrument._instrument_class)
-
-                # check that we can find each instrument from any other
-                # find_instrument is explicitly mapped in RemoteInstrument
-                # so this call gets executed in the main process
-                self.assertEqual(
-                    instrument,
-                    other_instrument.find_instrument(instrument.name))
-
-                # but find_component is not, so it executes on the server
-                self.assertEqual(
-                    instrument.name,
-                    other_instrument.find_component(instrument.name + '.name'))
-
-            # check that we can find this instrument from the base class
-            self.assertEqual(instrument,
-                             Instrument.find_instrument(instrument.name))
-
-        # somehow instances never go away... there are always 3
-        # extra references to every instrument object, so del doesn't
-        # work. For this reason, instrument tests should take
-        # the *last* instance to test.
-        # so we can't test that the list of defined instruments is actually
-        # *only* what we want to see defined.
-
-    def test_instance_name_uniqueness(self):
-        with self.assertRaises(KeyError):
-            MockGates(model=self.model)
-
-    def test_remove_instance(self):
-        self.gates.close()
-        self.assertEqual(self.gates.instances(), [])
-        with self.assertRaises(KeyError):
-            Instrument.find_instrument('gates')
-
-        type(self).gates = MockGates(model=self.model, server_name="")
-        self.assertEqual(self.gates.instances(), [self.gates])
-        self.assertEqual(Instrument.find_instrument('gates'), self.gates)
-
-    def test_creation_failure(self):
-        # this we already know should fail (see test_max_delay_errors)
-        name = 'gatesFailing'
-        with self.assertRaises(ValueError):
-            GatesBadDelayValue(model=self.model, name=name, server_name='')
-
-        # this instrument should not be in the instance list
-        with self.assertRaises(KeyError):
-            Instrument.find_instrument(name)
-
-        # now do the same with a local instrument
-        name = 'gatesFailing2'
-        with self.assertRaises(ValueError):
-            GatesBadDelayValue(model=self.model, name=name, server_name=None)
-        # gc is confused by the context manager we just used
-        # we want to make sure the ojbect we just tried to create
-        # but it threw an exception is properly gc'ed. Which
-        # is what happens wihtout the context manager AND
-        # it's how the __del__ method is supposed to work.
-
-        gc.collect()
-
-        # this instrument should not be in the instance list
-        with self.assertRaises(KeyError):
-            Instrument.find_instrument(name)
-
-    def test_mock_instrument(self):
-        gates, source, meter = self.gates, self.source, self.meter
-
-        # initial state
-        # short form of getter
-        self.assertEqual(gates.get('chan0'), 0)
-        # shortcut to the parameter, longer form of get
-        self.assertEqual(gates['chan0'].get(), 0)
-        # explicit long form of getter
-        self.assertEqual(gates.parameters['chan0'].get(), 0)
-        # all 3 should produce the same history entry
-        hist = gates.getattr('history')
-        self.assertEqual(len(hist), 3)
-        for item in hist:
-            self.assertEqual(item[1:], ('ask', 'c0'))
-
-        # errors trying to set (or validate) invalid param values
-        # put here so we ensure that these errors don't make it to
-        # the history (ie they don't result in hardware commands)
-        with self.assertRaises(TypeError):
-            gates.set('chan1', '1')
-        with self.assertRaises(TypeError):
-            gates.parameters['chan1'].validate('1')
-
-        # change one param at a time
-        gates.set('chan0', 0.5)
-        self.assertEqual(gates.get('chan0'), 0.5)
-        self.assertEqual(meter.get('amplitude'), 0.05)
-
-        gates.set('chan1', 2)
-        self.assertEqual(gates.get('chan1'), 2)
-        self.assertEqual(meter.get('amplitude'), 0.45)
-
-        gates.set('chan2', -3.2)
-        self.assertEqual(gates.get('chan2'), -3.2)
-        self.assertEqual(meter.get('amplitude'), -2.827)
-
-        source.set('amplitude', 0.6)
-        self.assertEqual(source.get('amplitude'), 0.6)
-        self.assertEqual(meter.get('amplitude'), -16.961)
-
-        gatehist = gates.getattr('history')
-        sourcehist = source.getattr('history')
-        meterhist = meter.getattr('history')
-        # check just the size and timestamps of histories
-        for entry in gatehist + sourcehist + meterhist:
-            self.check_ts(entry[0])
-        self.assertEqual(len(gatehist), 9)
-        self.assertEqual(len(sourcehist), 5)
-        # meter does not keep history but should still have a history attr
-        self.assertEqual(len(meterhist), 0)
-
-        # plus enough setters to check the parameter sweep
-        # first source has to get the starting value
-        self.assertEqual(sourcehist[0][1:], ('ask', 'ampl'))
-        # then it writes each
-        self.assertEqual(sourcehist[1][1:], ('write', 'ampl', '0.3000'))
-        self.assertEqual(sourcehist[2][1:], ('write', 'ampl', '0.5000'))
-        self.assertEqual(sourcehist[3][1:], ('write', 'ampl', '0.6000'))
-
-        source.set('amplitude', 0.8)
-        self.assertEqual(source.get('amplitude'), 0.8)
-        gates.set('chan1', -2)
-        self.assertEqual(gates.get('chan1'), -2)
-
-        # test functions
-        self.assertEqual(meter.call('echo', 1.2345), 1.23)  # model returns .2f
-        # too many ways to do this...
-        self.assertEqual(meter.echo.call(1.2345), 1.23)
-        self.assertEqual(meter.echo(1.2345), 1.23)
-        self.assertEqual(meter['echo'].call(1.2345), 1.23)
-        self.assertEqual(meter['echo'](1.2345), 1.23)
-        with self.assertRaises(TypeError):
-            meter.call('echo', 1, 2)
-        with self.assertRaises(TypeError):
-            meter.call('echo', '1')
-
-        # validating before actually trying to call
-        with self.assertRaises(TypeError):
-            meter.functions['echo'].validate(1, 2)
-        with self.assertRaises(TypeError):
-            meter.functions['echo'].validate('1')
-        gates.call('reset')
-        self.assertEqual(gates.get('chan0'), 0)
-
-        self.assertEqual(meter.call('echo', 4.567), 4.57)
-        gates.set('chan0', 1)
-        self.assertEqual(gates.get('chan0'), 1)
-        gates.call('reset')
-        self.assertEqual(gates.get('chan0'), 0)
-
-    def test_mock_idn(self):
-        self.assertEqual(self.gates.IDN(), {
-            'vendor': None,
-            'model': 'MockGates',
-            'serial': 'gates',
-            'firmware': None
-        })
-
-    def test_mock_set_sweep(self):
-        gates = self.gates
-        gates.set('chan0step', 0.5)
-        gatehist = gates.getattr('history')
-        self.assertEqual(len(gatehist), 6)
-        self.assertEqual(
-            [float(h[3]) for h in gatehist if h[1] == 'write'],
-            [0.1, 0.2, 0.3, 0.4, 0.5])
-
-    def test_mock_instrument_errors(self):
-        gates, meter = self.gates, self.meter
-        with self.assertRaises(ValueError):
-            gates.ask('no question')
-        with self.assertRaises(ValueError):
-            gates.ask('question?yes but more after')
-
-        with self.assertRaises(ValueError):
-            gates.ask('ampl?')
-
-        with self.assertRaises(TypeError):
-            MockInstrument('mockbaddelay1', delay='forever')
-        with self.assertRaises(TypeError):
-            # TODO: since this instrument didn't work, it should be OK
-            # to use the same name again... how do we allow that?
-            MockInstrument('mockbaddelay2', delay=-1)
-
-        # TODO: when an error occurs during constructing an instrument,
-        # we don't have the instrument but its server doesn't know to stop.
-        # should figure out a way to remove it. (I thought I had but it
-        # doesn't seem to have worked...)
-        get_instrument_server_manager('MockInstruments').close()
-        time.sleep(0.5)
-
-        with self.assertRaises(AttributeError):
-            MockInstrument('', model=None)
-
-        with self.assertRaises(KeyError):
-            gates.add_parameter('chan0', get_cmd='boo')
-        with self.assertRaises(KeyError):
-            gates.add_function('reset', call_cmd='hoo')
-
-        with self.assertRaises(NotImplementedError):
-            meter.set('amplitude', 0.5)
-        meter.add_parameter('gain', set_cmd='gain {:.3f}')
-        with self.assertRaises(NotImplementedError):
-            meter.get('gain')
-
-        with self.assertRaises(TypeError):
-            gates.add_parameter('fugacity', set_cmd='f {:.4f}', vals=[1, 2, 3])
-
-    def check_set_amplitude2(self, val, log_count, history_count):
-        source = self.sourceLocal
-        with LogCapture() as logs:
-            source.amplitude2.set(val)
-
-        loglines = logs.value.split('\n')[:-1]
-
-        self.assertEqual(len(loglines), log_count, logs.value)
-        for line in loglines:
-            self.assertIn('cannot sweep', line.lower())
-        hist = source.getattr('history')
-        self.assertEqual(len(hist), history_count)
-
-    def test_sweep_steps_edge_case(self):
-        # MultiType with sweeping is weird - not sure why one would do this,
-        # but we should handle it
-        # at least for now, need a local instrument to check logging
-        source = self.sourceLocal = MockSource(model=self.model,
-                                               server_name=None,
-                                               name='sourcelocal')
-        source.add_parameter('amplitude2', get_cmd='ampl?',
-                             set_cmd='ampl:{}', get_parser=float,
-                             vals=MultiType(Numbers(0, 1), Strings()),
-                             step=0.2, delay=0.02)
-        self.assertEqual(len(source.getattr('history')), 0)
-
-        # 2 history items - get then set, and one warning (cannot sweep
-        # number to string value)
-        self.check_set_amplitude2('Off', log_count=1, history_count=2)
-
-        # one more history item - single set, and one warning (cannot sweep
-        # string to number)
-        self.check_set_amplitude2(0.2, log_count=1, history_count=3)
-
-        # the only real sweep (0.2 to 0.8) adds 3 set's to history and no logs
-        self.check_set_amplitude2(0.8, log_count=0, history_count=6)
-
-        # single set added to history, and another sweep warning num->string
-        self.check_set_amplitude2('Off', log_count=1, history_count=7)
-
-    def test_set_sweep_errors(self):
-        gates = self.gates
-
-        # for reference, some add_parameter's that should work
-        gates.add_parameter('t0', set_cmd='{}', vals=Numbers(),
-                            step=0.1, delay=0.01)
-        gates.add_parameter('t2', set_cmd='{}', vals=Ints(),
-                            step=1, delay=0.01,
-                            max_val_age=0)
-
-        with self.assertRaises(TypeError):
-            # can't sweep non-numerics
-            gates.add_parameter('t1', set_cmd='{}', vals=Strings(),
-                                step=1, delay=0.01)
-        with self.assertRaises(TypeError):
-            # need a numeric step too
-            gates.add_parameter('t1', set_cmd='{}', vals=Numbers(),
-                                step='a skosh', delay=0.01)
-        with self.assertRaises(TypeError):
-            # Ints requires and int step
-            gates.add_parameter('t1', set_cmd='{}', vals=Ints(),
-                                step=0.1, delay=0.01)
-        with self.assertRaises(ValueError):
-            # need a non-negative step
-            gates.add_parameter('t1', set_cmd='{}', vals=Numbers(),
-                                step=-0.1, delay=0.01)
-        with self.assertRaises(TypeError):
-            # need a numeric delay
-            gates.add_parameter('t1', set_cmd='{}', vals=Numbers(),
-                                step=0.1, delay='a tad')
-        with self.assertRaises(ValueError):
-            # need a non-negative delay
-            gates.add_parameter('t1', set_cmd='{}', vals=Numbers(),
-                                step=0.1, delay=-0.01)
-        with self.assertRaises(TypeError):
-            # need a numeric max_val_age
-            gates.add_parameter('t1', set_cmd='{}', vals=Numbers(),
-                                step=0.1, delay=0.01,
-                                max_val_age='an hour')
-        with self.assertRaises(ValueError):
-            # need a non-negative max_val_age
-            gates.add_parameter('t1', set_cmd='{}', vals=Numbers(),
-                                step=0.1, delay=0.01,
-                                max_val_age=-1)
-
-    def getmem(self, key):
-        return self.source.ask('mem{}?'.format(key))
-
-    def test_val_mapping(self):
-        gates = self.gates
-
-        # memraw has no mappings - it just sets and gets what the instrument
-        # uses to encode this parameter
-        gates.add_parameter('memraw', set_cmd='mem0:{}', get_cmd='mem0?',
-                            vals=Enum('zero', 'one'))
-
-        # memcoded maps the instrument codes ('zero' and 'one') into nicer
-        # user values 0 and 1
-        gates.add_parameter('memcoded', set_cmd='mem0:{}', get_cmd='mem0?',
-                            val_mapping={0: 'zero', 1: 'one'})
-
-        gates.memcoded.set(0)
-        self.assertEqual(gates.memraw.get(), 'zero')
-        self.assertEqual(gates.memcoded.get(), 0)
-        self.assertEqual(self.getmem(0), 'zero')
-
-        gates.memraw.set('one')
-        self.assertEqual(gates.memcoded.get(), 1)
-        self.assertEqual(gates.memraw.get(), 'one')
-        self.assertEqual(self.getmem(0), 'one')
-
-        with self.assertRaises(ValueError):
-            gates.memraw.set(0)
-
-        with self.assertRaises(ValueError):
-            gates.memcoded.set('zero')
-
-    def test_val_mapping_ints(self):
-        gates = self.gates
-
-        gates.add_parameter('moderaw', set_cmd='mem0:{}', get_cmd='mem0?',
-                            vals=Enum('0', '1'))
-
-        # modecoded maps the instrument codes ('0' and '1') into nicer
-        # user values 'AC' and 'DC'
-        # Here we're using integers in the mapping, rather than turning
-        # them into strings.
-        gates.add_parameter('modecoded', set_cmd='mem0:{}', get_cmd='mem0?',
-                            val_mapping={'DC': 0, 'AC': 1})
-
-        gates.modecoded.set('AC')
-        self.assertEqual(gates.moderaw.get(), '1')
-        self.assertEqual(gates.modecoded.get(), 'AC')
-        self.assertEqual(self.getmem(0), '1')
-
-        gates.moderaw.set('0')
-        self.assertEqual(gates.modecoded.get(), 'DC')
-        self.assertEqual(gates.moderaw.get(), '0')
-        self.assertEqual(self.getmem(0), '0')
-
-        with self.assertRaises(ValueError):
-            gates.modecoded.set(0)
-
-        with self.assertRaises(ValueError):
-            gates.modecoded.set('0')
-
-        with self.assertRaises(ValueError):
-            gates.moderaw.set('DC')
-
-    def test_val_mapping_parsers(self):
-        gates = self.gates
-
-        gates.add_parameter('moderaw', set_cmd='mem0:{}', get_cmd='mem0?',
-                            vals=Enum('0', '1'))
-
-        with self.assertRaises(TypeError):
-            # set_parser is not allowed with val_mapping
-            gates.add_parameter('modecoded', set_cmd='mem0:{}',
-                                get_cmd='mem0?',
-                                val_mapping={'DC': 0, 'AC': 1},
-                                set_parser=float)
-
-        gates.add_parameter('modecoded', set_cmd='mem0:{:.0f}',
-                            get_cmd='mem0?',
-                            val_mapping={'DC': 0.0, 'AC': 1.0},
-                            get_parser=float)
-
-        gates.modecoded.set('AC')
-        self.assertEqual(gates.moderaw.get(), '1')
-        self.assertEqual(gates.modecoded.get(), 'AC')
-        self.assertEqual(self.getmem(0), '1')
-
-        gates.moderaw.set('0')
-        self.assertEqual(gates.modecoded.get(), 'DC')
-        self.assertEqual(gates.moderaw.get(), '0')
-        self.assertEqual(self.getmem(0), '0')
-
-        with self.assertRaises(ValueError):
-            gates.modecoded.set(0)
-
-        with self.assertRaises(ValueError):
-            gates.modecoded.set('0')
-
-    def test_standard_snapshot(self):
-        self.maxDiff = None
-        snap = self.meter.snapshot()
-        strip_qc(snap)
-        for psnap in snap['parameters'].values():
-            strip_qc(psnap)
-
-        self.assertEqual(snap, {
-            '__class__': 'tests.instrument_mocks.MockMeter',
-            'name': 'meter',
-            'parameters': {
-                'IDN': {
-                    '__class__': (
-                        'qcodes.instrument.parameter.StandardParameter'),
-                    'instrument': 'tests.instrument_mocks.MockMeter',
-                    'instrument_name': 'meter',
-                    'label': 'IDN',
-                    'name': 'IDN',
-                    'ts': None,
-                    'unit': '',
-                    'value': None,
-                    'vals': '<Anything>'
-                },
-                'amplitude': {
-                    '__class__': (
-                        'qcodes.instrument.parameter.StandardParameter'),
-                    'instrument': 'tests.instrument_mocks.MockMeter',
-                    'instrument_name': 'meter',
-                    'label': 'amplitude',
-                    'name': 'amplitude',
-                    'ts': None,
-                    'unit': '',
-                    'value': None,
-                    'vals': '<Numbers>'
-                }
-            },
-            'functions': {'echo': {}}
-        })
-
-        ampsnap = self.meter.snapshot(update=True)['parameters']['amplitude']
-        amp = self.meter.get('amplitude')
-        self.assertEqual(ampsnap['value'], amp)
-        amp_ts = datetime.strptime(ampsnap['ts'], '%Y-%m-%d %H:%M:%S')
-        self.assertLessEqual(amp_ts, datetime.now())
-        self.assertGreater(amp_ts, datetime.now() - timedelta(seconds=1.1))
-
-    def test_manual_snapshot(self):
-        self.source.add_parameter('noise', parameter_class=ManualParameter)
-        noise = self.source.noise
-
-        noisesnap = self.source.snapshot()['parameters']['noise']
-        strip_qc(noisesnap)
-        self.assertEqual(noisesnap, {
-            '__class__': 'qcodes.instrument.parameter.ManualParameter',
-            'instrument': 'tests.instrument_mocks.MockSource',
-            'instrument_name': 'source',
-            'label': 'noise',
-            'name': 'noise',
-            'ts': None,
-            'unit': '',
-            'value': None,
-            'vals': '<Numbers>'
-        })
-
-        noise.set(100)
-        noisesnap = self.source.snapshot()['parameters']['noise']
-        self.assertEqual(noisesnap['value'], 100)
-
-        noise_ts = datetime.strptime(noisesnap['ts'], '%Y-%m-%d %H:%M:%S')
-        self.assertLessEqual(noise_ts, datetime.now())
-        self.assertGreater(noise_ts, datetime.now() - timedelta(seconds=1.1))
-
-    def tests_get_latest(self):
-        self.source.add_parameter('noise', parameter_class=ManualParameter)
-        noise = self.source.noise
-
-        self.assertIsNone(noise.get_latest())
-
-        noise.set(100)
-
-        mock_ts = datetime(2000, 3, 4)
-        ts_str = mock_ts.strftime('%Y-%m-%d %H:%M:%S')
-        noise.setattr('_latest_ts', mock_ts)
-        self.assertEqual(noise.snapshot()['ts'], ts_str)
-
-        self.assertEqual(noise.get_latest(), 100)
-        self.assertEqual(noise.get_latest.get(), 100)
-
-        # get_latest should not update ts
-        self.assertEqual(noise.snapshot()['ts'], ts_str)
-
-        # get_latest is not settable
-        with self.assertRaises(AttributeError):
-            noise.get_latest.set(50)
-
-    def test_base_instrument_errors(self):
-        b = Instrument('silent', server_name=None)
-
-        with self.assertRaises(NotImplementedError):
-            b.write('hello!')
-        with self.assertRaises(NotImplementedError):
-            b.ask('how are you?')
-
-        with self.assertRaises(TypeError):
-            b.add_function('skip', call_cmd='skip {}',
-                           args=['not a validator'])
-        with self.assertRaises(NoCommandError):
-            b.add_function('jump')
-        with self.assertRaises(NoCommandError):
-            b.add_parameter('height')
-
-    def test_manual_parameter(self):
-        self.source.add_parameter('bias_resistor',
-                                  parameter_class=ManualParameter,
-                                  initial_value=1000)
-        res = self.source.bias_resistor
-        self.assertEqual(res.get(), 1000)
-
-        res.set(1e9)
-        self.assertEqual(res.get(), 1e9)
-        # default vals is all numbers
-        # set / get with __call__ shortcut
-        res(-1)
-        self.assertEqual(res(), -1)
-
-        self.source.add_parameter('alignment',
-                                  parameter_class=ManualParameter,
-                                  vals=Enum('lawful', 'neutral', 'chaotic'))
-        alignment = self.source.alignment
-
-        # a ManualParameter can have initial_value=None (default) even if
-        # that's not a valid value to set later
-        self.assertIsNone(alignment.get())
-        with self.assertRaises(ValueError):
-            alignment.set(None)
-
-        alignment.set('lawful')
-        self.assertEqual(alignment.get(), 'lawful')
-
-        # None is the only invalid initial_value you can use
-        with self.assertRaises(TypeError):
-            self.source.add_parameter('alignment2',
-                                      parameter_class=ManualParameter,
-                                      initial_value='nearsighted')
-
-    def test_deferred_ops(self):
-        gates = self.gates
-        c0, c1, c2 = gates.chan0, gates.chan1, gates.chan2
-
-        c0.set(0)
-        c1.set(1)
-        c2.set(2)
-
-        self.assertEqual((c0 + c1 + c2)(), 3)
-        self.assertEqual((10 + (c0**2) + (c1**2) + (c2**2))(), 15)
-
-        d = c1.get_latest / c0.get_latest
-        with self.assertRaises(ZeroDivisionError):
-            d()
-
-    def test_attr_access(self):
-        instrument = self.gates
-
-        # set one attribute with nested levels
-        instrument.setattr('d1', {'a': {1: 2}})
-
-        # get the whole dict
-        self.assertEqual(instrument.getattr('d1'), {'a': {1: 2}})
-        self.assertEqual(instrument.getattr('d1', 55), {'a': {1: 2}})
-
-        # get parts
-        self.assertEqual(instrument.getattr('d1["a"]'), {1: 2})
-        self.assertEqual(instrument.getattr("d1['a'][1]"), 2)
-        self.assertEqual(instrument.getattr('d1["a"][1]', 3), 2)
-
-        # add an attribute inside, then delete it again
-        instrument.setattr('d1["a"][2]', 23)
-        self.assertEqual(instrument.getattr('d1'), {'a': {1: 2, 2: 23}})
-        instrument.delattr('d1["a"][2]')
-        self.assertEqual(instrument.getattr('d1'), {'a': {1: 2}})
-
-        # test restarting the InstrumentServer - this clears these attrs
-        instrument._manager.restart()
-        self.assertIsNone(instrument.getattr('d1', None))
-
-    def test_component_attr_access(self):
-        instrument = self.gates
-        method = instrument.add5
-        parameter = instrument.chan1
-        function = instrument.reset
-
-        # RemoteMethod objects have no attributes besides __doc__, so test
-        # that this gets appropriately decorated
-        self.assertIn('RemoteMethod add5 in RemoteInstrument', method.__doc__)
-        # and also contains the remote doc
-        self.assertIn('not the same function as the original method',
-                      method.__doc__)
-
-        # unit is a remote attribute of parameters
-        # this one is initially blank
-        self.assertEqual(parameter.unit, '')
-        parameter.unit = 'Smoots'
-        self.assertEqual(parameter.unit, 'Smoots')
-        self.assertNotIn('unit', parameter.__dict__)
-        self.assertEqual(instrument.getattr(parameter.name + '.unit'),
-                         'Smoots')
-        # we can delete it remotely, and this is reflected in dir()
-        self.assertIn('unit', dir(parameter))
-        del parameter.unit
-        self.assertNotIn('unit', dir(parameter))
-        with self.assertRaises(AttributeError):
-            parameter.unit
-
-        # and set it again, it's still remote.
-        parameter.unit = 'Furlongs per fortnight'
-        self.assertIn('unit', dir(parameter))
-        self.assertEqual(parameter.unit, 'Furlongs per fortnight')
-        self.assertNotIn('unit', parameter.__dict__)
-        self.assertEqual(instrument.getattr(parameter.name + '.unit'),
-                         'Furlongs per fortnight')
-        # we get the correct result if someone else sets it on the server
-        instrument._write_server('setattr', parameter.name + '.unit', 'T')
-        self.assertEqual(parameter.unit, 'T')
-        self.assertEqual(parameter.getattr('unit'), 'T')
-
-        # attributes not specified as remote are local
-        with self.assertRaises(AttributeError):
-            parameter.something
-        parameter.something = 42
-        self.assertEqual(parameter.something, 42)
-        self.assertEqual(parameter.__dict__['something'], 42)
-        with self.assertRaises(AttributeError):
-            instrument.getattr(parameter.name + '.something')
-        with self.assertRaises(AttributeError):
-            # getattr method is only for remote attributes
-            parameter.getattr('something')
-        self.assertIn('something', dir(parameter))
-        del parameter.something
-        self.assertNotIn('something', dir(parameter))
-        with self.assertRaises(AttributeError):
-            parameter.something
-
-        # call a remote method
-        self.assertEqual(set(parameter.callattr('get_attrs')),
-                         parameter._attrs)
-
-        # functions have remote attributes too
-        self.assertEqual(function._args, [])
-        self.assertNotIn('_args', function.__dict__)
-        function._args = 'args!'
-        self.assertEqual(function._args, 'args!')
-
-        # a component with no docstring still gets the decoration
-        foo = instrument.foo
-        self.assertEqual(foo.__doc__,
-                         'RemoteParameter foo in RemoteInstrument gates')
-
-    def test_update_components(self):
-        gates = self.gates
-
-        gates.delattr('chan0.label')
-        gates.setattr('chan0.cheese', 'gorgonzola')
-        # we've altered the server copy, but not the RemoteParameter
-        self.assertIn('label', gates.chan0._attrs)
-        self.assertNotIn('cheese', gates.chan0._attrs)
-        # keep a reference to the original chan0 RemoteParameter to make sure
-        # it is still the same object later
-        chan0_original = gates.chan0
-
-        gates.update()
-
-        self.assertIs(gates.chan0, chan0_original)
-        # now the RemoteParameter should have the updates
-        self.assertNotIn('label', gates.chan0._attrs)
-        self.assertIn('cheese', gates.chan0._attrs)
-
-    def test_add_delete_components(self):
-        gates = self.gates
-
-        # rather than call gates.add_parameter, which has a special proxy
-        # on the remote so it updates the components immediately, we'll call
-        # the server version directly
-        attr_list = gates.callattr('add_parameter', 'chan0X', get_cmd='c0?',
-                                   set_cmd='c0:{:.4f}', get_parser=float)
-        gates.delattr('parameters["chan0"]')
-
-        # the RemoteInstrument does not have these changes yet
-        self.assertIn('chan0', gates.parameters)
-        self.assertNotIn('chan0X', gates.parameters)
-
-        gates.update()
-
-        # now the RemoteInstrument has the changes
-        self.assertNotIn('chan0', gates.parameters)
-        self.assertIn('chan0X', gates.parameters)
-        self.assertEqual(gates.chan0X._attrs, set(attr_list))
-
-    def test_reprs(self):
-        gates = self.gates
-        self.assertIn(gates.name, repr(gates))
-        self.assertIn('chan1', repr(gates.chan1))
-        self.assertIn('reset', repr(gates.reset))
-
-    def test_remote_sweep_values(self):
-        chan1 = self.gates.chan1
-
-        sv1 = chan1[1:4:1]
-        self.assertEqual(len(sv1), 3)
-        self.assertIn(2, sv1)
-
-        sv2 = chan1.sweep(start=2, stop=3, num=6)
-        self.assertEqual(len(sv2), 6)
-        self.assertIn(2.2, sv2)
-
-    def test_add_function(self):
-        gates = self.gates
-        # add a function remotely
-        gates.add_function('reset2', call_cmd='rst')
-        gates.chan1(4)
-        self.assertEqual(gates.chan1(), 4)
-        gates.reset2()
-        self.assertEqual(gates.chan1(), 0)
-
-
-class TestLocalMock(TestCase):
-
-    @classmethod
-    def setUpClass(cls):
-        cls.model = AMockModel()
-
-        cls.gates = MockGates(model=cls.model, server_name=None)
-        cls.source = MockSource(model=cls.model, server_name=None)
-        cls.meter = MockMeter(model=cls.model, server_name=None)
-
-    @classmethod
-    def tearDownClass(cls):
-        cls.model.close()
-        for instrument in [cls.gates, cls.source, cls.meter]:
-            instrument.close()
-
-    def test_local(self):
-        self.gates.chan1.set(3.33)
-        self.assertEqual(self.gates.chan1.get(), 3.33)
-
-        self.gates.reset()
-        self.assertEqual(self.gates.chan1.get(), 0)
-
-        with self.assertRaises(ValueError):
-            self.gates.ask('knock knock? Oh never mind.')
-
-    def test_instances(self):
-        # copied from the main (server-based) version
-        # make sure it all works the same here
-        instruments = [self.gates, self.source, self.meter]
-        for instrument in instruments:
-            for other_instrument in instruments:
-                instances = instrument.instances()
-                # check that each instrument is in only its own
-                # instances list
-                if other_instrument is instrument:
-                    self.assertIn(instrument, instances)
-                else:
-                    self.assertNotIn(other_instrument, instances)
-
-                # check that we can find each instrument from any other
-                # use find_component here to test that it rolls over to
-                # find_instrument if only a name is given
-                self.assertEqual(
-                    instrument,
-                    other_instrument.find_component(instrument.name))
-
-                self.assertEqual(
-                    instrument.name,
-                    other_instrument.find_component(instrument.name + '.name'))
-
-            # check that we can find this instrument from the base class
-            self.assertEqual(instrument,
-                             Instrument.find_instrument(instrument.name))
-
-
-class TestModelAttrAccess(TestCase):
-
-    def setUp(self):
-        self.model = AMockModel()
-
-    def tearDown(self):
-        self.model.close()
-
-    def test_attr_access(self):
-        model = self.model
-
-        model.a = 'local'
-        with self.assertRaises(AttributeError):
-            model.getattr('a')
-
-        self.assertEqual(model.getattr('a', 'dflt'), 'dflt')
-
-        model.setattr('a', 'remote')
-        self.assertEqual(model.a, 'local')
-        self.assertEqual(model.getattr('a'), 'remote')
-
-        model.delattr('a')
-        self.assertEqual(model.getattr('a', 'dflt'), 'dflt')
-
-        model.fmt = 'local override of a remote method'
-        self.assertEqual(model.callattr('fmt', 42), '42.000')
-        self.assertEqual(model.callattr('fmt', value=12.4), '12.400')
+from .instrument_mocks import DummyInstrument
 
 
 class TestInstrument2(TestCase):
@@ -995,7 +36,7 @@ def test_attr_access(self):
         instrument.close()
 
         # make sure we can still print the instrument
-        _ = instrument.__repr__()
+        instrument.__repr__()
 
         # make sure the gate is removed
         self.assertEqual(hasattr(instrument, 'dac1'), False)

From 0bf8f21cd4c95db8e2ba998729df32287ae21767 Mon Sep 17 00:00:00 2001
From: Giulio Ungaretti <giulioungaretti@me.com>
Date: Mon, 6 Mar 2017 16:13:35 +0100
Subject: [PATCH 09/36] feature: Rremove more mocks

---
 qcodes/process/__init__.py |  0
 qcodes/tests/data_mocks.py | 24 ------------------------
 qcodes/tests/test_data.py  | 19 +++----------------
 3 files changed, 3 insertions(+), 40 deletions(-)
 delete mode 100644 qcodes/process/__init__.py

diff --git a/qcodes/process/__init__.py b/qcodes/process/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/qcodes/tests/data_mocks.py b/qcodes/tests/data_mocks.py
index 73cc7c70230..d561064afe2 100644
--- a/qcodes/tests/data_mocks.py
+++ b/qcodes/tests/data_mocks.py
@@ -1,34 +1,10 @@
 import numpy
-import multiprocessing as mp
 
 from qcodes.data.data_array import DataArray
 from qcodes.data.data_set import new_data
 from qcodes.data.io import DiskIO
 
 
-class MockDataManager:
-    query_lock = mp.RLock()
-
-    def __init__(self):
-        self.needs_restart = False
-
-    def ask(self, *args, timeout=None):
-        if args == ('get_data', 'location'):
-            return self.location
-        elif args == ('get_data',):
-            return self.live_data
-        elif args[0] == 'new_data' and len(args) == 2:
-            if self.needs_restart:
-                raise AttributeError('data_manager needs a restart')
-            else:
-                self.data_set = args[1]
-        else:
-            raise Exception('unexpected query to MockDataManager')
-
-    def restart(self):
-        self.needs_restart = False
-
-
 class MockFormatter:
     def read(self, data_set):
         data_set.has_read_data = True
diff --git a/qcodes/tests/test_data.py b/qcodes/tests/test_data.py
index ccd7af58181..d000346f5b1 100644
--- a/qcodes/tests/test_data.py
+++ b/qcodes/tests/test_data.py
@@ -1,21 +1,18 @@
 from unittest import TestCase
-from unittest.mock import patch
 import numpy as np
 import os
 import pickle
 import logging
 
 from qcodes.data.data_array import DataArray
-from qcodes.data.manager import get_data_manager, NoData
 from qcodes.data.io import DiskIO
 from qcodes.data.data_set import load_data, new_data, DataSet
-from qcodes.process.helpers import kill_processes
 from qcodes.utils.helpers import LogCapture
-from qcodes import active_children
 
-from .data_mocks import (MockDataManager, MockFormatter, MatchIO,
-                         MockLive, MockArray, DataSet2D, DataSet1D,
+from .data_mocks import (MockFormatter, MatchIO,
+                         DataSet2D, DataSet1D,
                          DataSetCombined, RecordingMockFormatter)
+
 from .common import strip_qc
 
 
@@ -284,9 +281,6 @@ def test_fraction_complete(self):
 
 class TestLoadData(TestCase):
 
-    def setUp(self):
-        kill_processes()
-
     def test_no_saved_data(self):
         with self.assertRaises(IOError):
             load_data('_no/such/file_')
@@ -296,9 +290,6 @@ def test_load_false(self):
             load_data(False)
 
     def test_get_read(self):
-        dm = MockDataManager()
-        dm.location = 'somewhere else'
-
         data = load_data(formatter=MockFormatter(), location='here!')
         self.assertEqual(data.has_read_data, True)
         self.assertEqual(data.has_read_metadata, True)
@@ -346,7 +337,6 @@ class TestNewData(TestCase):
 
     @classmethod
     def setUpClass(cls):
-        kill_processes()
         cls.original_lp = DataSet.location_provider
 
     @classmethod
@@ -383,9 +373,6 @@ def my_location2(io, record):
 
 class TestDataSet(TestCase):
 
-    def tearDown(self):
-        kill_processes()
-
     def test_constructor_errors(self):
         # no location - only allowed with load_data
         with self.assertRaises(ValueError):

From c599b8ab25c37c13fa35ce855874ab6d245e8dbc Mon Sep 17 00:00:00 2001
From: Giulio Ungaretti <giulioungaretti@me.com>
Date: Mon, 6 Mar 2017 16:48:16 +0100
Subject: [PATCH 10/36] finally eradicate mp

---
 qcodes/__init__.py                     |   7 -
 qcodes/data/manager.py                 | 163 --------
 qcodes/instrument/base.py              |  21 +-
 qcodes/instrument/mock.py              | 280 +------------
 qcodes/instrument/remote.py            | 529 -------------------------
 qcodes/instrument/server.py            | 190 ---------
 qcodes/instrument/visa.py              |  21 -
 qcodes/process/helpers.py              |  63 ---
 qcodes/process/qcodes_process.py       |  72 ----
 qcodes/process/server.py               | 399 -------------------
 qcodes/process/stream_queue.py         | 152 -------
 qcodes/station.py                      |   9 +-
 qcodes/tests/instrument_mocks.py       | 195 ---------
 qcodes/tests/test_driver_testcase.py   |  58 ---
 qcodes/tests/test_instrument_server.py | 157 --------
 qcodes/tests/test_multiprocessing.py   | 471 ----------------------
 qcodes/tests/test_nested_attrs.py      | 100 -----
 qcodes/tests/test_visa.py              |  43 --
 18 files changed, 5 insertions(+), 2925 deletions(-)
 delete mode 100644 qcodes/data/manager.py
 delete mode 100644 qcodes/instrument/remote.py
 delete mode 100644 qcodes/instrument/server.py
 delete mode 100644 qcodes/process/helpers.py
 delete mode 100644 qcodes/process/qcodes_process.py
 delete mode 100644 qcodes/process/server.py
 delete mode 100644 qcodes/process/stream_queue.py
 delete mode 100644 qcodes/tests/test_driver_testcase.py
 delete mode 100644 qcodes/tests/test_instrument_server.py
 delete mode 100644 qcodes/tests/test_multiprocessing.py
 delete mode 100644 qcodes/tests/test_nested_attrs.py

diff --git a/qcodes/__init__.py b/qcodes/__init__.py
index b1b2644ccd9..f12b0489fc1 100644
--- a/qcodes/__init__.py
+++ b/qcodes/__init__.py
@@ -2,10 +2,6 @@
 
 # flake8: noqa (we don't need the "<...> imported but unused" error)
 
-# just for convenience in debugging, so we don't have to
-# separately import multiprocessing
-from multiprocessing import active_children
-
 # config
 
 from qcodes.config import Config
@@ -13,7 +9,6 @@
 config = Config()
 
 from qcodes.version import __version__
-from qcodes.process.helpers import set_mp_method
 from qcodes.utils.helpers import in_notebook
 
 # code that should only be imported into the main (notebook) thread
@@ -44,7 +39,6 @@
 from qcodes.measure import Measure
 from qcodes.actions import Task, Wait, BreakIf
 
-from qcodes.data.manager import get_data_manager
 from qcodes.data.data_set import DataSet, new_data, load_data
 from qcodes.data.location import FormatLocation
 from qcodes.data.data_array import DataArray
@@ -56,7 +50,6 @@
 from qcodes.instrument.base import Instrument
 from qcodes.instrument.ip import IPInstrument
 from qcodes.instrument.visa import VisaInstrument
-from qcodes.instrument.mock import MockInstrument, MockModel
 
 from qcodes.instrument.function import Function
 from qcodes.instrument.parameter import (
diff --git a/qcodes/data/manager.py b/qcodes/data/manager.py
deleted file mode 100644
index 53121dac2fd..00000000000
--- a/qcodes/data/manager.py
+++ /dev/null
@@ -1,163 +0,0 @@
-from datetime import datetime, timedelta
-from queue import Empty
-from traceback import format_exc
-import logging
-
-from qcodes.process.server import ServerManager, BaseServer
-
-
-def get_data_manager(only_existing=False):
-    """
-    create or retrieve the storage manager
-    makes sure we don't accidentally create multiple DataManager processes
-    """
-    dm = DataManager.default
-    if dm and dm._server.is_alive():
-        return dm
-    elif only_existing:
-        return None
-    return DataManager()
-
-
-class NoData:
-    """
-    A placeholder object for DataServer to hold
-    when there is no loop running.
-    """
-    location = None
-
-    def store(self, *args, **kwargs):
-        raise RuntimeError('no DataSet to add to')
-
-    def write(self, *args, **kwargs):
-        pass
-
-
-class DataManager(ServerManager):
-    default = None
-    """
-    creates a separate process (DataServer) that holds running measurement
-    and monitor data, and manages writing these to disk or other storage
-
-    DataServer communicates with other processes through messages
-    Written using multiprocessing Queue's, but should be easily
-    extensible to other messaging systems
-    """
-    def __init__(self):
-        type(self).default = self
-        super().__init__(name='DataServer', server_class=DataServer)
-
-    def restart(self, force=False):
-        """
-        Restart the DataServer
-        Use force=True to abort a running measurement.
-        """
-        if (not force) and self.ask('get_data', 'location'):
-            raise RuntimeError('A measurement is running. Use '
-                               'restart(force=True) to override.')
-        super().restart()
-
-
-class DataServer(BaseServer):
-    """
-    Running in its own process, receives, holds, and returns current `Loop` and
-    monitor data, and writes it to disk (or other storage)
-
-    When a `Loop` is *not* running, the DataServer also calls the monitor
-    routine. But when a `Loop` *is* running, *it* calls the monitor so that it
-    can avoid conflicts. Also while a `Loop` is running, there are
-    complementary `DataSet` objects in the loop and `DataServer` processes -
-    they are nearly identical objects, but are configured differently so that
-    the loop `DataSet` doesn't hold any data itself, it only passes that data
-    on to the `DataServer`
-    """
-    default_storage_period = 1  # seconds between data storage calls
-    queries_per_store = 5
-    default_monitor_period = 60  # seconds between monitoring storage calls
-
-    def __init__(self, query_queue, response_queue, extras=None):
-        super().__init__(query_queue, response_queue, extras)
-
-        self._storage_period = self.default_storage_period
-        self._monitor_period = self.default_monitor_period
-
-        self._data = NoData()
-        self._measuring = False
-
-        self.run_event_loop()
-
-    def run_event_loop(self):
-        self.running = True
-        next_store_ts = datetime.now()
-        next_monitor_ts = datetime.now()
-
-        while self.running:
-            read_timeout = self._storage_period / self.queries_per_store
-            try:
-                query = self._query_queue.get(timeout=read_timeout)
-                self.process_query(query)
-            except Empty:
-                pass
-
-            try:
-                now = datetime.now()
-
-                if self._measuring and now > next_store_ts:
-                    td = timedelta(seconds=self._storage_period)
-                    next_store_ts = now + td
-                    self._data.write()
-
-                if now > next_monitor_ts:
-                    td = timedelta(seconds=self._monitor_period)
-                    next_monitor_ts = now + td
-                    # TODO: update the monitor data storage
-
-            except:
-                logging.error(format_exc())
-
-    ######################################################################
-    # query handlers                                                     #
-    ######################################################################
-
-    def handle_new_data(self, data_set):
-        """
-        Load a new (normally empty) DataSet into the DataServer, and
-        prepare it to start receiving and storing data
-        """
-        if self._measuring:
-            raise RuntimeError('Already executing a measurement')
-
-        self._data = data_set
-        self._data.init_on_server()
-        self._measuring = True
-
-    def handle_finalize_data(self):
-        """
-        Mark this DataSet as complete and write its final changes to storage
-        """
-        self._data.finalize()
-        self._measuring = False
-
-    def handle_store_data(self, *args):
-        """
-        Put some data into the DataSet
-        """
-        self._data.store(*args)
-
-    def handle_get_measuring(self):
-        """
-        Is a measurement loop presently running?
-        """
-        return self._measuring
-
-    def handle_get_data(self, attr=None):
-        """
-        Return the active DataSet or some attribute of it
-        """
-        return getattr(self._data, attr) if attr else self._data
-
-    def handle_get_changes(self, synced_indices):
-        """
-        Return all new data after the last sync
-        """
-        return self._data.get_changes(synced_indices)
diff --git a/qcodes/instrument/base.py b/qcodes/instrument/base.py
index c131f7b9663..ff1ef079413 100644
--- a/qcodes/instrument/base.py
+++ b/qcodes/instrument/base.py
@@ -1,21 +1,17 @@
 """Instrument base class."""
 import logging
 import time
-import warnings
 import weakref
 import numpy as np
 
 from qcodes.utils.metadata import Metadatable
 from qcodes.utils.helpers import DelegateAttributes, strip_attrs, full_class
-from qcodes.utils.nested_attrs import NestedAttrAccess
 from qcodes.utils.validators import Anything
 from .parameter import StandardParameter
 from .function import Function
-from .metaclass import InstrumentMetaclass
 
 
-class Instrument(Metadatable, DelegateAttributes, NestedAttrAccess,
-                 metaclass=InstrumentMetaclass):
+class Instrument(Metadatable, DelegateAttributes):
 
     """
     Base class for all QCodes instruments.
@@ -137,21 +133,6 @@ def get_idn(self):
 
         return dict(zip(('vendor', 'model', 'serial', 'firmware'), idparts))
 
-    @classmethod
-    def default_server_name(cls, **kwargs):
-        """
-        Generate a default name for the server to host this instrument.
-
-        Args:
-            **kwargs: the constructor kwargs, used if necessary to choose a
-                name.
-
-        Returns:
-            str: The default server name for the specific instrument instance
-                we are constructing.
-        """
-        return 'Instruments'
-
     def connect_message(self, idn_param='IDN', begin_time=None):
         """
         Print a standard message on initial connection to an instrument.
diff --git a/qcodes/instrument/mock.py b/qcodes/instrument/mock.py
index ec100134e6f..c53cf3e93a0 100644
--- a/qcodes/instrument/mock.py
+++ b/qcodes/instrument/mock.py
@@ -1,288 +1,10 @@
 """Mock instruments for testing purposes."""
-import time
-from datetime import datetime
 
-from .base import Instrument
 from .parameter import MultiParameter
 from qcodes import Loop
 from qcodes.data.data_array import DataArray
-from qcodes.process.server import ServerManager, BaseServer
-from qcodes.utils.nested_attrs import _NoDefault
 
 
-class MockInstrument(Instrument):
-
-    """
-    Create a software instrument, mostly for testing purposes.
-
-    Also works for simulations, but usually this will be simpler, easier to
-    use, and faster if made as a single ``Instrument`` subclass.
-
-    ``MockInstrument``\s have extra overhead as they serialize all commands
-    (to mimic a network communication channel) and use at least two processes
-    (instrument server and model server) both of which must be involved in any
-    given query.
-
-    parameters to pass to model should be declared with:
-
-        - get_cmd = param_name + '?'
-        - set_cmd = param_name + ':{:.3f}' (specify the format & precision)
-
-    alternatively independent set/get functions may still be provided.
-
-    Args:
-        name (str): The name of this instrument.
-
-        delay (number): Time (in seconds) to wait after any operation
-            to simulate communication delay. Default 0.
-
-        model (MockModel): A model to connect to. Subclasses MUST accept
-            ``model`` as a constructor kwarg ONLY, even though it is required.
-            See notes in ``Instrument`` docstring.
-            The model should have one or two methods related directly to this
-            instrument by ``name``:
-            ``<name>_set(param, value)``: set a parameter on the model
-            ``<name>_get(param)``: returns the value of a parameter
-
-        keep_history (bool): Whether to record (in self.history) every command
-            sent to this instrument. Default True.
-
-        server_name (Union[str, None]): leave default ('') to make a
-            MockInsts-####### server with the number matching the model server
-            id, or set None to not use a server.
-
-    Attributes:
-        shared_kwargs (List[str]): Class attribute, constructor kwargs to
-            provide via server init. For MockInstrument this should always be
-            ['model'] at least.
-
-        keep_history (bool): Whether to record all commands and responses. Set
-            on init, but may be changed at any time.
-
-        history (List[tuple]): All commands and responses while keep_history is
-            enabled, as tuples:
-            (timestamp, 'ask' or 'write', param_name[, value])
-    """
-
-    shared_kwargs = ['model']
-
-    def __init__(self, name, delay=0, model=None, keep_history=True, **kwargs):
-        super().__init__(name, **kwargs)
-
-        if not isinstance(delay, (int, float)) or delay < 0:
-            raise TypeError('delay must be a non-negative number')
-        self._delay = delay
-
-        # try to access write and ask so we know they exist
-        model.write
-        model.ask
-        self._model = model
-
-        # keep a record of every command sent to this instrument
-        # for debugging purposes?
-        self.keep_history = bool(keep_history)
-        self.history = []
-
-    @classmethod
-    def default_server_name(cls, **kwargs):
-        """
-        Get the default server name for this instrument.
-
-        Args:
-            **kwargs: All the kwargs supplied in the constructor.
-
-        Returns:
-            str: Default MockInstrument server name is MockInsts-#######, where
-                ####### is the first 7 characters of the MockModel's uuid.
-        """
-        model = kwargs.get('model', None)
-        if model:
-            return model.name.replace('Model', 'MockInsts')
-        return 'MockInstruments'
-
-    def get_idn(self):
-        """Shim for IDN parameter."""
-        return {
-            'vendor': None,
-            'model': type(self).__name__,
-            'serial': self.name,
-            'firmware': None
-        }
-
-    def write_raw(self, cmd):
-        """
-        Low-level interface to ``model.write``.
-
-        Prepends self.name + ':' to the command, so the ``MockModel``
-        will direct this query to its ``<name>_set`` method
-
-        Args:
-            cmd (str): The command to send to the instrument.
-        """
-        if self._delay:
-            time.sleep(self._delay)
-
-        try:
-            parameter, value = cmd.split(':', 1)
-        except ValueError:
-            parameter, value = cmd, None  # for functions with no value
-
-        if self.keep_history:
-            self.history.append((datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
-                                 'write', parameter, value))
-
-        self._model.write('cmd', self.name + ':' + cmd)
-
-    def ask_raw(self, cmd):
-        """
-        Low-level interface to ``model.ask``.
-
-        Prepends self.name + ':' to the command, so the ``MockModel``
-        will direct this query to its ``<name>_get`` method
-
-        Args:
-            cmd (str): The command to send to the instrument.
-
-        Returns:
-            str: The instrument's response.
-
-        Raises:
-            ValueError: If ``cmd`` is malformed in that it contains text
-                after the '?'
-        """
-        if self._delay:
-            time.sleep(self._delay)
-
-        parameter, blank = cmd.split('?')
-        if blank:
-            raise ValueError('text found after end of query')
-
-        if self.keep_history:
-            self.history.append((datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
-                                 'ask', parameter))
-
-        return self._model.ask('cmd', self.name + ':' + cmd)
-
-
-# MockModel is purely in service of mock instruments which *are* tested
-# so coverage testing this (by running it locally) would be a waste.
-class MockModel(ServerManager, BaseServer):  # pragma: no cover
-
-    """
-    Base class for models to connect to various MockInstruments.
-
-    Creates a separate process that holds the model state, so that
-    any process can interact with the model and get the same state.
-
-    Args:
-        name (str): The server name to create for the model.
-            Default 'Model-{:.7s}' uses the first 7 characters of
-            the server's uuid.
-
-    for every instrument that connects to this model, create two methods:
-        - ``<instrument>_set(param, value)``: set a parameter on the model
-        - ``<instrument>_get(param)``: returns the value of a parameter
-          ``param`` and the set/return values should all be strings
-
-    If ``param`` and/or ``value`` is not recognized, the method should raise
-    an error.
-
-    Other uses of ServerManager use separate classes for the server and its
-    manager, but here I put the two together into a single class, to make it
-    easier to define models. The downside is you have a local object with
-    methods you shouldn't call: the extras (<instrument>_(set|get)) should
-    only be called on the server copy. Normally this should only be called via
-    the attached instruments anyway.
-
-    The model supports ``NestedAttrAccess`` calls ``getattr``, ``setattr``,
-    ``callattr``, and ``delattr`` Because the manager and server are the same
-    object, we override these methods with proxy methods after the server has
-    been started.
-    """
-
-    def __init__(self, name='Model-{:.7s}'):
-        super().__init__(name, server_class=None)
-
-        # now that the server has started, we can remap attribute access
-        # from the private methods (_getattr) to the public ones (getattr)
-        # but the server copy will still have the NestedAttrAccess ones
-        self.getattr = self._getattr
-        self.setattr = self._setattr
-        self.callattr = self._callattr
-        self.delattr = self._delattr
-
-    def _run_server(self):
-        self.run_event_loop()
-
-    def handle_cmd(self, cmd):
-        """
-        Handler for all model queries.
-
-        Args:
-            cmd (str): Can take several forms:
-
-                - '<instrument>:<parameter>?':
-                  calls ``self.<instrument>_get(<parameter>)`` and forwards
-                  the return value.
-                - '<instrument>:<parameter>:<value>':
-                  calls ``self.<instrument>_set(<parameter>, <value>)``
-                - '<instrument>:<parameter>'.
-                  calls ``self.<instrument>_set(<parameter>, None)``
-
-        Returns:
-            Union(str, None): The parameter value, if ``cmd`` has the form
-            '<instrument>:<parameter>?', otherwise no return.
-
-        Raises:
-            ValueError: if cmd does not match one of the patterns above.
-        """
-        query = cmd.split(':')
-
-        instrument = query[0]
-        param = query[1]
-
-        if param[-1] == '?' and len(query) == 2:
-            return getattr(self, instrument + '_get')(param[:-1])
-
-        elif len(query) <= 3:
-            value = query[2] if len(query) == 3 else None
-            getattr(self, instrument + '_set')(param, value)
-
-        else:
-            raise ValueError()
-
-    def _getattr(self, attr, default=_NoDefault):
-        """
-        Get a (possibly nested) attribute of this model on its server.
-
-        See NestedAttrAccess for details.
-        """
-        return self.ask('method_call', 'getattr', attr, default)
-
-    def _setattr(self, attr, value):
-        """
-        Set a (possibly nested) attribute of this model on its server.
-
-        See NestedAttrAccess for details.
-        """
-        self.ask('method_call', 'setattr', attr, value)
-
-    def _callattr(self, attr, *args, **kwargs):
-        """
-        Call a (possibly nested) method of this model on its server.
-
-        See NestedAttrAccess for details.
-        """
-        return self.ask('method_call', 'callattr', attr, *args, **kwargs)
-
-    def _delattr(self, attr):
-        """
-        Delete a (possibly nested) attribute of this model on its server.
-
-        See NestedAttrAccess for details.
-        """
-        self.ask('method_call', 'delattr', attr)
-
 class ArrayGetter(MultiParameter):
     """
     Example parameter that just returns a single array
@@ -313,4 +35,4 @@ def get(self):
         loop = Loop(self.sweep_values, self.delay).each(self.measured_param)
         data = loop.run_temp()
         array = data.arrays[self.measured_param.full_name]
-        return (array,)
\ No newline at end of file
+        return (array,)
diff --git a/qcodes/instrument/remote.py b/qcodes/instrument/remote.py
deleted file mode 100644
index 37401e80b23..00000000000
--- a/qcodes/instrument/remote.py
+++ /dev/null
@@ -1,529 +0,0 @@
-"""Proxies to interact with server-based instruments from another process."""
-import multiprocessing as mp
-
-from qcodes.utils.deferred_operations import DeferredOperations
-from qcodes.utils.helpers import DelegateAttributes, named_repr
-from .parameter import Parameter, GetLatest
-from .server import get_instrument_server_manager
-
-
-class RemoteInstrument(DelegateAttributes):
-
-    """
-    A proxy for an instrument (of any class) running on a server process.
-
-    Creates the server if necessary, then loads this instrument onto it,
-    then mirrors the API to that instrument.
-
-    Args:
-        *args: Passed along to the real instrument constructor.
-
-        instrument_class (type): The class of the real instrument to make.
-
-        server_name (str): The name of the server to create or use for this
-            instrument. If not provided (''), gets a name from
-            ``instrument_class.default_server_name(**kwargs)`` using the
-            same kwargs passed to the instrument constructor.
-
-        **kwargs: Passed along to the real instrument constructor, also
-            to ``default_server_name`` as mentioned.
-
-    Attributes:
-        name (str): an identifier for this instrument, particularly for
-            attaching it to a Station.
-
-        parameters (Dict[Parameter]): All the parameters supported by this
-            instrument. Usually populated via ``add_parameter``
-
-        functions (Dict[Function]): All the functions supported by this
-            instrument. Usually populated via ``add_function``
-    """
-
-    delegate_attr_dicts = ['_methods', 'parameters', 'functions']
-
-    def __init__(self, *args, instrument_class=None, server_name='',
-                 **kwargs):
-        if server_name == '':
-            server_name = instrument_class.default_server_name(**kwargs)
-
-        shared_kwargs = {}
-        for kwname in instrument_class.shared_kwargs:
-            if kwname in kwargs:
-                shared_kwargs[kwname] = kwargs[kwname]
-                del kwargs[kwname]
-
-        self._server_name = server_name
-        self._shared_kwargs = shared_kwargs
-        self._manager = get_instrument_server_manager(self._server_name,
-                                                      self._shared_kwargs)
-
-        self._instrument_class = instrument_class
-        self._args = args
-        self._kwargs = kwargs
-
-        self.connect()
-
-    def connect(self):
-        """Create the instrument on the server and replicate its API here."""
-
-        # connection_attrs is created by instrument.connection_attrs(),
-        # called by InstrumentServer.handle_new after it creates the instrument
-        # on the server.
-        connection_attrs = self._manager.connect(self, self._instrument_class,
-                                                 self._args, self._kwargs)
-
-        self.name = connection_attrs['name']
-        self._id = connection_attrs['id']
-        self._methods = {}
-        self.parameters = {}
-        self.functions = {}
-
-        # bind all the different categories of actions we need
-        # to interface with the remote instrument
-
-        self._update_components(connection_attrs)
-
-    def _update_components(self, connection_attrs):
-        """
-        Update the three component dicts with new or updated connection attrs.
-
-        Args:
-            connection_attrs (dict): as returned by
-                ``Instrument.connection_attrs``, should contain at least keys
-                ``_methods``, ``parameters``, and ``functions``, whose values
-                are themselves dicts of {component_name: list of attributes}.
-                These get translated into the corresponding dicts eg:
-                ``self.parameters = {parameter_name: RemoteParameter}``
-        """
-        component_types = (('_methods', RemoteMethod),
-                           ('parameters', RemoteParameter),
-                           ('functions', RemoteFunction))
-
-        for container_name, component_class in component_types:
-            container = getattr(self, container_name)
-            components_spec = connection_attrs[container_name]
-
-            # first delete components that are gone and update those that
-            # have changed
-            for name in list(container.keys()):
-                if name in components_spec:
-                    container[name].update(components_spec[name])
-                else:
-                    del container[name]
-
-            # then add new components
-            for name, attrs in components_spec.items():
-                if name not in container:
-                    container[name] = component_class(name, self, attrs)
-
-    def update(self):
-        """Check with the server for updated components."""
-        connection_attrs = self._ask_server('connection_attrs', self._id)
-        self._update_components(connection_attrs)
-
-    def _ask_server(self, func_name, *args, **kwargs):
-        """Query the server copy of this instrument, expecting a response."""
-        return self._manager.ask('cmd', self._id, func_name, *args, **kwargs)
-
-    def _write_server(self, func_name, *args, **kwargs):
-        """Send a command to the server, without waiting for a response."""
-        self._manager.write('cmd', self._id, func_name, *args, **kwargs)
-
-    def add_parameter(self, name, **kwargs):
-        """
-        Proxy to add a new parameter to the server instrument.
-
-        This is only for adding parameters remotely to the server copy.
-        Normally parameters are added in the instrument constructor, rather
-        than via this method. This method is limited in that you can generally
-        only use the string form of a command, not the callable form.
-
-        Args:
-            name (str): How the parameter will be stored within
-                ``instrument.parameters`` and also how you address it using the
-                shortcut methods: ``instrument.set(param_name, value)`` etc.
-
-            parameter_class (Optional[type]): You can construct the parameter
-                out of any class. Default ``StandardParameter``.
-
-            **kwargs: constructor arguments for ``parameter_class``.
-        """
-        attrs = self._ask_server('add_parameter', name, **kwargs)
-        self.parameters[name] = RemoteParameter(name, self, attrs)
-
-    def add_function(self, name, **kwargs):
-        """
-        Proxy to add a new Function to the server instrument.
-
-        This is only for adding functions remotely to the server copy.
-        Normally functions are added in the instrument constructor, rather
-        than via this method. This method is limited in that you can generally
-        only use the string form of a command, not the callable form.
-
-        Args:
-            name (str): how the function will be stored within
-            ``instrument.functions`` and also how you  address it using the
-            shortcut methods: ``instrument.call(func_name, *args)`` etc.
-
-            **kwargs: constructor kwargs for ``Function``
-        """
-        attrs = self._ask_server('add_function', name, **kwargs)
-        self.functions[name] = RemoteFunction(name, self, attrs)
-
-    def instances(self):
-        """
-        A RemoteInstrument shows as an instance of its proxied class.
-
-        Returns:
-            List[Union[Instrument, RemoteInstrument]]
-        """
-        return self._instrument_class.instances()
-
-    def find_instrument(self, name, instrument_class=None):
-        """
-        Find an existing instrument by name.
-
-        Args:
-            name (str)
-
-        Returns:
-            Union[Instrument, RemoteInstrument]
-
-        Raises:
-            KeyError: if no instrument of that name was found, or if its
-                reference is invalid (dead).
-        """
-        return self._instrument_class.find_instrument(
-            name, instrument_class=instrument_class)
-
-    def close(self):
-        """Irreversibly close and tear down the server & remote instruments."""
-        if hasattr(self, '_manager'):
-            if self._manager._server in mp.active_children():
-                self._manager.delete(self._id)
-            del self._manager
-        self._instrument_class.remove_instance(self)
-
-    def restart(self):
-        """
-        Remove and recreate the server copy of this instrument.
-
-        All instrument state will be returned to the initial conditions,
-        including deleting any parameters you've added after initialization,
-        or modifications to parameters etc.
-        """
-        self._manager.delete(self._id)
-        self.connect()
-
-    def __getitem__(self, key):
-        """Delegate instrument['name'] to parameter or function 'name'."""
-        try:
-            return self.parameters[key]
-        except KeyError:
-            return self.functions[key]
-
-    def __repr__(self):
-        """repr including the instrument name."""
-        return named_repr(self)
-
-
-class RemoteComponent:
-
-    """
-    An object that lives inside a RemoteInstrument.
-
-    Proxies all of its calls and specific listed attributes to the
-    corresponding object in the server instrument.
-
-    Args:
-        name (str): The name of this component.
-
-        instrument (RemoteInstrument): the instrument this is part of.
-
-        attrs (List[str]): instance attributes to proxy to the server
-            copy of this component.
-
-    Attributes:
-        name (str): The name of this component.
-
-        _instrument (RemoteInstrument): the instrument this is part of.
-
-        _attrs (Set[str]): All the attributes we are allowed to proxy.
-
-        _delattrs (Set[str]): Attributes we've deleted from the server,
-            a subset of ``_attrs``, but if you set them again, they will
-            still be set on the server.
-
-        _local_attrs (Set[str]): (class attribute only) Attributes that we
-            shouldn't look for on the server, even if they do not exist
-            locally. Mostly present to prevent infinite recursion in the
-            accessors.
-    """
-    _local_attrs = {
-        '_attrs',
-        'name',
-        '_instrument',
-        '_local_attrs',
-        '__doc__',
-        '_delattrs'
-    }
-
-    def __init__(self, name, instrument, attrs):
-        self.name = name
-        self._instrument = instrument
-        self.update(attrs)
-
-    def update(self, attrs):
-        """
-        Update the set of attributes proxied by this component.
-
-        The docstring is not proxied every time it is accessed, but it is
-        read and updated during this method.
-
-        Args:
-            attrs (Sequence[str]): the new set of attributes to proxy.
-        """
-        self._attrs = set(attrs)
-        self._delattrs = set()
-        self._set_doc()
-
-    def __getattr__(self, attr):
-        """
-        Get an attribute value from the server.
-
-        If there was a local attribute, we don't even get here.
-        """
-        if attr not in type(self)._local_attrs and attr in self._attrs:
-            full_attr = self.name + '.' + attr
-            return self._instrument._ask_server('getattr', full_attr)
-        else:
-            raise AttributeError('RemoteComponent has no local or remote '
-                                 'attribute: ' + attr)
-
-    def __setattr__(self, attr, val):
-        """
-        Set a new attribute value.
-
-        If the attribute is listed as remote, we'll set it on the server,
-        otherwise we'll set it locally.
-        """
-        if attr not in type(self)._local_attrs and attr in self._attrs:
-            full_attr = self.name + '.' + attr
-            self._instrument._ask_server('setattr', full_attr, val)
-            if attr in self._delattrs:
-                self._delattrs.remove(attr)
-        else:
-            object.__setattr__(self, attr, val)
-
-    def __delattr__(self, attr):
-        """
-        Delete an attribute.
-
-        If the attribute is listed as remote, we'll delete it on the server,
-        otherwise we'll delete it locally.
-        """
-
-        if attr not in type(self)._local_attrs and attr in self._attrs:
-            full_attr = self.name + '.' + attr
-            self._instrument._ask_server('delattr', full_attr)
-            self._delattrs.add(attr)
-
-        else:
-            object.__delattr__(self, attr)
-
-    def __dir__(self):
-        """dir listing including both local and server attributes."""
-        remote_attrs = self._attrs - self._delattrs
-        return sorted(remote_attrs.union(super().__dir__()))
-
-    def _set_doc(self):
-        """
-        Prepend a note about remoteness to the server docstring.
-
-        If no server docstring is found, we leave the class docstring.
-
-        __doc__, as a magic attribute, is handled differently from
-        other attributes so we won't make it dynamic (updating on the
-        server when you change it here)
-        """
-        doc = self._instrument._ask_server('getattr',
-                                           self.name + '.__doc__')
-
-        docbase = '{} {} in RemoteInstrument {}'.format(
-            type(self).__name__, self.name, self._instrument.name)
-
-        self.__doc__ = docbase + (('\n---\n\n' + doc) if doc else '')
-
-    def __repr__(self):
-        """repr including the component name."""
-        return named_repr(self)
-
-
-class RemoteMethod(RemoteComponent):
-
-    """Proxy for a method of the server instrument."""
-
-    def __call__(self, *args, **kwargs):
-        """Call the method on the server, passing on any args and kwargs."""
-        return self._instrument._ask_server(self.name, *args, **kwargs)
-
-
-class RemoteParameter(RemoteComponent, DeferredOperations):
-
-    """Proxy for a Parameter of the server instrument."""
-
-    def __init__(self, *args, **kwargs):
-        super().__init__(*args, **kwargs)
-        self.get_latest = GetLatest(self)
-
-    def __call__(self, *args):
-        """
-        Shortcut to get (with no args) or set (with one arg) the parameter.
-
-        Args:
-            *args: If empty, get the parameter. If one arg, set the parameter
-                to this value
-
-        Returns:
-            any: The parameter value, if called with no args,
-                otherwise no return.
-        """
-        if len(args) == 0:
-            return self.get()
-        else:
-            self.set(*args)
-
-    def get(self):
-        """
-        Read the value of this parameter.
-
-        Returns:
-            any: the current value of the parameter.
-        """
-        return self._instrument._ask_server('get', self.name)
-
-    def set(self, value):
-        """
-        Set a new value of this parameter.
-
-        Args:
-            value (any): the new value for the parameter.
-        """
-        # TODO: sometimes we want set to block (as here) and sometimes
-        # we want it async... which would just be changing the '_ask_server'
-        # to '_write_server' below. how do we decide, and how do we let the
-        # user do it?
-        self._instrument._ask_server('set', self.name, value)
-
-    def validate(self, value):
-        """
-        Raise an error if the given value is not allowed for this Parameter.
-
-        Args:
-            value (any): the proposed new parameter value.
-
-        Raises:
-            TypeError: if ``value`` has the wrong type for this Parameter.
-            ValueError: if the type is correct but the value is wrong.
-        """
-        self._instrument._ask_server('callattr',
-                                     self.name + '.validate', value)
-
-    # manually copy over sweep and __getitem__ so they execute locally
-    # and are still based off the RemoteParameter
-    def __getitem__(self, keys):
-        """Create a SweepValues from this parameter with slice notation."""
-        return Parameter.__getitem__(self, keys)
-
-    def sweep(self, *args, **kwargs):
-        """Create a SweepValues from this parameter. See Parameter.sweep."""
-        return Parameter.sweep(self, *args, **kwargs)
-
-    def _latest(self):
-        return self._instrument._ask_server('callattr', self.name + '._latest')
-
-    def snapshot(self, update=False):
-        """
-        State of the parameter as a JSON-compatible dict.
-
-        Args:
-            update (bool): If True, update the state by querying the
-                instrument. If False, just use the latest value in memory.
-
-        Returns:
-            dict: snapshot
-        """
-        return self._instrument._ask_server('callattr',
-                                            self.name + '.snapshot', update)
-
-    def setattr(self, attr, value):
-        """
-        Set an attribute of the parameter on the server.
-
-        Args:
-            attr (str): the attribute name. Can be nested as in
-                ``NestedAttrAccess``.
-            value: The new value to set.
-        """
-        self._instrument._ask_server('setattr', self.name + '.' + attr, value)
-
-    def getattr(self, attr):
-        """
-        Get an attribute of the parameter on the server.
-
-        Args:
-            attr (str): the attribute name. Can be nested as in
-                ``NestedAttrAccess``.
-
-        Returns:
-            any: The attribute value.
-        """
-        return self._instrument._ask_server('getattr', self.name + '.' + attr)
-
-    def callattr(self, attr, *args, **kwargs):
-        """
-        Call arbitrary methods of the parameter on the server.
-
-        Args:
-            attr (str): the method name. Can be nested as in
-                ``NestedAttrAccess``.
-            *args: positional args to the method
-            **kwargs: keyword args to the method
-
-        Returns:
-            any: the return value of the called method.
-        """
-        return self._instrument._ask_server(
-            'callattr', self.name + '.' + attr, *args, **kwargs)
-
-
-class RemoteFunction(RemoteComponent):
-
-    """Proxy for a Function of the server instrument."""
-
-    def __call__(self, *args):
-        """
-        Call the Function.
-
-        Args:
-            *args: The positional args to this Function. Functions only take
-                positional args, not kwargs.
-
-        Returns:
-            any: the return value of the function.
-        """
-        return self._instrument._ask_server('call', self.name, *args)
-
-    def call(self, *args):
-        """An alias for __call__."""
-        return self.__call__(*args)
-
-    def validate(self, *args):
-        """
-        Raise an error if the given args are not allowed for this Function.
-
-        Args:
-            *args: the proposed arguments with which to call the Function.
-        """
-        return self._instrument._ask_server(
-            'callattr', self.name + '.validate', *args)
diff --git a/qcodes/instrument/server.py b/qcodes/instrument/server.py
deleted file mode 100644
index 0772ff68783..00000000000
--- a/qcodes/instrument/server.py
+++ /dev/null
@@ -1,190 +0,0 @@
-import multiprocessing as mp
-
-from qcodes.process.server import ServerManager, BaseServer
-
-
-def get_instrument_server_manager(server_name, shared_kwargs={}):
-    """
-    Find or make a given `InstrumentServerManager`.
-
-    An `InstrumentServer` holds one or more Instrument objects, and an
-    `InstrumentServerManager` allows other processes to communicate with this
-    `InstrumentServer`.
-
-    Both the name and the shared attributes must match exactly. If no manager
-    exists with this name, it will be created with the given `shared_kwargs`.
-    If an manager exists with this name but different `shared_kwargs` we
-    raise an error.
-
-    server_name: (default 'Instruments') which server to put the instrument on.
-        If a server with this name exists, the instrument will be added to it.
-        If not, a new server is created with this name.
-
-    shared_kwargs: unpicklable items needed by the instruments on the
-        server, will get sent with the manager when it's started up
-        and included in the kwargs to construct each new instrument
-    """
-    if not server_name:
-        server_name = 'Instruments'
-
-    instances = InstrumentServerManager.instances
-    manager = instances.get(server_name, None)
-
-    if manager and manager._server in mp.active_children():
-        if shared_kwargs and manager.shared_kwargs != shared_kwargs:
-            # it's OK to add another instrument that has  *no* shared_kwargs
-            # but if there are some and they're different from what's
-            # already associated with this server, that's an error.
-            raise ValueError(('An InstrumentServer with name "{}" already '
-                              'exists but with different shared_attrs'
-                              ).format(server_name))
-    else:
-        manager = InstrumentServerManager(server_name, shared_kwargs)
-
-    return manager
-
-
-class InstrumentServerManager(ServerManager):
-    """
-    Creates and manages connections to an InstrumentServer
-
-    Args:
-        name: the name of the server to create
-        kwargs: extra items to send to the server on creation (such as
-            additional queues, that can only be shared on creation)
-            These items will be set as attributes of any instrument that
-            connects to the server
-    """
-    instances = {}
-
-    def __init__(self, name, shared_kwargs=None):
-        self.name = name
-        self.shared_kwargs = shared_kwargs
-        self.instances[name] = self
-
-        self.instruments = {}
-
-        super().__init__(name=name, server_class=InstrumentServer,
-                         shared_attrs=shared_kwargs)
-
-    def restart(self):
-        """
-        Restart the InstrumentServer and reconnect the instruments that
-        had been connected previously
-        """
-        super().restart()
-
-        instruments = self.instruments.values()
-        self.instruments = {}
-        for instrument in instruments:
-            instrument.connect()
-
-    def connect(self, remote_instrument, instrument_class, args, kwargs):
-        new_id = self.ask('new_id')
-        try:
-            info = self.ask('new', instrument_class, new_id, *args, **kwargs)
-            self.instruments[new_id] = remote_instrument
-
-        except:
-            # if anything went wrong adding a new instrument, delete it
-            # in case it still exists there half-formed.
-            self.delete(new_id)
-            raise
-
-        return info
-
-    def delete(self, instrument_id):
-        self.write('delete', instrument_id)
-
-        if self.instruments.get(instrument_id, None):
-            del self.instruments[instrument_id]
-
-            if not self.instruments:
-                self.close()
-                self.instances.pop(self.name, None)
-
-
-class InstrumentServer(BaseServer):
-    # just for testing - how long to allow it to wait on a queue.get
-    timeout = None
-
-    def __init__(self, query_queue, response_queue, shared_kwargs):
-        super().__init__(query_queue, response_queue, shared_kwargs)
-
-        self.instruments = {}
-        self.next_id = 0
-
-        # Ensure no references of instruments defined in the main process
-        # are copied to the server process. With the spawn multiprocessing
-        # method this is not an issue, as the class is reimported in the
-        # new process, but with fork it can be a problem ironically.
-        from qcodes.instrument.base import Instrument
-        Instrument._all_instruments = {}
-
-        self.run_event_loop()
-
-    def handle_new_id(self):
-        """
-        split out id generation from adding an instrument
-        so that we can delete it if something goes wrong!
-        """
-        new_id = self.next_id
-        self.next_id += 1
-        return new_id
-
-    def handle_new(self, instrument_class, new_id, *args, **kwargs):
-        """
-        Add a new instrument to the server.
-
-        After the initial load, the instrument is referred to by its ID.
-
-        Args:
-            instrument_class (class): The type of instrument to construct.
-
-            new_id (int): The ID by which this instrument will be known on the
-                server.
-
-            *args: positional arguments to the instrument constructor.
-
-            **kwargs: keyword arguments to the instrument constructor.
-
-        Returns:
-            dict: info to reconstruct this instrument's API in the remote.
-                See ``Instrument.connection_attrs`` for details.
-        """
-
-        # merge shared_kwargs into kwargs for the constructor,
-        # but only if this instrument_class is expecting them.
-        # The *first* instrument put on a given server must have
-        # all the shared_kwargs sent with it, but others may skip
-        # (for now others must have *none* but later maybe they could
-        # just skip some of them)
-        for key, value in self._shared_attrs.items():
-            if key in instrument_class.shared_kwargs:
-                kwargs[key] = value
-        ins = instrument_class(*args, server_name=None, **kwargs)
-
-        self.instruments[new_id] = ins
-
-        # info to reconstruct the instrument API in the RemoteInstrument
-        return ins.connection_attrs(new_id)
-
-    def handle_delete(self, instrument_id):
-        """
-        Delete an instrument from the server, and stop the server if their
-        are no more instruments left after this.
-        """
-        if instrument_id in self.instruments:
-            self.instruments[instrument_id].close()
-
-            del self.instruments[instrument_id]
-
-            if not any(self.instruments):
-                self.handle_halt()
-
-    def handle_cmd(self, instrument_id, func_name, *args, **kwargs):
-        """
-        Run some method of an instrument
-        """
-        func = getattr(self.instruments[instrument_id], func_name)
-        return func(*args, **kwargs)
diff --git a/qcodes/instrument/visa.py b/qcodes/instrument/visa.py
index d020a65ac2b..8260c650fad 100644
--- a/qcodes/instrument/visa.py
+++ b/qcodes/instrument/visa.py
@@ -1,6 +1,5 @@
 """Visa instrument driver based on pyvisa."""
 import visa
-import logging
 
 from .base import Instrument
 import qcodes.utils.validators as vals
@@ -57,26 +56,6 @@ def __init__(self, name, address=None, timeout=5, terminator='', **kwargs):
         self.set_terminator(terminator)
         self.timeout.set(timeout)
 
-    @classmethod
-    def default_server_name(cls, **kwargs):
-        """
-        Get the default server name for this instrument.
-
-        Args:
-            **kwargs: All the kwargs supplied in the constructor.
-
-        Returns:
-            str: The default server name, either 'GPIBServer', 'SerialServer',
-                or 'VisaServer' depending on ``kwargs['address']``.
-        """
-        upper_address = kwargs.get('address', '').upper()
-        if 'GPIB' in upper_address:
-            return 'GPIBServer'
-        elif 'ASRL' in upper_address:
-            return 'SerialServer'
-
-        return 'VisaServer'
-
     def set_address(self, address):
         """
         Change the address for this instrument.
diff --git a/qcodes/process/helpers.py b/qcodes/process/helpers.py
deleted file mode 100644
index 195eb2928fb..00000000000
--- a/qcodes/process/helpers.py
+++ /dev/null
@@ -1,63 +0,0 @@
-"""multiprocessing helper functions."""
-
-import multiprocessing as mp
-import time
-import warnings
-
-MP_ERR = 'context has already been set'
-
-
-def set_mp_method(method, force=False):
-    """
-    An idempotent wrapper for multiprocessing.set_start_method.
-
-    The most important use of this is to force Windows behavior
-    on a Mac or Linux: set_mp_method('spawn')
-    args are the same:
-
-    Args:
-        method (string): one of the following
-
-            - 'fork' (default on unix/mac)
-            - 'spawn' (default, and only option, on windows)
-            - 'forkserver'
-
-        force (bool): allow changing context? default False
-            in the original function, even calling the function again
-            with the *same* method raises an error, but here we only
-            raise the error if you *don't* force *and* the context changes
-    """
-    warnings.warn("Multiprocessing is in beta, use at own risk", UserWarning)
-    try:
-        mp.set_start_method(method, force=force)
-    except RuntimeError as err:
-        if err.args != (MP_ERR, ):
-            raise
-
-    mp_method = mp.get_start_method()
-    if mp_method != method:
-        raise RuntimeError(
-            'unexpected multiprocessing method '
-            '\'{}\' when trying to set \'{}\''.format(mp_method, method))
-
-
-def kill_queue(queue):
-    """Tear down a multiprocessing.Queue to help garbage collection."""
-    try:
-        queue.close()
-        queue.join_thread()
-    except:
-        pass
-
-
-def kill_processes():
-    """Kill all running child processes."""
-    # TODO: Instrument processes don't appropriately stop in all tests...
-    for process in mp.active_children():
-        try:
-            process.terminate()
-        except:
-            pass
-
-    if mp.active_children():
-        time.sleep(0.2)
diff --git a/qcodes/process/qcodes_process.py b/qcodes/process/qcodes_process.py
deleted file mode 100644
index 7d80bea1d07..00000000000
--- a/qcodes/process/qcodes_process.py
+++ /dev/null
@@ -1,72 +0,0 @@
-"""Modifications to multiprocessing.Process common to all Qcodes processes."""
-
-import multiprocessing as mp
-from traceback import print_exc
-import signal
-
-from qcodes.utils.helpers import in_notebook
-
-from .stream_queue import get_stream_queue
-
-
-class QcodesProcess(mp.Process):
-
-    """
-    Modified multiprocessing.Process specialized to Qcodes needs.
-
-    - Nicer repr
-    - Automatic streaming of stdout and stderr to our StreamQueue singleton
-      for reporting back to the main process
-    - Ignore interrupt signals so that commands in the main process can be
-      canceled without affecting server and background processes.
-    """
-
-    def __init__(self, *args, name='QcodesProcess', queue_streams=True,
-                 daemon=True, **kwargs):
-        """
-        Construct the QcodesProcess, but like Process, do not start it.
-
-        name: string to include in repr, and in the StreamQueue
-            default 'QcodesProcess'
-        queue_streams: should we connect stdout and stderr to the StreamQueue?
-            default True
-        daemon: should this process be treated as daemonic, so it gets
-            terminated with the parent.
-            default True, overriding the base inheritance
-        any other args and kwargs are passed to multiprocessing.Process
-        """
-        # make sure the singleton StreamQueue exists
-        # prior to launching a new process
-        if queue_streams and in_notebook():
-            self.stream_queue = get_stream_queue()
-        else:
-            self.stream_queue = None
-        super().__init__(*args, name=name, daemon=daemon, **kwargs)
-
-    def run(self):
-        """Executed in the new process, and calls the target function."""
-        # ignore interrupt signals, as they come from `KeyboardInterrupt`
-        # which we want only to apply to the main process and not the
-        # server and background processes (which can be halted in different
-        # ways)
-        signal.signal(signal.SIGINT, signal.SIG_IGN)
-
-        if self.stream_queue:
-            self.stream_queue.connect(str(self.name))
-        try:
-            super().run()
-        except:
-            # if we let the system print the exception by itself, sometimes
-            # it disconnects the stream partway through printing.
-            print_exc()
-        finally:
-            if (self.stream_queue and
-                    self.stream_queue.initial_streams is not None):
-                self.stream_queue.disconnect()
-
-    def __repr__(self):
-        """Shorter and more helpful repr of our processes."""
-        cname = self.__class__.__name__
-        r = super().__repr__()
-        r = r.replace(cname + '(', '').replace(')>', '>')
-        return r.replace(', started daemon', '')
diff --git a/qcodes/process/server.py b/qcodes/process/server.py
deleted file mode 100644
index d3a103b6f2a..00000000000
--- a/qcodes/process/server.py
+++ /dev/null
@@ -1,399 +0,0 @@
-"""Common Server process and ServerManager architecture."""
-
-import multiprocessing as mp
-from traceback import format_exc
-from uuid import uuid4
-import builtins
-import logging
-
-QUERY_WRITE = 'WRITE'
-QUERY_ASK = 'ASK'
-RESPONSE_OK = 'OK'
-RESPONSE_ERROR = 'ERROR'
-
-from qcodes.utils.nested_attrs import NestedAttrAccess
-from .qcodes_process import QcodesProcess
-from .helpers import kill_queue
-
-
-class ServerManager:
-
-    """
-    Creates and communicates with a separate server process.
-
-    Starts a *QcodesProcess*, and on that process it constructs a server
-    object of type *server_class*, which should normally be a subclass of
-    `BaseServer`. Client processes query the server via:
-
-    - ``manager.ask(func_name, *args, **kwargs)``: if they want a response or want
-      to wait for confirmation that the query has completed
-    - ``manager.write(func_name, *args, **kwargs)``: if they want to continue
-      immediately without blocking for the query.
-
-    The server communicates with this manager via two multiprocessing *Queue*\s.
-    """
-
-    def __init__(self, name, server_class, shared_attrs=None,
-                 query_timeout=None):
-        """
-        Construct the ServerManager and start its server.
-
-        Args:
-            name: the name of the server. Can include .format specs to insert
-                all or part of the uuid
-            server_class: the class to create within the new process.
-                the constructor will be passed arguments:
-                    query_queue, response_queue, shared_attrs
-                and should start an infinite loop watching query_queue and posting
-                responses to response_queue.
-            shared_attrs: any objects that need to be passed to the server on
-                startup, generally objects like Queues that are picklable only for
-                inheritance by a new process.
-            query_timeout: (default None) the default max time to wait for
-                responses
-        """
-        self._query_queue = mp.Queue()
-        self._response_queue = mp.Queue()
-        self._server_class = server_class
-        self._shared_attrs = shared_attrs
-
-        # query_lock is only used with queries that get responses
-        # to make sure the process that asked the question is the one
-        # that gets the response.
-        # Any query that does NOT expect a response can just dump it in
-        # and move on.
-        self.query_lock = mp.RLock()
-
-        # uuid is used to pass references to this object around
-        # for example, to get it after someone else has sent it to a server
-        self.uuid = uuid4().hex
-
-        self.name = name.format(self.uuid)
-
-        self.query_timeout = query_timeout
-        self._start_server()
-
-    def _start_server(self):
-        self._server = QcodesProcess(target=self._run_server, name=self.name)
-        self._server.start()
-
-    def _run_server(self):
-        self._server_class(self._query_queue, self._response_queue,
-                           self._shared_attrs)
-
-    def _check_alive(self):
-        try:
-            if not self._server.is_alive():
-                logging.warning('restarted {}'.format(self._server))
-                self.restart()
-        except:
-            # can't test is_alive from outside the main process
-            pass
-
-    def write(self, func_name, *args, **kwargs):
-        """
-        Send a query to the server that does not expect a response.
-
-        `write(func_name, *args, **kwargs)` proxies to server method:
-        `server.handle_<func_name>(*args, **kwargs)`
-        """
-        self._check_alive()
-        self._query_queue.put((QUERY_WRITE, func_name, args, kwargs))
-
-    def ask(self, func_name, *args, timeout=None, **kwargs):
-        """
-        Send a query to the server and wait for a response.
-
-        `resp = ask(func_name, *args, **kwargs)` proxies to server method:
-        `resp = server.handle_<func_name>(*args, **kwargs)`
-
-        optional timeout (default None) - not recommended, as if we quit
-        before reading the response, the query queue can get out of sync
-        """
-        self._check_alive()
-
-        timeout = timeout or self.query_timeout
-        self._expect_error = False
-
-        query = (QUERY_ASK, func_name, args, kwargs)
-
-        with self.query_lock:
-            # in case a previous query errored and left something on the
-            # response queue, clear it
-            while not self._response_queue.empty():
-                value = self._get_response()
-                logging.warning(
-                    'unexpected data in response queue before ask:\n' +
-                    repr(value))
-
-            self._query_queue.put(query)
-
-            value = self._get_response(timeout=timeout, query=query)
-
-            while not self._response_queue.empty():
-                logging .warning(
-                    'unexpected multiple responses in queue during ask, '
-                    'using the last one. earlier item(s):\n' +
-                    repr(value))
-                value = self._get_response(query=query)
-
-        return value
-
-    def _get_response(self, timeout=None, query=None):
-        res = self._response_queue.get(timeout=timeout)
-        try:
-            code, value = res
-        except (TypeError, ValueError):
-            code, value = '<MALFORMED>', res
-
-        if code == RESPONSE_OK:
-            return value
-
-        self._handle_error(code, value, query)
-
-    def _handle_error(self, code, error_str, query=None):
-        error_head = '*** error on {} ***'.format(self.name)
-
-        if query:
-            error_head += '\nwhile executing query: {}'.format(repr(query))
-
-        if code != RESPONSE_ERROR:
-            error_head += '\nunrecognized response code: {}'.format(code)
-
-        # try to match the error type, if it's a built-in type
-        error_type_line = error_str.rstrip().rsplit('\n', 1)[-1]
-        error_type_str = error_type_line.split(':')[0].strip()
-
-        err_type = getattr(builtins, error_type_str, None)
-        if err_type is None or not issubclass(err_type, Exception):
-            err_type = RuntimeError
-
-        raise err_type(error_head + '\n\n' + error_str)
-
-    def halt(self, timeout=2):
-        """
-        Halt the server and end its process.
-
-        Does not tear down, after this the server can still be started again.
-        """
-        try:
-            if self._server.is_alive():
-                self.write('halt')
-            self._server.join(timeout)
-
-            if self._server.is_alive():
-                self._server.terminate()
-                logging.warning('ServerManager did not respond to halt '
-                                'signal, terminated')
-                self._server.join(timeout)
-        except AssertionError:
-            # happens when we get here from other than the main process
-            # where we shouldn't be able to kill the server anyway
-            pass
-
-    def restart(self):
-        """Restart the server."""
-        self.halt()
-        self._start_server()
-
-    def close(self):
-        """Irreversibly stop the server and manager."""
-        self.halt()
-        for q in ['query', 'response', 'error']:
-            qname = '_{}_queue'.format(q)
-            if hasattr(self, qname):
-                kill_queue(getattr(self, qname))
-                del self.__dict__[qname]
-        if hasattr(self, 'query_lock'):
-            del self.query_lock
-
-
-class BaseServer(NestedAttrAccess):
-
-    """
-    Base class for servers to run in separate processes.
-
-    The server is started inside a `QcodesProcess` by a `ServerManager`,
-    and unifies the query handling protocol so that we are robust against
-    deadlocks, out of sync queues, or hidden errors.
-
-    This base class doesn't start the event loop, a subclass should
-    either call `self.run_event_loop()` at the end of its `__init__` or
-    provide its own event loop. If making your own event loop, be sure to
-    call `self.process_query(query)` on any item that arrives in
-    `self._query_queue`.
-
-    Subclasses should define handlers `handle_<func_name>`, such that calls:
-        `response = server_manager.ask(func_name, *args, **kwargs)`
-        `server_manager.write(func_name, *args, **kwargs)`
-    map onto method calls:
-        `response = self.handle_<func_name>(*args, **kwargs)`
-
-    The actual query passed through the queue and unpacked by `process_query`
-    has the form `(code, func_name[, args][, kwargs])` where `code` is:
-
-    - `QUERY_ASK` (from `server_manager.ask`): will always send a response,
-      even if the function returns nothing (None) or throws an error.
-
-    - `QUERY_WRITE` (from `server_manager.write`): will NEVER send a response,
-      return values are ignored and errors go to the logging framework.
-
-    Three handlers are predefined:
-
-    - `handle_halt` (but override it if your event loop does not use
-      self.running=False to stop)
-
-    - `handle_get_handlers` (lists all available handler methods)
-
-    - `handle_method_call` (call an arbitrary method on the server)
-    """
-
-    # just for testing - how long to allow it to wait on a queue.get
-    # in real situations this should always be None
-    timeout = None
-
-    def __init__(self, query_queue, response_queue, shared_attrs=None):
-        """
-        Create the BaseServer.
-
-        Subclasses should match this call signature exactly, even if they
-        do not need shared_attrs, because it is used by `ServerManager`
-        to instantiate the server.
-        The base class does not start the event loop, subclasses should do
-        this at the end of their own `__init__`.
-
-        query_queue: a multiprocessing.Queue that we listen to
-
-        response_queue: a multiprocessing.Queue where we put responses
-
-        shared_attrs: (default None) any objects (such as other Queues)
-            that we need to supply on initialization of the server because
-            they cannot be picked normally to pass through the Queue later.
-        """
-        self._query_queue = query_queue
-        self._response_queue = response_queue
-        self._shared_attrs = shared_attrs
-
-    def run_event_loop(self):
-        """
-        The default event loop. When this method returns, the server stops.
-
-        Override this method if you need to do more than just process queries
-        repeatedly, but make sure your event loop:
-
-        - calls `self.process_query` to ensure robust error handling
-        - provides a way to halt the server (and override `handle_halt` if
-          it's not by setting `self.running = False`)
-        """
-        self.running = True
-        while self.running:
-            query = self._query_queue.get(timeout=self.timeout)
-            self.process_query(query)
-
-    def process_query(self, query):
-        """
-        Act on one query received through the query queue.
-
-        query: should have the form `(code, func_name[, args][, kwargs])`
-        """
-        try:
-            code = None
-            code, func_name = query[:2]
-
-            func = getattr(self, 'handle_' + func_name)
-
-            args = None
-            kwargs = None
-            for part in query[2:]:
-                if isinstance(part, tuple) and args is None:
-                    args = part
-                elif isinstance(part, dict) and kwargs is None:
-                    kwargs = part
-                else:
-                    raise ValueError(part)
-
-            if code == QUERY_ASK:
-                self._process_ask(func, args or (), kwargs or {})
-            elif code == QUERY_WRITE:
-                self._process_write(func, args or (), kwargs or {})
-            else:
-                raise ValueError(code)
-        except:
-            self.report_error(query, code)
-
-    def report_error(self, query, code):
-        """
-        Common error handler for all queries.
-
-        QUERY_ASK puts errors into the response queue for the asker to see.
-        QUERY_WRITE shouldn't write a response, so it logs errors instead.
-        Unknown modes do *both*, because we don't know where the user will be
-        looking and an error that severe it's OK to muck up the queue.
-        That's the only way you'll get a response without asking for one.
-        """
-        error_str = (
-            'Expected query to be a tuple (code, func_name[, args][, kwargs]) '
-            'where code is QUERY_ASK or QUERY_WRITE, func_name points to a '
-            'method `handle_<func_name>`, and optionally args is a tuple and '
-            'kwargs is a dict\nquery: ' + repr(query) + '\n' + format_exc())
-
-        if code != QUERY_ASK:
-            logging.error(error_str)
-        if code != QUERY_WRITE:
-            try:
-                self._response_queue.put((RESPONSE_ERROR, error_str))
-            except:
-                logging.error('Could not put error on response queue\n' +
-                              error_str)
-
-    def _process_ask(self, func, args, kwargs):
-        try:
-            response = func(*args, **kwargs)
-            self._response_queue.put((RESPONSE_OK, response))
-        except:
-            self._response_queue.put(
-                (RESPONSE_ERROR, repr((func, args, kwargs)) + '\n' +
-                    format_exc()))
-
-    def _process_write(self, func, args, kwargs):
-        try:
-            func(*args, **kwargs)
-        except:
-            logging.error(repr((func, args, kwargs)) + '\n' + format_exc())
-
-    def handle_halt(self):
-        """
-        Quit this server.
-
-        Just sets self.running=False, which the default event loop looks for
-        between queries. If you provide your own event loop and it does NOT
-        look for self.running, you should override this handler with a
-        different way to halt.
-        """
-        self.running = False
-
-    def handle_get_handlers(self):
-        """List all available query handlers."""
-        handlers = []
-        for name in dir(self):
-            if name.startswith('handle_') and callable(getattr(self, name)):
-                handlers.append(name[len('handle_'):])
-        return handlers
-
-    def handle_method_call(self, method_name, *args, **kwargs):
-        """
-        Pass through arbitrary method calls to the server.
-
-        Args:
-            method_name (str): the method name to call.
-                Primarily intended for NestedAttrAccess, ie:
-                ``getattr``, ``setattr``, ``callattr``, ``delattr``.
-
-            *args (Any): passed to the method
-
-            **kwargs (Any): passed to the method
-
-        Returns:
-            Any: the return value of the method
-        """
-        return getattr(self, method_name)(*args, **kwargs)
diff --git a/qcodes/process/stream_queue.py b/qcodes/process/stream_queue.py
deleted file mode 100644
index 3dcbc5bff62..00000000000
--- a/qcodes/process/stream_queue.py
+++ /dev/null
@@ -1,152 +0,0 @@
-"""StreamQueue: collect subprocess stdout/stderr to a single queue."""
-
-import multiprocessing as mp
-import sys
-import time
-
-from datetime import datetime
-
-from .helpers import kill_queue
-
-
-def get_stream_queue():
-    """
-    Convenience function to get a singleton StreamQueue.
-
-    note that this must be called from the main process before starting any
-    subprocesses that will use it, otherwise the subprocess will create its
-    own StreamQueue that no other processes know about
-    """
-    if StreamQueue.instance is None:
-        StreamQueue.instance = StreamQueue()
-    return StreamQueue.instance
-
-
-class StreamQueue:
-
-    """
-    Manages redirection of child process output for the main process to view.
-
-    Do not instantiate this directly: use get_stream_queue so we only make one.
-    One StreamQueue should be created in the consumer process, and passed
-    to each child process. In the child, we call StreamQueue.connect with a
-    process name that will be unique and meaningful to the user. The consumer
-    then periodically calls StreamQueue.get() to read these messages.
-
-    inspired by http://stackoverflow.com/questions/23947281/
-    """
-
-    instance = None
-
-    def __init__(self, *args, **kwargs):
-        """Create a StreamQueue, passing all args & kwargs to Queue."""
-        self.queue = mp.Queue(*args, **kwargs)
-        self.last_read_ts = mp.Value('d', time.time())
-        self._last_stream = None
-        self._on_new_line = True
-        self.lock = mp.RLock()
-        self.initial_streams = None
-
-    def connect(self, process_name):
-        """
-        Connect a child process to the StreamQueue.
-
-        After this, stdout and stderr go to a queue rather than being
-        printed to a console.
-
-        process_name: a short string that will clearly identify this process
-            to the user.
-        """
-        if self.initial_streams is not None:
-            raise RuntimeError('StreamQueue is already connected')
-
-        self.initial_streams = (sys.stdout, sys.stderr)
-
-        sys.stdout = _SQWriter(self, process_name)
-        sys.stderr = _SQWriter(self, process_name + ' ERR')
-
-    def disconnect(self):
-        """Disconnect a child from the queues and revert stdout & stderr."""
-        if self.initial_streams is None:
-            raise RuntimeError('StreamQueue is not connected')
-        sys.stdout, sys.stderr = self.initial_streams
-        self.initial_streams = None
-
-    def get(self):
-        """Read new messages from the queue and format them for printing."""
-        out = ''
-        while not self.queue.empty():
-            timestr, stream_name, msg = self.queue.get()
-            line_head = '[{} {}] '.format(timestr, stream_name)
-
-            if self._on_new_line:
-                out += line_head
-            elif stream_name != self._last_stream:
-                out += '\n' + line_head
-
-            out += msg[:-1].replace('\n', '\n' + line_head) + msg[-1]
-
-            self._on_new_line = (msg[-1] == '\n')
-            self._last_stream = stream_name
-
-        self.last_read_ts.value = time.time()
-        return out
-
-    def __del__(self):
-        """Tear down the StreamQueue either on the main or a child process."""
-        try:
-            self.disconnect()
-        except:
-            pass
-
-        if hasattr(type(self), 'instance'):
-            # so nobody else tries to use this dismantled stream queue later
-            type(self).instance = None
-
-        if hasattr(self, 'queue'):
-            kill_queue(self.queue)
-            del self.queue
-        if hasattr(self, 'lock'):
-            del self.lock
-
-
-class _SQWriter:
-    MIN_READ_TIME = 3
-
-    def __init__(self, stream_queue, stream_name):
-        self.queue = stream_queue.queue
-        self.last_read_ts = stream_queue.last_read_ts
-        self.stream_name = stream_name
-
-    def write(self, msg):
-        try:
-            if msg:
-                msgtuple = (datetime.now().strftime('%H:%M:%S.%f')[:-3],
-                            self.stream_name, msg)
-                self.queue.put(msgtuple)
-
-                queue_age = time.time() - self.last_read_ts.value
-                if queue_age > self.MIN_READ_TIME and msg != '\n':
-                    # long time since the queue was read? maybe nobody is
-                    # watching it at all - send messages to the terminal too
-                    # but they'll still be in the queue if someone DOES look.
-                    termstr = '[{} {}] {}'.format(*msgtuple)
-                    # we always want a new line this way (so I don't use
-                    # end='' in the print) but we don't want an extra if the
-                    # caller already included a newline.
-                    if termstr[-1] == '\n':
-                        termstr = termstr[:-1]
-                    try:
-                        print(termstr, file=sys.__stdout__)
-                    except ValueError:  # pragma: no cover
-                        # ValueError: underlying buffer has been detached
-                        # this may just occur in testing on Windows, not sure.
-                        pass
-        except:
-            # don't want to get an infinite loop if there's something wrong
-            # with the queue - put the regular streams back before handling
-            sys.stdout, sys.stderr = sys.__stdout__, sys.__stderr__
-            raise
-
-    def flush(self):
-        pass
diff --git a/qcodes/station.py b/qcodes/station.py
index 08bd8ba44fb..7b6cd9a020b 100644
--- a/qcodes/station.py
+++ b/qcodes/station.py
@@ -3,8 +3,6 @@
 from qcodes.utils.metadata import Metadatable
 from qcodes.utils.helpers import make_unique, DelegateAttributes
 
-from qcodes.instrument.remote import RemoteInstrument
-from qcodes.instrument.remote import RemoteParameter
 from qcodes.instrument.base import Instrument
 from qcodes.instrument.parameter import Parameter
 from qcodes.instrument.parameter import ManualParameter
@@ -86,13 +84,12 @@ def snapshot_base(self, update=False):
         }
 
         for name, itm in self.components.items():
-            if isinstance(itm, (RemoteInstrument,
-                                Instrument)):
+            if isinstance(itm, (Instrument)):
                 snap['instruments'][name] = itm.snapshot(update=update)
             elif isinstance(itm, (Parameter,
                                   ManualParameter,
-                                  StandardParameter,
-                                  RemoteParameter)):
+                                  StandardParameter
+                                  )):
                 snap['parameters'][name] = itm.snapshot(update=update)
             else:
                 snap['components'][name] = itm.snapshot(update=update)
diff --git a/qcodes/tests/instrument_mocks.py b/qcodes/tests/instrument_mocks.py
index 3163d2e95b6..59c264d8b08 100644
--- a/qcodes/tests/instrument_mocks.py
+++ b/qcodes/tests/instrument_mocks.py
@@ -1,205 +1,10 @@
-import time
 import numpy as np
 
 from qcodes.instrument.base import Instrument
-from qcodes.instrument.mock import MockInstrument, MockModel
 from qcodes.utils.validators import Numbers
 from qcodes.instrument.parameter import MultiParameter, ManualParameter
 
 
-class AMockModel(MockModel):
-
-    def __init__(self):
-        self._memory = {}
-        self._reset()
-        super().__init__()
-
-    def _reset(self):
-        self._gates = [0.0, 0.0, 0.0]
-        self._excitation = 0.1
-
-    @staticmethod
-    def fmt(value):
-        return '{:.3f}'.format(value)
-
-    def gates_set(self, parameter, value):
-        if parameter[0] == 'c':
-            self._gates[int(parameter[1:])] = float(value)
-        elif parameter == 'rst' and value is None:
-            # resets gates AND excitation, so we can use gates.reset() to
-            # reset the entire model
-            self._reset()
-        elif parameter[:3] == 'mem':
-            slot = int(parameter[3:])
-            self._memory[slot] = value
-        else:
-            raise ValueError
-
-    def gates_get(self, parameter):
-        if parameter[0] == 'c':
-            return self.fmt(self._gates[int(parameter[1:])])
-        elif parameter[:3] == 'mem':
-            slot = int(parameter[3:])
-            return self._memory[slot]
-        else:
-            raise ValueError
-
-    def source_set(self, parameter, value):
-        if parameter == 'ampl':
-            try:
-                self._excitation = float(value)
-            except ValueError:
-                # "Off" as in the MultiType sweep step test
-                self._excitation = None
-        else:
-            raise ValueError(parameter, value)
-
-    def source_get(self, parameter):
-        if parameter == 'ampl':
-            return self.fmt(self._excitation)
-        # put mem here too, just so we can be 100% sure it's going through
-        # the model
-        elif parameter[:3] == 'mem':
-            slot = int(parameter[3:])
-            return self._memory[slot]
-        else:
-            raise ValueError
-
-    def meter_get(self, parameter):
-        if parameter == 'ampl':
-            gates = self._gates
-            # here's my super complex model output!
-            return self.fmt(self._excitation *
-                            (gates[0] + gates[1]**2 + gates[2]**3))
-        elif parameter[:5] == 'echo ':
-            return self.fmt(float(parameter[5:]))
-
-    # alias because we need new names when we instantiate an instrument
-    # locally at the same time as remotely
-    def gateslocal_set(self, parameter, value):
-        return self.gates_set(parameter, value)
-
-    def gateslocal_get(self, parameter):
-        return self.gates_get(parameter)
-
-    def sourcelocal_set(self, parameter, value):
-        return self.source_set(parameter, value)
-
-    def sourcelocal_get(self, parameter):
-        return self.source_get(parameter)
-
-    def meterlocal_get(self, parameter):
-        return self.meter_get(parameter)
-
-
-class ParamNoDoc:
-
-    def __init__(self, name, *args, **kwargs):
-        self.name = name
-
-    def get_attrs(self):
-        return []
-
-
-class MockInstTester(MockInstrument):
-
-    def __init__(self, *args, **kwargs):
-        super().__init__(*args, **kwargs)
-        self.attach_adder()
-
-    def attach_adder(self):
-        """
-        this function attaches a closure to the object, so can only be
-        executed after creating the server because a closure is not
-        picklable
-        """
-        a = 5
-
-        def f(b):
-            """
-            not the same function as the original method
-            """
-            return a + b
-        self.add5 = f
-
-    def add5(self, b):
-        """
-        The class copy of this should not get run, because it should
-        be overwritten on the server by the closure version.
-        """
-        raise RuntimeError('dont run this one!')
-
-
-class MockGates(MockInstTester):
-
-    def __init__(self, name='gates', model=None, **kwargs):
-        super().__init__(name, model=model, delay=0.001, **kwargs)
-
-        for i in range(3):
-            cmdbase = 'c{}'.format(i)
-            self.add_parameter('chan{}'.format(i), get_cmd=cmdbase + '?',
-                               set_cmd=cmdbase + ':{:.4f}',
-                               get_parser=float,
-                               vals=Numbers(-10, 10))
-            self.add_parameter('chan{}step'.format(i),
-                               get_cmd=cmdbase + '?',
-                               set_cmd=cmdbase + ':{:.4f}',
-                               get_parser=float,
-                               vals=Numbers(-10, 10),
-                               step=0.1, delay=0.005)
-
-        self.add_parameter('chan0slow', get_cmd='c0?',
-                           set_cmd=self.slow_neg_set, get_parser=float,
-                           vals=Numbers(-10, 10), step=0.2,
-                           delay=0.02)
-        self.add_parameter('chan0slow2', get_cmd='c0?',
-                           set_cmd=self.slow_neg_set, get_parser=float,
-                           vals=Numbers(-10, 10), step=0.2,
-                           delay=0.01, max_delay=0.02)
-        self.add_parameter('chan0slow3', get_cmd='c0?',
-                           set_cmd=self.slow_neg_set, get_parser=float,
-                           vals=Numbers(-10, 10), step=0.2,
-                           delay=0.01, max_delay=0.08)
-        self.add_parameter('chan0slow4', get_cmd='c0?',
-                           set_cmd=self.slow_neg_set, get_parser=float,
-                           vals=Numbers(-10, 10),
-                           delay=0.01, max_delay=0.02)
-        self.add_parameter('chan0slow5', get_cmd='c0?',
-                           set_cmd=self.slow_neg_set, get_parser=float,
-                           vals=Numbers(-10, 10),
-                           delay=0.01, max_delay=0.08)
-
-        self.add_function('reset', call_cmd='rst')
-
-        self.add_parameter('foo', parameter_class=ParamNoDoc)
-
-    def slow_neg_set(self, val):
-        if val < 0:
-            time.sleep(0.05)
-        self.chan0.set(val)
-
-
-class MockSource(MockInstTester):
-
-    def __init__(self, name='source', model=None, **kwargs):
-        super().__init__(name, model=model, delay=0.001, **kwargs)
-
-        self.add_parameter('amplitude', get_cmd='ampl?',
-                           set_cmd='ampl:{:.4f}', get_parser=float,
-                           vals=Numbers(0, 1),
-                           step=0.2, delay=0.005)
-
-
-class MockMeter(MockInstTester):
-
-    def __init__(self, name='meter', model=None, **kwargs):
-        super().__init__(name, model=model, delay=0.001, **kwargs)
-
-        self.add_parameter('amplitude', get_cmd='ampl?', get_parser=float)
-        self.add_function('echo', call_cmd='echo {:.2f}?',
-                          args=[Numbers(0, 1000)], return_parser=float)
-
-
 class MockParabola(Instrument):
     '''
     Holds dummy parameters which are get and set able as well as provides
diff --git a/qcodes/tests/test_driver_testcase.py b/qcodes/tests/test_driver_testcase.py
deleted file mode 100644
index b91b04411c5..00000000000
--- a/qcodes/tests/test_driver_testcase.py
+++ /dev/null
@@ -1,58 +0,0 @@
-import unittest
-
-from qcodes.instrument_drivers.test import DriverTestCase
-from qcodes.instrument.mock import MockInstrument, MockModel
-
-
-class EmptyModel(MockModel):
-    pass
-
-
-class MockMock(MockInstrument):
-    pass
-
-
-@unittest.skip('just need this definition')
-class HasNoDriver(DriverTestCase):
-    noskip = True
-
-
-class MockMock2(MockInstrument):
-    pass
-
-
-@unittest.skip('just need this definition')
-class HasNoInstances(DriverTestCase):
-    noskip = True
-    driver = MockMock2
-
-
-class TestDriverTestCase(DriverTestCase):
-    driver = MockMock
-    noskip = True
-
-    @classmethod
-    def setUpClass(cls):
-        cls.an_empty_model = EmptyModel()
-        cls.an_instrument = MockMock('a', model=cls.an_empty_model, server_name='')
-        super().setUpClass()
-
-    @classmethod
-    def tearDownClass(cls):
-        cls.an_empty_model.close()
-        cls.an_instrument._manager.close()
-
-    def test_instance_found(self):
-        self.assertEqual(self.instrument, self.an_instrument)
-
-    def test_no_driver(self):
-        with self.assertRaises(TypeError):
-            HasNoDriver.setUpClass()
-
-    def test_no_instances(self):
-        baseMock = MockInstrument('not the same class',
-                                  model=self.an_empty_model)
-        self.assertIn(baseMock, MockInstrument.instances())
-
-        with self.assertRaises(ValueError):
-            HasNoInstances.setUpClass()
diff --git a/qcodes/tests/test_instrument_server.py b/qcodes/tests/test_instrument_server.py
deleted file mode 100644
index 1284e03d0b7..00000000000
--- a/qcodes/tests/test_instrument_server.py
+++ /dev/null
@@ -1,157 +0,0 @@
-from unittest import TestCase
-import time
-import multiprocessing as mp
-
-from qcodes.instrument.server import InstrumentServer
-from qcodes.instrument.base import Instrument
-from qcodes.process.server import (QUERY_WRITE, QUERY_ASK, RESPONSE_OK,
-                                   RESPONSE_ERROR)
-from qcodes.utils.helpers import LogCapture
-
-
-def schedule(queries, query_queue):
-    """
-    Args:
-        queries: is a sequence of (delay, args)
-        query_queue: is a queue to push these queries to, with each one waiting
-            its delay after sending the previous one
-    """
-    for delay, args in queries:
-        time.sleep(delay)
-        query_queue.put(args)
-
-
-def run_schedule(queries, query_queue):
-    p = mp.Process(target=schedule, args=(queries, query_queue))
-    p.start()
-    return p
-
-
-def get_results(response_queue):
-    time.sleep(0.05)  # wait for any lingering messages to the queues
-    responses = []
-    while not response_queue.empty():
-        responses.append(response_queue.get())
-
-    return responses
-
-
-class Holder:
-    shared_kwargs = ['where']
-    name = 'J Edgar'
-    parameters = {}
-    functions = {}
-
-    def __init__(self, server_name=None, **kwargs):
-        self.kwargs = kwargs
-        self.d = {}
-
-    def get(self, key):
-        return self.d[key]
-
-    def set(self, key, val):
-        self.d[key] = val
-
-    def get_extras(self):
-        return self.kwargs
-
-    def _get_method_attrs(self):
-        return {}
-
-    def close(self):
-        pass
-
-    def connection_attrs(self, new_id):
-        return Instrument.connection_attrs(self, new_id)
-
-
-class TimedInstrumentServer(InstrumentServer):
-    timeout = 2
-
-
-class TestInstrumentServer(TestCase):
-    maxDiff = None
-
-    @classmethod
-    def setUpClass(cls):
-        cls.query_queue = mp.Queue()
-        cls.response_queue = mp.Queue()
-        cls.error_queue = mp.Queue()
-
-    @classmethod
-    def tearDownClass(cls):
-        del cls.query_queue
-        del cls.response_queue
-        del cls.error_queue
-
-    def test_normal(self):
-        # we really only need to test local here - as a server it's already
-        # used in other tests, but only implicitly (and not covered as it's
-        # in a subprocess)
-        queries = (
-            # add an "instrument" to the server
-            (0.5, (QUERY_ASK, 'new_id',)),
-            (0.01, (QUERY_ASK, 'new', (Holder, 0))),
-
-            # some sets and gets that work
-            (0.01, (QUERY_WRITE, 'cmd',
-                    (0, 'set', 'happiness', 'a warm gun'), {})),
-            (0.01, (QUERY_WRITE, 'cmd',
-                    (0, 'set'), {'val': 42, 'key': 'the answer'})),
-            (0.01, (QUERY_ASK, 'cmd', (0, 'get'), {'key': 'happiness'})),
-            (0.01, (QUERY_ASK, 'cmd', (0, 'get', 'the answer',), {})),
-
-            # then some that make errors
-            # KeyError
-            (0.01, (QUERY_ASK, 'cmd', (0, 'get', 'Carmen Sandiego',), {})),
-            # TypeError (too many args) shows up in logs
-            (0.01, (QUERY_WRITE, 'cmd', (0, 'set', 1, 2, 3), {})),
-            # TypeError (unexpected kwarg) shows up in logs
-            (0.01, (QUERY_WRITE, 'cmd', (0, 'set', 'do'), {'c': 'middle'})),
-
-            # and another good one, just so we know it still works
-            (0.01, (QUERY_ASK, 'cmd', (0, 'get_extras'), {})),
-
-            # delete the instrument and stop the server
-            # (no need to explicitly halt)
-            (0.01, (QUERY_ASK, 'delete', (0,)))
-        )
-        extras = {'where': 'infinity and beyond'}
-
-        run_schedule(queries, self.query_queue)
-
-        try:
-            with LogCapture() as logs:
-                TimedInstrumentServer(self.query_queue, self.response_queue,
-                                      extras)
-        except TypeError:
-            from traceback import format_exc
-            print(format_exc())
-
-        self.assertEqual(logs.value.count('TypeError'), 2)
-        for item in ('1, 2, 3', 'middle'):
-            self.assertIn(item, logs.value)
-
-        responses = get_results(self.response_queue)
-
-        expected_responses = [
-            (RESPONSE_OK, 0),
-            (RESPONSE_OK, {
-                'functions': {},
-                'id': 0,
-                'name': 'J Edgar',
-                '_methods': {},
-                'parameters': {}
-            }),
-            (RESPONSE_OK, 'a warm gun'),
-            (RESPONSE_OK, 42),
-            (RESPONSE_ERROR, ('KeyError', 'Carmen Sandiego')),
-            (RESPONSE_OK, extras)
-        ]
-        for response, expected in zip(responses, expected_responses):
-            if expected[0] == RESPONSE_OK:
-                self.assertEqual(response, expected)
-            else:
-                self.assertEqual(response[0], expected[0])
-                for item in expected[1]:
-                    self.assertIn(item, response[1])
diff --git a/qcodes/tests/test_multiprocessing.py b/qcodes/tests/test_multiprocessing.py
deleted file mode 100644
index 5d9d0ee8233..00000000000
--- a/qcodes/tests/test_multiprocessing.py
+++ /dev/null
@@ -1,471 +0,0 @@
-from unittest import TestCase, skipIf
-import time
-import re
-import sys
-import multiprocessing as mp
-from queue import Empty
-from unittest.mock import patch
-
-import qcodes
-from qcodes.process.helpers import set_mp_method, kill_queue
-from qcodes.process.qcodes_process import QcodesProcess
-from qcodes.process.stream_queue import get_stream_queue, _SQWriter
-from qcodes.process.server import ServerManager, RESPONSE_OK, RESPONSE_ERROR
-import qcodes.process.helpers as qcmp
-from qcodes.utils.helpers import in_notebook, LogCapture
-from qcodes.utils.timing import calibrate
-
-BREAK_SIGNAL = '~~BREAK~~'
-
-
-class sqtest_echo:
-    def __init__(self, name, delay=0.01, has_q=True):
-        self.q_out = mp.Queue()
-        self.q_err = mp.Queue()
-        self.p = QcodesProcess(target=sqtest_echo_f,
-                               args=(name, delay, self.q_out, self.q_err,
-                                     has_q),
-                               name=name)
-        self.p.start()
-        self.delay = delay
-        self.resp_delay = delay * 2 + 0.03
-
-    def send_out(self, msg):
-        self.q_out.put(msg)
-        time.sleep(self.resp_delay)
-
-    def send_err(self, msg):
-        self.q_err.put(msg)
-        time.sleep(self.resp_delay)
-
-    def halt(self):
-        if not (hasattr(self, 'p') and self.p.is_alive()):
-            return
-        self.q_out.put(BREAK_SIGNAL)
-        self.p.join()
-        time.sleep(self.resp_delay)
-        for q in ['q_out', 'q_err']:
-            if hasattr(self, q):
-                queue = getattr(self, q)
-                kill_queue(queue)
-                kill_queue(queue)  # repeat just to make sure it doesn't error
-
-    def __del__(self):
-        self.halt()
-
-
-def sqtest_echo_f(name, delay, q_out, q_err, has_q):
-    while True:
-        time.sleep(delay)
-
-        if not q_out.empty():
-            out = q_out.get()
-
-            if out == BREAK_SIGNAL:
-                # now test that disconnect works, and reverts to
-                # regular stdout and stderr
-                if has_q:
-                    try:
-                        get_stream_queue().disconnect()
-                    except RuntimeError:
-                        pass
-                    print('stdout ', end='', flush=True)
-                    print('stderr ', file=sys.stderr, end='', flush=True)
-                break
-
-            print(out, end='', flush=True)
-
-        if not q_err.empty():
-            print(q_err.get(), file=sys.stderr, end='', flush=True)
-
-
-def sqtest_exception():
-    raise RuntimeError('Boo!')
-
-
-class TestMpMethod(TestCase):
-    def test_set_mp_method(self):
-        start_method = mp.get_start_method()
-        self.assertIn(start_method, ('fork', 'spawn', 'forkserver'))
-
-        # multiprocessing's set_start_method is NOT idempotent
-        with self.assertRaises(RuntimeError):
-            mp.set_start_method(start_method)
-
-        # but ours is
-        set_mp_method(start_method)
-
-        # it will still error on gibberish, but different errors depending
-        # on whether you force or not
-        with self.assertRaises(RuntimeError):
-            set_mp_method('spoon')
-        with self.assertRaises(ValueError):
-            set_mp_method('spoon', force=True)
-
-        # change the error we look for to test strange error handling
-        mp_err_normal = qcmp.MP_ERR
-        qcmp.MP_ERR = 'who cares?'
-        with self.assertRaises(RuntimeError):
-            set_mp_method('start_method')
-        qcmp.MP_ERR = mp_err_normal
-
-
-class TestQcodesProcess(TestCase):
-    def setUp(self):
-        mp_stats = calibrate(quiet=True)
-        self.MP_START_DELAY = mp_stats['mp_start_delay']
-        self.MP_FINISH_DELAY = mp_stats['mp_finish_delay']
-        self.SLEEP_DELAY = mp_stats['sleep_delay']
-        self.BLOCKING_TIME = mp_stats['blocking_time']
-        self.sq = get_stream_queue()
-
-    @skipIf(getattr(qcodes, '_IN_NOTEBOOK', False),
-            'called from notebook')
-    def test_not_in_notebook(self):
-        # below we'll patch this to True, but make sure that it's False
-        # in the normal test runner.
-        self.assertEqual(in_notebook(), False)
-
-        # and make sure that processes run this way do not use the queue
-        with self.sq.lock:
-            p = sqtest_echo('hidden', has_q=False)
-            time.sleep(self.MP_START_DELAY)
-            p.send_out('should go to stdout;')
-            p.send_err('should go to stderr;')
-            p.halt()
-
-            self.assertEqual(self.sq.get(), '')
-
-    @patch('qcodes.process.qcodes_process.in_notebook')
-    def test_qcodes_process_exception(self, in_nb_patch):
-        in_nb_patch.return_value = True
-
-        with self.sq.lock:
-            name = 'Hamlet'
-            p = QcodesProcess(target=sqtest_exception, name=name)
-
-            initial_outs = (sys.stdout, sys.stderr)
-
-            # normally you call p.start(), but for this test we want
-            # the function to actually run in the main process
-            # it will run the actual target, but will print the exception
-            # (to the queue) rather than raising it.
-            p.run()
-
-            # output streams are back to how they started
-            self.assertEqual((sys.stdout, sys.stderr), initial_outs)
-            time.sleep(0.01)
-            exc_text = self.sq.get()
-            # but we have the exception in the queue
-            self.maxDiff = None
-            self.assertGreaterEqual(exc_text.count(name + ' ERR'), 5)
-            self.assertEqual(exc_text.count('Traceback'), 1, exc_text)
-            self.assertEqual(exc_text.count('RuntimeError'), 2)
-            self.assertEqual(exc_text.count('Boo!'), 2)
-
-    @patch('qcodes.process.qcodes_process.in_notebook')
-    def test_qcodes_process(self, in_nb_patch):
-        in_nb_patch.return_value = True
-
-        queue_format = re.compile(
-            '^\[\d\d:\d\d:\d\d\.\d\d\d p\d( ERR)?\] [^\[\]]*$')
-
-        with self.sq.lock:
-            p1 = sqtest_echo('p1')
-            p2 = sqtest_echo('p2')
-            time.sleep(self.MP_START_DELAY + p1.delay + p2.delay)
-
-            self.assertEqual(self.sq.get(), '')
-
-            procNames = ['<{}>'.format(name)
-                         for name in ('p1', 'p2')]
-
-            reprs = [repr(p) for p in mp.active_children()]
-            for name in procNames:
-                self.assertIn(name, reprs)
-
-            # test each individual stream to send several messages on same
-            # and different lines
-
-            for sender, label, term in ([[p1.send_out, 'p1] ', ''],
-                                         [p1.send_err, 'p1 ERR] ', '\n'],
-                                         [p2.send_out, 'p2] ', '\n'],
-                                         [p2.send_err, 'p2 ERR] ', '']]):
-                sender('row row ')
-                sender('row your boat\n')
-                sender('gently down ')
-                time.sleep(0.01)
-                data = [line for line in self.sq.get().split('\n') if line]
-                expected = [
-                    label + 'row row row your boat',
-                    label + 'gently down '
-                ]
-                # TODO - intermittent error here
-                self.assertEqual(len(data), len(expected), data)
-                for line, expected_line in zip(data, expected):
-                    self.assertIsNotNone(queue_format.match(line), data)
-                    self.assertEqual(line[14:], expected_line, data)
-
-                sender(' the stream' + term)
-                # no label/header as we're continuing  the previous line
-                self.assertEqual(self.sq.get(), ' the stream' + term)
-
-            p1.send_out('marco')
-            p2.send_out('polo\n')  # we don't see these single terminators
-            p1.send_out('marco\n')  # when we change streams
-            p2.send_out('polo')
-            time.sleep(0.01)
-
-            data = self.sq.get().split('\n')
-            for line in data:
-                if line:
-                    self.assertIsNotNone(queue_format.match(line))
-
-            data_msgs = [line[14:] for line in data]
-            expected = [
-                '',
-                'p1] marco',
-                'p2] polo',
-                'p1] marco',
-                'p2] polo'
-            ]
-            self.assertEqual(data_msgs, expected)
-
-            # Some OS's start more processes just for fun... so don't test
-            # that p1 and p2 are the only ones.
-            # self.assertEqual(len(reprs), 2, reprs)
-
-            p1.halt()
-            p2.halt()
-            # both p1 and p2 should have finished now, and ended.
-            reprs = [repr(p) for p in mp.active_children()]
-            for name in procNames:
-                self.assertNotIn(name, reprs)
-
-
-class TestStreamQueue(TestCase):
-    def test_connection(self):
-        sq = get_stream_queue()
-        sq.connect('')
-        # TODO: do we really want double-connect to raise? or maybe
-        # only raise if the process name changes?
-        with self.assertRaises(RuntimeError):
-            sq.connect('')
-        sq.disconnect()
-        with self.assertRaises(RuntimeError):
-            sq.disconnect()
-
-    def test_del(self):
-        sq = get_stream_queue()
-        self.assertTrue(hasattr(sq, 'queue'))
-        self.assertTrue(hasattr(sq, 'lock'))
-        self.assertIsNotNone(sq.instance)
-
-        sq.__del__()
-
-        self.assertFalse(hasattr(sq, 'queue'))
-        self.assertFalse(hasattr(sq, 'lock'))
-        self.assertIsNone(sq.instance)
-
-        sq.__del__()  # just to make sure it doesn't error
-
-    # this is basically tested in TestQcodesProcess, but the test happens
-    # in a subprocess so coverage doesn't know about it. Anyway, there are
-    # a few edge cases left that we have to test locally.
-    def test_sq_writer(self):
-        sq = get_stream_queue()
-        with sq.lock:
-            sq_clearer = _SQWriter(sq, 'Someone else')
-            sq_clearer.write('Boo!\n')
-
-            # apparently we need a little delay to make sure the queue
-            # properly appears populated.
-            time.sleep(0.01)
-
-            sq.get()
-            sq_name = 'A Queue'
-            sqw = _SQWriter(sq, sq_name)
-
-            # flush should exist, but does nothing
-            sqw.flush()
-
-            lines = [
-                'Knock knock.\nWho\'s there?\n',
-                'Interrupting cow.\n',
-                'Interr-',
-                'MOO!\n',
-                ''
-            ]
-
-            for line in lines:
-                sqw.write(line)
-
-            time.sleep(0.01)
-
-            # _SQWriter doesn't do any transformations to the messages, beyond
-            # adding a time string and the stream name
-            for line in lines:
-                if not line:
-                    self.assertEqual(sq.queue.empty(), True)
-                    continue
-
-                self.assertEqual(sq.queue.empty(), False)
-                timestr, stream_name, msg = sq.queue.get()
-                self.assertEqual(msg, line)
-                self.assertEqual(stream_name, sq_name)
-
-            # now test that even if the queue is unwatched the messages still
-            # go there. If we're feeling adventurous maybe we can test if
-            # something was actually printed.
-            sqw.MIN_READ_TIME = -1
-            new_message = 'should get printed\n'
-            sqw.write(new_message)
-
-            time.sleep(0.01)
-
-            self.assertEqual(sq.queue.empty(), False)
-            self.assertEqual(sq.queue.get()[2], new_message)
-
-            # test that an error in writing resets stdout and stderr
-            # nose uses its own stdout and stderr... so keep them (as we will
-            # force stdout and stderr to several other things) so we can put
-            # them back at the end
-            nose_stdout = sys.stdout
-            nose_stderr = sys.stderr
-            sys.stdout = _SQWriter(sq, 'mock_stdout')
-            sys.stderr = _SQWriter(sq, 'mock_stderr')
-            self.assertNotIn(sys.stdout, (sys.__stdout__, nose_stdout))
-            self.assertNotIn(sys.stderr, (sys.__stderr__, nose_stderr))
-
-            sqw.MIN_READ_TIME = 'not a number'
-            with self.assertRaises(TypeError):
-                sqw.write('trigger an error')
-
-            self.assertEqual(sys.stdout, sys.__stdout__)
-            self.assertEqual(sys.stderr, sys.__stderr__)
-
-            sys.stdout = nose_stdout
-            sys.stderr = nose_stderr
-            time.sleep(0.01)
-            sq.get()
-
-
-class ServerManagerTest(ServerManager):
-    def _start_server(self):
-        # don't really start the server - we'll test its pieces separately,
-        # in the main process
-        pass
-
-
-class EmptyServer:
-    def __init__(self, query_queue, response_queue, extras):
-        query_queue.put('why?')
-        response_queue.put(extras)
-
-
-class CustomError(Exception):
-    pass
-
-
-def delayed_put(queue, val, delay):
-    time.sleep(delay)
-    queue.put(val)
-
-
-class TestServerManager(TestCase):
-    def check_error(self, manager, error_str, error_class):
-        manager._response_queue.put(RESPONSE_ERROR, error_str)
-        with self.assertRaises(error_class):
-            manager.ask('which way does the wind blow?')
-
-    def test_mechanics(self):
-        extras = 'super secret don\'t tell anyone'
-
-        sm = ServerManagerTest(name='test', server_class=EmptyServer,
-                               shared_attrs=extras)
-        sm._run_server()
-
-        self.assertEqual(sm._query_queue.get(timeout=1), 'why?')
-        self.assertEqual(sm._response_queue.get(timeout=1), extras)
-
-        # builtin errors we propagate to the server
-        builtin_error_str = ('traceback\n  lines\n and then\n'
-                             '  OSError: your hard disk went floppy.')
-        sm._response_queue.put((RESPONSE_ERROR, builtin_error_str))
-        with self.assertRaises(OSError):
-            sm.ask('which way does the wind blow?')
-
-        # non-built-in errors we fall back on RuntimeError
-        custom_error_str = ('traceback\nlines\nand then\n'
-                            'CustomError: the Balrog is loose!')
-        extra_resp1 = 'should get tossed by the error checker'
-        extra_resp2 = 'so should this.'
-        sm._response_queue.put((RESPONSE_OK, extra_resp1))
-        sm._response_queue.put((RESPONSE_OK, extra_resp2))
-        sm._response_queue.put((RESPONSE_ERROR, custom_error_str))
-
-        # TODO: we have an intermittent failure below, but only when running
-        # the full test suite (including pyqt and matplotlib?), not if we
-        # run just this module, or at least not nearly as frequently.
-        time.sleep(0.2)
-
-        with LogCapture() as logs:
-            with self.assertRaises(RuntimeError):
-                sm.ask('something benign')
-            self.assertTrue(sm._response_queue.empty())
-        self.assertIn(extra_resp1, logs.value)
-        self.assertIn(extra_resp2, logs.value)
-
-        # extra responses to a query, only the last should be taken
-        extra_resp1 = 'boo!'
-        extra_resp2 = 'a barrel of monkeys!'
-        sm._response_queue.put((RESPONSE_OK, extra_resp1))
-        sm._response_queue.put((RESPONSE_OK, extra_resp2))
-        time.sleep(0.05)
-        p = mp.Process(target=delayed_put,
-                       args=(sm._response_queue, (RESPONSE_OK, 42), 0.05))
-        p.start()
-
-        with LogCapture() as logs:
-            self.assertEqual(sm.ask('what is the answer'), 42)
-        self.assertIn(extra_resp1, logs.value)
-        self.assertIn(extra_resp2, logs.value)
-
-        # no response to a query
-        with self.assertRaises(Empty):
-            sm.ask('A sphincter says what?', timeout=0.05)
-
-        # test halting an unresponsive server
-        sm._server = mp.Process(target=time.sleep, args=(1000,))
-        sm._server.start()
-
-        self.assertIn(sm._server, mp.active_children())
-
-        with LogCapture() as logs:
-            sm.halt(0.01)
-        self.assertIn('ServerManager did not respond '
-                      'to halt signal, terminated', logs.value)
-
-        self.assertNotIn(sm._server, mp.active_children())
-
-    def test_pathological_edge_cases(self):
-        # kill_queue should never fail
-        kill_queue(None)
-
-        # and halt should ignore AssertionErrors, which arise in
-        # subprocesses when trying to kill a different subprocess
-        sm = ServerManagerTest(name='test', server_class=None)
-
-        class HorribleProcess:
-            def is_alive(self):
-                raise AssertionError
-
-            def write(self):
-                raise AssertionError
-
-            def join(self):
-                raise AssertionError
-
-        sm._server = HorribleProcess()
-
-        sm.halt()
diff --git a/qcodes/tests/test_nested_attrs.py b/qcodes/tests/test_nested_attrs.py
deleted file mode 100644
index 0cf0dc19744..00000000000
--- a/qcodes/tests/test_nested_attrs.py
+++ /dev/null
@@ -1,100 +0,0 @@
-from unittest import TestCase
-from qcodes.utils.nested_attrs import NestedAttrAccess
-
-
-class TestNestedAttrAccess(TestCase):
-    def test_simple(self):
-        obj = NestedAttrAccess()
-
-        # before setting attr1
-        self.assertEqual(obj.getattr('attr1', 99), 99)
-        with self.assertRaises(AttributeError):
-            obj.getattr('attr1')
-
-        with self.assertRaises(TypeError):
-            obj.setattr('attr1')
-
-        self.assertFalse(hasattr(obj, 'attr1'))
-
-        # set it to a value
-        obj.setattr('attr1', 98)
-        self.assertTrue(hasattr(obj, 'attr1'))
-
-        self.assertEqual(obj.getattr('attr1', 99), 98)
-        self.assertEqual(obj.getattr('attr1'), 98)
-
-        # then delete it
-        obj.delattr('attr1')
-
-        with self.assertRaises(AttributeError):
-            obj.delattr('attr1')
-
-        with self.assertRaises(AttributeError):
-            obj.getattr('attr1')
-
-        # make and call a method
-        def f(a, b=0):
-            return a + b
-
-        obj.setattr('m1', f)
-        self.assertEqual(obj.callattr('m1', 4, 1), 5)
-        self.assertEqual(obj.callattr('m1', 21, b=42), 63)
-
-    def test_nested(self):
-        obj = NestedAttrAccess()
-
-        self.assertFalse(hasattr(obj, 'd1'))
-
-        with self.assertRaises(TypeError):
-            obj.setattr('d1')
-
-        # set one attribute that creates nesting
-        obj.setattr('d1', {'a': {1: 2, 'l': [5, 6]}})
-
-        # can't nest inside a non-container
-        with self.assertRaises(TypeError):
-            obj.setattr('d1["a"][1]["secret"]', 42)
-
-        # get the whole dict
-        self.assertEqual(obj.getattr('d1'), {'a': {1: 2, 'l': [5, 6]}})
-        self.assertEqual(obj.getattr('d1', 55), {'a': {1: 2, 'l': [5, 6]}})
-
-        # get parts
-        self.assertEqual(obj.getattr('d1["a"]'), {1: 2, 'l': [5, 6]})
-        self.assertEqual(obj.getattr('d1["a"][1]'), 2)
-        self.assertEqual(obj.getattr('d1["a"][1]', 3), 2)
-        with self.assertRaises(KeyError):
-            obj.getattr('d1["b"]')
-
-        # add an attribute inside, then delete it again
-        obj.setattr('d1["a"][2]', 4)
-        self.assertEqual(obj.getattr('d1'), {'a': {1: 2, 2: 4, 'l': [5, 6]}})
-        obj.delattr('d1["a"][2]')
-        self.assertEqual(obj.getattr('d1'), {'a': {1: 2, 'l': [5, 6]}})
-        self.assertEqual(obj.d1, {'a': {1: 2, 'l': [5, 6]}})
-
-        # list access
-        obj.setattr('d1["a"]["l"][0]', 7)
-        obj.callattr('d1["a"]["l"].extend', [5, 3])
-        obj.delattr('d1["a"]["l"][1]')
-        # while we're at it test single quotes
-        self.assertEqual(obj.getattr("d1['a']['l'][1]"), 5)
-        self.assertEqual(obj.d1['a']['l'], [7, 5, 3])
-
-    def test_bad_attr(self):
-        obj = NestedAttrAccess()
-        obj.d = {}
-        # this one works
-        obj.setattr('d["x"]', 1)
-
-        bad_attrs = [
-            '', '.', '[', 'x.', '[]',  # simply malformed
-            '.x'  # don't put a dot at the start
-            '["hi"]',  # can't set an item at the top level
-            'd[x]', 'd["x]', 'd["x\']'  # quoting errors
-        ]
-
-        for attr in bad_attrs:
-            with self.subTest(attr=attr):
-                with self.assertRaises(ValueError):
-                    obj.setattr(attr, 1)
diff --git a/qcodes/tests/test_visa.py b/qcodes/tests/test_visa.py
index 07a7e0638b1..76407afdc84 100644
--- a/qcodes/tests/test_visa.py
+++ b/qcodes/tests/test_visa.py
@@ -60,12 +60,6 @@ def ask(self, cmd):
 
 
 class TestVisaInstrument(TestCase):
-    def test_default_server_name(self):
-        dsn = VisaInstrument.default_server_name
-        self.assertEqual(dsn(), 'VisaServer')
-        self.assertEqual(dsn(address='Gpib::10'), 'GPIBServer')
-        self.assertEqual(dsn(address='aSRL4'), 'SerialServer')
-
     # error args for set(-10)
     args1 = [
         'be more positive!',
@@ -116,43 +110,6 @@ def test_ask_write_local(self):
 
         mv.close()
 
-    def test_ask_write_server(self):
-        # same thing as above but Joe is on a server now...
-        mv = MockVisa('Joe', server_name='')
-
-        # test normal ask and write behavior
-        mv.state.set(2)
-        self.assertEqual(mv.state.get(), 2)
-        mv.state.set(3.4567)
-        self.assertEqual(mv.state.get(), 3.457)  # driver rounds to 3 digits
-
-        # test ask and write errors
-        with self.assertRaises(ValueError) as e:
-            mv.state.set(-10)
-        for arg in self.args1:
-            self.assertIn(repr(arg), e.exception.args[0])
-        self.assertEqual(mv.state.get(), -10)  # set still happened
-
-        # only built-in errors get propagated to the main process as the
-        # same type. Perhaps we could include some more common ones like
-        # this (visa.VisaIOError) in the future...
-        with self.assertRaises(RuntimeError) as e:
-            mv.state.set(0)
-        for arg in self.args2:
-            self.assertIn(repr(arg), e.exception.args[0])
-        # the error type isn't VisaIOError, but it should be in the message
-        self.assertIn('VisaIOError', e.exception.args[0])
-        self.assertIn('VI_ERROR_TMO', e.exception.args[0])
-        self.assertEqual(mv.state.get(), 0)
-
-        mv.state.set(15)
-        with self.assertRaises(ValueError) as e:
-            mv.state.get()
-        for arg in self.args3:
-            self.assertIn(repr(arg), e.exception.args[0])
-
-        mv.close()
-
     @patch('qcodes.instrument.visa.visa.ResourceManager')
     def test_visa_backend(self, rm_mock):
         address_opened = [None]

From 1ea05fc3d3ccbdfb54a60082ffa81b9d357304fe Mon Sep 17 00:00:00 2001
From: Giulio Ungaretti <giulioungaretti@me.com>
Date: Tue, 7 Mar 2017 11:21:03 +0100
Subject: [PATCH 11/36] remove Widgets

---
 qcodes/__init__.py         |   5 -
 qcodes/widgets/__init__.py |   0
 qcodes/widgets/display.py  |  47 --------
 qcodes/widgets/widgets.css |  77 ------------
 qcodes/widgets/widgets.js  | 237 -------------------------------------
 qcodes/widgets/widgets.py  | 215 ---------------------------------
 6 files changed, 581 deletions(-)
 delete mode 100644 qcodes/widgets/__init__.py
 delete mode 100644 qcodes/widgets/display.py
 delete mode 100644 qcodes/widgets/widgets.css
 delete mode 100644 qcodes/widgets/widgets.js
 delete mode 100644 qcodes/widgets/widgets.py

diff --git a/qcodes/__init__.py b/qcodes/__init__.py
index f12b0489fc1..71bc19c9400 100644
--- a/qcodes/__init__.py
+++ b/qcodes/__init__.py
@@ -29,11 +29,6 @@
               'try "from qcodes.plots.pyqtgraph import QtPlot" '
               'to see the full error')
 
-# only import in name space if the gui is set to noebook
-# and there is multiprocessing
-if config['gui']['notebook'] and config['core']['legacy_mp']:
-    from qcodes.widgets.widgets import show_subprocess_widget
-
 from qcodes.station import Station
 from qcodes.loops import Loop
 from qcodes.measure import Measure
diff --git a/qcodes/widgets/__init__.py b/qcodes/widgets/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/qcodes/widgets/display.py b/qcodes/widgets/display.py
deleted file mode 100644
index 6a705dbb2cd..00000000000
--- a/qcodes/widgets/display.py
+++ /dev/null
@@ -1,47 +0,0 @@
-"""Helper for adding content stored in a file to a jupyter notebook."""
-import os
-from pkg_resources import resource_string
-from IPython.display import display, Javascript, HTML
-
-
-# Originally I implemented this using regular open() and read(), so it
-# could use relative paths from the importing file.
-#
-# But for distributable packages, pkg_resources.resource_string is the
-# best way to load data files, because it works even if the package is
-# in an egg or zip file. See:
-# http://pythonhosted.org/setuptools/setuptools.html#accessing-data-files-at-runtime
-
-def display_auto(qcodes_path, file_type=None):
-    """
-    Display some javascript, css, or html content in a jupyter notebook.
-
-    Content comes from a package-relative file path. Will use the file
-    extension to determine file type unless overridden by file_type
-
-    Args:
-        qcodes_path (str): the path to the target file within the qcodes
-            package, like 'widgets/widgets.js'
-
-        file_type (Optional[str]): Override the file extension to determine
-            what type of file this is. Case insensitive, supported values
-            are 'js', 'css', and 'html'
-    """
-    contents = resource_string('qcodes', qcodes_path).decode('utf-8')
-
-    if file_type is None:
-        ext = os.path.splitext(qcodes_path)[1].lower()
-    elif 'js' in file_type.lower():
-        ext = '.js'
-    elif 'css' in file_type.lower():
-        ext = '.css'
-    else:
-        ext = '.html'
-
-    if ext == '.js':
-        display(Javascript(contents))
-    elif ext == '.css':
-        display(HTML('<style>' + contents + '</style>'))
-    else:
-        # default to html. Anything else?
-        display(HTML(contents))
diff --git a/qcodes/widgets/widgets.css b/qcodes/widgets/widgets.css
deleted file mode 100644
index ab4204ae5e4..00000000000
--- a/qcodes/widgets/widgets.css
+++ /dev/null
@@ -1,77 +0,0 @@
-.qcodes-output-view:not(.ui-draggable) {
-    bottom: 0;
-    right: 5px;
-}
-.qcodes-output-view {
-    position: fixed;
-    z-index: 999;
-    background-color: #fff;
-    box-shadow: 0 0 12px 1px rgba(87, 87, 87, 0.2);
-}
-
-.qcodes-output-header {
-    float: right;
-}
-
-.qcodes-highlight {
-    animation: pulse 1s linear;
-    background-color: #fa4;
-}
-
-@keyframes pulse {
-    0% {
-        background-color: #f00;
-    }
-    100% {
-        background-color: #fa4;
-    }
-}
-
-.qcodes-process-list {
-    float: left;
-    max-width: 780px;
-    margin: 3px 5px 3px 10px;
-    overflow: hidden;
-    white-space: nowrap;
-    text-overflow: ellipsis;
-}
-
-.qcodes-output-view[qcodes-state=minimized] .qcodes-process-list {
-    max-width: 300px;
-}
-
-.qcodes-output-view span {
-    padding: 2px 6px 3px 12px;
-}
-
-.qcodes-output-view .btn {
-    margin: 0 3px 0 0;
-}
-
-.qcodes-output-view[qcodes-state=docked] .qcodes-docked,
-.qcodes-output-view[qcodes-state=floated] .qcodes-floated,
-.qcodes-output-view[qcodes-state=minimized] .qcodes-minimized,
-.qcodes-output-view[qcodes-state=minimized] .qcodes-content {
-    display: none;
-}
-
-.qcodes-output-view .disabled {
-    opacity: 0.4;
-}
-
-.qcodes-abort-loop {
-    background-color: #844;
-    color: #fff;
-}
-
-.qcodes-output-view pre {
-    clear: both;
-    margin: 0;
-    border: 0;
-    border-top: 1px solid #ccc;
-    background-color: #ffe;
-    min-height: 50px;
-    max-height: 400px;
-    min-width: 400px;
-    max-width: 1000px;
-}
\ No newline at end of file
diff --git a/qcodes/widgets/widgets.js b/qcodes/widgets/widgets.js
deleted file mode 100644
index c93f0882d38..00000000000
--- a/qcodes/widgets/widgets.js
+++ /dev/null
@@ -1,237 +0,0 @@
-/*
- * Qcodes Jupyter/IPython widgets
- */
-require([
-    'nbextensions/widgets/widgets/js/widget',
-    'nbextensions/widgets/widgets/js/manager'
-], function (widget, manager) {
-
-    var UpdateView = widget.DOMWidgetView.extend({
-        render: function() {
-            window.MYWIDGET = this;
-            this._interval = 0;
-            this.update();
-        },
-        update: function() {
-            this.display(this.model.get('_message'));
-            this.setInterval();
-        },
-        display: function(message) {
-            /*
-             * display method: override this for custom display logic
-             */
-            this.el.innerHTML = message;
-        },
-        remove: function() {
-            clearInterval(this._updater);
-        },
-        setInterval: function(newInterval) {
-            var me = this;
-            if(newInterval===undefined) newInterval = me.model.get('interval');
-            if(newInterval===me._interval) return;
-
-            me._interval = newInterval;
-
-            if(me._updater) clearInterval(me._updater);
-
-            if(me._interval) {
-                me._updater = setInterval(function() {
-                    me.send({myupdate: true});
-                    if(!me.model.comm_live) {
-                        console.log('missing comm, canceling widget updates', me);
-                        clearInterval(me._updater);
-                    }
-                }, me._interval * 1000);
-            }
-        }
-    });
-    manager.WidgetManager.register_widget_view('UpdateView', UpdateView);
-
-    var HiddenUpdateView = UpdateView.extend({
-        display: function(message) {
-            this.$el.hide();
-        }
-    });
-    manager.WidgetManager.register_widget_view('HiddenUpdateView', HiddenUpdateView);
-
-    var SubprocessView = UpdateView.extend({
-        render: function() {
-            var me = this;
-            me._interval = 0;
-            me._minimize = '<i class="fa-minus fa"></i>';
-            me._restore = '<i class="fa-plus fa"></i>';
-
-            // max lines of output to show
-            me.maxOutputLength = 500;
-
-            // in case there is already an outputView present,
-            // like from before restarting the kernel
-            $('.qcodes-output-view').not(me.$el).remove();
-
-            me.$el
-                .addClass('qcodes-output-view')
-                .attr('qcodes-state', 'docked')
-                .html(
-                    '<div class="qcodes-output-header toolbar">' +
-                        '<div class="qcodes-process-list"></div>' +
-                        '<button class="btn qcodes-processlines"><i class="fa-list fa"></i></button>' +
-                        '<button class="btn qcodes-abort-loop disabled">Abort</button>' +
-                        '<button class="btn qcodes-clear-output disabled qcodes-content">Clear</button>' +
-                        '<button class="btn js-state qcodes-minimized"><i class="fa-minus fa"></i></button>' +
-                        '<button class="btn js-state qcodes-docked"><i class="fa-toggle-up fa"></i></button>' +
-                        '<button class="btn js-state qcodes-floated"><i class="fa-arrows fa"></i></button>' +
-                    '</div>' +
-                    '<pre class="qcodes-content"></pre>'
-                );
-
-            me.clearButton = me.$el.find('.qcodes-clear-output');
-            me.minButton = me.$el.find('.qcodes-minimize');
-            me.outputArea = me.$el.find('pre');
-            me.subprocessList = me.$el.find('.qcodes-process-list');
-            me.abortButton = me.$el.find('.qcodes-abort-loop');
-            me.processLinesButton = me.$el.find('.qcodes-processlines')
-
-            me.outputLines = [];
-
-            me.clearButton.click(function() {
-                me.outputArea.html('');
-                me.clearButton.addClass('disabled');
-            });
-
-            me.abortButton.click(function() {
-                me.send({abort: true});
-            });
-
-            me.processLinesButton.click(function() {
-                // toggle multiline process list display
-                me.subprocessesMultiline = !me.subprocessesMultiline;
-                me.showSubprocesses();
-            });
-
-            me.$el.find('.js-state').click(function() {
-                var state = this.className.substr(this.className.indexOf('qcodes'))
-                        .split('-')[1].split(' ')[0];
-                me.model.set('_state', state);
-            });
-
-            $(window)
-                .off('resize.qcodes')
-                .on('resize.qcodes', function() {me.clipBounds();});
-
-            me.update();
-        },
-
-        updateState: function() {
-            var me = this,
-                oldState = me.$el.attr('qcodes-state'),
-                state = me.model.get('_state');
-
-            if(state === oldState) return;
-
-            setTimeout(function() {
-                // not sure why I can't pop it out of the widgetarea in render, but it seems that
-                // some other bit of code resets the parent after render if I do it there.
-                // To be safe, just do it on every state click.
-                me.$el.appendTo('body');
-
-                if(oldState === 'floated') {
-                    console.log('here');
-                    me.$el.draggable('destroy').css({left:'', top: ''});
-                }
-
-                me.$el.attr('qcodes-state', state);
-
-                if(state === 'floated') {
-                    me.$el
-                        .draggable({stop: function() { me.clipBounds(); }})
-                        .css({
-                            left: window.innerWidth - me.$el.width() - 15,
-                            top: window.innerHeight - me.$el.height() - 10
-                        });
-                }
-
-                // any previous highlighting is now moot
-                me.$el.removeClass('qcodes-highlight');
-            }, 0);
-
-        },
-
-        clipBounds: function() {
-            var me = this;
-            if(me.$el.attr('qcodes-state') === 'floated') {
-                var bounds = me.$el[0].getBoundingClientRect(),
-                    minVis = 40,
-                    maxLeft = window.innerWidth - minVis,
-                    minLeft = minVis - bounds.width,
-                    maxTop = window.innerHeight - minVis;
-
-                if(bounds.left > maxLeft) me.$el.css('left', maxLeft);
-                else if(bounds.left < minLeft) me.$el.css('left', minLeft);
-
-                if(bounds.top > maxTop) me.$el.css('top', maxTop);
-                else if(bounds.top < 0) me.$el.css('top', 0);
-            }
-        },
-
-        display: function(message) {
-            var me = this;
-            if(message) {
-                var initialScroll = me.outputArea.scrollTop();
-                me.outputArea.scrollTop(me.outputArea.prop('scrollHeight'));
-                var scrollBottom = me.outputArea.scrollTop();
-
-                if(me.$el.attr('qcodes-state') === 'minimized') {
-                    // if we add text and the box is minimized, highlight the
-                    // title bar to alert the user that there are new messages.
-                    // remove then add the class, so we get the animation again
-                    // if it's already highlighted
-                    me.$el.removeClass('qcodes-highlight');
-                    setTimeout(function(){
-                        me.$el.addClass('qcodes-highlight');
-                    }, 0);
-                }
-
-                var newLines = message.split('\n'),
-                    out = me.outputLines,
-                    outLen = out.length;
-                if(outLen) out[outLen - 1] += newLines[0];
-                else out.push(newLines[0]);
-
-                for(var i = 1; i < newLines.length; i++) {
-                    out.push(newLines[i]);
-                }
-
-                if(out.length > me.maxOutputLength) {
-                    out.splice(0, out.length - me.maxOutputLength + 1,
-                        '<<< Output clipped >>>');
-                }
-
-                me.outputArea.text(out.join('\n'));
-                me.clearButton.removeClass('disabled');
-
-                // if we were scrolled to the bottom initially, make sure
-                // we stay that way.
-                me.outputArea.scrollTop(initialScroll === scrollBottom ?
-                    me.outputArea.prop('scrollHeight') : initialScroll);
-            }
-
-            me.showSubprocesses();
-            me.updateState();
-        },
-
-        showSubprocesses: function() {
-            var me = this,
-                replacer = me.subprocessesMultiline ? '<br>' : ', ',
-                processes = (me.model.get('_processes') || '')
-                    .replace(/\n/g, '&gt;' + replacer + '&lt;');
-
-            if(processes) processes = '&lt;' + processes + '&gt;';
-            else processes = 'No subprocesses';
-
-            me.abortButton.toggleClass('disabled', processes.indexOf('Measurement')===-1);
-
-            me.subprocessList.html(processes);
-        }
-    });
-    manager.WidgetManager.register_widget_view('SubprocessView', SubprocessView);
-});
diff --git a/qcodes/widgets/widgets.py b/qcodes/widgets/widgets.py
deleted file mode 100644
index 56ea36dd45c..00000000000
--- a/qcodes/widgets/widgets.py
+++ /dev/null
@@ -1,215 +0,0 @@
-"""Qcodes-specific widgets for jupyter notebook."""
-from IPython.display import display
-from ipywidgets import widgets
-from multiprocessing import active_children
-from traitlets import Unicode, Float, Enum
-
-from qcodes.process.stream_queue import get_stream_queue
-from .display import display_auto
-from qcodes.loops import MP_NAME, halt_bg
-
-display_auto('widgets/widgets.js')
-display_auto('widgets/widgets.css')
-
-
-class UpdateWidget(widgets.DOMWidget):
-
-    """
-    Execute a callable periodically, and display its return in the output area.
-
-    The Javascript portion of this is in widgets.js with the same name.
-
-    Args:
-        fn (callable): To be called (with no parameters) periodically.
-
-        interval (number): The call period, in seconds. Can be changed later
-            by setting the ``interval`` attribute. ``interval=0`` or the
-            ``halt()`` method disables updates.
-
-        first_call (bool): Whether to call the update function immediately
-            or only after the first interval. Default True.
-    """
-
-    _view_name = Unicode('UpdateView', sync=True)  # see widgets.js
-    _message = Unicode(sync=True)
-    interval = Float(sync=True)
-
-    def __init__(self, fn, interval, first_call=True):
-        super().__init__()
-
-        self._fn = fn
-        self.interval = interval
-        self.previous_interval = interval
-
-        # callbacks send the widget (self) as the first arg
-        # so bind to __func__ and we can leave the duplicate out
-        # of the method signature
-        self.on_msg(self.do_update.__func__)
-
-        if first_call:
-            self.do_update({}, [])
-
-    def do_update(self, content=None, buffers=None):
-        """
-        Execute the callback and send its return value to the notebook.
-
-        Args:
-            content: required by DOMWidget, unused
-            buffers: required by DOMWidget, unused
-        """
-        self._message = str(self._fn())
-
-    def halt(self):
-        """
-        Stop future updates.
-
-        Keeps a record of the interval so we can ``restart()`` later.
-        You can also restart by explicitly setting ``self.interval`` to a
-        positive value.
-        """
-        if self.interval:
-            self.previous_interval = self.interval
-        self.interval = 0
-
-    def restart(self, **kwargs):
-        """
-        Reinstate updates with the most recent interval.
-
-        TODO: why did I include kwargs?
-        """
-        if not hasattr(self, 'previous_interval'):
-            self.previous_interval = 1
-
-        if self.interval != self.previous_interval:
-            self.interval = self.previous_interval
-
-
-class HiddenUpdateWidget(UpdateWidget):
-
-    """
-    A variant on UpdateWidget that hides its section of the output area.
-
-    The Javascript portion of this is in widgets.js with the same name.
-
-    Just lets the front end periodically execute code that takes care of its
-    own display. By default, first_call is False here, unlike UpdateWidget,
-    because it is assumed this widget is created to update something that
-    has been displayed by other means.
-
-    Args:
-        fn (callable): To be called (with no parameters) periodically.
-
-        interval (number): The call period, in seconds. Can be changed later
-            by setting the ``interval`` attribute. ``interval=0`` or the
-            ``halt()`` method disables updates.
-
-        first_call (bool): Whether to call the update function immediately
-            or only after the first interval. Default False.
-    """
-
-    _view_name = Unicode('HiddenUpdateView', sync=True)  # see widgets.js
-
-    def __init__(self, *args, first_call=False, **kwargs):
-        super().__init__(*args, first_call=first_call, **kwargs)
-
-
-def get_subprocess_widget(**kwargs):
-    """
-    Convenience function to get a singleton SubprocessWidget.
-
-    Restarts widget updates if it has been halted.
-
-    Args:
-        **kwargs: passed to SubprocessWidget constructor
-
-    Returns:
-        SubprocessWidget
-    """
-    if SubprocessWidget.instance is None:
-        w = SubprocessWidget(**kwargs)
-    else:
-        w = SubprocessWidget.instance
-
-    w.restart()
-
-    return w
-
-
-def show_subprocess_widget(**kwargs):
-    """
-    Display the subprocess widget, creating it if needed.
-
-    Args:
-        **kwargs: passed to SubprocessWidget constructor
-    """
-    display(get_subprocess_widget(**kwargs))
-
-
-class SubprocessWidget(UpdateWidget):
-
-    """
-    Display subprocess output in a box in the jupyter notebook window.
-
-    Output is collected from each process's stdout and stderr by the
-    ``StreamQueue`` and read periodically from the main process, triggered
-    by Javascript.
-
-    The Javascript portion of this is in widgets.js with the same name.
-
-    Args:
-        interval (number): The call period, in seconds. Can be changed later
-            by setting the ``interval`` attribute. ``interval=0`` or the
-            ``halt()`` method disables updates. Default 0.5.
-        state (str): starting window state of the widget. Options are
-            'docked' (default), 'minimized', 'floated'
-    """
-
-    _view_name = Unicode('SubprocessView', sync=True)  # see widgets.js
-    _processes = Unicode(sync=True)
-    _state = Enum(('minimized', 'docked', 'floated'), sync=True)
-
-    instance = None
-
-    # max seconds to wait for a measurement to abort
-    abort_timeout = 30
-
-    def __init__(self, interval=0.5, state='docked'):
-        if self.instance is not None:
-            raise RuntimeError(
-                'Only one instance of SubprocessWidget should exist at '
-                'a time. Use the function get_subprocess_output to find or '
-                'create it.')
-
-        self.stream_queue = get_stream_queue()
-        self._state = state
-        super().__init__(fn=None, interval=interval)
-
-        self.__class__.instance = self
-
-    def do_update(self, content=None, buffers=None):
-        """
-        Update the information to be displayed in the widget.
-
-        Send any new messages to the notebook, and update the list of
-        active processes.
-
-        Args:
-            content: required by DOMWidget, unused
-            buffers: required by DOMWidget, unused
-        """
-        self._message = self.stream_queue.get()
-
-        loops = []
-        others = []
-
-        for p in active_children():
-            if getattr(p, 'name', '') == MP_NAME:
-                # take off the <> on the ends, just to shorten the names
-                loops.append(str(p)[1:-1])
-            else:
-                others.append(str(p)[1:-1])
-
-        self._processes = '\n'.join(loops + others)
-
-        if content.get('abort'):
-            halt_bg(timeout=self.abort_timeout, traceback=False)

From 3aada668eac77197122039864f71e367215b4686 Mon Sep 17 00:00:00 2001
From: Giulio Ungaretti <giulioungaretti@me.com>
Date: Tue, 7 Mar 2017 11:38:52 +0100
Subject: [PATCH 12/36] chore: Remove benchmarking and reloading

Benchmarking should go if anything to its own repo
reloading is dangerous, and it can trick many new users.
---
 benchmarking/mptest.py                  | 156 ------------------------
 benchmarking/mptest_results_mac.txt     | 117 ------------------
 benchmarking/mptest_results_windows.txt |  88 -------------
 benchmarking/thread_test.py             |  55 ---------
 qcodes/utils/reload_code.py             |  98 ---------------
 5 files changed, 514 deletions(-)
 delete mode 100644 benchmarking/mptest.py
 delete mode 100644 benchmarking/mptest_results_mac.txt
 delete mode 100644 benchmarking/mptest_results_windows.txt
 delete mode 100644 benchmarking/thread_test.py
 delete mode 100644 qcodes/utils/reload_code.py

diff --git a/benchmarking/mptest.py b/benchmarking/mptest.py
deleted file mode 100644
index 4072ef92169..00000000000
--- a/benchmarking/mptest.py
+++ /dev/null
@@ -1,156 +0,0 @@
-# stress test multiprocessing
-# run with: python mptest.py <proc_count> <period> <repetitions> <start_method>
-# proc_count: the number of processes to spin up and load qcodes
-# period: milliseconds to wait between calling each process
-# repetitions: how many times to call each one
-# start_method: multiprocessing method to use (fork, forkserver, spawn)
-
-import multiprocessing as mp
-import sys
-import os
-import psutil
-import time
-
-import qcodes as qc
-
-
-timer = time.perf_counter
-
-
-def print_perf():
-    print(time.perf_counter())
-
-
-def mp_test(name, qin, qout, qglobal):
-    '''
-    simple test that keeps a process running until asked to stop,
-    and looks for an attribute within qcodes just to ensure it has loaded it
-    '''
-    delays = []
-    first = True
-    while True:
-        item, qtime = qin.get()
-        if first:  # ignore the first one... process is still starting
-            first = False
-        else:
-            delays.append(timer() - qtime)
-        if item == 'break':
-            qglobal.put({
-                'name': name,
-                'avg': sum(delays) / len(delays),
-                'max': max(delays)
-            })
-            break
-        qout.put(repr(getattr(qc, item)))
-
-
-def get_memory(pid):
-    mi = psutil.Process(pid).memory_info()
-    return mi.rss, mi.vms
-
-
-def get_all_memory(processes, title):
-    main_memory = get_memory(os.getpid())
-    proc_memory = [0, 0]
-    for proc in processes:
-        for i, v in enumerate(get_memory(proc.pid)):
-            proc_memory[i] += v
-            # print(v)
-
-    return {
-        'main_physical': main_memory[0]/1e6,
-        'main_virtual': main_memory[1]/1e6,
-        'proc_physical': proc_memory[0]/1e6,
-        'proc_virtual': proc_memory[1]/1e6,
-        'title': title
-    }
-
-
-def format_memory(mem):
-    return ('{title}\n'
-            '  main:  {main_physical:.0f} MB phys, '
-            '{main_virtual:.0f} MB virt\n'
-            '  procs: {proc_physical:.0f} MB phys, '
-            '{proc_virtual:.0f} MB virt\n'
-            '').format(**mem)
-
-
-if __name__ == '__main__':
-    proc_count = int(sys.argv[-4])
-    period = float(sys.argv[-3])
-    reps = int(sys.argv[-2])
-    method = sys.argv[-1]
-    mp.set_start_method(method)
-
-    qglobal = mp.Queue()
-
-    mem = [get_all_memory([], 'on startup')]
-
-    queues = []
-    processes = []
-    resp_delays = []
-
-    t_before_start = timer()
-
-    for proc_num in range(proc_count):
-        qin = mp.Queue()
-        qout = mp.Queue()
-        queues.append((qin, qout))
-        p = mp.Process(target=mp_test,
-                       args=('p{}'.format(proc_num), qin, qout, qglobal))
-        processes.append(p)
-        p.start()
-
-    start_delay = (timer() - t_before_start) * 1000
-
-    mem.append(get_all_memory(processes, 'procs started'))
-
-    for i in range(reps):
-        for qin, qout in queues:
-            t1 = timer()
-            qin.put(('Loop', timer()))
-            loop_repr = qout.get()
-            if i:
-                # ignore the first one, process is still starting
-                resp_delays.append((timer() - t1) * 1000)
-            if(loop_repr != repr(qc.Loop)):
-                raise RuntimeError('{} != {}'.format(loop_repr, repr(qc.Loop)))
-        print('.', end='', flush=True)
-        time.sleep(period / 1000)
-    print('')
-
-    mem.append(get_all_memory(processes, 'procs done working'))
-
-    for qin, qout in queues:
-        qin.put(('break', timer()))
-
-    t_before_join = timer()
-    for proc in processes:
-        proc.join()
-    join_delay = (timer() - t_before_join) * 1000
-
-    delays = [qglobal.get() for proc in processes]
-    avg_delay = sum([d['avg'] for d in delays]) * 1000 / len(delays)
-    max_delay = max([d['max'] for d in delays]) * 1000
-
-    avg_resp_delay = sum(resp_delays) / len(resp_delays)
-    max_resp_delay = max(resp_delays)
-
-    print(('Ran {} procs using "{}" method\n'
-           'sent messages every {} milliseconds, {} times\n'
-           ).format(proc_count, method, period, reps))
-
-    print('Milliseconds to start all processes: {:.3f}'.format(start_delay))
-    print('Final join delay: {:.3f}\n'.format(join_delay))
-
-    print('Milliseconds to receive to queue request')
-    print('  avg: {:.6f}'.format(avg_delay))
-    print('  max: {:.6f}\n'.format(max_delay))
-
-    print('Milliseconds to respond to queue request')
-    print('  avg: {:.6f}'.format(avg_resp_delay))
-    print('  max: {:.6f}\n'.format(max_resp_delay))
-
-    # report on the memory results
-    for m in mem:
-        print(format_memory(m))
diff --git a/benchmarking/mptest_results_mac.txt b/benchmarking/mptest_results_mac.txt
deleted file mode 100644
index ec8e2a7765d..00000000000
--- a/benchmarking/mptest_results_mac.txt
+++ /dev/null
@@ -1,117 +0,0 @@
-Mac OS X
--------------------
-
-Alexs-Air-2:Qcodes alex$ p3 mptest.py 5 50 50 spawn
-..................................................
-Ran 5 procs using "spawn" method
-sent messages every 50.0 milliseconds, 50 times
-
-Milliseconds to start all processes: 30.601
-Final join delay: 130.124
-
-Milliseconds to receive to queue request
-  avg: 0.321102
-  max: 1.061535
-
-Milliseconds to respond to queue request
-  avg: 0.607558
-  max: 1.465819
-
-on startup
-  main:  29 MB phys, 2498 MB virt
-  procs: 0 MB phys, 0 MB virt
-
-procs started
-  main:  29 MB phys, 2498 MB virt
-  procs: 8 MB phys, 12327 MB virt
-
-procs done working
-  main:  29 MB phys, 2524 MB virt
-  procs: 142 MB phys, 12509 MB virt
-
-
-Alexs-Air-2:Qcodes alex$ p3 mptest.py 20 50 50 spawn
-..................................................
-Ran 20 procs using "spawn" method
-sent messages every 50.0 milliseconds, 50 times
-
-Milliseconds to start all processes: 512.364
-Final join delay: 456.155
-
-Milliseconds to receive to queue request
-  avg: 0.302726
-  max: 2.754109
-
-Milliseconds to respond to queue request
-  avg: 0.555251
-  max: 1.123662
-
-on startup
-  main:  28 MB phys, 2498 MB virt
-  procs: 0 MB phys, 0 MB virt
-
-procs started
-  main:  29 MB phys, 2498 MB virt
-  procs: 150 MB phys, 49561 MB virt
-
-procs done working
-  main:  29 MB phys, 2603 MB virt
-  procs: 571 MB phys, 50029 MB virt
-
-
-Alexs-Air-2:Qcodes alex$ p3 mptest.py 100 50 50 spawn
-..................................................
-Ran 100 procs using "spawn" method
-sent messages every 50.0 milliseconds, 50 times
-
-Milliseconds to start all processes: 5242.341
-Final join delay: 3806.779
-
-Milliseconds to receive to queue request
-  avg: 0.527770
-  max: 59.421732
-
-Milliseconds to respond to queue request
-  avg: 0.416881
-  max: 4.560305
-
-on startup
-  main:  28 MB phys, 2497 MB virt
-  procs: 0 MB phys, 0 MB virt
-
-procs started
-  main:  30 MB phys, 2499 MB virt
-  procs: 1234 MB phys, 248003 MB virt
-
-procs done working
-  main:  11 MB phys, 3026 MB virt
-  procs: 2144 MB phys, 250162 MB virt
-
-
-Alexs-Air-2:Qcodes alex$ p3 mptest.py 100 50 50 fork
-..................................................
-Ran 100 procs using "fork" method
-sent messages every 50.0 milliseconds, 50 times
-
-Milliseconds to start all processes: 447.375
-Final join delay: 113.426
-
-Milliseconds to receive to queue request
-  avg: 0.351694
-  max: 11.889809
-
-Milliseconds to respond to queue request
-  avg: 0.494252
-  max: 2.525026
-
-on startup
-  main:  28 MB phys, 2498 MB virt
-  procs: 0 MB phys, 0 MB virt
-
-procs started
-  main:  29 MB phys, 2499 MB virt
-  procs: 444 MB phys, 249616 MB virt
-
-procs done working
-  main:  32 MB phys, 3025 MB virt
-  procs: 525 MB phys, 250142 MB virt
diff --git a/benchmarking/mptest_results_windows.txt b/benchmarking/mptest_results_windows.txt
deleted file mode 100644
index e267edeb280..00000000000
--- a/benchmarking/mptest_results_windows.txt
+++ /dev/null
@@ -1,88 +0,0 @@
-Windows
--------------------
-
-c:\Qcodes>python mptest.py 5 50 50 spawn
-..................................................
-Ran 5 procs using "spawn" method
-sent messages every 50.0 milliseconds, 50 times
-
-Milliseconds to start all processes: 15.406
-Final join delay: 92.359
-
-Milliseconds to receive to queue request
-  avg: -510.603209
-  max: -509.684951
-
-Milliseconds to respond to queue request
-  avg: 0.360488
-  max: 0.659211
-
-on startup
-  main:  36 MB phys, 31 MB virt
-  procs: 0 MB phys, 0 MB virt
-
-procs started
-  main:  36 MB phys, 31 MB virt
-  procs: 14 MB phys, 9 MB virt
-
-procs done working
-  main:  36 MB phys, 32 MB virt
-  procs: 179 MB phys, 155 MB virt
-
-
-c:\Qcodes>python mptest.py 20 50 50 spawn
-..................................................
-Ran 20 procs using "spawn" method
-sent messages every 50.0 milliseconds, 50 times
-
-Milliseconds to start all processes: 126.134
-Final join delay: 228.260
-
-Milliseconds to receive to queue request
-  avg: -1591.011659
-  max: -1563.003352
-
-Milliseconds to respond to queue request
-  avg: 0.365974
-  max: 0.794690
-
-on startup
-  main:  36 MB phys, 31 MB virt
-  procs: 0 MB phys, 0 MB virt
-
-procs started
-  main:  36 MB phys, 31 MB virt
-  procs: 98 MB phys, 60 MB virt
-
-procs done working
-  main:  37 MB phys, 32 MB virt
-  procs: 716 MB phys, 620 MB virt
-
-
-c:\Qcodes>python mptest.py 100 50 50 spawn
-..................................................
-Ran 100 procs using "spawn" method
-sent messages every 50.0 milliseconds, 50 times
-
-Milliseconds to start all processes: 761.556
-Final join delay: 927.847
-
-Milliseconds to receive to queue request
-  avg: -8560.453780
-  max: -8470.848083
-
-Milliseconds to respond to queue request
-  avg: 0.423033
-  max: 1.299948
-
-on startup
-  main:  35 MB phys, 31 MB virt
-  procs: 0 MB phys, 0 MB virt
-
-procs started
-  main:  37 MB phys, 32 MB virt
-  procs: 872 MB phys, 572 MB virt
-
-procs done working
-  main:  40 MB phys, 36 MB virt
-  procs: 3575 MB phys, 3094 MB virt
diff --git a/benchmarking/thread_test.py b/benchmarking/thread_test.py
deleted file mode 100644
index 40dac28bc69..00000000000
--- a/benchmarking/thread_test.py
+++ /dev/null
@@ -1,55 +0,0 @@
-import threading
-import time
-
-
-def sleeper(t, n, out, make_error):
-    time.sleep(t)
-    out[n] = n
-    if make_error:
-        raise RuntimeError('hello from # {}!'.format(n))
-
-
-def runmany(n, t, error_nums):
-    out = [None] * n
-
-    t0 = time.perf_counter()
-
-    threads = [
-        CatchingThread(target=sleeper, args=(t, i, out, i in error_nums))
-        for i in range(n)]
-
-    # start threads backward
-    [t.start() for t in reversed(threads)]
-    [t.join() for t in threads]
-
-    t1 = time.perf_counter()
-
-    out_ok = []
-    for i in range(n):
-        if out[i] != i:
-            out_ok += ['ERROR! out[{}] = {}'.format(i, out[i])]
-
-    if not out_ok:
-        out_ok += ['all output correct']
-
-    print('{} parallel threads sleeping\n'.format(n) +
-          'given time: {}\n'.format(t) +
-          'resulting time: {}\n'.format(t1 - t0) +
-          '\n'.join(out_ok))
-
-
-class CatchingThread(threading.Thread):
-    def __init__(self, *args, **kwargs):
-        super().__init__(*args, **kwargs)
-        self.exception = None
-
-    def run(self):
-        try:
-            super().run()
-        except Exception as e:
-            self.exception = e
-
-    def join(self):
-        super().join()
-        if self.exception:
-            raise self.exception
diff --git a/qcodes/utils/reload_code.py b/qcodes/utils/reload_code.py
deleted file mode 100644
index 08cedf5d1dd..00000000000
--- a/qcodes/utils/reload_code.py
+++ /dev/null
@@ -1,98 +0,0 @@
-import os
-import sys
-import imp
-from traceback import format_exc
-
-# Routine to reload modules during execution, for development only.
-# This is finicky and SHOULD NOT be used in regular experiments,
-# as they can cause non-intuitive errors later on. It is not included in
-# the base qcodes import, nor tested; Use at your own risk.
-
-
-# see http://stackoverflow.com/questions/22195382/
-# how-to-check-if-a-module-library-package-is-part-of-the-python-standard-library
-syspaths = [os.path.abspath(p) for p in sys.path]
-stdlib = tuple(p for p in syspaths
-               if p.startswith((sys.prefix, sys.base_prefix))
-               and 'site-packages' not in p)
-# a few things in site-packages we will consider part of the standard lib
-# it causes problems if we reload some of these, others are just stable
-# dependencies - this is mainly for reloading our own code.
-# could even whitelist site-packages items to allow, rather than to ignore?
-otherlib = ('jupyter', 'ipy', 'IPy', 'matplotlib', 'numpy', 'scipy', 'pyvisa',
-            'traitlets', 'zmq', 'tornado', 'dateutil', 'six', 'pexpect')
-otherpattern = tuple('site-packages/' + n for n in otherlib)
-
-
-def reload_code(pattern=None, lib=False, site=False):
-    '''
-    reload all modules matching a given pattern
-    or all (non-built-in) modules if pattern is omitted
-    if lib is False (default), ignore the standard library and major packages
-    if site is False (default), ignore everything in site-packages, only reload
-    files in nonstandard paths
-    '''
-    reloaded_files = []
-
-    for i in range(2):
-        # sometimes we need to reload twice to propagate all links,
-        # even though we reload the deepest modules first. Not sure if
-        # twice is always sufficient, but we'll try it.
-        for module in sys.modules.values():
-            if (pattern is None or pattern in module.__name__):
-                reload_recurse(module, reloaded_files, lib, site)
-
-    return reloaded_files
-
-
-def is_good_module(module, lib=False, site=False):
-    '''
-    is an object (module) a module we can reload?
-    if lib is False (default), ignore the standard library and major packages
-    '''
-    # take out non-modules and underscore modules
-    name = getattr(module, '__name__', '_')
-    if name[0] == '_' or not isinstance(module, type(sys)):
-        return False
-
-    # take out modules we can't find and built-ins
-    if name in sys.builtin_module_names or not hasattr(module, '__file__'):
-        return False
-
-    path = os.path.abspath(module.__file__)
-
-    if 'site-packages' in path and not site:
-        return False
-
-    if not lib:
-        if path.startswith(stdlib) and 'site-packages' not in path:
-            return False
-
-        for pattern in otherpattern:
-            if pattern in path:
-                return False
-
-    return True
-
-
-def reload_recurse(module, reloaded_files, lib, site):
-    '''
-    recursively search module for its own dependencies to reload,
-    ignoring those already in reloaded_files
-    if lib is False (default), ignore the standard library and major packages
-    '''
-    if (not is_good_module(module, lib, site) or
-            module.__file__ in reloaded_files):
-        return
-
-    reloaded_files.append(module.__file__)
-
-    try:
-        for name in dir(module):
-            module2 = getattr(module, name)
-            reload_recurse(module2, reloaded_files, lib, site)
-        imp.reload(module)
-
-    except:
-        print('error reloading "{}"'.format(getattr(module, '__name__', '?')))
-        print(format_exc())

From ee5375f59ed7f92ab3458357dabe38fa00dd9e4d Mon Sep 17 00:00:00 2001
From: Giulio Ungaretti <giulioungaretti@me.com>
Date: Tue, 7 Mar 2017 12:00:50 +0100
Subject: [PATCH 13/36] chore: Add todo

---
 qcodes/tests/test_helpers.py | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/qcodes/tests/test_helpers.py b/qcodes/tests/test_helpers.py
index 483792db060..f55827d0c9c 100644
--- a/qcodes/tests/test_helpers.py
+++ b/qcodes/tests/test_helpers.py
@@ -167,6 +167,10 @@ def test_bad_calls(self):
                 permissive_range(*args)
 
     def test_good_calls(self):
+        # TODO(giulioungaretti)
+        # not sure what we are testing here.
+        # in pyhton 1.0 and 1 are actually the same
+        # https://docs.python.org/3.5/library/functions.html#hash
         good_args = {
             (1, 7, 2): [1, 3, 5],
             (1, 7, 4): [1, 5],

From 44138c59167553864265b5e28804413dd324c47f Mon Sep 17 00:00:00 2001
From: Giulio Ungaretti <giulioungaretti@me.com>
Date: Tue, 7 Mar 2017 12:36:47 +0100
Subject: [PATCH 14/36] chore: Use py.test

move faster without reinventing the wheel at all times
---
 CONTRIBUTING.rst           | 113 ++++-------------------------------
 README.rst                 |   4 +-
 docs/community/index.rst   |   1 -
 docs/community/testing.rst |  80 -------------------------
 qcodes/__init__.py         |   1 -
 qcodes/test.py             | 119 -------------------------------------
 6 files changed, 15 insertions(+), 303 deletions(-)
 delete mode 100644 docs/community/testing.rst
 delete mode 100644 qcodes/test.py

diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst
index 63aef9e7e31..abaa46f3066 100644
--- a/CONTRIBUTING.rst
+++ b/CONTRIBUTING.rst
@@ -59,13 +59,18 @@ Setup
 Running Tests
 ~~~~~~~~~~~~~
 
-The core test runner is in ``qcodes/test.py``:
+We don't want to reinvent the wheel, and thus use py.test.
+It's easy to install:
 
 ::
 
-    python qcodes/test.py
-    # optional extra verbosity and fail fast
-    python qcodes/test.py -v -f
+    pip install coverage pytest-cov pytest
+
+Then to test and view the coverage:
+
+::
+    py.test --cov=qcodes --cov-report xml --cov-config=.coveragerc
+
 
 You can also run single tests with:
 
@@ -78,92 +83,6 @@ You can also run single tests with:
     # or
     python -m unittest qcodes.tests.test_metadata.TestMetadatable.test_snapshot
 
-If you run the core test runner, you should see output that looks
-something like this:
-
-::
-
-    .........***** found one MockMock, testing *****
-    ............................................Timing resolution:
-    startup time: 0.000e+00
-    min/med/avg/max dev: 9.260e-07, 9.670e-07, 1.158e-06, 2.109e-03
-    async sleep delays:
-    startup time: 2.069e-04
-    min/med/avg/max dev: 3.372e-04, 6.376e-04, 6.337e-04, 1.007e-03
-    multiprocessing startup delay and regular sleep delays:
-    startup time: 1.636e-02
-    min/med/avg/max dev: 3.063e-05, 2.300e-04, 2.232e-04, 1.743e-03
-    should go to stdout;should go to stderr;.stdout stderr stdout stderr ..[10:44:09.063 A Queue] should get printed
-    ...................................
-    ----------------------------------------------------------------------
-    Ran 91 tests in 4.192s
-
-    OK
-    Name                         Stmts   Miss  Cover   Missing
-    ----------------------------------------------------------
-    data/data_array.py             104      0   100%
-    data/data_set.py               179    140    22%   38-55, 79-94, 99-104, 123-135, 186-212, 215-221, 224-244, 251-254, 257-264, 272, 280-285, 300-333, 347-353, 360-384, 395-399, 405-407, 414-420, 426-427, 430, 433-438
-    data/format.py                 225    190    16%   44-55, 61-62, 70, 78-97, 100, 114-148, 157-188, 232, 238, 246, 258-349, 352, 355-358, 361-368, 375-424, 427-441, 444, 447-451
-    data/io.py                      76     50    34%   71-84, 90-91, 94, 97, 103, 109-110, 119-148, 154-161, 166, 169, 172, 175-179, 182, 185-186
-    data/manager.py                124     89    28%   15-20, 31, 34, 48-62, 65-67, 70, 76-77, 80-84, 90-102, 108-110, 117-121, 142-151, 154-182, 185, 188, 207-208, 215-221, 227-229, 237, 243, 249
-    instrument/base.py              74      0   100%
-    instrument/function.py          45      1    98%   77
-    instrument/ip.py                20     12    40%   10-16, 19-20, 24-25, 29-38
-    instrument/mock.py              63      0   100%
-    instrument/parameter.py        200      2    99%   467, 470
-    instrument/sweep_values.py     107     33    69%   196-207, 220-227, 238-252, 255-277
-    instrument/visa.py              36     24    33%   10-25, 28-32, 35-36, 40-41, 47-48, 57-58, 62-64, 68
-    loops.py                       285    239    16%   65-74, 81-91, 120-122, 133-141, 153-165, 172-173, 188-207, 216-240, 243-313, 316-321, 324-350, 354-362, 371-375, 378-381, 414-454, 457-474, 477-484, 487-491, 510-534, 537-543, 559-561, 564, 577, 580, 590-608, 611-618, 627-628, 631
-    station.py                      35     24    31%   17-32, 35, 45-50, 60, 67-82, 88
-    utils/helpers.py                95      0   100%
-    utils/metadata.py               13      0   100%
-    utils/multiprocessing.py        95      2    98%   125, 134
-    utils/sync_async.py            114      8    93%   166, 171-173, 176, 180, 184, 189-191
-    utils/timing.py                 72      0   100%
-    utils/validators.py            110      0   100%
-    ----------------------------------------------------------
-    TOTAL                         2072    814    61%
-
-The key is ``OK`` in the middle (that means all the tests passed), and
-the presence of the coverage report after it. If any tests fail, we do
-not show a coverage report, and the end of the output will contain
-tracebacks and messages about what failed, for example:
-
-::
-
-    ======================================================================
-    FAIL: test_sweep_steps_edge_case (tests.test_instrument.TestParameters)
-    ----------------------------------------------------------------------
-    Traceback (most recent call last):
-      File "/Users/alex/qdev/Qcodes/qcodes/tests/test_instrument.py", line 360, in test_sweep_steps_edge_case
-        self.check_set_amplitude2('Off', log_count=1, history_count=2)
-      File "/Users/alex/qdev/Qcodes/qcodes/tests/test_instrument.py", line 345, in check_set_amplitude2
-        self.assertTrue(line.startswith('negative delay'), line)
-    AssertionError: False is not true : cannot sweep amplitude2 from 0.1 to Off - jumping.
-
-    ----------------------------------------------------------------------
-    Ran 91 tests in 4.177s
-
-    FAILED (failures=1)
-
-The coverage report is only useful if you have been adding new code, to
-see whether your tests visit all of your code. Look at the file(s) you
-have been working on, and ensure that the "missing" section does not
-contain the line numbers of any of the blocks you have touched.
-Currently the core still has a good deal of untested code - eventually
-we will have all of this tested, but for now you can ignore all the rest
-of the missing coverage.
-
-You can also run these tests from inside python. The output is similar
-except that a) you don't get coverage reporting, and b) one test has to
-be skipped because it does not apply within a notebook, so the output
-will end ``OK (skipped=1)``:
-
-.. code:: python
-
-    import qcodes
-    qcodes.test_core()  # optional verbosity = 1 (default) or 2
-
 If the tests pass, you should be ready to start developing!
 
 To tests actual instruments, first instantiate them in an interactive
@@ -315,13 +234,7 @@ simplify to a one command that says: if there's enough cover, and all
 good or fail and where it fails.
 
 -  The standard test commands are listed above under
-   :ref:`runnningtests`. More notes on different test runners can
-   be found in  :ref:`testing`.
-
--  Core tests live in
-   `qcodes/tests <https://github.com/qdev-dk/Qcodes/tree/master/qcodes/tests>`__
-   and instrument tests live in the same directories as the instrument
-   drivers.
+   :ref:`runnningtests` .
 
 -  We should have a *few* high-level "integration" tests, but simple
    unit tests (that just depend on code in one module) are more valuable
@@ -330,7 +243,6 @@ good or fail and where it fails.
 -  When features change it is likely that more tests will need to change
 -  Unit tests can cover many scenarios much faster than integration
    tests.
-
 -  If you're having difficulty making unit tests, first consider whether
    your code could be restructured to make it less dependent on other
    modules. Often, however, extra techniques are needed to break down a
@@ -339,9 +251,8 @@ good or fail and where it fails.
 -  Patching, one of the most useful parts of the
    `unittest.mock <https://docs.python.org/3/library/unittest.mock.html>`__
    library. This lets you specify exactly how other functions/objects
-   should behave when they're called by the code you are testing. For a
-   simple example, see
-   `test\_multiprocessing.py <https://github.com/qdev-dk/Qcodes/blob/58a8692bed55272f4c5865d6ec37f846154ead16/qcodes/tests/test_multiprocessing.py#L63-L65>`__
+   should behave when they're called by the code you are testing.
+
 -  Supporting files / data: Lets say you have a test of data acquisition
    and analysis. You can break that up into an acquisition test and an
    analysis by saving the intermediate state, namely the data file, in
diff --git a/README.rst b/README.rst
index 423dfab85e8..c17387b7d92 100644
--- a/README.rst
+++ b/README.rst
@@ -70,9 +70,11 @@ $QCODES_INSTALL_DIR is the folder where you want to have the source code.
     cd $QCODES_INSTALL_DIR
     pyenv install 3.5.2
     pyenv virtualenv 3.5.2 qcodes-dev
+    pyenv activate qcodes-dev
     pip install -r requirements.txt
+    pip install coverage pytest-cov pytest --upgrade
     pip install -e .
-    python qcodes/test.py -f
+    py.test --cov=qcodes --cov-config=.coveragerc
 
 If the tests pass you are ready to hack!
 This is the reference setup one needs to have to contribute, otherwise
diff --git a/docs/community/index.rst b/docs/community/index.rst
index 0d42653900d..c0cd05f6962 100644
--- a/docs/community/index.rst
+++ b/docs/community/index.rst
@@ -11,4 +11,3 @@ This is the guide for you, the developer that wants to maintain/expand QCoDes.
    install
    contributing
    objects
-   testing
diff --git a/docs/community/testing.rst b/docs/community/testing.rst
deleted file mode 100644
index dc0ef7d2210..00000000000
--- a/docs/community/testing.rst
+++ /dev/null
@@ -1,80 +0,0 @@
-..  _testing:
-
-
-Notes on test runners compatible with Qcodes
-============================================
-
-There is now a test script `test.py <qcodes/test.py>`__ in the qcodes
-directory that uses the standard ``unittest`` machinery to run all the
-core tests (does not include instrument drivers). It has been tested on
-Mac (terminal), and Windows (cmd, git bash, and PowerShell). It includes
-coverage testing, but will only print a coverage report if tests pass.
-
-The biggest difficulty with testing Qcodes is windows multiprocessing.
-The spawn method restricts execution in ways that are annoying for
-regular users (no class/function definitions in the notebook, no
-closures) but seem to be completely incompatible with some test runners
-(and/or coverage tracking)
-
-I considered the following test runners: - **nose**: works well, but it
-has a `note on its homepage <https://nose.readthedocs.org/en/latest/>`__
-that it is no longer being actively maintained (in favor of nose2
-development), so we should not use it long-term.
-
--  **unittest**: the standard, built-in python tester. The only thing we
-   really need to add to this is coverage testing, so now the question
-   is what's the easiest way to do this? On Windows just using unittest
-   wrapped in coverage fails.
-
--  **nose2**: has a broken coverage plugin - it reports all the
-   unindented lines, ie everything # that executes on import, as
-   uncovered - but can be used by wrapping it inside coverage instead,
-   just like unittest.
-
--  **py.test**: seems to add lots of features, but it's not clear they
-   are useful for us? Has a good coverage plugin but seems to require
-   tons of command-line options. Requires both ``pytest`` and
-   ``pytest-cov`` packages
-
-on Mac terminal:
-
-::
-
-    # the following work with coverage:
-    nosetests
-    python setup.py nosetests
-    py.test --cov-config .coveragerc --cov qcodes --cov-report term-missing
-    coverage run -m nose2 && coverage report -m
-    # both of these run unittest:
-    coverage run setup.py test && coverage report -m
-    coverage run -m unittest && coverage report -m
-
-    # nose2's coverage plugin is broken - it reports all the unindented lines (everything
-    # that executes on import) as uncovered
-    nose2 -C --coverage-report term-missing
-
-Windows cmd shell and git bash behave identically, PowerShell has
-different chain syntax (commands with &&):
-
-::
-
-    # the following work with coverage:
-    nosetests
-    py.test --cov-config .coveragerc --cov qcodes --cov-report term-missing
-    coverage run -m nose2 && coverage report -m  # cmd or bash
-    (coverage run -m nose2) -and (coverage report -m)  # PowerShell
-
-    # the following work without coverage:
-    python -m unittest discover
-    python -m unittest  # discover is unnecessary now, perhaps because I put test_suite in setup.py?
-
-    # the following do not work:
-
-    # fails on relative import in unittest inside separate process (why is it importing that anyway?)
-    coverage run -m unittest discover && coverage report -m  # cmd or bash
-    (coverage run -m unittest discover) -and (coverage report -m)  # PowerShell
-    # these fail asking for freeze_support() but nothing I do with that seems to help
-    python setup.py test
-    coverage run setup.py test && coverage report -m  # cmd or bash
-    (coverage run setup.py test) -and (coverage report -m)  # PowerShell
-    python setup.py nosetests
diff --git a/qcodes/__init__.py b/qcodes/__init__.py
index 71bc19c9400..b7d7676af23 100644
--- a/qcodes/__init__.py
+++ b/qcodes/__init__.py
@@ -60,4 +60,3 @@
 from qcodes.utils import validators
 
 from qcodes.instrument_drivers.test import test_instruments, test_instrument
-from qcodes.test import test_core, test_part
diff --git a/qcodes/test.py b/qcodes/test.py
deleted file mode 100644
index b04c412b06a..00000000000
--- a/qcodes/test.py
+++ /dev/null
@@ -1,119 +0,0 @@
-"""Unified qcodes test runners."""
-
-import sys
-
-
-def test_core(verbosity=1, failfast=False):
-    """
-    Run the qcodes core tests.
-
-    Args:
-        verbosity (int, optional): 0, 1, or 2, higher displays more info
-            Default 1.
-        failfast (bool, optional): If true, stops running on first failure
-            Default False.
-
-    Coverage testing is only available from the command line
-    """
-    import qcodes
-    if qcodes.in_notebook():
-        qcodes._IN_NOTEBOOK = True
-
-    _test_core(verbosity=verbosity, failfast=failfast)
-
-
-def _test_core(test_pattern='test*.py', **kwargs):
-    import unittest
-
-    import qcodes.tests as qctest
-    import qcodes
-
-    suite = unittest.defaultTestLoader.discover(
-        qctest.__path__[0], top_level_dir=qcodes.__path__[0],
-        pattern=test_pattern)
-    if suite.countTestCases() == 0:
-        print('found no tests')
-        sys.exit(1)
-    print('testing %d cases' % suite.countTestCases())
-
-    result = unittest.TextTestRunner(**kwargs).run(suite)
-    return result.wasSuccessful()
-
-
-def test_part(name):
-    """
-    Run part of the qcodes core test suite.
-
-    Args:
-        name (str): a name within the qcodes.tests directory. May be:
-            - a module ('test_loop')
-            - a TestCase ('test_loop.TestLoop')
-            - a test method ('test_loop.TestLoop.test_nesting')
-    """
-    import unittest
-    fullname = 'qcodes.tests.' + name
-    suite = unittest.defaultTestLoader.loadTestsFromName(fullname)
-    return unittest.TextTestRunner().run(suite).wasSuccessful()
-
-if __name__ == '__main__':
-    import argparse
-    import os
-    import multiprocessing as mp
-
-    try:
-        import coverage
-        coverage_missing = False
-    except ImportError:
-        coverage_missing = True
-
-    # make sure coverage looks for .coveragerc in the right place
-    os.chdir(os.path.dirname(os.path.abspath(__file__)))
-
-    parser = argparse.ArgumentParser(
-        description=('Core test suite for Qcodes, '
-                     'covering everything except instrument drivers'))
-
-    parser.add_argument('-v', '--verbose', action='store_true',
-                        help='increase verbosity')
-
-    parser.add_argument('-q', '--quiet', action='store_true',
-                        help='reduce verbosity (opposite of --verbose)')
-
-    parser.add_argument('-s', '--skip-coverage', action='store_true',
-                        help='skip coverage reporting')
-
-    parser.add_argument('-t', '--test_pattern', type=str, default='test*.py',
-                        help=('regexp for test name to match, '
-                              'default "test*.py"'))
-
-    parser.add_argument('-f', '--failfast', action='store_true',
-                        help='halt on first error/failure')
-
-    parser.add_argument('-m', '--mp-spawn', action='store_true',
-                        help=('force "spawn" method of starting child '
-                              'processes to emulate Win behavior on Unix'))
-
-    args = parser.parse_args()
-
-    if args.mp_spawn:
-        mp.set_start_method('spawn')
-
-    args.skip_coverage |= coverage_missing
-
-    if not args.skip_coverage:
-        cov = coverage.Coverage(source=['qcodes'])
-        cov.start()
-
-    success = _test_core(verbosity=(1 + args.verbose - args.quiet),
-                         failfast=args.failfast,
-                         test_pattern=args.test_pattern)
-
-    if not args.skip_coverage:
-        cov.stop()
-        cov.save()
-        cov.report()
-
-    # restore unix-y behavior
-    # exit status 1 on fail
-    if not success:
-        sys.exit(1)

From 480933e64822b2c1ada70884f29e027c73fe4737 Mon Sep 17 00:00:00 2001
From: Giulio Ungaretti <giulioungaretti@me.com>
Date: Tue, 7 Mar 2017 16:33:24 +0100
Subject: [PATCH 15/36] fix: Remove nested attrs as unused

---
 qcodes/utils/nested_attrs.py | 175 -----------------------------------
 1 file changed, 175 deletions(-)
 delete mode 100644 qcodes/utils/nested_attrs.py

diff --git a/qcodes/utils/nested_attrs.py b/qcodes/utils/nested_attrs.py
deleted file mode 100644
index 66c9063fa3f..00000000000
--- a/qcodes/utils/nested_attrs.py
+++ /dev/null
@@ -1,175 +0,0 @@
-"""Nested attribute / item access for use by remote proxies."""
-
-import re
-
-
-class _NoDefault:
-
-    """Empty class to provide a missing default to getattr."""
-
-
-class NestedAttrAccess:
-
-    """
-    A Mixin class to provide nested access to attributes and their items.
-
-    Primarily for use by remote proxies, so we don't need to separately
-    proxy all the components, and all of their components, and worry about
-    which are picklable, etc.
-    """
-
-    def getattr(self, attr, default=_NoDefault):
-        """
-        Get a (possibly nested) attribute of this object.
-
-        If there is no ``.`` or ``[]`` in ``attr``, this exactly matches
-        the ``getattr`` function, but you can also access smaller pieces.
-
-        Args:
-            attr (str): An attribute or accessor string, like:
-                ``'attr.subattr[item]'``. ``item`` can be an integer or a
-                string. If it's a string it must be quoted.
-            default (any): If the attribute does not exist (at any level of
-                nesting), we return this. If no default is provided, throws
-                an ``AttributeError``.
-
-        Returns:
-            The value of this attribute.
-
-        Raises:
-            ValueError: If ``attr`` could not be understood.
-            AttributeError: If the attribute is missing and no default is
-                provided.
-            KeyError: If the item cannot be found and no default is provided.
-        """
-        parts = self._split_attr(attr)
-
-        try:
-            return self._follow_parts(parts)
-
-        except (AttributeError, KeyError):
-            if default is _NoDefault:
-                raise
-            else:
-                return default
-
-    def setattr(self, attr, value):
-        """
-        Set a (possibly nested) attribute of this object.
-
-        If there is no ``.`` or ``[]`` in ``attr``, this exactly matches
-        the ``setattr`` function, but you can also access smaller pieces.
-
-        Args:
-            attr (str): An attribute or accessor string, like:
-                ``'attr.subattr[item]'``. ``item`` can be an integer or a
-                string; If it's a string it must be quoted as usual.
-
-            value (any): The object to store in this attribute.
-
-        Raises:
-            ValueError: If ``attr`` could not be understood
-
-            TypeError: If an intermediate nesting level is not a container
-                and the next level is an item.
-
-            AttributeError: If an attribute with this name cannot be set.
-        """
-        parts = self._split_attr(attr)
-        obj = self._follow_parts(parts[:-1])
-        leaf = parts[-1]
-
-        if str(leaf).startswith('.'):
-            setattr(obj, leaf[1:], value)
-        else:
-            obj[leaf] = value
-
-    def delattr(self, attr):
-        """
-        Delete a (possibly nested) attribute of this object.
-
-        If there is no ``.`` or ``[]`` in ``attr``, this exactly matches
-        the ``delattr`` function, but you can also access smaller pieces.
-
-        Args:
-            attr (str): An attribute or accessor string, like:
-                ``'attr.subattr[item]'``. ``item`` can be an integer or a
-                string; If it's a string it must be quoted as usual.
-
-        Raises:
-            ValueError: If ``attr`` could not be understood
-        """
-        parts = self._split_attr(attr)
-        obj = self._follow_parts(parts[:-1])
-        leaf = parts[-1]
-
-        if str(leaf).startswith('.'):
-            delattr(obj, leaf[1:])
-        else:
-            del obj[leaf]
-
-    def callattr(self, attr, *args, **kwargs):
-        """
-        Call a (possibly nested) method of this object.
-
-        Args:
-            attr (str): An attribute or accessor string, like:
-                ``'attr.subattr[item]'``. ``item`` can be an integer or a
-                string; If it's a string it must be quoted as usual.
-
-            *args: Passed on to the method.
-
-            **kwargs: Passed on to the method.
-
-        Returns:
-            any: Whatever the method returns.
-
-        Raises:
-            ValueError: If ``attr`` could not be understood
-        """
-        func = self.getattr(attr)
-        return func(*args, **kwargs)
-
-    _PARTS_RE = re.compile(r'([\.\[])')
-    _ITEM_RE = re.compile(r'\[(?P<item>[^\[\]]+)\]')
-    _QUOTED_RE = re.compile(r'(?P<q>[\'"])(?P<str>[^\'"]*)(?P=q)')
-
-    def _split_attr(self, attr):
-        """
-        Return attr as a list of parts.
-
-        Items in the list are:
-            str '.attr' for attribute access,
-            str 'item' for string dict keys,
-            integers for integer dict/sequence keys.
-        Other key formats are not supported
-        """
-        # the first item is implicitly an attribute
-        parts = ('.' + self._PARTS_RE.sub(r'~\1', attr)).split('~')
-        for i, part in enumerate(parts):
-            item_match = self._ITEM_RE.fullmatch(part)
-            if item_match:
-                item = item_match.group('item')
-                quoted_match = self._QUOTED_RE.fullmatch(item)
-                if quoted_match:
-                    parts[i] = quoted_match.group('str')
-                else:
-                    try:
-                        parts[i] = int(item)
-                    except ValueError:
-                        raise ValueError('unrecognized item: ' + item)
-            elif part[0] != '.' or len(part) < 2:
-                raise ValueError('unrecognized attribute part: ' + part)
-
-        return parts
-
-    def _follow_parts(self, parts):
-        obj = self
-
-        for key in parts:
-            if str(key).startswith('.'):
-                obj = getattr(obj, key[1:])
-            else:
-                obj = obj[key]
-
-        return obj

From 783e0f97c5f13ab7c13f6f706bfef5c5c88fdfe3 Mon Sep 17 00:00:00 2001
From: Giulio Ungaretti <giulioungaretti@me.com>
Date: Wed, 8 Mar 2017 17:45:58 +0100
Subject: [PATCH 16/36] Fix remove try/Interrupt, missing variable imax

---
 qcodes/loops.py           | 136 ++++++++++++++++++--------------------
 qcodes/tests/test_loop.py |   6 +-
 2 files changed, 67 insertions(+), 75 deletions(-)

diff --git a/qcodes/loops.py b/qcodes/loops.py
index f00a35b6aa6..5f1a3c6ee78 100644
--- a/qcodes/loops.py
+++ b/qcodes/loops.py
@@ -777,74 +777,70 @@ def _run_loop(self, first_delay=0, action_indices=(),
 
         self.last_task_failed = False
 
-        try:
-            for i, value in enumerate(self.sweep_values):
-                if self.progress_interval is not None:
-                    tprint('loop %s: %d/%d (%.1f [s])' % (
-                        self.sweep_values.name, i, imax, time.time() - t0),
-                        dt=self.progress_interval, tag='outerloop')
-
-                set_val = self.sweep_values.set(value)
-
-                new_indices = loop_indices + (i,)
-                new_values = current_values + (value,)
-                data_to_store = {}
-
-                if hasattr(self.sweep_values, "parameters"):
-                    set_name = self.data_set.action_id_map[action_indices]
-                    if hasattr(self.sweep_values, 'aggregate'):
-                        value = self.sweep_values.aggregate(*set_val)
-                    self.data_set.store(new_indices, {set_name: value})
-                    for j, val in enumerate(set_val):
-                        set_index = action_indices + (j+1, )
-                        set_name = (self.data_set.action_id_map[set_index])
-                        data_to_store[set_name] = val
-                else:
-                    set_name = self.data_set.action_id_map[action_indices]
-                    data_to_store[set_name] = value
-
-                self.data_set.store(new_indices, data_to_store)
-
-                if not self._nest_first:
-                    # only wait the delay time if an inner loop will not inherit it
-                    self._wait(delay)
-
-                try:
-                    for f in callables:
-                        f(first_delay=delay,
-                          loop_indices=new_indices,
-                          current_values=new_values)
-
-                        # after the first action, no delay is inherited
-                        delay = 0
-                except _QcodesBreak:
-                    break
-
-                # after the first setpoint, delay reverts to the loop delay
-                delay = self.delay
-
-                # now check for a background task and execute it if it's
-                # been long enough since the last time
-                # don't let exceptions in the background task interrupt
-                # the loop
-                # if the background task fails twice consecutively, stop
-                # executing it
-                if self.bg_task is not None:
-                    t = time.time()
-                    if t - last_task >= self.bg_min_delay:
-                        try:
-                            self.bg_task()
-                        except Exception:
-                            if self.last_task_failed:
-                                self.bg_task = None
-                            self.last_task_failed = True
-                            log.exception("Failed to execute bg task")
-
-                        last_task = t
-
-        except Interrupt:
-            log.debug("Stopping loop cleanly")
-            return
+        for i, value in enumerate(self.sweep_values):
+            if self.progress_interval is not None:
+                tprint('loop %s: %d/%d (%.1f [s])' % (
+                    self.sweep_values.name, i, imax, time.time() - t0),
+                    dt=self.progress_interval, tag='outerloop')
+
+            set_val = self.sweep_values.set(value)
+
+            new_indices = loop_indices + (i,)
+            new_values = current_values + (value,)
+            data_to_store = {}
+
+            if hasattr(self.sweep_values, "parameters"):
+                set_name = self.data_set.action_id_map[action_indices]
+                if hasattr(self.sweep_values, 'aggregate'):
+                    value = self.sweep_values.aggregate(*set_val)
+                self.data_set.store(new_indices, {set_name: value})
+                for j, val in enumerate(set_val):
+                    set_index = action_indices + (j+1, )
+                    set_name = (self.data_set.action_id_map[set_index])
+                    data_to_store[set_name] = val
+            else:
+                set_name = self.data_set.action_id_map[action_indices]
+                data_to_store[set_name] = value
+
+            self.data_set.store(new_indices, data_to_store)
+
+            if not self._nest_first:
+                # only wait the delay time if an inner loop will not inherit it
+                self._wait(delay)
+
+            try:
+                for f in callables:
+                    f(first_delay=delay,
+                      loop_indices=new_indices,
+                      current_values=new_values)
+
+                    # after the first action, no delay is inherited
+                    delay = 0
+            except _QcodesBreak:
+                break
+
+            # after the first setpoint, delay reverts to the loop delay
+            delay = self.delay
+
+            # now check for a background task and execute it if it's
+            # been long enough since the last time
+            # don't let exceptions in the background task interrupt
+            # the loop
+            # if the background task fails twice consecutively, stop
+            # executing it
+            if self.bg_task is not None:
+                t = time.time()
+                if t - last_task >= self.bg_min_delay:
+                    try:
+                        self.bg_task()
+                    except Exception:
+                        if self.last_task_failed:
+                            self.bg_task = None
+                        self.last_task_failed = True
+                        log.exception("Failed to execute bg task")
+
+                    last_task = t
+
         # run the background task one last time to catch the last setpoint(s)
         if self.bg_task is not None:
             self.bg_task()
@@ -862,7 +858,3 @@ def _wait(self, delay):
             finish_clock = time.perf_counter() + delay
             t = wait_secs(finish_clock)
             time.sleep(t)
-
-
-class Interrupt(Exception):
-    pass
diff --git a/qcodes/tests/test_loop.py b/qcodes/tests/test_loop.py
index ae76594936a..6409e67e1cf 100644
--- a/qcodes/tests/test_loop.py
+++ b/qcodes/tests/test_loop.py
@@ -4,8 +4,8 @@
 import numpy as np
 from unittest.mock import patch
 
-from qcodes.loops import Loop, Interrupt
-from qcodes.actions import Task, Wait, BreakIf
+from qcodes.loops import Loop
+from qcodes.actions import Task, Wait, BreakIf, _QcodesBreak
 from qcodes.station import Station
 from qcodes.data.data_array import DataArray
 from qcodes.instrument.parameter import ManualParameter
@@ -461,7 +461,7 @@ def __init__(self, *args, count=1, msg=None, **kwargs):
     def get(self):
         self._count -= 1
         if self._count <= 0:
-            raise Interrupt
+            raise _QcodesBreak
         return super().get()
 
     def reset(self):

From addd056bf7a5d4c88a9c721129ea2e5e4edacd38 Mon Sep 17 00:00:00 2001
From: Giulio Ungaretti <giulioungaretti@me.com>
Date: Fri, 10 Mar 2017 15:12:30 +0100
Subject: [PATCH 17/36] fix: Remove trailing number from test name

---
 qcodes/tests/test_instrument.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/qcodes/tests/test_instrument.py b/qcodes/tests/test_instrument.py
index d4a94c92832..d02ccdcc254 100644
--- a/qcodes/tests/test_instrument.py
+++ b/qcodes/tests/test_instrument.py
@@ -6,7 +6,7 @@
 from .instrument_mocks import DummyInstrument
 
 
-class TestInstrument2(TestCase):
+class TestInstrument(TestCase):
 
     def setUp(self):
         self.instrument = DummyInstrument(

From c08ca659d7c9b4eba9bea6cbb399fb60a9eb5212 Mon Sep 17 00:00:00 2001
From: Giulio Ungaretti <giulioungaretti@me.com>
Date: Fri, 10 Mar 2017 15:14:46 +0100
Subject: [PATCH 18/36] fix: Use unit

---
 qcodes/tests/instrument_mocks.py | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/qcodes/tests/instrument_mocks.py b/qcodes/tests/instrument_mocks.py
index 59c264d8b08..4de3c460dad 100644
--- a/qcodes/tests/instrument_mocks.py
+++ b/qcodes/tests/instrument_mocks.py
@@ -102,7 +102,8 @@ def __init__(self, name='dummy', gates=['dac1', 'dac2', 'dac3'], **kwargs):
             self.add_parameter(g,
                                parameter_class=ManualParameter,
                                initial_value=0,
-                               label='Gate {} (arb. units)'.format(g),
+                               label='Gate {}'.format(g),
+                               unit="V",
                                vals=Numbers(-800, 400))
 
 

From c7b4ac7b5be5f1b8d65d61a8647ca5b59a0cd306 Mon Sep 17 00:00:00 2001
From: Giulio Ungaretti <giulioungaretti@me.com>
Date: Fri, 10 Mar 2017 15:15:30 +0100
Subject: [PATCH 19/36] chore: Update documentation

---
 CONTRIBUTING.rst     | 3 ---
 docs/api/private.rst | 3 ---
 docs/api/public.rst  | 9 ---------
 3 files changed, 15 deletions(-)

diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst
index abaa46f3066..0657ab003c0 100644
--- a/CONTRIBUTING.rst
+++ b/CONTRIBUTING.rst
@@ -233,9 +233,6 @@ and then unit testing should be run on pull-request, using CI. Maybe
 simplify to a one command that says: if there's enough cover, and all
 good or fail and where it fails.
 
--  The standard test commands are listed above under
-   :ref:`runnningtests` .
-
 -  We should have a *few* high-level "integration" tests, but simple
    unit tests (that just depend on code in one module) are more valuable
    for several reasons:
diff --git a/docs/api/private.rst b/docs/api/private.rst
index 8fffb7cb2fa..f5e38caebc9 100644
--- a/docs/api/private.rst
+++ b/docs/api/private.rst
@@ -12,8 +12,5 @@ Classes and Functions
 
     utils.command
     utils.deferred_operations
-    utils.nested_attrs
     utils.helpers
-    utils.timing
     utils.metadata
-    process.qcodes_process
diff --git a/docs/api/public.rst b/docs/api/public.rst
index 12acc2e9464..04521a6f0d5 100644
--- a/docs/api/public.rst
+++ b/docs/api/public.rst
@@ -42,8 +42,6 @@ Loops
 .. autosummary::
    :toctree: generated/
 
-   get_bg
-   halt_bg
    Loop
 
 Measure
@@ -70,9 +68,6 @@ Data
 .. autosummary::
    :toctree: generated/
 
-    get_data_manager
-    qcodes.data.manager.DataManager
-    DataMode
     DataSet
     new_data
     load_data
@@ -102,8 +97,6 @@ Instrument
    Instrument
    IPInstrument
    VisaInstrument
-   MockInstrument
-   MockModel
 
 
 Plot
@@ -123,7 +116,5 @@ Utils & misc
    :toctree: generated/
 
    qcodes.utils.validators
-   qcodes.process.helpers.set_mp_method
    qcodes.utils.helpers.in_notebook
-   qcodes.widgets.widgets.show_subprocess_widget
 

From 5f8fb7ea5b95fb2ff026950e51393d7ef8fe357e Mon Sep 17 00:00:00 2001
From: Giulio Ungaretti <giulioungaretti@me.com>
Date: Fri, 10 Mar 2017 15:27:11 +0100
Subject: [PATCH 20/36] fix: Remove toymodel, and simlify examples

---
 docs/examples/Measure without a Loop.ipynb |  475 +-----
 docs/examples/Tutorial.ipynb               | 1567 ++------------------
 docs/examples/toymodel.py                  |  149 --
 3 files changed, 161 insertions(+), 2030 deletions(-)
 delete mode 100644 docs/examples/toymodel.py

diff --git a/docs/examples/Measure without a Loop.ipynb b/docs/examples/Measure without a Loop.ipynb
index 828db49fce4..f59aeebab11 100644
--- a/docs/examples/Measure without a Loop.ipynb	
+++ b/docs/examples/Measure without a Loop.ipynb	
@@ -2,7 +2,10 @@
  "cells": [
   {
    "cell_type": "markdown",
-   "metadata": {},
+   "metadata": {
+    "deletable": true,
+    "editable": true
+   },
    "source": [
     "# Measure without a Loop\n",
     "\n",
@@ -13,358 +16,38 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 1,
+   "execution_count": null,
    "metadata": {
-    "collapsed": false
+    "collapsed": false,
+    "deletable": true,
+    "editable": true
    },
-   "outputs": [
-    {
-     "data": {
-      "application/javascript": [
-       "/*\n",
-       " * Qcodes Jupyter/IPython widgets\n",
-       " */\n",
-       "require([\n",
-       "    'nbextensions/widgets/widgets/js/widget',\n",
-       "    'nbextensions/widgets/widgets/js/manager'\n",
-       "], function (widget, manager) {\n",
-       "\n",
-       "    var UpdateView = widget.DOMWidgetView.extend({\n",
-       "        render: function() {\n",
-       "            window.MYWIDGET = this;\n",
-       "            this._interval = 0;\n",
-       "            this.update();\n",
-       "        },\n",
-       "        update: function() {\n",
-       "            this.display(this.model.get('_message'));\n",
-       "            this.setInterval();\n",
-       "        },\n",
-       "        display: function(message) {\n",
-       "            /*\n",
-       "             * display method: override this for custom display logic\n",
-       "             */\n",
-       "            this.el.innerHTML = message;\n",
-       "        },\n",
-       "        remove: function() {\n",
-       "            clearInterval(this._updater);\n",
-       "        },\n",
-       "        setInterval: function(newInterval) {\n",
-       "            var me = this;\n",
-       "            if(newInterval===undefined) newInterval = me.model.get('interval');\n",
-       "            if(newInterval===me._interval) return;\n",
-       "\n",
-       "            me._interval = newInterval;\n",
-       "\n",
-       "            if(me._updater) clearInterval(me._updater);\n",
-       "\n",
-       "            if(me._interval) {\n",
-       "                me._updater = setInterval(function() {\n",
-       "                    me.send({myupdate: true});\n",
-       "                    if(!me.model.comm_live) {\n",
-       "                        console.log('missing comm, canceling widget updates', me);\n",
-       "                        clearInterval(me._updater);\n",
-       "                    }\n",
-       "                }, me._interval * 1000);\n",
-       "            }\n",
-       "        }\n",
-       "    });\n",
-       "    manager.WidgetManager.register_widget_view('UpdateView', UpdateView);\n",
-       "\n",
-       "    var HiddenUpdateView = UpdateView.extend({\n",
-       "        display: function(message) {\n",
-       "            this.$el.hide();\n",
-       "        }\n",
-       "    });\n",
-       "    manager.WidgetManager.register_widget_view('HiddenUpdateView', HiddenUpdateView);\n",
-       "\n",
-       "    var SubprocessView = UpdateView.extend({\n",
-       "        render: function() {\n",
-       "            var me = this;\n",
-       "            me._interval = 0;\n",
-       "            me._minimize = '<i class=\"fa-minus fa\"></i>';\n",
-       "            me._restore = '<i class=\"fa-plus fa\"></i>';\n",
-       "\n",
-       "            // max lines of output to show\n",
-       "            me.maxOutputLength = 500;\n",
-       "\n",
-       "            // in case there is already an outputView present,\n",
-       "            // like from before restarting the kernel\n",
-       "            $('.qcodes-output-view').not(me.$el).remove();\n",
-       "\n",
-       "            me.$el\n",
-       "                .addClass('qcodes-output-view')\n",
-       "                .attr('qcodes-state', 'docked')\n",
-       "                .html(\n",
-       "                    '<div class=\"qcodes-output-header toolbar\">' +\n",
-       "                        '<div class=\"qcodes-process-list\"></div>' +\n",
-       "                        '<button class=\"btn qcodes-processlines\"><i class=\"fa-list fa\"></i></button>' +\n",
-       "                        '<button class=\"btn qcodes-abort-loop disabled\">Abort</button>' +\n",
-       "                        '<button class=\"btn qcodes-clear-output disabled qcodes-content\">Clear</button>' +\n",
-       "                        '<button class=\"btn js-state qcodes-minimized\"><i class=\"fa-minus fa\"></i></button>' +\n",
-       "                        '<button class=\"btn js-state qcodes-docked\"><i class=\"fa-toggle-up fa\"></i></button>' +\n",
-       "                        '<button class=\"btn js-state qcodes-floated\"><i class=\"fa-arrows fa\"></i></button>' +\n",
-       "                    '</div>' +\n",
-       "                    '<pre class=\"qcodes-content\"></pre>'\n",
-       "                );\n",
-       "\n",
-       "            me.clearButton = me.$el.find('.qcodes-clear-output');\n",
-       "            me.minButton = me.$el.find('.qcodes-minimize');\n",
-       "            me.outputArea = me.$el.find('pre');\n",
-       "            me.subprocessList = me.$el.find('.qcodes-process-list');\n",
-       "            me.abortButton = me.$el.find('.qcodes-abort-loop');\n",
-       "            me.processLinesButton = me.$el.find('.qcodes-processlines')\n",
-       "\n",
-       "            me.outputLines = [];\n",
-       "\n",
-       "            me.clearButton.click(function() {\n",
-       "                me.outputArea.html('');\n",
-       "                me.clearButton.addClass('disabled');\n",
-       "            });\n",
-       "\n",
-       "            me.abortButton.click(function() {\n",
-       "                me.send({abort: true});\n",
-       "            });\n",
-       "\n",
-       "            me.processLinesButton.click(function() {\n",
-       "                // toggle multiline process list display\n",
-       "                me.subprocessesMultiline = !me.subprocessesMultiline;\n",
-       "                me.showSubprocesses();\n",
-       "            });\n",
-       "\n",
-       "            me.$el.find('.js-state').click(function() {\n",
-       "                var state = this.className.substr(this.className.indexOf('qcodes'))\n",
-       "                        .split('-')[1].split(' ')[0];\n",
-       "                me.model.set('_state', state);\n",
-       "            });\n",
-       "\n",
-       "            $(window)\n",
-       "                .off('resize.qcodes')\n",
-       "                .on('resize.qcodes', function() {me.clipBounds();});\n",
-       "\n",
-       "            me.update();\n",
-       "        },\n",
-       "\n",
-       "        updateState: function() {\n",
-       "            var me = this,\n",
-       "                oldState = me.$el.attr('qcodes-state'),\n",
-       "                state = me.model.get('_state');\n",
-       "\n",
-       "            if(state === oldState) return;\n",
-       "\n",
-       "            setTimeout(function() {\n",
-       "                // not sure why I can't pop it out of the widgetarea in render, but it seems that\n",
-       "                // some other bit of code resets the parent after render if I do it there.\n",
-       "                // To be safe, just do it on every state click.\n",
-       "                me.$el.appendTo('body');\n",
-       "\n",
-       "                if(oldState === 'floated') {\n",
-       "                    console.log('here');\n",
-       "                    me.$el.draggable('destroy').css({left:'', top: ''});\n",
-       "                }\n",
-       "\n",
-       "                me.$el.attr('qcodes-state', state);\n",
-       "\n",
-       "                if(state === 'floated') {\n",
-       "                    me.$el\n",
-       "                        .draggable({stop: function() { me.clipBounds(); }})\n",
-       "                        .css({\n",
-       "                            left: window.innerWidth - me.$el.width() - 15,\n",
-       "                            top: window.innerHeight - me.$el.height() - 10\n",
-       "                        });\n",
-       "                }\n",
-       "\n",
-       "                // any previous highlighting is now moot\n",
-       "                me.$el.removeClass('qcodes-highlight');\n",
-       "            }, 0);\n",
-       "\n",
-       "        },\n",
-       "\n",
-       "        clipBounds: function() {\n",
-       "            var me = this;\n",
-       "            if(me.$el.attr('qcodes-state') === 'floated') {\n",
-       "                var bounds = me.$el[0].getBoundingClientRect(),\n",
-       "                    minVis = 40,\n",
-       "                    maxLeft = window.innerWidth - minVis,\n",
-       "                    minLeft = minVis - bounds.width,\n",
-       "                    maxTop = window.innerHeight - minVis;\n",
-       "\n",
-       "                if(bounds.left > maxLeft) me.$el.css('left', maxLeft);\n",
-       "                else if(bounds.left < minLeft) me.$el.css('left', minLeft);\n",
-       "\n",
-       "                if(bounds.top > maxTop) me.$el.css('top', maxTop);\n",
-       "                else if(bounds.top < 0) me.$el.css('top', 0);\n",
-       "            }\n",
-       "        },\n",
-       "\n",
-       "        display: function(message) {\n",
-       "            var me = this;\n",
-       "            if(message) {\n",
-       "                var initialScroll = me.outputArea.scrollTop();\n",
-       "                me.outputArea.scrollTop(me.outputArea.prop('scrollHeight'));\n",
-       "                var scrollBottom = me.outputArea.scrollTop();\n",
-       "\n",
-       "                if(me.$el.attr('qcodes-state') === 'minimized') {\n",
-       "                    // if we add text and the box is minimized, highlight the\n",
-       "                    // title bar to alert the user that there are new messages.\n",
-       "                    // remove then add the class, so we get the animation again\n",
-       "                    // if it's already highlighted\n",
-       "                    me.$el.removeClass('qcodes-highlight');\n",
-       "                    setTimeout(function(){\n",
-       "                        me.$el.addClass('qcodes-highlight');\n",
-       "                    }, 0);\n",
-       "                }\n",
-       "\n",
-       "                var newLines = message.split('\\n'),\n",
-       "                    out = me.outputLines,\n",
-       "                    outLen = out.length;\n",
-       "                if(outLen) out[outLen - 1] += newLines[0];\n",
-       "                else out.push(newLines[0]);\n",
-       "\n",
-       "                for(var i = 1; i < newLines.length; i++) {\n",
-       "                    out.push(newLines[i]);\n",
-       "                }\n",
-       "\n",
-       "                if(out.length > me.maxOutputLength) {\n",
-       "                    out.splice(0, out.length - me.maxOutputLength + 1,\n",
-       "                        '<<< Output clipped >>>');\n",
-       "                }\n",
-       "\n",
-       "                me.outputArea.text(out.join('\\n'));\n",
-       "                me.clearButton.removeClass('disabled');\n",
-       "\n",
-       "                // if we were scrolled to the bottom initially, make sure\n",
-       "                // we stay that way.\n",
-       "                me.outputArea.scrollTop(initialScroll === scrollBottom ?\n",
-       "                    me.outputArea.prop('scrollHeight') : initialScroll);\n",
-       "            }\n",
-       "\n",
-       "            me.showSubprocesses();\n",
-       "            me.updateState();\n",
-       "        },\n",
-       "\n",
-       "        showSubprocesses: function() {\n",
-       "            var me = this,\n",
-       "                replacer = me.subprocessesMultiline ? '<br>' : ', ',\n",
-       "                processes = (me.model.get('_processes') || '')\n",
-       "                    .replace(/\\n/g, '&gt;' + replacer + '&lt;');\n",
-       "\n",
-       "            if(processes) processes = '&lt;' + processes + '&gt;';\n",
-       "            else processes = 'No subprocesses';\n",
-       "\n",
-       "            me.abortButton.toggleClass('disabled', processes.indexOf('Measurement')===-1);\n",
-       "\n",
-       "            me.subprocessList.html(processes);\n",
-       "        }\n",
-       "    });\n",
-       "    manager.WidgetManager.register_widget_view('SubprocessView', SubprocessView);\n",
-       "});\n"
-      ],
-      "text/plain": [
-       "<IPython.core.display.Javascript object>"
-      ]
-     },
-     "metadata": {},
-     "output_type": "display_data"
-    },
-    {
-     "data": {
-      "text/html": [
-       "<style>.qcodes-output-view:not(.ui-draggable) {\n",
-       "    bottom: 0;\n",
-       "    right: 5px;\n",
-       "}\n",
-       ".qcodes-output-view {\n",
-       "    position: fixed;\n",
-       "    z-index: 999;\n",
-       "    background-color: #fff;\n",
-       "    box-shadow: 0 0 12px 1px rgba(87, 87, 87, 0.2);\n",
-       "}\n",
-       "\n",
-       ".qcodes-output-header {\n",
-       "    float: right;\n",
-       "}\n",
-       "\n",
-       ".qcodes-highlight {\n",
-       "    animation: pulse 1s linear;\n",
-       "    background-color: #fa4;\n",
-       "}\n",
-       "\n",
-       "@keyframes pulse {\n",
-       "    0% {\n",
-       "        background-color: #f00;\n",
-       "    }\n",
-       "    100% {\n",
-       "        background-color: #fa4;\n",
-       "    }\n",
-       "}\n",
-       "\n",
-       ".qcodes-process-list {\n",
-       "    float: left;\n",
-       "    max-width: 780px;\n",
-       "    margin: 3px 5px 3px 10px;\n",
-       "    overflow: hidden;\n",
-       "    white-space: nowrap;\n",
-       "    text-overflow: ellipsis;\n",
-       "}\n",
-       "\n",
-       ".qcodes-output-view[qcodes-state=minimized] .qcodes-process-list {\n",
-       "    max-width: 300px;\n",
-       "}\n",
-       "\n",
-       ".qcodes-output-view span {\n",
-       "    padding: 2px 6px 3px 12px;\n",
-       "}\n",
-       "\n",
-       ".qcodes-output-view .btn {\n",
-       "    margin: 0 3px 0 0;\n",
-       "}\n",
-       "\n",
-       ".qcodes-output-view[qcodes-state=docked] .qcodes-docked,\n",
-       ".qcodes-output-view[qcodes-state=floated] .qcodes-floated,\n",
-       ".qcodes-output-view[qcodes-state=minimized] .qcodes-minimized,\n",
-       ".qcodes-output-view[qcodes-state=minimized] .qcodes-content {\n",
-       "    display: none;\n",
-       "}\n",
-       "\n",
-       ".qcodes-output-view .disabled {\n",
-       "    opacity: 0.4;\n",
-       "}\n",
-       "\n",
-       ".qcodes-abort-loop {\n",
-       "    background-color: #844;\n",
-       "    color: #fff;\n",
-       "}\n",
-       "\n",
-       ".qcodes-output-view pre {\n",
-       "    clear: both;\n",
-       "    margin: 0;\n",
-       "    border: 0;\n",
-       "    border-top: 1px solid #ccc;\n",
-       "    background-color: #ffe;\n",
-       "    min-height: 50px;\n",
-       "    max-height: 400px;\n",
-       "    min-width: 400px;\n",
-       "    max-width: 1000px;\n",
-       "}</style>"
-      ],
-      "text/plain": [
-       "<IPython.core.display.HTML object>"
-      ]
-     },
-     "metadata": {},
-     "output_type": "display_data"
-    }
-   ],
+   "outputs": [],
    "source": [
-    "# setup\n",
     "%matplotlib nbagg\n",
-    "import numpy as np\n",
-    "import qcodes as qc"
+    "import qcodes as qc\n",
+    "# import dummy driver for the tutorial\n",
+    "from qcodes.tests.instrument_mocks import DummyInstrument\n",
+    "from qcodes.instrument.mock import ArrayGetter\n",
+    "\n",
+    "dac1 = DummyInstrument(name=\"dac\")\n",
+    "dac2 = DummyInstrument(name=\"dac2\")\n",
+    "# the default dummy instrument returns always a constant value, in the following line we make it random \n",
+    "# just for the looks 💅\n",
+    "import random\n",
+    "dac2.dac2.get =  lambda: random.randint(0,100)\n",
+    "\n",
+    "# The station is a container for all instruments that makes it easy \n",
+    "# to log meta-data\n",
+    "station = qc.Station(dac1, dac2)"
    ]
   },
   {
    "cell_type": "markdown",
-   "metadata": {},
+   "metadata": {
+    "deletable": true,
+    "editable": true
+   },
    "source": [
     "## Instantiates all the instruments needed for the demo\n",
     "\n",
@@ -372,34 +55,11 @@
    ]
   },
   {
-   "cell_type": "code",
-   "execution_count": 2,
+   "cell_type": "markdown",
    "metadata": {
-    "collapsed": true
+    "deletable": true,
+    "editable": true
    },
-   "outputs": [],
-   "source": [
-    "from toymodel import AModel, MockGates, MockSource, MockMeter, AverageAndRaw\n",
-    "from qcodes.instrument.mock import ArrayGetter\n",
-    "\n",
-    "# now create this \"experiment\", note that all these are instruments \n",
-    "model = AModel()\n",
-    "gates = MockGates('gates', model=model)\n",
-    "source = MockSource('source', model=model)\n",
-    "meter = MockMeter('meter', model=model)\n",
-    "\n",
-    "# The station is a container for all instruments that makes it easy \n",
-    "# to log meta-data\n",
-    "station = qc.Station(gates, source, meter)\n",
-    "\n",
-    "# it's nice to have the key parameters be part of the global namespace\n",
-    "# that way they're objects that we can easily set, get, and slice\n",
-    "c0, c1, c2, vsd = gates.chan0, gates.chan1, gates.chan2, source.amplitude"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
    "source": [
     "### Only array output\n",
     "The arguments to Measure are all the same actions you use in a Loop.\n",
@@ -408,74 +68,21 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 3,
+   "execution_count": null,
    "metadata": {
-    "collapsed": false
+    "collapsed": false,
+    "deletable": true,
+    "editable": true
    },
-   "outputs": [
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "DataSet:\n",
-      "   mode     = DataMode.LOCAL\n",
-      "   location = '2016-10-20/12-14-31'\n",
-      "   <Type>   | <array_id>          | <array.name> | <array.shape>\n",
-      "   Measured | chan2_1             | chan2        | (100,)\n",
-      "   Measured | meter_amplitude_1_0 | amplitude    | (100,)\n",
-      "   Measured | chan2_3             | chan2        | (100,)\n",
-      "   Measured | meter_amplitude_3_0 | amplitude    | (100,)\n",
-      "acquired at 2016-10-20 12:14:31\n"
-     ]
-    }
-   ],
+   "outputs": [],
    "source": [
     "data = qc.Measure(\n",
-    "    qc.Task(c0.set, 0),\n",
-    "    ArrayGetter(meter.amplitude, c2[-10:10:0.2], 0.001),\n",
-    "    qc.Task(c0.set, 2),\n",
-    "    ArrayGetter(meter.amplitude, c2[-10:10:0.2], 0.001)\n",
+    "    qc.Task(dac1.dac1.set, 0),\n",
+    "    ArrayGetter(dac1.dac2, dac1.dac3.sweep(-10,10,0.2), 0.001),\n",
+    "    qc.Task(dac1.dac1.set, 2),\n",
+    "    ArrayGetter(dac1.dac2, dac1.dac3.sweep(-10,10,0.2), 0.001),\n",
     ").run()"
    ]
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "### Output with scalars\n",
-    "Scalars still get treated as data, but it's not exactly natural:\n",
-    "- They still get put into arrays, just 1D 1-element arrays.\n",
-    "- They need a setpoint array, at least for now, so we make a fake one \"single_set.\" There's something nice about this, actually, in that it makes it absolutely clear that these items are not really arrays."
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 4,
-   "metadata": {
-    "collapsed": false
-   },
-   "outputs": [
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "DataSet:\n",
-      "   mode     = DataMode.LOCAL\n",
-      "   location = '2016-10-20/12-14-35'\n",
-      "   <Type>   | <array_id>          | <array.name>  | <array.shape>\n",
-      "   Setpoint | single_set          | single        | (1,)\n",
-      "   Measured | gates_chan0         | chan0         | (1,)\n",
-      "   Measured | gates_chan1         | chan1         | (1,)\n",
-      "   Measured | chan2               | chan2         | (100,)\n",
-      "   Measured | meter_amplitude     | amplitude     | (100,)\n",
-      "   Measured | meter_avg_amplitude | avg_amplitude | (1,)\n",
-      "acquired at 2016-10-20 12:14:35\n"
-     ]
-    }
-   ],
-   "source": [
-    "data = qc.Measure(c0, c1, AverageAndRaw(meter.amplitude, c2[-10:10:0.2], 0.001)).run()"
-   ]
   }
  ],
  "metadata": {
@@ -494,7 +101,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.5.0"
+   "version": "3.5.2"
   }
  },
  "nbformat": 4,
diff --git a/docs/examples/Tutorial.ipynb b/docs/examples/Tutorial.ipynb
index 97a4a71dc4a..11464a3a71a 100644
--- a/docs/examples/Tutorial.ipynb
+++ b/docs/examples/Tutorial.ipynb
@@ -2,7 +2,10 @@
  "cells": [
   {
    "cell_type": "markdown",
-   "metadata": {},
+   "metadata": {
+    "deletable": true,
+    "editable": true
+   },
    "source": [
     "# QCoDeS tutorial \n",
     "Basic overview of QCoDeS"
@@ -10,7 +13,10 @@
   },
   {
    "cell_type": "markdown",
-   "metadata": {},
+   "metadata": {
+    "deletable": true,
+    "editable": true
+   },
    "source": [
     "## Typical QCodes workflow \n",
     "1. Start up an interactive python session (e.g. using jupyter) \n",
@@ -21,415 +27,84 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 1,
+   "execution_count": null,
    "metadata": {
     "collapsed": false,
+    "deletable": true,
+    "editable": true,
     "scrolled": false
    },
-   "outputs": [
-    {
-     "data": {
-      "application/javascript": [
-       "/*\n",
-       " * Qcodes Jupyter/IPython widgets\n",
-       " */\n",
-       "require([\n",
-       "    'nbextensions/widgets/widgets/js/widget',\n",
-       "    'nbextensions/widgets/widgets/js/manager'\n",
-       "], function (widget, manager) {\n",
-       "\n",
-       "    var UpdateView = widget.DOMWidgetView.extend({\n",
-       "        render: function() {\n",
-       "            window.MYWIDGET = this;\n",
-       "            this._interval = 0;\n",
-       "            this.update();\n",
-       "        },\n",
-       "        update: function() {\n",
-       "            this.display(this.model.get('_message'));\n",
-       "            this.setInterval();\n",
-       "        },\n",
-       "        display: function(message) {\n",
-       "            /*\n",
-       "             * display method: override this for custom display logic\n",
-       "             */\n",
-       "            this.el.innerHTML = message;\n",
-       "        },\n",
-       "        remove: function() {\n",
-       "            clearInterval(this._updater);\n",
-       "        },\n",
-       "        setInterval: function(newInterval) {\n",
-       "            var me = this;\n",
-       "            if(newInterval===undefined) newInterval = me.model.get('interval');\n",
-       "            if(newInterval===me._interval) return;\n",
-       "\n",
-       "            me._interval = newInterval;\n",
-       "\n",
-       "            if(me._updater) clearInterval(me._updater);\n",
-       "\n",
-       "            if(me._interval) {\n",
-       "                me._updater = setInterval(function() {\n",
-       "                    me.send({myupdate: true});\n",
-       "                    if(!me.model.comm_live) {\n",
-       "                        console.log('missing comm, canceling widget updates', me);\n",
-       "                        clearInterval(me._updater);\n",
-       "                    }\n",
-       "                }, me._interval * 1000);\n",
-       "            }\n",
-       "        }\n",
-       "    });\n",
-       "    manager.WidgetManager.register_widget_view('UpdateView', UpdateView);\n",
-       "\n",
-       "    var HiddenUpdateView = UpdateView.extend({\n",
-       "        display: function(message) {\n",
-       "            this.$el.hide();\n",
-       "        }\n",
-       "    });\n",
-       "    manager.WidgetManager.register_widget_view('HiddenUpdateView', HiddenUpdateView);\n",
-       "\n",
-       "    var SubprocessView = UpdateView.extend({\n",
-       "        render: function() {\n",
-       "            var me = this;\n",
-       "            me._interval = 0;\n",
-       "            me._minimize = '<i class=\"fa-minus fa\"></i>';\n",
-       "            me._restore = '<i class=\"fa-plus fa\"></i>';\n",
-       "\n",
-       "            // max lines of output to show\n",
-       "            me.maxOutputLength = 500;\n",
-       "\n",
-       "            // in case there is already an outputView present,\n",
-       "            // like from before restarting the kernel\n",
-       "            $('.qcodes-output-view').not(me.$el).remove();\n",
-       "\n",
-       "            me.$el\n",
-       "                .addClass('qcodes-output-view')\n",
-       "                .attr('qcodes-state', 'docked')\n",
-       "                .html(\n",
-       "                    '<div class=\"qcodes-output-header toolbar\">' +\n",
-       "                        '<div class=\"qcodes-process-list\"></div>' +\n",
-       "                        '<button class=\"btn qcodes-processlines\"><i class=\"fa-list fa\"></i></button>' +\n",
-       "                        '<button class=\"btn qcodes-abort-loop disabled\">Abort</button>' +\n",
-       "                        '<button class=\"btn qcodes-clear-output disabled qcodes-content\">Clear</button>' +\n",
-       "                        '<button class=\"btn js-state qcodes-minimized\"><i class=\"fa-minus fa\"></i></button>' +\n",
-       "                        '<button class=\"btn js-state qcodes-docked\"><i class=\"fa-toggle-up fa\"></i></button>' +\n",
-       "                        '<button class=\"btn js-state qcodes-floated\"><i class=\"fa-arrows fa\"></i></button>' +\n",
-       "                    '</div>' +\n",
-       "                    '<pre class=\"qcodes-content\"></pre>'\n",
-       "                );\n",
-       "\n",
-       "            me.clearButton = me.$el.find('.qcodes-clear-output');\n",
-       "            me.minButton = me.$el.find('.qcodes-minimize');\n",
-       "            me.outputArea = me.$el.find('pre');\n",
-       "            me.subprocessList = me.$el.find('.qcodes-process-list');\n",
-       "            me.abortButton = me.$el.find('.qcodes-abort-loop');\n",
-       "            me.processLinesButton = me.$el.find('.qcodes-processlines')\n",
-       "\n",
-       "            me.outputLines = [];\n",
-       "\n",
-       "            me.clearButton.click(function() {\n",
-       "                me.outputArea.html('');\n",
-       "                me.clearButton.addClass('disabled');\n",
-       "            });\n",
-       "\n",
-       "            me.abortButton.click(function() {\n",
-       "                me.send({abort: true});\n",
-       "            });\n",
-       "\n",
-       "            me.processLinesButton.click(function() {\n",
-       "                // toggle multiline process list display\n",
-       "                me.subprocessesMultiline = !me.subprocessesMultiline;\n",
-       "                me.showSubprocesses();\n",
-       "            });\n",
-       "\n",
-       "            me.$el.find('.js-state').click(function() {\n",
-       "                var state = this.className.substr(this.className.indexOf('qcodes'))\n",
-       "                        .split('-')[1].split(' ')[0];\n",
-       "                me.model.set('_state', state);\n",
-       "            });\n",
-       "\n",
-       "            $(window)\n",
-       "                .off('resize.qcodes')\n",
-       "                .on('resize.qcodes', function() {me.clipBounds();});\n",
-       "\n",
-       "            me.update();\n",
-       "        },\n",
-       "\n",
-       "        updateState: function() {\n",
-       "            var me = this,\n",
-       "                oldState = me.$el.attr('qcodes-state'),\n",
-       "                state = me.model.get('_state');\n",
-       "\n",
-       "            if(state === oldState) return;\n",
-       "\n",
-       "            setTimeout(function() {\n",
-       "                // not sure why I can't pop it out of the widgetarea in render, but it seems that\n",
-       "                // some other bit of code resets the parent after render if I do it there.\n",
-       "                // To be safe, just do it on every state click.\n",
-       "                me.$el.appendTo('body');\n",
-       "\n",
-       "                if(oldState === 'floated') {\n",
-       "                    console.log('here');\n",
-       "                    me.$el.draggable('destroy').css({left:'', top: ''});\n",
-       "                }\n",
-       "\n",
-       "                me.$el.attr('qcodes-state', state);\n",
-       "\n",
-       "                if(state === 'floated') {\n",
-       "                    me.$el\n",
-       "                        .draggable({stop: function() { me.clipBounds(); }})\n",
-       "                        .css({\n",
-       "                            left: window.innerWidth - me.$el.width() - 15,\n",
-       "                            top: window.innerHeight - me.$el.height() - 10\n",
-       "                        });\n",
-       "                }\n",
-       "\n",
-       "                // any previous highlighting is now moot\n",
-       "                me.$el.removeClass('qcodes-highlight');\n",
-       "            }, 0);\n",
-       "\n",
-       "        },\n",
-       "\n",
-       "        clipBounds: function() {\n",
-       "            var me = this;\n",
-       "            if(me.$el.attr('qcodes-state') === 'floated') {\n",
-       "                var bounds = me.$el[0].getBoundingClientRect(),\n",
-       "                    minVis = 40,\n",
-       "                    maxLeft = window.innerWidth - minVis,\n",
-       "                    minLeft = minVis - bounds.width,\n",
-       "                    maxTop = window.innerHeight - minVis;\n",
-       "\n",
-       "                if(bounds.left > maxLeft) me.$el.css('left', maxLeft);\n",
-       "                else if(bounds.left < minLeft) me.$el.css('left', minLeft);\n",
-       "\n",
-       "                if(bounds.top > maxTop) me.$el.css('top', maxTop);\n",
-       "                else if(bounds.top < 0) me.$el.css('top', 0);\n",
-       "            }\n",
-       "        },\n",
-       "\n",
-       "        display: function(message) {\n",
-       "            var me = this;\n",
-       "            if(message) {\n",
-       "                var initialScroll = me.outputArea.scrollTop();\n",
-       "                me.outputArea.scrollTop(me.outputArea.prop('scrollHeight'));\n",
-       "                var scrollBottom = me.outputArea.scrollTop();\n",
-       "\n",
-       "                if(me.$el.attr('qcodes-state') === 'minimized') {\n",
-       "                    // if we add text and the box is minimized, highlight the\n",
-       "                    // title bar to alert the user that there are new messages.\n",
-       "                    // remove then add the class, so we get the animation again\n",
-       "                    // if it's already highlighted\n",
-       "                    me.$el.removeClass('qcodes-highlight');\n",
-       "                    setTimeout(function(){\n",
-       "                        me.$el.addClass('qcodes-highlight');\n",
-       "                    }, 0);\n",
-       "                }\n",
-       "\n",
-       "                var newLines = message.split('\\n'),\n",
-       "                    out = me.outputLines,\n",
-       "                    outLen = out.length;\n",
-       "                if(outLen) out[outLen - 1] += newLines[0];\n",
-       "                else out.push(newLines[0]);\n",
-       "\n",
-       "                for(var i = 1; i < newLines.length; i++) {\n",
-       "                    out.push(newLines[i]);\n",
-       "                }\n",
-       "\n",
-       "                if(out.length > me.maxOutputLength) {\n",
-       "                    out.splice(0, out.length - me.maxOutputLength + 1,\n",
-       "                        '<<< Output clipped >>>');\n",
-       "                }\n",
-       "\n",
-       "                me.outputArea.text(out.join('\\n'));\n",
-       "                me.clearButton.removeClass('disabled');\n",
-       "\n",
-       "                // if we were scrolled to the bottom initially, make sure\n",
-       "                // we stay that way.\n",
-       "                me.outputArea.scrollTop(initialScroll === scrollBottom ?\n",
-       "                    me.outputArea.prop('scrollHeight') : initialScroll);\n",
-       "            }\n",
-       "\n",
-       "            me.showSubprocesses();\n",
-       "            me.updateState();\n",
-       "        },\n",
-       "\n",
-       "        showSubprocesses: function() {\n",
-       "            var me = this,\n",
-       "                replacer = me.subprocessesMultiline ? '<br>' : ', ',\n",
-       "                processes = (me.model.get('_processes') || '')\n",
-       "                    .replace(/\\n/g, '&gt;' + replacer + '&lt;');\n",
-       "\n",
-       "            if(processes) processes = '&lt;' + processes + '&gt;';\n",
-       "            else processes = 'No subprocesses';\n",
-       "\n",
-       "            me.abortButton.toggleClass('disabled', processes.indexOf('Measurement')===-1);\n",
-       "\n",
-       "            me.subprocessList.html(processes);\n",
-       "        }\n",
-       "    });\n",
-       "    manager.WidgetManager.register_widget_view('SubprocessView', SubprocessView);\n",
-       "});\n"
-      ],
-      "text/plain": [
-       "<IPython.core.display.Javascript object>"
-      ]
-     },
-     "metadata": {},
-     "output_type": "display_data"
-    },
-    {
-     "data": {
-      "text/html": [
-       "<style>.qcodes-output-view:not(.ui-draggable) {\n",
-       "    bottom: 0;\n",
-       "    right: 5px;\n",
-       "}\n",
-       ".qcodes-output-view {\n",
-       "    position: fixed;\n",
-       "    z-index: 999;\n",
-       "    background-color: #fff;\n",
-       "    box-shadow: 0 0 12px 1px rgba(87, 87, 87, 0.2);\n",
-       "}\n",
-       "\n",
-       ".qcodes-output-header {\n",
-       "    float: right;\n",
-       "}\n",
-       "\n",
-       ".qcodes-highlight {\n",
-       "    animation: pulse 1s linear;\n",
-       "    background-color: #fa4;\n",
-       "}\n",
-       "\n",
-       "@keyframes pulse {\n",
-       "    0% {\n",
-       "        background-color: #f00;\n",
-       "    }\n",
-       "    100% {\n",
-       "        background-color: #fa4;\n",
-       "    }\n",
-       "}\n",
-       "\n",
-       ".qcodes-process-list {\n",
-       "    float: left;\n",
-       "    max-width: 780px;\n",
-       "    margin: 3px 5px 3px 10px;\n",
-       "    overflow: hidden;\n",
-       "    white-space: nowrap;\n",
-       "    text-overflow: ellipsis;\n",
-       "}\n",
-       "\n",
-       ".qcodes-output-view[qcodes-state=minimized] .qcodes-process-list {\n",
-       "    max-width: 300px;\n",
-       "}\n",
-       "\n",
-       ".qcodes-output-view span {\n",
-       "    padding: 2px 6px 3px 12px;\n",
-       "}\n",
-       "\n",
-       ".qcodes-output-view .btn {\n",
-       "    margin: 0 3px 0 0;\n",
-       "}\n",
-       "\n",
-       ".qcodes-output-view[qcodes-state=docked] .qcodes-docked,\n",
-       ".qcodes-output-view[qcodes-state=floated] .qcodes-floated,\n",
-       ".qcodes-output-view[qcodes-state=minimized] .qcodes-minimized,\n",
-       ".qcodes-output-view[qcodes-state=minimized] .qcodes-content {\n",
-       "    display: none;\n",
-       "}\n",
-       "\n",
-       ".qcodes-output-view .disabled {\n",
-       "    opacity: 0.4;\n",
-       "}\n",
-       "\n",
-       ".qcodes-abort-loop {\n",
-       "    background-color: #844;\n",
-       "    color: #fff;\n",
-       "}\n",
-       "\n",
-       ".qcodes-output-view pre {\n",
-       "    clear: both;\n",
-       "    margin: 0;\n",
-       "    border: 0;\n",
-       "    border-top: 1px solid #ccc;\n",
-       "    background-color: #ffe;\n",
-       "    min-height: 50px;\n",
-       "    max-height: 400px;\n",
-       "    min-width: 400px;\n",
-       "    max-width: 1000px;\n",
-       "}</style>"
-      ],
-      "text/plain": [
-       "<IPython.core.display.HTML object>"
-      ]
-     },
-     "metadata": {},
-     "output_type": "display_data"
-    }
-   ],
+   "outputs": [],
    "source": [
-    "%matplotlib nbagg\n",
-    "import matplotlib.pyplot as plt\n",
-    "from pprint import pprint\n",
-    "import time\n",
-    "import numpy as np\n",
     "import qcodes as qc"
    ]
   },
   {
    "cell_type": "markdown",
-   "metadata": {},
+   "metadata": {
+    "deletable": true,
+    "editable": true
+   },
    "source": [
     "## Instantiates all the instruments needed for the demo"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 2,
+   "execution_count": null,
    "metadata": {
-    "collapsed": false
+    "collapsed": false,
+    "deletable": true,
+    "editable": true
    },
    "outputs": [],
    "source": [
-    "# spawn doesn't like function or class definitions in the interpreter\n",
-    "# session - had to move them to a file.\n",
-    "from toymodel import AModel, MockGates, MockSource, MockMeter, AverageGetter, AverageAndRaw\n",
+    "# import dummy driver for the tutorial\n",
+    "from qcodes.tests.instrument_mocks import DummyInstrument\n",
+    "from qcodes.instrument.mock import ArrayGetter\n",
     "\n",
-    "# now create this \"experiment\", note that all these are instruments \n",
-    "model = AModel()\n",
-    "gates = MockGates('gates', model=model)\n",
-    "source = MockSource('source', model=model)\n",
-    "meter = MockMeter('meter', model=model)\n",
+    "dac1 = DummyInstrument(name=\"dac\")\n",
+    "dac2 = DummyInstrument(name=\"dac2\")\n",
+    "# the default dummy instrument returns always a constant value, in the following line we make it random \n",
+    "# just for the looks 💅\n",
+    "import random\n",
+    "dac2.dac2.get =  lambda: random.randint(0,100)\n",
     "\n",
     "# The station is a container for all instruments that makes it easy \n",
     "# to log meta-data\n",
-    "station = qc.Station(gates, source, meter)\n",
-    "\n",
-    "# it's nice to have the key parameters be part of the global namespace\n",
-    "# that way they're objects that we can easily set, get, and slice\n",
-    "c0, c1, c2, vsd = gates.chan0, gates.chan1, gates.chan2, source.amplitude"
+    "station = qc.Station(dac1, dac2)"
    ]
   },
   {
    "cell_type": "markdown",
-   "metadata": {},
+   "metadata": {
+    "deletable": true,
+    "editable": true
+   },
    "source": [
     "### The location provider can be set globally "
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 3,
+   "execution_count": null,
    "metadata": {
-    "collapsed": true
+    "collapsed": true,
+    "deletable": true,
+    "editable": true
    },
    "outputs": [],
    "source": [
-    "# dm = qc.data.manager.get_data_manager()\n",
     "loc_provider = qc.data.location.FormatLocation(fmt='data/{date}/#{counter}_{name}_{time}')\n",
     "qc.data.data_set.DataSet.location_provider=loc_provider"
    ]
   },
   {
    "cell_type": "markdown",
-   "metadata": {},
+   "metadata": {
+    "deletable": true,
+    "editable": true
+   },
    "source": [
     "# Running an experiment \n",
     "\n",
@@ -437,148 +112,40 @@
     "\n",
     "Before you run a measurement loop you do two things:\n",
     "1. You describe what parameter(s) to vary and how. This is the creation of a `Loop` object: `loop = Loop(sweep_values, ...)`\n",
-    "2. You describe what to do at each step in the loop. This is `loop.each(*actions)` which converts the `Loop` object into an `ActiveLoop` object. Actions can be:\n",
+    "2. You describe what to do at each step in the loop. This is `loop.each(*actions)` \n",
     "  - measurements (any object with a `.get` method will be interpreted as a measurement)\n",
     "  - `Task`: some callable (which can have arguments with it) to be executed each time through the loop. Does not generate data.\n",
     "  - `Wait`: a specialized `Task` just to wait a certain time.\n",
-    "  - `BreakIf`: some condition that, if it returns truthy, breaks (this level of) the loop\n",
-    "  - Another `ActiveLoop` to nest inside the outer one.\n",
-    "\n",
-    "For more details, see issue #232 docs: Write bigger picture"
+    "  - `BreakIf`: some condition that, if it returns truthy, breaks (this level of) the loop"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 4,
+   "execution_count": null,
    "metadata": {
-    "collapsed": false
+    "collapsed": true,
+    "deletable": true,
+    "editable": true
    },
-   "outputs": [
-    {
-     "name": "stderr",
-     "output_type": "stream",
-     "text": [
-      "WARNING:root:negative delay -0.001849 sec\n"
-     ]
-    },
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "DataSet:\n",
-      "   mode     = DataMode.LOCAL\n",
-      "   location = 'data/2016-11-08/#024_testsweep_13-29-04'\n",
-      "   <Type>   | <array_id>      | <array.name> | <array.shape>\n",
-      "   Setpoint | gates_chan0_set | chan0        | (201,)\n",
-      "   Measured | meter_amplitude | amplitude    | (201,)\n",
-      "started at 2016-11-08 13:29:23\n"
-     ]
-    }
-   ],
-   "source": [
-    "# Notice that one can use an explicit location and `overwrite=True` here so that\n",
-    "# running this notebook over and over won't result in extra files.\n",
-    "# If you leave these out, you get a new timestamped DataSet each time.\n",
-    "\n",
-    "\n",
-    "loop = qc.Loop(c0.sweep(0,20,0.1), delay=0.001).each(meter.amplitude)\n",
-    "data = loop.get_data_set(name='testsweep')\n",
-    "plot = qc.QtPlot()\n",
-    "plot.add(data.meter_amplitude)\n",
-    "_ = loop.with_bg_task(plot.update, plot.save).run()"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "## Output of the loop\n",
-    "Notice the **\"DataSet\"**.  \n",
-    "A loop returns a dataset.  \n",
-    "The representation of the dataset shows what arrays it contains and where it is saved.   \n",
-    "The dataset initially starts out empty (filled with NAN's) and get's filled while the Loop get's executed. "
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
+   "outputs": [],
    "source": [
-    "Once the measurement is done, take a look at the file in finder/explorer (the dataset.location should give you the relative path). \n",
-    "Note also the snapshot that captures the settings of all instruments at the start of the Loop. \n",
-    "This metadata is also accesible from the dataset and captures a snapshot of each instrument listed in the station. "
+    "loop = qc.Loop(dac1.dac1.sweep(0,20,0.1), delay=0.001).each(dac2.dac2)\n",
+    "data = loop.get_data_set(name='testsweep')"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 5,
+   "execution_count": null,
    "metadata": {
-    "collapsed": false
+    "collapsed": false,
+    "deletable": true,
+    "editable": true
    },
-   "outputs": [
-    {
-     "data": {
-      "text/plain": [
-       "{'__class__': 'toymodel.MockMeter',\n",
-       " 'functions': {},\n",
-       " 'name': 'meter',\n",
-       " 'parameters': {'IDN': {'__class__': 'qcodes.instrument.parameter.StandardParameter',\n",
-       "   'instrument': 'toymodel.MockMeter',\n",
-       "   'instrument_name': 'meter',\n",
-       "   'label': 'IDN',\n",
-       "   'name': 'IDN',\n",
-       "   'ts': '2016-11-08 13:29:02',\n",
-       "   'units': '',\n",
-       "   'value': {'firmware': None,\n",
-       "    'model': 'MockMeter',\n",
-       "    'serial': 'meter',\n",
-       "    'vendor': None}},\n",
-       "  'amplitude': {'__class__': 'qcodes.instrument.parameter.StandardParameter',\n",
-       "   'instrument': 'toymodel.MockMeter',\n",
-       "   'instrument_name': 'meter',\n",
-       "   'label': 'Current (nA)',\n",
-       "   'name': 'amplitude',\n",
-       "   'ts': '2016-11-08 13:29:23',\n",
-       "   'units': '',\n",
-       "   'value': 0.117}}}"
-      ]
-     },
-     "execution_count": 5,
-     "metadata": {},
-     "output_type": "execute_result"
-    }
-   ],
-   "source": [
-    "meter.snapshot()"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "## Plotting the loop  II\n",
-    "\n",
-    "QCodes supports both matplotlib inline plotting and pyqtgraph for plotting. \n",
-    "For a comparison see http://pyqtgraph.org/ (actually not that biased)"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "The same API works for plotting a measured dataset or an old  dataset."
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
+   "outputs": [],
    "source": [
-    "`DataSet` objects are not intended to be instantiated directly, but\n",
-    "rather through the helper functions:\n",
-    "- `load_data` for existing data sets, including the data currently\n",
-    "  being acquired.\n",
-    "- `new_data` to make an empty data set to be populated with new\n",
-    "  measurements or simulation data. `new_data` is called internally by\n",
-    "  `Loop.run()` so is also generally not needed directly."
+    "plot = qc.QtPlot()\n",
+    "plot.add(data.dac2_dac2)\n",
+    "_ = loop.with_bg_task(plot.update, plot.save).run()"
    ]
   },
   {
@@ -586,1024 +153,130 @@
    "execution_count": null,
    "metadata": {
     "collapsed": false,
-    "scrolled": false
+    "deletable": true,
+    "editable": true
    },
    "outputs": [],
    "source": [
-    "loaded_data = qc.load_data(\"data/2016-10-10/#002_testsweep_10-08-32\")\n",
-    "plot = qc.MatPlot(loaded_data.meter_amplitude)"
+    "plot"
    ]
   },
   {
    "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "## Example: multiple 2D measurements with live plotting"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 6,
    "metadata": {
-    "collapsed": true
+    "deletable": true,
+    "editable": true
    },
-   "outputs": [],
    "source": [
-    "loop = qc.Loop(c1[-15:15:1], 0.01).loop(c0[-15:12:.5], 0.001).each(\n",
-    "    meter.amplitude, # first measurement, at c2=0 -> amplitude_0 bcs it's action 0\n",
-    "    qc.Task(c2.set, 1), # action 1 -> c2.set(1)\n",
-    "    qc.Wait(0.001),\n",
-    "    meter.amplitude, # second measurement, at c2=1 -> amplitude_4 bcs it's action 4\n",
-    "    qc.Task(c2.set, 0)\n",
-    "    )\n",
-    "data = loop.get_data_set(name='2D_test')"
+    "## Output of the loop\n",
+    "A loop returns a dataset.  \n",
+    "The representation of the dataset shows what arrays it contains and where it is saved.   \n",
+    "The dataset initially starts out empty (filled with NAN's) and get's filled while the Loop get's executed. "
    ]
   },
   {
    "cell_type": "markdown",
-   "metadata": {},
+   "metadata": {
+    "deletable": true,
+    "editable": true
+   },
    "source": [
-    "### Plot with matplotlib "
+    "Once the measurement is done, take a look at the file in finder/explorer (the dataset.location should give you the relative path). \n",
+    "Note also the snapshot that captures the settings of all instruments at the start of the Loop. \n",
+    "This metadata is also accesible from the dataset and captures a snapshot of each instrument listed in the station. "
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 7,
+   "execution_count": null,
    "metadata": {
     "collapsed": false,
-    "scrolled": false
+    "deletable": true,
+    "editable": true
    },
-   "outputs": [
-    {
-     "data": {
-      "application/javascript": [
-       "/* Put everything inside the global mpl namespace */\n",
-       "window.mpl = {};\n",
-       "\n",
-       "mpl.get_websocket_type = function() {\n",
-       "    if (typeof(WebSocket) !== 'undefined') {\n",
-       "        return WebSocket;\n",
-       "    } else if (typeof(MozWebSocket) !== 'undefined') {\n",
-       "        return MozWebSocket;\n",
-       "    } else {\n",
-       "        alert('Your browser does not have WebSocket support.' +\n",
-       "              'Please try Chrome, Safari or Firefox ≥ 6. ' +\n",
-       "              'Firefox 4 and 5 are also supported but you ' +\n",
-       "              'have to enable WebSockets in about:config.');\n",
-       "    };\n",
-       "}\n",
-       "\n",
-       "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n",
-       "    this.id = figure_id;\n",
-       "\n",
-       "    this.ws = websocket;\n",
-       "\n",
-       "    this.supports_binary = (this.ws.binaryType != undefined);\n",
-       "\n",
-       "    if (!this.supports_binary) {\n",
-       "        var warnings = document.getElementById(\"mpl-warnings\");\n",
-       "        if (warnings) {\n",
-       "            warnings.style.display = 'block';\n",
-       "            warnings.textContent = (\n",
-       "                \"This browser does not support binary websocket messages. \" +\n",
-       "                    \"Performance may be slow.\");\n",
-       "        }\n",
-       "    }\n",
-       "\n",
-       "    this.imageObj = new Image();\n",
-       "\n",
-       "    this.context = undefined;\n",
-       "    this.message = undefined;\n",
-       "    this.canvas = undefined;\n",
-       "    this.rubberband_canvas = undefined;\n",
-       "    this.rubberband_context = undefined;\n",
-       "    this.format_dropdown = undefined;\n",
-       "\n",
-       "    this.image_mode = 'full';\n",
-       "\n",
-       "    this.root = $('<div/>');\n",
-       "    this._root_extra_style(this.root)\n",
-       "    this.root.attr('style', 'display: inline-block');\n",
-       "\n",
-       "    $(parent_element).append(this.root);\n",
-       "\n",
-       "    this._init_header(this);\n",
-       "    this._init_canvas(this);\n",
-       "    this._init_toolbar(this);\n",
-       "\n",
-       "    var fig = this;\n",
-       "\n",
-       "    this.waiting = false;\n",
-       "\n",
-       "    this.ws.onopen =  function () {\n",
-       "            fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n",
-       "            fig.send_message(\"send_image_mode\", {});\n",
-       "            fig.send_message(\"refresh\", {});\n",
-       "        }\n",
-       "\n",
-       "    this.imageObj.onload = function() {\n",
-       "            if (fig.image_mode == 'full') {\n",
-       "                // Full images could contain transparency (where diff images\n",
-       "                // almost always do), so we need to clear the canvas so that\n",
-       "                // there is no ghosting.\n",
-       "                fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n",
-       "            }\n",
-       "            fig.context.drawImage(fig.imageObj, 0, 0);\n",
-       "        };\n",
-       "\n",
-       "    this.imageObj.onunload = function() {\n",
-       "        this.ws.close();\n",
-       "    }\n",
-       "\n",
-       "    this.ws.onmessage = this._make_on_message_function(this);\n",
-       "\n",
-       "    this.ondownload = ondownload;\n",
-       "}\n",
-       "\n",
-       "mpl.figure.prototype._init_header = function() {\n",
-       "    var titlebar = $(\n",
-       "        '<div class=\"ui-dialog-titlebar ui-widget-header ui-corner-all ' +\n",
-       "        'ui-helper-clearfix\"/>');\n",
-       "    var titletext = $(\n",
-       "        '<div class=\"ui-dialog-title\" style=\"width: 100%; ' +\n",
-       "        'text-align: center; padding: 3px;\"/>');\n",
-       "    titlebar.append(titletext)\n",
-       "    this.root.append(titlebar);\n",
-       "    this.header = titletext[0];\n",
-       "}\n",
-       "\n",
-       "\n",
-       "\n",
-       "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n",
-       "\n",
-       "}\n",
-       "\n",
-       "\n",
-       "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n",
-       "\n",
-       "}\n",
-       "\n",
-       "mpl.figure.prototype._init_canvas = function() {\n",
-       "    var fig = this;\n",
-       "\n",
-       "    var canvas_div = $('<div/>');\n",
-       "\n",
-       "    canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n",
-       "\n",
-       "    function canvas_keyboard_event(event) {\n",
-       "        return fig.key_event(event, event['data']);\n",
-       "    }\n",
-       "\n",
-       "    canvas_div.keydown('key_press', canvas_keyboard_event);\n",
-       "    canvas_div.keyup('key_release', canvas_keyboard_event);\n",
-       "    this.canvas_div = canvas_div\n",
-       "    this._canvas_extra_style(canvas_div)\n",
-       "    this.root.append(canvas_div);\n",
-       "\n",
-       "    var canvas = $('<canvas/>');\n",
-       "    canvas.addClass('mpl-canvas');\n",
-       "    canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n",
-       "\n",
-       "    this.canvas = canvas[0];\n",
-       "    this.context = canvas[0].getContext(\"2d\");\n",
-       "\n",
-       "    var rubberband = $('<canvas/>');\n",
-       "    rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n",
-       "\n",
-       "    var pass_mouse_events = true;\n",
-       "\n",
-       "    canvas_div.resizable({\n",
-       "        start: function(event, ui) {\n",
-       "            pass_mouse_events = false;\n",
-       "        },\n",
-       "        resize: function(event, ui) {\n",
-       "            fig.request_resize(ui.size.width, ui.size.height);\n",
-       "        },\n",
-       "        stop: function(event, ui) {\n",
-       "            pass_mouse_events = true;\n",
-       "            fig.request_resize(ui.size.width, ui.size.height);\n",
-       "        },\n",
-       "    });\n",
-       "\n",
-       "    function mouse_event_fn(event) {\n",
-       "        if (pass_mouse_events)\n",
-       "            return fig.mouse_event(event, event['data']);\n",
-       "    }\n",
-       "\n",
-       "    rubberband.mousedown('button_press', mouse_event_fn);\n",
-       "    rubberband.mouseup('button_release', mouse_event_fn);\n",
-       "    // Throttle sequential mouse events to 1 every 20ms.\n",
-       "    rubberband.mousemove('motion_notify', mouse_event_fn);\n",
-       "\n",
-       "    rubberband.mouseenter('figure_enter', mouse_event_fn);\n",
-       "    rubberband.mouseleave('figure_leave', mouse_event_fn);\n",
-       "\n",
-       "    canvas_div.on(\"wheel\", function (event) {\n",
-       "        event = event.originalEvent;\n",
-       "        event['data'] = 'scroll'\n",
-       "        if (event.deltaY < 0) {\n",
-       "            event.step = 1;\n",
-       "        } else {\n",
-       "            event.step = -1;\n",
-       "        }\n",
-       "        mouse_event_fn(event);\n",
-       "    });\n",
-       "\n",
-       "    canvas_div.append(canvas);\n",
-       "    canvas_div.append(rubberband);\n",
-       "\n",
-       "    this.rubberband = rubberband;\n",
-       "    this.rubberband_canvas = rubberband[0];\n",
-       "    this.rubberband_context = rubberband[0].getContext(\"2d\");\n",
-       "    this.rubberband_context.strokeStyle = \"#000000\";\n",
-       "\n",
-       "    this._resize_canvas = function(width, height) {\n",
-       "        // Keep the size of the canvas, canvas container, and rubber band\n",
-       "        // canvas in synch.\n",
-       "        canvas_div.css('width', width)\n",
-       "        canvas_div.css('height', height)\n",
-       "\n",
-       "        canvas.attr('width', width);\n",
-       "        canvas.attr('height', height);\n",
-       "\n",
-       "        rubberband.attr('width', width);\n",
-       "        rubberband.attr('height', height);\n",
-       "    }\n",
-       "\n",
-       "    // Set the figure to an initial 600x600px, this will subsequently be updated\n",
-       "    // upon first draw.\n",
-       "    this._resize_canvas(600, 600);\n",
-       "\n",
-       "    // Disable right mouse context menu.\n",
-       "    $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n",
-       "        return false;\n",
-       "    });\n",
-       "\n",
-       "    function set_focus () {\n",
-       "        canvas.focus();\n",
-       "        canvas_div.focus();\n",
-       "    }\n",
-       "\n",
-       "    window.setTimeout(set_focus, 100);\n",
-       "}\n",
-       "\n",
-       "mpl.figure.prototype._init_toolbar = function() {\n",
-       "    var fig = this;\n",
-       "\n",
-       "    var nav_element = $('<div/>')\n",
-       "    nav_element.attr('style', 'width: 100%');\n",
-       "    this.root.append(nav_element);\n",
-       "\n",
-       "    // Define a callback function for later on.\n",
-       "    function toolbar_event(event) {\n",
-       "        return fig.toolbar_button_onclick(event['data']);\n",
-       "    }\n",
-       "    function toolbar_mouse_event(event) {\n",
-       "        return fig.toolbar_button_onmouseover(event['data']);\n",
-       "    }\n",
-       "\n",
-       "    for(var toolbar_ind in mpl.toolbar_items) {\n",
-       "        var name = mpl.toolbar_items[toolbar_ind][0];\n",
-       "        var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
-       "        var image = mpl.toolbar_items[toolbar_ind][2];\n",
-       "        var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
-       "\n",
-       "        if (!name) {\n",
-       "            // put a spacer in here.\n",
-       "            continue;\n",
-       "        }\n",
-       "        var button = $('<button/>');\n",
-       "        button.addClass('ui-button ui-widget ui-state-default ui-corner-all ' +\n",
-       "                        'ui-button-icon-only');\n",
-       "        button.attr('role', 'button');\n",
-       "        button.attr('aria-disabled', 'false');\n",
-       "        button.click(method_name, toolbar_event);\n",
-       "        button.mouseover(tooltip, toolbar_mouse_event);\n",
-       "\n",
-       "        var icon_img = $('<span/>');\n",
-       "        icon_img.addClass('ui-button-icon-primary ui-icon');\n",
-       "        icon_img.addClass(image);\n",
-       "        icon_img.addClass('ui-corner-all');\n",
-       "\n",
-       "        var tooltip_span = $('<span/>');\n",
-       "        tooltip_span.addClass('ui-button-text');\n",
-       "        tooltip_span.html(tooltip);\n",
-       "\n",
-       "        button.append(icon_img);\n",
-       "        button.append(tooltip_span);\n",
-       "\n",
-       "        nav_element.append(button);\n",
-       "    }\n",
-       "\n",
-       "    var fmt_picker_span = $('<span/>');\n",
-       "\n",
-       "    var fmt_picker = $('<select/>');\n",
-       "    fmt_picker.addClass('mpl-toolbar-option ui-widget ui-widget-content');\n",
-       "    fmt_picker_span.append(fmt_picker);\n",
-       "    nav_element.append(fmt_picker_span);\n",
-       "    this.format_dropdown = fmt_picker[0];\n",
-       "\n",
-       "    for (var ind in mpl.extensions) {\n",
-       "        var fmt = mpl.extensions[ind];\n",
-       "        var option = $(\n",
-       "            '<option/>', {selected: fmt === mpl.default_extension}).html(fmt);\n",
-       "        fmt_picker.append(option)\n",
-       "    }\n",
-       "\n",
-       "    // Add hover states to the ui-buttons\n",
-       "    $( \".ui-button\" ).hover(\n",
-       "        function() { $(this).addClass(\"ui-state-hover\");},\n",
-       "        function() { $(this).removeClass(\"ui-state-hover\");}\n",
-       "    );\n",
-       "\n",
-       "    var status_bar = $('<span class=\"mpl-message\"/>');\n",
-       "    nav_element.append(status_bar);\n",
-       "    this.message = status_bar[0];\n",
-       "}\n",
-       "\n",
-       "mpl.figure.prototype.request_resize = function(x_pixels, y_pixels) {\n",
-       "    // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n",
-       "    // which will in turn request a refresh of the image.\n",
-       "    this.send_message('resize', {'width': x_pixels, 'height': y_pixels});\n",
-       "}\n",
-       "\n",
-       "mpl.figure.prototype.send_message = function(type, properties) {\n",
-       "    properties['type'] = type;\n",
-       "    properties['figure_id'] = this.id;\n",
-       "    this.ws.send(JSON.stringify(properties));\n",
-       "}\n",
-       "\n",
-       "mpl.figure.prototype.send_draw_message = function() {\n",
-       "    if (!this.waiting) {\n",
-       "        this.waiting = true;\n",
-       "        this.ws.send(JSON.stringify({type: \"draw\", figure_id: this.id}));\n",
-       "    }\n",
-       "}\n",
-       "\n",
-       "\n",
-       "mpl.figure.prototype.handle_save = function(fig, msg) {\n",
-       "    var format_dropdown = fig.format_dropdown;\n",
-       "    var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n",
-       "    fig.ondownload(fig, format);\n",
-       "}\n",
-       "\n",
-       "\n",
-       "mpl.figure.prototype.handle_resize = function(fig, msg) {\n",
-       "    var size = msg['size'];\n",
-       "    if (size[0] != fig.canvas.width || size[1] != fig.canvas.height) {\n",
-       "        fig._resize_canvas(size[0], size[1]);\n",
-       "        fig.send_message(\"refresh\", {});\n",
-       "    };\n",
-       "}\n",
-       "\n",
-       "mpl.figure.prototype.handle_rubberband = function(fig, msg) {\n",
-       "    var x0 = msg['x0'];\n",
-       "    var y0 = fig.canvas.height - msg['y0'];\n",
-       "    var x1 = msg['x1'];\n",
-       "    var y1 = fig.canvas.height - msg['y1'];\n",
-       "    x0 = Math.floor(x0) + 0.5;\n",
-       "    y0 = Math.floor(y0) + 0.5;\n",
-       "    x1 = Math.floor(x1) + 0.5;\n",
-       "    y1 = Math.floor(y1) + 0.5;\n",
-       "    var min_x = Math.min(x0, x1);\n",
-       "    var min_y = Math.min(y0, y1);\n",
-       "    var width = Math.abs(x1 - x0);\n",
-       "    var height = Math.abs(y1 - y0);\n",
-       "\n",
-       "    fig.rubberband_context.clearRect(\n",
-       "        0, 0, fig.canvas.width, fig.canvas.height);\n",
-       "\n",
-       "    fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n",
-       "}\n",
-       "\n",
-       "mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n",
-       "    // Updates the figure title.\n",
-       "    fig.header.textContent = msg['label'];\n",
-       "}\n",
-       "\n",
-       "mpl.figure.prototype.handle_cursor = function(fig, msg) {\n",
-       "    var cursor = msg['cursor'];\n",
-       "    switch(cursor)\n",
-       "    {\n",
-       "    case 0:\n",
-       "        cursor = 'pointer';\n",
-       "        break;\n",
-       "    case 1:\n",
-       "        cursor = 'default';\n",
-       "        break;\n",
-       "    case 2:\n",
-       "        cursor = 'crosshair';\n",
-       "        break;\n",
-       "    case 3:\n",
-       "        cursor = 'move';\n",
-       "        break;\n",
-       "    }\n",
-       "    fig.rubberband_canvas.style.cursor = cursor;\n",
-       "}\n",
-       "\n",
-       "mpl.figure.prototype.handle_message = function(fig, msg) {\n",
-       "    fig.message.textContent = msg['message'];\n",
-       "}\n",
-       "\n",
-       "mpl.figure.prototype.handle_draw = function(fig, msg) {\n",
-       "    // Request the server to send over a new figure.\n",
-       "    fig.send_draw_message();\n",
-       "}\n",
-       "\n",
-       "mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n",
-       "    fig.image_mode = msg['mode'];\n",
-       "}\n",
-       "\n",
-       "mpl.figure.prototype.updated_canvas_event = function() {\n",
-       "    // Called whenever the canvas gets updated.\n",
-       "    this.send_message(\"ack\", {});\n",
-       "}\n",
-       "\n",
-       "// A function to construct a web socket function for onmessage handling.\n",
-       "// Called in the figure constructor.\n",
-       "mpl.figure.prototype._make_on_message_function = function(fig) {\n",
-       "    return function socket_on_message(evt) {\n",
-       "        if (evt.data instanceof Blob) {\n",
-       "            /* FIXME: We get \"Resource interpreted as Image but\n",
-       "             * transferred with MIME type text/plain:\" errors on\n",
-       "             * Chrome.  But how to set the MIME type?  It doesn't seem\n",
-       "             * to be part of the websocket stream */\n",
-       "            evt.data.type = \"image/png\";\n",
-       "\n",
-       "            /* Free the memory for the previous frames */\n",
-       "            if (fig.imageObj.src) {\n",
-       "                (window.URL || window.webkitURL).revokeObjectURL(\n",
-       "                    fig.imageObj.src);\n",
-       "            }\n",
-       "\n",
-       "            fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
-       "                evt.data);\n",
-       "            fig.updated_canvas_event();\n",
-       "            fig.waiting = false;\n",
-       "            return;\n",
-       "        }\n",
-       "        else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n",
-       "            fig.imageObj.src = evt.data;\n",
-       "            fig.updated_canvas_event();\n",
-       "            fig.waiting = false;\n",
-       "            return;\n",
-       "        }\n",
-       "\n",
-       "        var msg = JSON.parse(evt.data);\n",
-       "        var msg_type = msg['type'];\n",
-       "\n",
-       "        // Call the  \"handle_{type}\" callback, which takes\n",
-       "        // the figure and JSON message as its only arguments.\n",
-       "        try {\n",
-       "            var callback = fig[\"handle_\" + msg_type];\n",
-       "        } catch (e) {\n",
-       "            console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n",
-       "            return;\n",
-       "        }\n",
-       "\n",
-       "        if (callback) {\n",
-       "            try {\n",
-       "                // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n",
-       "                callback(fig, msg);\n",
-       "            } catch (e) {\n",
-       "                console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n",
-       "            }\n",
-       "        }\n",
-       "    };\n",
-       "}\n",
-       "\n",
-       "// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n",
-       "mpl.findpos = function(e) {\n",
-       "    //this section is from http://www.quirksmode.org/js/events_properties.html\n",
-       "    var targ;\n",
-       "    if (!e)\n",
-       "        e = window.event;\n",
-       "    if (e.target)\n",
-       "        targ = e.target;\n",
-       "    else if (e.srcElement)\n",
-       "        targ = e.srcElement;\n",
-       "    if (targ.nodeType == 3) // defeat Safari bug\n",
-       "        targ = targ.parentNode;\n",
-       "\n",
-       "    // jQuery normalizes the pageX and pageY\n",
-       "    // pageX,Y are the mouse positions relative to the document\n",
-       "    // offset() returns the position of the element relative to the document\n",
-       "    var x = e.pageX - $(targ).offset().left;\n",
-       "    var y = e.pageY - $(targ).offset().top;\n",
-       "\n",
-       "    return {\"x\": x, \"y\": y};\n",
-       "};\n",
-       "\n",
-       "/*\n",
-       " * return a copy of an object with only non-object keys\n",
-       " * we need this to avoid circular references\n",
-       " * http://stackoverflow.com/a/24161582/3208463\n",
-       " */\n",
-       "function simpleKeys (original) {\n",
-       "  return Object.keys(original).reduce(function (obj, key) {\n",
-       "    if (typeof original[key] !== 'object')\n",
-       "        obj[key] = original[key]\n",
-       "    return obj;\n",
-       "  }, {});\n",
-       "}\n",
-       "\n",
-       "mpl.figure.prototype.mouse_event = function(event, name) {\n",
-       "    var canvas_pos = mpl.findpos(event)\n",
-       "\n",
-       "    if (name === 'button_press')\n",
-       "    {\n",
-       "        this.canvas.focus();\n",
-       "        this.canvas_div.focus();\n",
-       "    }\n",
-       "\n",
-       "    var x = canvas_pos.x;\n",
-       "    var y = canvas_pos.y;\n",
-       "\n",
-       "    this.send_message(name, {x: x, y: y, button: event.button,\n",
-       "                             step: event.step,\n",
-       "                             guiEvent: simpleKeys(event)});\n",
-       "\n",
-       "    /* This prevents the web browser from automatically changing to\n",
-       "     * the text insertion cursor when the button is pressed.  We want\n",
-       "     * to control all of the cursor setting manually through the\n",
-       "     * 'cursor' event from matplotlib */\n",
-       "    event.preventDefault();\n",
-       "    return false;\n",
-       "}\n",
-       "\n",
-       "mpl.figure.prototype._key_event_extra = function(event, name) {\n",
-       "    // Handle any extra behaviour associated with a key event\n",
-       "}\n",
-       "\n",
-       "mpl.figure.prototype.key_event = function(event, name) {\n",
-       "\n",
-       "    // Prevent repeat events\n",
-       "    if (name == 'key_press')\n",
-       "    {\n",
-       "        if (event.which === this._key)\n",
-       "            return;\n",
-       "        else\n",
-       "            this._key = event.which;\n",
-       "    }\n",
-       "    if (name == 'key_release')\n",
-       "        this._key = null;\n",
-       "\n",
-       "    var value = '';\n",
-       "    if (event.ctrlKey && event.which != 17)\n",
-       "        value += \"ctrl+\";\n",
-       "    if (event.altKey && event.which != 18)\n",
-       "        value += \"alt+\";\n",
-       "    if (event.shiftKey && event.which != 16)\n",
-       "        value += \"shift+\";\n",
-       "\n",
-       "    value += 'k';\n",
-       "    value += event.which.toString();\n",
-       "\n",
-       "    this._key_event_extra(event, name);\n",
-       "\n",
-       "    this.send_message(name, {key: value,\n",
-       "                             guiEvent: simpleKeys(event)});\n",
-       "    return false;\n",
-       "}\n",
-       "\n",
-       "mpl.figure.prototype.toolbar_button_onclick = function(name) {\n",
-       "    if (name == 'download') {\n",
-       "        this.handle_save(this, null);\n",
-       "    } else {\n",
-       "        this.send_message(\"toolbar_button\", {name: name});\n",
-       "    }\n",
-       "};\n",
-       "\n",
-       "mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n",
-       "    this.message.textContent = tooltip;\n",
-       "};\n",
-       "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to  previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n",
-       "\n",
-       "mpl.extensions = [\"eps\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\"];\n",
-       "\n",
-       "mpl.default_extension = \"png\";var comm_websocket_adapter = function(comm) {\n",
-       "    // Create a \"websocket\"-like object which calls the given IPython comm\n",
-       "    // object with the appropriate methods. Currently this is a non binary\n",
-       "    // socket, so there is still some room for performance tuning.\n",
-       "    var ws = {};\n",
-       "\n",
-       "    ws.close = function() {\n",
-       "        comm.close()\n",
-       "    };\n",
-       "    ws.send = function(m) {\n",
-       "        //console.log('sending', m);\n",
-       "        comm.send(m);\n",
-       "    };\n",
-       "    // Register the callback with on_msg.\n",
-       "    comm.on_msg(function(msg) {\n",
-       "        //console.log('receiving', msg['content']['data'], msg);\n",
-       "        // Pass the mpl event to the overriden (by mpl) onmessage function.\n",
-       "        ws.onmessage(msg['content']['data'])\n",
-       "    });\n",
-       "    return ws;\n",
-       "}\n",
-       "\n",
-       "mpl.mpl_figure_comm = function(comm, msg) {\n",
-       "    // This is the function which gets called when the mpl process\n",
-       "    // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
-       "\n",
-       "    var id = msg.content.data.id;\n",
-       "    // Get hold of the div created by the display call when the Comm\n",
-       "    // socket was opened in Python.\n",
-       "    var element = $(\"#\" + id);\n",
-       "    var ws_proxy = comm_websocket_adapter(comm)\n",
-       "\n",
-       "    function ondownload(figure, format) {\n",
-       "        window.open(figure.imageObj.src);\n",
-       "    }\n",
-       "\n",
-       "    var fig = new mpl.figure(id, ws_proxy,\n",
-       "                           ondownload,\n",
-       "                           element.get(0));\n",
-       "\n",
-       "    // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n",
-       "    // web socket which is closed, not our websocket->open comm proxy.\n",
-       "    ws_proxy.onopen();\n",
-       "\n",
-       "    fig.parent_element = element.get(0);\n",
-       "    fig.cell_info = mpl.find_output_cell(\"<div id='\" + id + \"'></div>\");\n",
-       "    if (!fig.cell_info) {\n",
-       "        console.error(\"Failed to find cell for figure\", id, fig);\n",
-       "        return;\n",
-       "    }\n",
-       "\n",
-       "    var output_index = fig.cell_info[2]\n",
-       "    var cell = fig.cell_info[0];\n",
-       "\n",
-       "};\n",
-       "\n",
-       "mpl.figure.prototype.handle_close = function(fig, msg) {\n",
-       "    fig.root.unbind('remove')\n",
-       "\n",
-       "    // Update the output cell to use the data from the current canvas.\n",
-       "    fig.push_to_output();\n",
-       "    var dataURL = fig.canvas.toDataURL();\n",
-       "    // Re-enable the keyboard manager in IPython - without this line, in FF,\n",
-       "    // the notebook keyboard shortcuts fail.\n",
-       "    IPython.keyboard_manager.enable()\n",
-       "    $(fig.parent_element).html('<img src=\"' + dataURL + '\">');\n",
-       "    fig.close_ws(fig, msg);\n",
-       "}\n",
-       "\n",
-       "mpl.figure.prototype.close_ws = function(fig, msg){\n",
-       "    fig.send_message('closing', msg);\n",
-       "    // fig.ws.close()\n",
-       "}\n",
-       "\n",
-       "mpl.figure.prototype.push_to_output = function(remove_interactive) {\n",
-       "    // Turn the data on the canvas into data in the output cell.\n",
-       "    var dataURL = this.canvas.toDataURL();\n",
-       "    this.cell_info[1]['text/html'] = '<img src=\"' + dataURL + '\">';\n",
-       "}\n",
-       "\n",
-       "mpl.figure.prototype.updated_canvas_event = function() {\n",
-       "    // Tell IPython that the notebook contents must change.\n",
-       "    IPython.notebook.set_dirty(true);\n",
-       "    this.send_message(\"ack\", {});\n",
-       "    var fig = this;\n",
-       "    // Wait a second, then push the new image to the DOM so\n",
-       "    // that it is saved nicely (might be nice to debounce this).\n",
-       "    setTimeout(function () { fig.push_to_output() }, 1000);\n",
-       "}\n",
-       "\n",
-       "mpl.figure.prototype._init_toolbar = function() {\n",
-       "    var fig = this;\n",
-       "\n",
-       "    var nav_element = $('<div/>')\n",
-       "    nav_element.attr('style', 'width: 100%');\n",
-       "    this.root.append(nav_element);\n",
-       "\n",
-       "    // Define a callback function for later on.\n",
-       "    function toolbar_event(event) {\n",
-       "        return fig.toolbar_button_onclick(event['data']);\n",
-       "    }\n",
-       "    function toolbar_mouse_event(event) {\n",
-       "        return fig.toolbar_button_onmouseover(event['data']);\n",
-       "    }\n",
-       "\n",
-       "    for(var toolbar_ind in mpl.toolbar_items){\n",
-       "        var name = mpl.toolbar_items[toolbar_ind][0];\n",
-       "        var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
-       "        var image = mpl.toolbar_items[toolbar_ind][2];\n",
-       "        var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
-       "\n",
-       "        if (!name) { continue; };\n",
-       "\n",
-       "        var button = $('<button class=\"btn btn-default\" href=\"#\" title=\"' + name + '\"><i class=\"fa ' + image + ' fa-lg\"></i></button>');\n",
-       "        button.click(method_name, toolbar_event);\n",
-       "        button.mouseover(tooltip, toolbar_mouse_event);\n",
-       "        nav_element.append(button);\n",
-       "    }\n",
-       "\n",
-       "    // Add the status bar.\n",
-       "    var status_bar = $('<span class=\"mpl-message\" style=\"text-align:right; float: right;\"/>');\n",
-       "    nav_element.append(status_bar);\n",
-       "    this.message = status_bar[0];\n",
-       "\n",
-       "    // Add the close button to the window.\n",
-       "    var buttongrp = $('<div class=\"btn-group inline pull-right\"></div>');\n",
-       "    var button = $('<button class=\"btn btn-mini btn-primary\" href=\"#\" title=\"Stop Interaction\"><i class=\"fa fa-power-off icon-remove icon-large\"></i></button>');\n",
-       "    button.click(function (evt) { fig.handle_close(fig, {}); } );\n",
-       "    button.mouseover('Stop Interaction', toolbar_mouse_event);\n",
-       "    buttongrp.append(button);\n",
-       "    var titlebar = this.root.find($('.ui-dialog-titlebar'));\n",
-       "    titlebar.prepend(buttongrp);\n",
-       "}\n",
-       "\n",
-       "mpl.figure.prototype._root_extra_style = function(el){\n",
-       "    var fig = this\n",
-       "    el.on(\"remove\", function(){\n",
-       "\tfig.close_ws(fig, {});\n",
-       "    });\n",
-       "}\n",
-       "\n",
-       "mpl.figure.prototype._canvas_extra_style = function(el){\n",
-       "    // this is important to make the div 'focusable\n",
-       "    el.attr('tabindex', 0)\n",
-       "    // reach out to IPython and tell the keyboard manager to turn it's self\n",
-       "    // off when our div gets focus\n",
-       "\n",
-       "    // location in version 3\n",
-       "    if (IPython.notebook.keyboard_manager) {\n",
-       "        IPython.notebook.keyboard_manager.register_events(el);\n",
-       "    }\n",
-       "    else {\n",
-       "        // location in version 2\n",
-       "        IPython.keyboard_manager.register_events(el);\n",
-       "    }\n",
-       "\n",
-       "}\n",
-       "\n",
-       "mpl.figure.prototype._key_event_extra = function(event, name) {\n",
-       "    var manager = IPython.notebook.keyboard_manager;\n",
-       "    if (!manager)\n",
-       "        manager = IPython.keyboard_manager;\n",
-       "\n",
-       "    // Check for shift+enter\n",
-       "    if (event.shiftKey && event.which == 13) {\n",
-       "        this.canvas_div.blur();\n",
-       "        // select the cell after this one\n",
-       "        var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n",
-       "        IPython.notebook.select(index + 1);\n",
-       "    }\n",
-       "}\n",
-       "\n",
-       "mpl.figure.prototype.handle_save = function(fig, msg) {\n",
-       "    fig.ondownload(fig, null);\n",
-       "}\n",
-       "\n",
-       "\n",
-       "mpl.find_output_cell = function(html_output) {\n",
-       "    // Return the cell and output element which can be found *uniquely* in the notebook.\n",
-       "    // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n",
-       "    // IPython event is triggered only after the cells have been serialised, which for\n",
-       "    // our purposes (turning an active figure into a static one), is too late.\n",
-       "    var cells = IPython.notebook.get_cells();\n",
-       "    var ncells = cells.length;\n",
-       "    for (var i=0; i<ncells; i++) {\n",
-       "        var cell = cells[i];\n",
-       "        if (cell.cell_type === 'code'){\n",
-       "            for (var j=0; j<cell.output_area.outputs.length; j++) {\n",
-       "                var data = cell.output_area.outputs[j];\n",
-       "                if (data.data) {\n",
-       "                    // IPython >= 3 moved mimebundle to data attribute of output\n",
-       "                    data = data.data;\n",
-       "                }\n",
-       "                if (data['text/html'] == html_output) {\n",
-       "                    return [cell, data, j];\n",
-       "                }\n",
-       "            }\n",
-       "        }\n",
-       "    }\n",
-       "}\n",
-       "\n",
-       "// Register the function which deals with the matplotlib target/channel.\n",
-       "// The kernel may be null if the page has been refreshed.\n",
-       "if (IPython.notebook.kernel != null) {\n",
-       "    IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n",
-       "}\n"
-      ],
-      "text/plain": [
-       "<IPython.core.display.Javascript object>"
-      ]
-     },
-     "metadata": {},
-     "output_type": "display_data"
-    },
-    {
-     "data": {
-      "text/html": [
-       "<img src=\"data:image/png;base64,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\">"
-      ],
-      "text/plain": [
-       "<IPython.core.display.HTML object>"
-      ]
-     },
-     "metadata": {},
-     "output_type": "display_data"
-    },
-    {
-     "name": "stderr",
-     "output_type": "stream",
-     "text": [
-      "WARNING:root:negative delay -0.001320 sec\n"
-     ]
-    },
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "DataSet:\n",
-      "   mode     = DataMode.LOCAL\n",
-      "   location = 'data/2016-11-08/#025_2D_test_13-29-23'\n",
-      "   <Type>   | <array_id>        | <array.name> | <array.shape>\n",
-      "   Setpoint | gates_chan1_set   | chan1        | (30,)\n",
-      "   Setpoint | gates_chan0_set   | chan0        | (30, 54)\n",
-      "   Measured | meter_amplitude_0 | amplitude    | (30, 54)\n",
-      "   Measured | meter_amplitude_3 | amplitude    | (30, 54)\n",
-      "started at 2016-11-08 13:29:35\n"
-     ]
-    }
-   ],
+   "outputs": [],
    "source": [
-    "plot = qc.MatPlot(data.meter_amplitude_0, cmap=plt.cm.hot, figsize=(12, 4.5), subplots=(1, 2))\n",
-    "plot.add(data.meter_amplitude_3, cmap=plt.cm.hot, subplot=2)\n",
-    "data2 = loop.with_bg_task(plot.update, plot.save,  0.05).run()"
+    "dac2.snapshot()"
    ]
   },
   {
    "cell_type": "markdown",
-   "metadata": {},
+   "metadata": {
+    "deletable": true,
+    "editable": true
+   },
    "source": [
-    "### The equivalent in QtPlot"
+    "## Loading data"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 8,
+   "execution_count": null,
    "metadata": {
-    "collapsed": false
+    "collapsed": false,
+    "deletable": true,
+    "editable": true,
+    "scrolled": false
    },
-   "outputs": [
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "DataSet:\n",
-      "   mode     = DataMode.LOCAL\n",
-      "   location = 'data/2016-11-08/#026_2D_test_13-29-35'\n",
-      "   <Type>   | <array_id>        | <array.name> | <array.shape>\n",
-      "   Setpoint | gates_chan1_set   | chan1        | (30,)\n",
-      "   Setpoint | gates_chan0_set   | chan0        | (30, 54)\n",
-      "   Measured | meter_amplitude_0 | amplitude    | (30, 54)\n",
-      "   Measured | meter_amplitude_3 | amplitude    | (30, 54)\n",
-      "started at 2016-11-08 13:29:57\n"
-     ]
-    }
-   ],
+   "outputs": [],
    "source": [
-    "loop = qc.Loop(c1[-15:15:1], 0.01).loop(c0[-15:12:.5], 0.001).each(\n",
-    "    meter.amplitude, # first measurement, at c2=0 -> amplitude_0 bcs it's action 0\n",
-    "    qc.Task(c2.set, 1), # action 1 -> c2.set(1)\n",
-    "    qc.Wait(0.001),\n",
-    "    meter.amplitude, # second measurement, at c2=1 -> amplitude_4 bcs it's action 4\n",
-    "    qc.Task(c2.set, 0)\n",
-    "    )\n",
-    "data = loop.get_data_set(name='2D_test')\n",
-    "\n",
-    "plotQ = qc.QtPlot()\n",
-    "plotQ.add(data.meter_amplitude_0, figsize=(1200, 500))\n",
-    "plotQ.add(data.meter_amplitude_3, subplot=2)\n",
-    "data2 = loop.with_bg_task(plotQ.update, plotQ.save).run()"
+    "loaded_data = qc.load_data(\"location\")\n",
+    "plot = qc.MatPlot(loaded_data.array_id)"
    ]
   },
   {
    "cell_type": "markdown",
-   "metadata": {},
+   "metadata": {
+    "deletable": true,
+    "editable": true
+   },
    "source": [
-    "### Example same outer loop, different inner loop "
+    "## Example: multiple 2D measurements with live plotting"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 9,
+   "execution_count": null,
    "metadata": {
-    "collapsed": false
+    "collapsed": false,
+    "deletable": true,
+    "editable": true
    },
    "outputs": [],
    "source": [
-    "loop3 = qc.Loop(c1[-15:15:1], 0.1).each(\n",
-    "    qc.Task(c0.set, -10),\n",
-    "    qc.Task(c2.set, 0),\n",
-    "    # a 1D measurement\n",
-    "    meter.amplitude,\n",
-    "    # a 2D sweep, .each is actually unnecessary because this is the default measurement\n",
-    "    qc.Loop(c0[-15:15:1], 0.001).each(meter.amplitude),\n",
-    "    qc.Task(c0.set, -10),\n",
-    "    # a 2D sweep with the same outer but different inner loop\n",
-    "    qc.Loop(c2[-10:10:0.2], 0.001).each(meter.amplitude),\n",
-    "    AverageGetter(meter.amplitude, c2[-10:10:0.2], 0.001)\n",
-    ")\n",
-    "data = loop3.get_data_set(name='TwoD_different_inner_test') "
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "### several plots updating simultaneously (Currently broken on matplotlib)"
+    "loop = qc.Loop(dac1.dac1.sweep(0,5,1), 0.1).loop(dac1.dac2.sweep(0,5,1), 0.1).each(\n",
+    "    dac2.dac2\n",
+    "    )\n",
+    "data = loop.get_data_set(name='2D_test')"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 10,
+   "execution_count": null,
    "metadata": {
-    "collapsed": false
+    "collapsed": false,
+    "deletable": true,
+    "editable": true
    },
-   "outputs": [
-    {
-     "name": "stderr",
-     "output_type": "stream",
-     "text": [
-      "/home/unga/src/Qcodes/qcodes/plots/pyqtgraph.py:292: UserWarning: nonuniform nested setpoint array passed to pyqtgraph. ignoring, using default scaling.\n",
-      "  'nonuniform nested setpoint array passed to '\n"
-     ]
-    },
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "DataSet:\n",
-      "   mode     = DataMode.LOCAL\n",
-      "   location = 'data/2016-11-08/#027_TwoD_different_inner_test_13-29-57'\n",
-      "   <Type>   | <array_id>          | <array.name>  | <array.shape>\n",
-      "   Setpoint | gates_chan1_set     | chan1         | (30,)\n",
-      "   Measured | meter_amplitude_2   | amplitude     | (30,)\n",
-      "   Setpoint | gates_chan0_set     | chan0         | (30, 30)\n",
-      "   Measured | meter_amplitude_3_0 | amplitude     | (30, 30)\n",
-      "   Setpoint | gates_chan2_set     | chan2         | (30, 100)\n",
-      "   Measured | meter_amplitude_5_0 | amplitude     | (30, 100)\n",
-      "   Measured | meter_avg_amplitude | avg_amplitude | (30,)\n",
-      "started at 2016-11-08 13:30:32\n"
-     ]
-    }
-   ],
-   "source": [
-    "plotQ = qc.QtPlot()\n",
-    "plotQ.add(data.meter_amplitude_3_0)\n",
-    "plotQ.add(data.meter_amplitude_5_0, cmap='viridis', subplot=2)\n",
-    "plotQ.add(data.meter_avg_amplitude, subplot=3)\n",
-    "data = loop3.with_bg_task(plotQ.update, plotQ.save).run()"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
+   "outputs": [],
    "source": [
-    "### Example 2D scan and average\n",
-    "\n",
-    " An example of a parameter that returns several values of different dimension\n",
-    " This produces the last two arrays from data3, but only takes the data once."
+    "plot = qc.QtPlot()\n",
+    "plot.add(data.dac2_dac2, figsize=(1200, 500))\n",
+    "#plot.add(data.dac2_dac3, subplot=2)\n",
+    "_ = loop.with_bg_task(plot.update, plot.save).run()"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 11,
+   "execution_count": null,
    "metadata": {
     "collapsed": false,
-    "scrolled": false
+    "deletable": true,
+    "editable": true
    },
-   "outputs": [
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "DataSet:\n",
-      "   mode     = DataMode.LOCAL\n",
-      "   location = 'data/2016-11-08/#028_TwoD_average_test_13-30-32'\n",
-      "   <Type>   | <array_id>          | <array.name>  | <array.shape>\n",
-      "   Setpoint | gates_chan1_set     | chan1         | (30,)\n",
-      "   Measured | chan2               | chan2         | (30, 100)\n",
-      "   Measured | meter_amplitude     | amplitude     | (30, 100)\n",
-      "   Measured | meter_avg_amplitude | avg_amplitude | (30,)\n",
-      "started at 2016-11-08 13:30:49\n"
-     ]
-    }
-   ],
+   "outputs": [],
    "source": [
-    "loop4 = qc.Loop(c1[-15:15:1], 0.01).each(\n",
-    "    AverageAndRaw(meter.amplitude, c2[-10:10:0.2], 0.001)\n",
-    ")\n",
-    "data4 = loop4.get_data_set(name='TwoD_average_test')\n",
-    "plotQ = qc.QtPlot()\n",
-    "plotQ.add(data4.meter_amplitude, figsize=(1200, 500), cmap='viridis')\n",
-    "plotQ.add(data4.meter_avg_amplitude, subplot=2)\n",
-    "data4 = loop4.with_bg_task(plotQ.update, plotQ.save).run()"
+    "plot"
    ]
   }
  ],
diff --git a/docs/examples/toymodel.py b/docs/examples/toymodel.py
deleted file mode 100644
index fb28c353b4a..00000000000
--- a/docs/examples/toymodel.py
+++ /dev/null
@@ -1,149 +0,0 @@
-# code for example notebook
-
-import math
-
-from qcodes import MockInstrument, MockModel, Parameter, Loop, DataArray
-from qcodes.utils.validators import Numbers
-from qcodes.instrument.mock import ArrayGetter
-
-class AModel(MockModel):
-    def __init__(self):
-        self._gates = [0.0, 0.0, 0.0]
-        self._excitation = 0.1
-        super().__init__()
-
-    def _output(self):
-        # my super exciting model!
-        # make a nice pattern that looks sort of double-dotty
-        # with the first two gates controlling the two dots,
-        # and the third looking like Vsd
-        delta_i = 10
-        delta_j = 10
-        di = (self._gates[0] + delta_i / 2) % delta_i - delta_i / 2
-        dj = (self._gates[1] + delta_j / 2) % delta_j - delta_j / 2
-        vsd = math.sqrt(self._gates[2]**2 + self._excitation**2)
-        dij = math.sqrt(di**2 + dj**2) - vsd
-        g = (vsd**2 + 1) * (1 / (dij**2 + 1) +
-                            0.1 * (math.atan(-dij) + math.pi / 2))
-        return g
-
-    def fmt(self, value):
-        return '{:.3f}'.format(value)
-
-    def gates_set(self, parameter, value):
-        if parameter[0] == 'c':
-            self._gates[int(parameter[1:])] = float(value)
-        elif parameter == 'rst' and value is None:
-            self._gates = [0.0, 0.0, 0.0]
-        else:
-            raise ValueError
-
-    def gates_get(self, parameter):
-        if parameter[0] == 'c':
-            return self.fmt(self._gates[int(parameter[1:])])
-        else:
-            raise ValueError
-
-    def source_set(self, parameter, value):
-        if parameter == 'ampl':
-            self._excitation = float(value)
-        else:
-            raise ValueError
-
-    def source_get(self, parameter):
-        if parameter == 'ampl':
-            return self.fmt(self._excitation)
-        else:
-            raise ValueError
-
-    def meter_get(self, parameter):
-        if parameter == 'ampl':
-            return self.fmt(self._output() * self._excitation)
-        else:
-            raise ValueError
-
-
-# make our mock instruments
-# real instruments would subclass IPInstrument or VisaInstrument
-# or just the base Instrument instead of MockInstrument,
-# and be instantiated with an address rather than a model
-class MockGates(MockInstrument):
-    def __init__(self, name, model=None, **kwargs):
-        super().__init__(name, model=model, **kwargs)
-
-        for i in range(3):
-            cmdbase = 'c{}'.format(i)
-            self.add_parameter('chan{}'.format(i),
-                               label='Gate Channel {} (mV)'.format(i),
-                               get_cmd=cmdbase + '?',
-                               set_cmd=cmdbase + ':{:.4f}',
-                               get_parser=float,
-                               vals=Numbers(-100, 100))
-
-        self.add_function('reset', call_cmd='rst')
-
-
-class MockSource(MockInstrument):
-    def __init__(self, name, model=None, **kwargs):
-        super().__init__(name, model=model, **kwargs)
-
-        # this parameter uses built-in sweeping to change slowly
-        self.add_parameter('amplitude',
-                           label='Source Amplitude (\u03bcV)',
-                           get_cmd='ampl?',
-                           set_cmd='ampl:{:.4f}',
-                           get_parser=float,
-                           vals=Numbers(0, 10),
-                           step=0.1,
-                           delay=0.05)
-
-
-class MockMeter(MockInstrument):
-    def __init__(self, name, model=None, **kwargs):
-        super().__init__(name, model=model, **kwargs)
-
-        self.add_parameter('amplitude',
-                           label='Current (nA)',
-                           get_cmd='ampl?',
-                           get_parser=float)
-
-
-class AverageGetter(Parameter):
-    def __init__(self, measured_param, sweep_values, delay):
-        super().__init__(name='avg_' + measured_param.name)
-        self._instrument = getattr(measured_param, '_instrument', None)
-        self.measured_param = measured_param
-        self.sweep_values = sweep_values
-        self.delay = delay
-        if hasattr(measured_param, 'label'):
-            self.label = 'Average: ' + measured_param.label
-
-    def get(self):
-        loop = Loop(self.sweep_values, self.delay).each(self.measured_param)
-        data = loop.run_temp()
-        array = data.arrays[self.measured_param.full_name]
-        return array.mean()
-
-
-class AverageAndRaw(Parameter):
-    def __init__(self, measured_param, sweep_values, delay):
-        name = measured_param.name
-        super().__init__(names=(name, 'avg_' + name))
-        self._instrument = getattr(measured_param, '_instrument', None)
-        self.measured_param = measured_param
-        self.sweep_values = sweep_values
-        self.delay = delay
-        self.shapes = ((len(sweep_values),), None)
-        set_array = DataArray(parameter=sweep_values.parameter,
-                              preset_data=sweep_values)
-        self.setpoints = ((set_array,), None)
-        if hasattr(measured_param, 'label'):
-            self.labels = (measured_param.label,
-                           'Average: ' + measured_param.label)
-
-    def get(self):
-        loop = Loop(self.sweep_values, self.delay).each(self.measured_param)
-        data = loop.run_temp()
-        array = data.arrays[self.measured_param.full_name]
-        return (array, array.mean())
-

From ef2fe071bc382ae18d79b56215185bdda8ad739e Mon Sep 17 00:00:00 2001
From: Giulio Ungaretti <giulioungaretti@me.com>
Date: Fri, 10 Mar 2017 16:15:53 +0100
Subject: [PATCH 21/36] docs: Remove more MP from docs

---
 docs/examples/Datasaving examples.ipynb       | 476 +++---------------
 docs/examples/Keithley_example.ipynb          | 104 ++--
 docs/examples/Metadata with instruments.ipynb |  33 +-
 .../examples/Qcodes example with Triton.ipynb |  36 +-
 4 files changed, 145 insertions(+), 504 deletions(-)

diff --git a/docs/examples/Datasaving examples.ipynb b/docs/examples/Datasaving examples.ipynb
index 1117b4b695b..9aa2b7746b1 100644
--- a/docs/examples/Datasaving examples.ipynb	
+++ b/docs/examples/Datasaving examples.ipynb	
@@ -4,346 +4,11 @@
    "cell_type": "code",
    "execution_count": 1,
    "metadata": {
-    "collapsed": false
+    "collapsed": false,
+    "deletable": true,
+    "editable": true
    },
-   "outputs": [
-    {
-     "data": {
-      "application/javascript": [
-       "/*\n",
-       " * Qcodes Jupyter/IPython widgets\n",
-       " */\n",
-       "require([\n",
-       "    'nbextensions/widgets/widgets/js/widget',\n",
-       "    'nbextensions/widgets/widgets/js/manager'\n",
-       "], function (widget, manager) {\n",
-       "\n",
-       "    var UpdateView = widget.DOMWidgetView.extend({\n",
-       "        render: function() {\n",
-       "            window.MYWIDGET = this;\n",
-       "            this._interval = 0;\n",
-       "            this.update();\n",
-       "        },\n",
-       "        update: function() {\n",
-       "            this.display(this.model.get('_message'));\n",
-       "            this.setInterval();\n",
-       "        },\n",
-       "        display: function(message) {\n",
-       "            /*\n",
-       "             * display method: override this for custom display logic\n",
-       "             */\n",
-       "            this.el.innerHTML = message;\n",
-       "        },\n",
-       "        remove: function() {\n",
-       "            clearInterval(this._updater);\n",
-       "        },\n",
-       "        setInterval: function(newInterval) {\n",
-       "            var me = this;\n",
-       "            if(newInterval===undefined) newInterval = me.model.get('interval');\n",
-       "            if(newInterval===me._interval) return;\n",
-       "\n",
-       "            me._interval = newInterval;\n",
-       "\n",
-       "            if(me._updater) clearInterval(me._updater);\n",
-       "\n",
-       "            if(me._interval) {\n",
-       "                me._updater = setInterval(function() {\n",
-       "                    me.send({myupdate: true});\n",
-       "                    if(!me.model.comm_live) {\n",
-       "                        console.log('missing comm, canceling widget updates', me);\n",
-       "                        clearInterval(me._updater);\n",
-       "                    }\n",
-       "                }, me._interval * 1000);\n",
-       "            }\n",
-       "        }\n",
-       "    });\n",
-       "    manager.WidgetManager.register_widget_view('UpdateView', UpdateView);\n",
-       "\n",
-       "    var HiddenUpdateView = UpdateView.extend({\n",
-       "        display: function(message) {\n",
-       "            this.$el.hide();\n",
-       "        }\n",
-       "    });\n",
-       "    manager.WidgetManager.register_widget_view('HiddenUpdateView', HiddenUpdateView);\n",
-       "\n",
-       "    var SubprocessView = UpdateView.extend({\n",
-       "        render: function() {\n",
-       "            var me = this;\n",
-       "            me._interval = 0;\n",
-       "            me._minimize = '<i class=\"fa-minus fa\"></i>';\n",
-       "            me._restore = '<i class=\"fa-plus fa\"></i>';\n",
-       "\n",
-       "            // max lines of output to show\n",
-       "            me.maxOutputLength = 500;\n",
-       "\n",
-       "            // in case there is already an outputView present,\n",
-       "            // like from before restarting the kernel\n",
-       "            $('.qcodes-output-view').not(me.$el).remove();\n",
-       "\n",
-       "            me.$el\n",
-       "                .addClass('qcodes-output-view')\n",
-       "                .attr('qcodes-state', 'docked')\n",
-       "                .html(\n",
-       "                    '<div class=\"qcodes-output-header toolbar\">' +\n",
-       "                        '<div class=\"qcodes-process-list\"></div>' +\n",
-       "                        '<button class=\"btn qcodes-processlines\"><i class=\"fa-list fa\"></i></button>' +\n",
-       "                        '<button class=\"btn qcodes-abort-loop disabled\">Abort</button>' +\n",
-       "                        '<button class=\"btn qcodes-clear-output disabled qcodes-content\">Clear</button>' +\n",
-       "                        '<button class=\"btn js-state qcodes-minimized\"><i class=\"fa-minus fa\"></i></button>' +\n",
-       "                        '<button class=\"btn js-state qcodes-docked\"><i class=\"fa-toggle-up fa\"></i></button>' +\n",
-       "                        '<button class=\"btn js-state qcodes-floated\"><i class=\"fa-arrows fa\"></i></button>' +\n",
-       "                    '</div>' +\n",
-       "                    '<pre class=\"qcodes-content\"></pre>'\n",
-       "                );\n",
-       "\n",
-       "            me.clearButton = me.$el.find('.qcodes-clear-output');\n",
-       "            me.minButton = me.$el.find('.qcodes-minimize');\n",
-       "            me.outputArea = me.$el.find('pre');\n",
-       "            me.subprocessList = me.$el.find('.qcodes-process-list');\n",
-       "            me.abortButton = me.$el.find('.qcodes-abort-loop');\n",
-       "            me.processLinesButton = me.$el.find('.qcodes-processlines')\n",
-       "\n",
-       "            me.outputLines = [];\n",
-       "\n",
-       "            me.clearButton.click(function() {\n",
-       "                me.outputArea.html('');\n",
-       "                me.clearButton.addClass('disabled');\n",
-       "            });\n",
-       "\n",
-       "            me.abortButton.click(function() {\n",
-       "                me.send({abort: true});\n",
-       "            });\n",
-       "\n",
-       "            me.processLinesButton.click(function() {\n",
-       "                // toggle multiline process list display\n",
-       "                me.subprocessesMultiline = !me.subprocessesMultiline;\n",
-       "                me.showSubprocesses();\n",
-       "            });\n",
-       "\n",
-       "            me.$el.find('.js-state').click(function() {\n",
-       "                var state = this.className.substr(this.className.indexOf('qcodes'))\n",
-       "                        .split('-')[1].split(' ')[0];\n",
-       "                me.model.set('_state', state);\n",
-       "            });\n",
-       "\n",
-       "            $(window)\n",
-       "                .off('resize.qcodes')\n",
-       "                .on('resize.qcodes', function() {me.clipBounds();});\n",
-       "\n",
-       "            me.update();\n",
-       "        },\n",
-       "\n",
-       "        updateState: function() {\n",
-       "            var me = this,\n",
-       "                oldState = me.$el.attr('qcodes-state'),\n",
-       "                state = me.model.get('_state');\n",
-       "\n",
-       "            if(state === oldState) return;\n",
-       "\n",
-       "            setTimeout(function() {\n",
-       "                // not sure why I can't pop it out of the widgetarea in render, but it seems that\n",
-       "                // some other bit of code resets the parent after render if I do it there.\n",
-       "                // To be safe, just do it on every state click.\n",
-       "                me.$el.appendTo('body');\n",
-       "\n",
-       "                if(oldState === 'floated') {\n",
-       "                    console.log('here');\n",
-       "                    me.$el.draggable('destroy').css({left:'', top: ''});\n",
-       "                }\n",
-       "\n",
-       "                me.$el.attr('qcodes-state', state);\n",
-       "\n",
-       "                if(state === 'floated') {\n",
-       "                    me.$el\n",
-       "                        .draggable({stop: function() { me.clipBounds(); }})\n",
-       "                        .css({\n",
-       "                            left: window.innerWidth - me.$el.width() - 15,\n",
-       "                            top: window.innerHeight - me.$el.height() - 10\n",
-       "                        });\n",
-       "                }\n",
-       "\n",
-       "                // any previous highlighting is now moot\n",
-       "                me.$el.removeClass('qcodes-highlight');\n",
-       "            }, 0);\n",
-       "\n",
-       "        },\n",
-       "\n",
-       "        clipBounds: function() {\n",
-       "            var me = this;\n",
-       "            if(me.$el.attr('qcodes-state') === 'floated') {\n",
-       "                var bounds = me.$el[0].getBoundingClientRect(),\n",
-       "                    minVis = 40,\n",
-       "                    maxLeft = window.innerWidth - minVis,\n",
-       "                    minLeft = minVis - bounds.width,\n",
-       "                    maxTop = window.innerHeight - minVis;\n",
-       "\n",
-       "                if(bounds.left > maxLeft) me.$el.css('left', maxLeft);\n",
-       "                else if(bounds.left < minLeft) me.$el.css('left', minLeft);\n",
-       "\n",
-       "                if(bounds.top > maxTop) me.$el.css('top', maxTop);\n",
-       "                else if(bounds.top < 0) me.$el.css('top', 0);\n",
-       "            }\n",
-       "        },\n",
-       "\n",
-       "        display: function(message) {\n",
-       "            var me = this;\n",
-       "            if(message) {\n",
-       "                var initialScroll = me.outputArea.scrollTop();\n",
-       "                me.outputArea.scrollTop(me.outputArea.prop('scrollHeight'));\n",
-       "                var scrollBottom = me.outputArea.scrollTop();\n",
-       "\n",
-       "                if(me.$el.attr('qcodes-state') === 'minimized') {\n",
-       "                    // if we add text and the box is minimized, highlight the\n",
-       "                    // title bar to alert the user that there are new messages.\n",
-       "                    // remove then add the class, so we get the animation again\n",
-       "                    // if it's already highlighted\n",
-       "                    me.$el.removeClass('qcodes-highlight');\n",
-       "                    setTimeout(function(){\n",
-       "                        me.$el.addClass('qcodes-highlight');\n",
-       "                    }, 0);\n",
-       "                }\n",
-       "\n",
-       "                var newLines = message.split('\\n'),\n",
-       "                    out = me.outputLines,\n",
-       "                    outLen = out.length;\n",
-       "                if(outLen) out[outLen - 1] += newLines[0];\n",
-       "                else out.push(newLines[0]);\n",
-       "\n",
-       "                for(var i = 1; i < newLines.length; i++) {\n",
-       "                    out.push(newLines[i]);\n",
-       "                }\n",
-       "\n",
-       "                if(out.length > me.maxOutputLength) {\n",
-       "                    out.splice(0, out.length - me.maxOutputLength + 1,\n",
-       "                        '<<< Output clipped >>>');\n",
-       "                }\n",
-       "\n",
-       "                me.outputArea.text(out.join('\\n'));\n",
-       "                me.clearButton.removeClass('disabled');\n",
-       "\n",
-       "                // if we were scrolled to the bottom initially, make sure\n",
-       "                // we stay that way.\n",
-       "                me.outputArea.scrollTop(initialScroll === scrollBottom ?\n",
-       "                    me.outputArea.prop('scrollHeight') : initialScroll);\n",
-       "            }\n",
-       "\n",
-       "            me.showSubprocesses();\n",
-       "            me.updateState();\n",
-       "        },\n",
-       "\n",
-       "        showSubprocesses: function() {\n",
-       "            var me = this,\n",
-       "                replacer = me.subprocessesMultiline ? '<br>' : ', ',\n",
-       "                processes = (me.model.get('_processes') || '')\n",
-       "                    .replace(/\\n/g, '&gt;' + replacer + '&lt;');\n",
-       "\n",
-       "            if(processes) processes = '&lt;' + processes + '&gt;';\n",
-       "            else processes = 'No subprocesses';\n",
-       "\n",
-       "            me.abortButton.toggleClass('disabled', processes.indexOf('Measurement')===-1);\n",
-       "\n",
-       "            me.subprocessList.html(processes);\n",
-       "        }\n",
-       "    });\n",
-       "    manager.WidgetManager.register_widget_view('SubprocessView', SubprocessView);\n",
-       "});\n"
-      ],
-      "text/plain": [
-       "<IPython.core.display.Javascript object>"
-      ]
-     },
-     "metadata": {},
-     "output_type": "display_data"
-    },
-    {
-     "data": {
-      "text/html": [
-       "<style>.qcodes-output-view:not(.ui-draggable) {\n",
-       "    bottom: 0;\n",
-       "    right: 5px;\n",
-       "}\n",
-       ".qcodes-output-view {\n",
-       "    position: fixed;\n",
-       "    z-index: 999;\n",
-       "    background-color: #fff;\n",
-       "    box-shadow: 0 0 12px 1px rgba(87, 87, 87, 0.2);\n",
-       "}\n",
-       "\n",
-       ".qcodes-output-header {\n",
-       "    float: right;\n",
-       "}\n",
-       "\n",
-       ".qcodes-highlight {\n",
-       "    animation: pulse 1s linear;\n",
-       "    background-color: #fa4;\n",
-       "}\n",
-       "\n",
-       "@keyframes pulse {\n",
-       "    0% {\n",
-       "        background-color: #f00;\n",
-       "    }\n",
-       "    100% {\n",
-       "        background-color: #fa4;\n",
-       "    }\n",
-       "}\n",
-       "\n",
-       ".qcodes-process-list {\n",
-       "    float: left;\n",
-       "    max-width: 780px;\n",
-       "    margin: 3px 5px 3px 10px;\n",
-       "    overflow: hidden;\n",
-       "    white-space: nowrap;\n",
-       "    text-overflow: ellipsis;\n",
-       "}\n",
-       "\n",
-       ".qcodes-output-view[qcodes-state=minimized] .qcodes-process-list {\n",
-       "    max-width: 300px;\n",
-       "}\n",
-       "\n",
-       ".qcodes-output-view span {\n",
-       "    padding: 2px 6px 3px 12px;\n",
-       "}\n",
-       "\n",
-       ".qcodes-output-view .btn {\n",
-       "    margin: 0 3px 0 0;\n",
-       "}\n",
-       "\n",
-       ".qcodes-output-view[qcodes-state=docked] .qcodes-docked,\n",
-       ".qcodes-output-view[qcodes-state=floated] .qcodes-floated,\n",
-       ".qcodes-output-view[qcodes-state=minimized] .qcodes-minimized,\n",
-       ".qcodes-output-view[qcodes-state=minimized] .qcodes-content {\n",
-       "    display: none;\n",
-       "}\n",
-       "\n",
-       ".qcodes-output-view .disabled {\n",
-       "    opacity: 0.4;\n",
-       "}\n",
-       "\n",
-       ".qcodes-abort-loop {\n",
-       "    background-color: #844;\n",
-       "    color: #fff;\n",
-       "}\n",
-       "\n",
-       ".qcodes-output-view pre {\n",
-       "    clear: both;\n",
-       "    margin: 0;\n",
-       "    border: 0;\n",
-       "    border-top: 1px solid #ccc;\n",
-       "    background-color: #ffe;\n",
-       "    min-height: 50px;\n",
-       "    max-height: 400px;\n",
-       "    min-width: 400px;\n",
-       "    max-width: 1000px;\n",
-       "}</style>"
-      ],
-      "text/plain": [
-       "<IPython.core.display.HTML object>"
-      ]
-     },
-     "metadata": {},
-     "output_type": "display_data"
-    }
-   ],
+   "outputs": [],
    "source": [
     "%matplotlib nbagg\n",
     "import numpy as np\n",
@@ -355,7 +20,9 @@
    "cell_type": "code",
    "execution_count": 2,
    "metadata": {
-    "collapsed": false
+    "collapsed": false,
+    "deletable": true,
+    "editable": true
    },
    "outputs": [],
    "source": [
@@ -381,7 +48,9 @@
    "cell_type": "code",
    "execution_count": 3,
    "metadata": {
-    "collapsed": false
+    "collapsed": false,
+    "deletable": true,
+    "editable": true
    },
    "outputs": [],
    "source": [
@@ -392,7 +61,10 @@
   },
   {
    "cell_type": "markdown",
-   "metadata": {},
+   "metadata": {
+    "deletable": true,
+    "editable": true
+   },
    "source": [
     "# Start a loop and generate data from dummy instruments "
    ]
@@ -401,7 +73,9 @@
    "cell_type": "code",
    "execution_count": 4,
    "metadata": {
-    "collapsed": false
+    "collapsed": false,
+    "deletable": true,
+    "editable": true
    },
    "outputs": [],
    "source": [
@@ -412,7 +86,9 @@
    "cell_type": "code",
    "execution_count": 5,
    "metadata": {
-    "collapsed": false
+    "collapsed": false,
+    "deletable": true,
+    "editable": true
    },
    "outputs": [
     {
@@ -440,10 +116,12 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 6,
+   "execution_count": 7,
    "metadata": {
     "collapsed": false,
-    "scrolled": true
+    "deletable": true,
+    "editable": true,
+    "scrolled": false
    },
    "outputs": [
     {
@@ -451,27 +129,27 @@
      "output_type": "stream",
      "text": [
       "DataSet:\n",
-      "   mode     = DataMode.LOCAL\n",
-      "   location = '2016-09-04/13-24-02_MockParabola_run'\n",
+      "   location = 'data/2017-03-10/#017_MockParabola_run_15-44-02'\n",
       "   <Type>   | <array_id>                   | <array.name>    | <array.shape>\n",
       "   Setpoint | MockParabola_x_set           | x               | (10,)\n",
       "   Measured | MockParabola_skewed_parabola | skewed_parabola | (10,)\n",
-      "started at 2016-09-04 13:24:02\n"
+      "started at 2017-03-10 15:44:02\n"
      ]
     }
    ],
    "source": [
     "loop = qc.Loop(station.MockParabola.x[-100:100:20]).each(station.MockParabola.skewed_parabola)\n",
-    "data_l = loop.run(name='MockParabola_run', formatter=qc.data.gnuplot_format.GNUPlotFormat(), \n",
-    "                  background=False, data_manager=False)\n",
+    "data_l = loop.run(name='MockParabola_run', formatter=qc.data.gnuplot_format.GNUPlotFormat())\n",
     "\n"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 7,
+   "execution_count": 8,
    "metadata": {
-    "collapsed": false
+    "collapsed": false,
+    "deletable": true,
+    "editable": true
    },
    "outputs": [
     {
@@ -479,13 +157,12 @@
      "output_type": "stream",
      "text": [
       "DataSet:\n",
-      "   mode     = DataMode.LOCAL\n",
-      "   location = '2016-09-04/13-24-02_MockParabola_run_002'\n",
+      "   location = 'data/2017-03-10/#018_MockParabola_run_15-44-07'\n",
       "   <Type>   | <array_id>                   | <array.name>    | <array.shape>\n",
       "   Setpoint | MockParabola_x_set           | x               | (10,)\n",
       "   Setpoint | MockParabola_y_set           | y               | (10, 15)\n",
       "   Measured | MockParabola_skewed_parabola | skewed_parabola | (10, 15)\n",
-      "started at 2016-09-04 13:24:03\n"
+      "started at 2017-03-10 15:44:07\n"
      ]
     }
    ],
@@ -494,14 +171,16 @@
     "h5fmt = hdf5_format.HDF5Format()\n",
     "loop = qc.Loop(station.MockParabola.x[-100:100:20]).loop(\n",
     "    station.MockParabola.y[-100:50:10]).each(station.MockParabola.skewed_parabola)\n",
-    "data_l = loop.run(name='MockParabola_run', formatter=h5fmt, background=False, data_manager=False)\n"
+    "data_l = loop.run(name='MockParabola_run', formatter=h5fmt)\n"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 8,
+   "execution_count": 9,
    "metadata": {
-    "collapsed": false
+    "collapsed": false,
+    "deletable": true,
+    "editable": true
    },
    "outputs": [],
    "source": [
@@ -515,16 +194,21 @@
   },
   {
    "cell_type": "markdown",
-   "metadata": {},
+   "metadata": {
+    "deletable": true,
+    "editable": true
+   },
    "source": [
     "# Run the tests for the dataformat"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 9,
+   "execution_count": 10,
    "metadata": {
     "collapsed": false,
+    "deletable": true,
+    "editable": true,
     "scrolled": false
    },
    "outputs": [
@@ -545,7 +229,22 @@
       "test_incremental_write (qcodes.tests.test_hdf5formatter.TestHDF5_Format) ... ok\n",
       "test_loop_writing (qcodes.tests.test_hdf5formatter.TestHDF5_Format) ... root - WARNING - Error getting or interpreting *IDN?: ''\n",
       "ok\n",
-      "test_loop_writing_2D (qcodes.tests.test_hdf5formatter.TestHDF5_Format) ... root - WARNING - Error getting or interpreting *IDN?: ''\n"
+      "test_loop_writing_2D (qcodes.tests.test_hdf5formatter.TestHDF5_Format) ... root - WARNING - Error getting or interpreting *IDN?: ''\n",
+      "ok\n",
+      "test_metadata_write_read (qcodes.tests.test_hdf5formatter.TestHDF5_Format) ... ok\n",
+      "test_read_writing_dicts_withlists_to_hdf5 (qcodes.tests.test_hdf5formatter.TestHDF5_Format) ... ok\n",
+      "test_reading_into_existing_data_array (qcodes.tests.test_hdf5formatter.TestHDF5_Format) ... ok\n",
+      "test_str_to_bool (qcodes.tests.test_hdf5formatter.TestHDF5_Format) ... ok\n",
+      "test_writing_metadata (qcodes.tests.test_hdf5formatter.TestHDF5_Format) ... ok\n",
+      "test_writing_unsupported_types_to_hdf5 (qcodes.tests.test_hdf5formatter.TestHDF5_Format) ... root - WARNING - List of type \"<class 'qcodes.data.data_set.DataSet'>\" for \"list_of_dataset\":\"[DataSet:\n",
+      "   location = '/Users/unga/src/Qcodes/qcodes/unittest_data/2017-03-10/#016_test_missing_attr_15-44-09'\n",
+      "   <Type> | <array_id> | <array.name> | <array.shape>, DataSet:\n",
+      "   location = '/Users/unga/src/Qcodes/qcodes/unittest_data/2017-03-10/#016_test_missing_attr_15-44-09'\n",
+      "   <Type> | <array_id> | <array.name> | <array.shape>]\" not supported, storing as string\n",
+      "root - WARNING - Type \"<class 'qcodes.data.data_set.DataSet'>\" for \"nested_dataset\":\"DataSet:\n",
+      "   location = '/Users/unga/src/Qcodes/qcodes/unittest_data/2017-03-10/#016_test_missing_attr_15-44-09'\n",
+      "   <Type> | <array_id> | <array.name> | <array.shape>\" not supported, storing as string\n",
+      "root - WARNING - List of mixed type for \"<class 'list'>\":\"list_of_mixed_type\" not supported, storing as string\n"
      ]
     },
     {
@@ -553,60 +252,28 @@
      "output_type": "stream",
      "text": [
       "DataSet:\n",
-      "   mode     = DataMode.LOCAL\n",
-      "   location = '/Users/Adriaan/GitHubRepos/DiCarloLab_Repositories/Qcodes/qcodes/unittest_data/2016-09-04/#631_MockLoop_hdf5_test_13-24-03'\n",
+      "   location = '/Users/unga/src/Qcodes/qcodes/unittest_data/2017-03-10/#010_MockLoop_hdf5_test_15-44-09'\n",
       "   <Type>   | <array_id>                        | <array.name>    | <array.shape>\n",
       "   Setpoint | Loop_writing_test_x_set           | x               | (10,)\n",
       "   Measured | Loop_writing_test_skewed_parabola | skewed_parabola | (10,)\n",
-      "started at 2016-09-04 13:24:04\n"
-     ]
-    },
-    {
-     "name": "stderr",
-     "output_type": "stream",
-     "text": [
-      "ok\n",
-      "test_metadata_write_read (qcodes.tests.test_hdf5formatter.TestHDF5_Format) ... ok\n",
-      "test_read_writing_dicts_withlists_to_hdf5 (qcodes.tests.test_hdf5formatter.TestHDF5_Format) ... ok\n",
-      "test_reading_into_existing_data_array (qcodes.tests.test_hdf5formatter.TestHDF5_Format) ... "
-     ]
-    },
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
+      "started at 2017-03-10 15:44:09\n",
       "DataSet:\n",
-      "   mode     = DataMode.LOCAL\n",
-      "   location = '/Users/Adriaan/GitHubRepos/DiCarloLab_Repositories/Qcodes/qcodes/unittest_data/2016-09-04/#632_MockLoop_hdf5_test_13-24-04'\n",
+      "   location = '/Users/unga/src/Qcodes/qcodes/unittest_data/2017-03-10/#011_MockLoop_hdf5_test_15-44-09'\n",
       "   <Type>   | <array_id>                           | <array.name>    | <array.shape>\n",
       "   Setpoint | Loop_writing_test_2D_x_set           | x               | (10,)\n",
       "   Setpoint | Loop_writing_test_2D_y_set           | y               | (10, 10)\n",
       "   Measured | Loop_writing_test_2D_skewed_parabola | skewed_parabola | (10, 10)\n",
-      "started at 2016-09-04 13:24:04\n"
+      "started at 2017-03-10 15:44:09\n"
      ]
     },
     {
      "name": "stderr",
      "output_type": "stream",
      "text": [
-      "ok\n",
-      "test_str_to_bool (qcodes.tests.test_hdf5formatter.TestHDF5_Format) ... ok\n",
-      "test_writing_unsupported_types_to_hdf5 (qcodes.tests.test_hdf5formatter.TestHDF5_Format) ... root - WARNING - List of mixed type for \"<class 'list'>\":\"list_of_mixed_type\" not supported, storing as string\n",
-      "root - WARNING - List of type \"<class 'qcodes.data.data_set.DataSet'>\" for \"list_of_dataset\":\"[DataSet:\n",
-      "   mode     = DataMode.LOCAL\n",
-      "   location = '/Users/Adriaan/GitHubRepos/DiCarloLab_Repositories/Qcodes/qcodes/unittest_data/2016-09-04/#636_test_missing_attr_13-24-04'\n",
-      "   <Type> | <array_id> | <array.name> | <array.shape>, DataSet:\n",
-      "   mode     = DataMode.LOCAL\n",
-      "   location = '/Users/Adriaan/GitHubRepos/DiCarloLab_Repositories/Qcodes/qcodes/unittest_data/2016-09-04/#636_test_missing_attr_13-24-04'\n",
-      "   <Type> | <array_id> | <array.name> | <array.shape>]\" not supported, storing as string\n",
-      "root - WARNING - Type \"<class 'qcodes.data.data_set.DataSet'>\" for \"nested_dataset\":\"DataSet:\n",
-      "   mode     = DataMode.LOCAL\n",
-      "   location = '/Users/Adriaan/GitHubRepos/DiCarloLab_Repositories/Qcodes/qcodes/unittest_data/2016-09-04/#636_test_missing_attr_13-24-04'\n",
-      "   <Type> | <array_id> | <array.name> | <array.shape>\" not supported, storing as string\n",
       "ok\n",
       "\n",
       "----------------------------------------------------------------------\n",
-      "Ran 16 tests in 1.970s\n",
+      "Ran 17 tests in 0.348s\n",
       "\n",
       "OK\n"
      ]
@@ -624,6 +291,15 @@
     "suite = unittest.defaultTestLoader.loadTestsFromTestCase(tst)\n",
     "result = unittest.TextTestRunner(verbosity=2).run(suite)\n"
    ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {
+    "collapsed": true
+   },
+   "outputs": [],
+   "source": []
   }
  ],
  "metadata": {
@@ -642,7 +318,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.5.1"
+   "version": "3.5.2"
   },
   "widgets": {
    "state": {},
diff --git a/docs/examples/Keithley_example.ipynb b/docs/examples/Keithley_example.ipynb
index 1d9799c229f..e5e3d301500 100644
--- a/docs/examples/Keithley_example.ipynb
+++ b/docs/examples/Keithley_example.ipynb
@@ -2,7 +2,10 @@
  "cells": [
   {
    "cell_type": "markdown",
-   "metadata": {},
+   "metadata": {
+    "deletable": true,
+    "editable": true
+   },
    "source": [
     "# Example script for Keithley driver"
    ]
@@ -11,7 +14,9 @@
    "cell_type": "code",
    "execution_count": 1,
    "metadata": {
-    "collapsed": false
+    "collapsed": false,
+    "deletable": true,
+    "editable": true
    },
    "outputs": [
     {
@@ -257,19 +262,15 @@
     "import time\n",
     "import numpy as np\n",
     "from imp import reload\n",
-    "\n",
-    "import qcodes as qc\n",
-    "\n",
-    "qc.set_mp_method('spawn')  # force Windows behavior on mac\n",
-    "\n",
-    "# this makes a widget in the corner of the window to show and control\n",
-    "# subprocesses and any output they would print to the terminal\n",
-    "qc.show_subprocess_widget()"
+    "import qcodes as qc"
    ]
   },
   {
    "cell_type": "markdown",
-   "metadata": {},
+   "metadata": {
+    "deletable": true,
+    "editable": true
+   },
    "source": [
     "## Keithley driver\n",
     "\n",
@@ -284,7 +285,9 @@
    "cell_type": "code",
    "execution_count": 12,
    "metadata": {
-    "collapsed": false
+    "collapsed": false,
+    "deletable": true,
+    "editable": true
    },
    "outputs": [
     {
@@ -300,14 +303,16 @@
    ],
    "source": [
     "import qcodes.instrument_drivers\n",
-    "import qcodes.instrument_drivers.tektronix.Keithley_2700 as keith; reload(keith)"
+    "import qcodes.instrument_drivers.tektronix.Keithley_2700 as keith"
    ]
   },
   {
    "cell_type": "code",
    "execution_count": 13,
    "metadata": {
-    "collapsed": false
+    "collapsed": false,
+    "deletable": true,
+    "editable": true
    },
    "outputs": [
     {
@@ -327,7 +332,9 @@
    "cell_type": "code",
    "execution_count": 4,
    "metadata": {
-    "collapsed": false
+    "collapsed": false,
+    "deletable": true,
+    "editable": true
    },
    "outputs": [
     {
@@ -347,6 +354,8 @@
    "execution_count": 5,
    "metadata": {
     "collapsed": false,
+    "deletable": true,
+    "editable": true,
     "scrolled": true
    },
    "outputs": [
@@ -372,7 +381,9 @@
    "cell_type": "code",
    "execution_count": 6,
    "metadata": {
-    "collapsed": false
+    "collapsed": false,
+    "deletable": true,
+    "editable": true
    },
    "outputs": [
     {
@@ -400,7 +411,9 @@
    "cell_type": "code",
    "execution_count": 7,
    "metadata": {
-    "collapsed": false
+    "collapsed": false,
+    "deletable": true,
+    "editable": true
    },
    "outputs": [
     {
@@ -422,7 +435,9 @@
    "cell_type": "code",
    "execution_count": 8,
    "metadata": {
-    "collapsed": false
+    "collapsed": false,
+    "deletable": true,
+    "editable": true
    },
    "outputs": [
     {
@@ -442,57 +457,6 @@
    "source": [
     "print(k1.nplc.__doc__)"
    ]
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "## Test whether the object can be pickled"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 9,
-   "metadata": {
-    "collapsed": false
-   },
-   "outputs": [
-    {
-     "ename": "ValueError",
-     "evalue": "ctypes objects containing pointers cannot be pickled",
-     "output_type": "error",
-     "traceback": [
-      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
-      "\u001b[1;31mValueError\u001b[0m                                Traceback (most recent call last)",
-      "\u001b[1;32m<ipython-input-9-92f78756193e>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m()\u001b[0m\n\u001b[0;32m      2\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mtempfile\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m      3\u001b[0m \u001b[1;32mwith\u001b[0m \u001b[0mtempfile\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mTemporaryFile\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'wb'\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;32mas\u001b[0m \u001b[0moutput\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 4\u001b[1;33m     \u001b[0mpickle\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdump\u001b[0m\u001b[1;33m(\u001b[0m \u001b[1;33m(\u001b[0m\u001b[0mk1\u001b[0m\u001b[1;33m,\u001b[0m  \u001b[1;33m)\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0moutput\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
-      "\u001b[1;31mValueError\u001b[0m: ctypes objects containing pointers cannot be pickled"
-     ]
-    }
-   ],
-   "source": [
-    "import pickle\n",
-    "import tempfile\n",
-    "with tempfile.TemporaryFile('wb') as output:\n",
-    "    pickle.dump( (k1,  ), output)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {
-    "collapsed": false
-   },
-   "outputs": [],
-   "source": []
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {
-    "collapsed": true
-   },
-   "outputs": [],
-   "source": []
   }
  ],
  "metadata": {
@@ -511,7 +475,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.5.1"
+   "version": "3.5.2"
   }
  },
  "nbformat": 4,
diff --git a/docs/examples/Metadata with instruments.ipynb b/docs/examples/Metadata with instruments.ipynb
index 8b5905412aa..21cf0b24cb1 100644
--- a/docs/examples/Metadata with instruments.ipynb	
+++ b/docs/examples/Metadata with instruments.ipynb	
@@ -4,7 +4,9 @@
    "cell_type": "code",
    "execution_count": 1,
    "metadata": {
-    "collapsed": false
+    "collapsed": false,
+    "deletable": true,
+    "editable": true
    },
    "outputs": [
     {
@@ -247,19 +249,16 @@
    ],
    "source": [
     "from pprint import pprint\n",
-    "\n",
-    "import qcodes as qc\n",
-    "\n",
-    "qc.set_mp_method('spawn')\n",
-    "\n",
-    "qc.show_subprocess_widget()"
+    "import qcodes as qc"
    ]
   },
   {
    "cell_type": "code",
    "execution_count": 2,
    "metadata": {
-    "collapsed": false
+    "collapsed": false,
+    "deletable": true,
+    "editable": true
    },
    "outputs": [],
    "source": [
@@ -294,6 +293,8 @@
    "execution_count": 3,
    "metadata": {
     "collapsed": false,
+    "deletable": true,
+    "editable": true,
     "scrolled": false
    },
    "outputs": [
@@ -647,6 +648,8 @@
    "execution_count": 4,
    "metadata": {
     "collapsed": false,
+    "deletable": true,
+    "editable": true,
     "scrolled": false
    },
    "outputs": [],
@@ -662,7 +665,9 @@
    "cell_type": "code",
    "execution_count": 5,
    "metadata": {
-    "collapsed": false
+    "collapsed": false,
+    "deletable": true,
+    "editable": true
    },
    "outputs": [
     {
@@ -684,7 +689,9 @@
    "cell_type": "code",
    "execution_count": 6,
    "metadata": {
-    "collapsed": false
+    "collapsed": false,
+    "deletable": true,
+    "editable": true
    },
    "outputs": [
     {
@@ -711,7 +718,9 @@
    "cell_type": "code",
    "execution_count": null,
    "metadata": {
-    "collapsed": true
+    "collapsed": true,
+    "deletable": true,
+    "editable": true
    },
    "outputs": [],
    "source": []
@@ -733,7 +742,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.5.1"
+   "version": "3.5.2"
   }
  },
  "nbformat": 4,
diff --git a/docs/examples/Qcodes example with Triton.ipynb b/docs/examples/Qcodes example with Triton.ipynb
index dd3d40e4148..b1737b8c3b4 100644
--- a/docs/examples/Qcodes example with Triton.ipynb	
+++ b/docs/examples/Qcodes example with Triton.ipynb	
@@ -4,7 +4,9 @@
    "cell_type": "code",
    "execution_count": 1,
    "metadata": {
-    "collapsed": false
+    "collapsed": false,
+    "deletable": true,
+    "editable": true
    },
    "outputs": [
     {
@@ -250,21 +252,16 @@
     "import matplotlib.pyplot as plt\n",
     "import time\n",
     "import numpy as np\n",
-    "\n",
-    "import qcodes as qc\n",
-    "\n",
-    "qc.set_mp_method('spawn')  # force Windows behavior on mac\n",
-    "\n",
-    "# this makes a widget in the corner of the window to show and control\n",
-    "# subprocesses and any output they would print to the terminal\n",
-    "qc.show_subprocess_widget()"
+    "import qcodes as qc"
    ]
   },
   {
    "cell_type": "code",
    "execution_count": 5,
    "metadata": {
-    "collapsed": false
+    "collapsed": false,
+    "deletable": true,
+    "editable": true
    },
    "outputs": [
     {
@@ -301,7 +298,9 @@
    "cell_type": "code",
    "execution_count": 8,
    "metadata": {
-    "collapsed": false
+    "collapsed": false,
+    "deletable": true,
+    "editable": true
    },
    "outputs": [],
    "source": [
@@ -312,7 +311,9 @@
    "cell_type": "code",
    "execution_count": 10,
    "metadata": {
-    "collapsed": false
+    "collapsed": false,
+    "deletable": true,
+    "editable": true
    },
    "outputs": [
     {
@@ -329,15 +330,6 @@
    "source": [
     "t.split(':')[1:]"
    ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {
-    "collapsed": true
-   },
-   "outputs": [],
-   "source": []
   }
  ],
  "metadata": {
@@ -356,7 +348,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.5.1"
+   "version": "3.5.2"
   }
  },
  "nbformat": 4,

From c07b6130a4305201f6f3e5a9aca399a68e718c83 Mon Sep 17 00:00:00 2001
From: Giulio Ungaretti <giulioungaretti@me.com>
Date: Thu, 16 Mar 2017 12:19:56 +0100
Subject: [PATCH 22/36] chore: Remove untested example adaptive sweep

---
 docs/examples/adaptive_sweep.py | 103 --------------------------------
 1 file changed, 103 deletions(-)
 delete mode 100644 docs/examples/adaptive_sweep.py

diff --git a/docs/examples/adaptive_sweep.py b/docs/examples/adaptive_sweep.py
deleted file mode 100644
index 709f1511411..00000000000
--- a/docs/examples/adaptive_sweep.py
+++ /dev/null
@@ -1,103 +0,0 @@
-import qcodes as qc
-
-
-class AdaptiveSweep(qc.SweepValues):
-    '''
-    an example class to show how adaptive sampling might be implemented
-    this code has not been tested
-
-    usage:
-    Loop(AdaptiveSweep(param, start, end, target_delta), delay).run()
-
-    inputs:
-        start: initial parameter value
-        end: final parameter value
-        target_delta: change in the measured val to target
-        max_step: biggest change in parameter value allowed
-        min_step: smallest change allowed, so we don't sweep forever
-        measurement_index: which measurement parameter are we feeding back on?
-    '''
-    def __init__(self, parameter, start, end, target_delta, max_step=None,
-                 min_step=None, measurement_index=0):
-        super().__init__(parameter)
-
-        self._start = start
-        self._end = end
-        self._direction = 1 if end > start else -1
-
-        self._target_delta = target_delta
-
-        self._max_step = max_step or abs(end - start) / 100
-        self._min_step = min_step or self._max_step / 100
-
-        self._measurement_index = measurement_index
-
-    def __iter__(self):
-        '''
-        start or restart the adaptive algorithm
-        called at the beginning of "for ... in ..."
-
-        in principle, each iteration could base its outputs
-        on the previous iteration, for example to follow peaks
-        that move slowly as a function of the outer loop parameter.
-        but in this simple example we're just basing each point on the
-        previous two
-        '''
-        self._setting = None
-        self._step = None
-        self._measured = None
-        self._delta = None
-        self._new_val_count = 0
-
-        # return self so iteration will call our own __next__
-        return self
-
-    def feedback(self, set_values, measured_values):
-        '''
-        the sweep routine will look for a .feedback method
-        to pass new measurements into the SweepValues object
-
-        it provides:
-            set_values: sequence of the current sweep parameters
-            measured_values: sequence of the measured values at this setting
-        '''
-        self._new_val_count += 1
-        if self._new_val_count > 1:
-            # more than one measurement per iteration means we're
-            # not in the inner loop. in principle one could adaptively
-            # sample an outer loop too, using the whole line of inner loop
-            # measurements, but the algorithm here only applies to the inner.
-            raise RuntimeError(
-                'AdaptiveSweep can only be used on the inner loop')
-
-        new_measured = measured_values[self._measurement_index]
-
-        if self._measured is not None:
-            self._delta = new_measured - self._measured
-
-        self._measured = new_measured
-
-    def __next__(self):
-        self._new_val_count = 0
-
-        if self._setting == self._end:
-            # terminate the iteration if we've already set the endpoint
-            raise StopIteration
-
-        # target the step so the next delta is target_delta, if data is linear
-        if self._delta is None:
-            step = self._min_step  # start off slow
-        else:
-            step = abs(self._step * self._target_delta / self._delta)
-            # don't increase too much at once
-            step = max(step, self._step * 3)
-
-        # constrain it to provide min and max
-        step = min(max(self._min_step, step), self._max_step)
-        self._setting += self._direction * step
-
-        # stop at the end
-        if self._setting * self._direction > self._end * self._direction:
-            self._setting = self._end
-
-        return self._setting

From 49fb337f849ed2002aadff7739107fdeb571409c Mon Sep 17 00:00:00 2001
From: Giulio Ungaretti <giulioungaretti@me.com>
Date: Thu, 16 Mar 2017 12:21:24 +0100
Subject: [PATCH 23/36] docs: Update docs

---
 .../Creating Instrument Drivers.ipynb         |  72 +++-
 docs/examples/Parameters.ipynb                |  71 ++-
 .../Keithley_example.ipynb                    |   0
 .../Qcodes example ATS_ONWORK.ipynb           |   0
 .../Qcodes example with Agilent 34400A.ipynb  |   0
 .../Qcodes example with Decadac.ipynb         |   0
 .../Qcodes example with Ithaco.ipynb          |   0
 .../Qcodes example with Keithley 2600.ipynb   |   0
 ...es example with Mercury IPS (Magnet).ipynb |   0
 .../Qcodes example with QDac.ipynb            |   0
 ...odes example with Rohde Schwarz ZN20.ipynb |   0
 ...odes example with Tektronix AWG5014C.ipynb |   0
 .../Qcodes example with Triton.ipynb          |   0
 .../Triton1_thermometry.reg                   |   0
 docs/examples/testsweep/gates_chan0_set.dat   | 404 ------------------
 docs/examples/testsweep/snapshot.json         | 216 ----------
 docs/user/tutorial.rst                        |  19 +-
 17 files changed, 114 insertions(+), 668 deletions(-)
 rename docs/examples/{ => driver_examples}/Keithley_example.ipynb (100%)
 rename docs/examples/{ => driver_examples}/Qcodes example ATS_ONWORK.ipynb (100%)
 rename docs/examples/{ => driver_examples}/Qcodes example with Agilent 34400A.ipynb (100%)
 rename docs/examples/{ => driver_examples}/Qcodes example with Decadac.ipynb (100%)
 rename docs/examples/{ => driver_examples}/Qcodes example with Ithaco.ipynb (100%)
 rename docs/examples/{ => driver_examples}/Qcodes example with Keithley 2600.ipynb (100%)
 rename docs/examples/{ => driver_examples}/Qcodes example with Mercury IPS (Magnet).ipynb (100%)
 rename docs/examples/{ => driver_examples}/Qcodes example with QDac.ipynb (100%)
 rename docs/examples/{ => driver_examples}/Qcodes example with Rohde Schwarz ZN20.ipynb (100%)
 rename docs/examples/{ => driver_examples}/Qcodes example with Tektronix AWG5014C.ipynb (100%)
 rename docs/examples/{ => driver_examples}/Qcodes example with Triton.ipynb (100%)
 rename docs/examples/{ => driver_examples}/Triton1_thermometry.reg (100%)
 delete mode 100644 docs/examples/testsweep/gates_chan0_set.dat
 delete mode 100644 docs/examples/testsweep/snapshot.json

diff --git a/docs/examples/Creating Instrument Drivers.ipynb b/docs/examples/Creating Instrument Drivers.ipynb
index 807a5dc6eac..138e33d71f2 100644
--- a/docs/examples/Creating Instrument Drivers.ipynb	
+++ b/docs/examples/Creating Instrument Drivers.ipynb	
@@ -2,7 +2,10 @@
  "cells": [
   {
    "cell_type": "markdown",
-   "metadata": {},
+   "metadata": {
+    "deletable": true,
+    "editable": true
+   },
    "source": [
     "# Creating QCoDeS instrument drivers"
    ]
@@ -11,7 +14,9 @@
    "cell_type": "code",
    "execution_count": 1,
    "metadata": {
-    "collapsed": true
+    "collapsed": true,
+    "deletable": true,
+    "editable": true
    },
    "outputs": [],
    "source": [
@@ -28,7 +33,10 @@
   },
   {
    "cell_type": "markdown",
-   "metadata": {},
+   "metadata": {
+    "deletable": true,
+    "editable": true
+   },
    "source": [
     "## Base Classes\n",
     "\n",
@@ -42,7 +50,10 @@
   },
   {
    "cell_type": "markdown",
-   "metadata": {},
+   "metadata": {
+    "deletable": true,
+    "editable": true
+   },
    "source": [
     "## VisaInstrument: Simple example\n",
     "The Weinschel 8320 driver is about as basic a driver as you can get. It only defines one parameter, \"attenuation\". All the comments here are my additions to describe what's happening."
@@ -52,7 +63,9 @@
    "cell_type": "code",
    "execution_count": 2,
    "metadata": {
-    "collapsed": true
+    "collapsed": true,
+    "deletable": true,
+    "editable": true
    },
    "outputs": [],
    "source": [
@@ -100,7 +113,10 @@
   },
   {
    "cell_type": "markdown",
-   "metadata": {},
+   "metadata": {
+    "deletable": true,
+    "editable": true
+   },
    "source": [
     "## VisaInstrument: a more involved example\n",
     "the K2600 breaks one physical instrument into two software instruments, one for each channel. It:\n",
@@ -117,7 +133,9 @@
    "cell_type": "code",
    "execution_count": 3,
    "metadata": {
-    "collapsed": true
+    "collapsed": true,
+    "deletable": true,
+    "editable": true
    },
    "outputs": [],
    "source": [
@@ -195,7 +213,10 @@
   },
   {
    "cell_type": "markdown",
-   "metadata": {},
+   "metadata": {
+    "deletable": true,
+    "editable": true
+   },
    "source": [
     "## DLL-based instruments\n",
     "The Alazar cards use their own DLL. C interfaces tend to need a lot of boilerplate, so I'm not going to include it all. The key is: use `Instrument` directly, load the DLL, and have parameters interact with it."
@@ -205,7 +226,9 @@
    "cell_type": "code",
    "execution_count": 4,
    "metadata": {
-    "collapsed": true
+    "collapsed": true,
+    "deletable": true,
+    "editable": true
    },
    "outputs": [],
    "source": [
@@ -243,7 +266,10 @@
   },
   {
    "cell_type": "markdown",
-   "metadata": {},
+   "metadata": {
+    "deletable": true,
+    "editable": true
+   },
    "source": [
     "## Manual instruments\n",
     "A totally manual instrument (like the ithaco 1211) will contain only `ManualParameter`s. Some instruments may have a mix of manual and standard parameters. Here we also define a new `CurrentParameter` class that uses the ithaco parameters to convert a measured voltage to a current."
@@ -253,7 +279,9 @@
    "cell_type": "code",
    "execution_count": 5,
    "metadata": {
-    "collapsed": false
+    "collapsed": false,
+    "deletable": true,
+    "editable": true
    },
    "outputs": [],
    "source": [
@@ -360,7 +388,10 @@
   },
   {
    "cell_type": "markdown",
-   "metadata": {},
+   "metadata": {
+    "deletable": true,
+    "editable": true
+   },
    "source": [
     "## Custom Parameter classes\n",
     "\n",
@@ -383,7 +414,10 @@
   },
   {
    "cell_type": "markdown",
-   "metadata": {},
+   "metadata": {
+    "deletable": true,
+    "editable": true
+   },
    "source": [
     "## Dynamically adding and removing parameters\n",
     "\n",
@@ -401,7 +435,10 @@
   },
   {
    "cell_type": "markdown",
-   "metadata": {},
+   "metadata": {
+    "deletable": true,
+    "editable": true
+   },
    "source": [
     "## Functions\n",
     "\n",
@@ -410,7 +447,10 @@
   },
   {
    "cell_type": "markdown",
-   "metadata": {},
+   "metadata": {
+    "deletable": true,
+    "editable": true
+   },
    "source": [
     "## Organization\n",
     "\n",
@@ -445,7 +485,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.5.0"
+   "version": "3.5.2"
   }
  },
  "nbformat": 4,
diff --git a/docs/examples/Parameters.ipynb b/docs/examples/Parameters.ipynb
index b279762f077..722840217ba 100644
--- a/docs/examples/Parameters.ipynb
+++ b/docs/examples/Parameters.ipynb
@@ -2,7 +2,10 @@
  "cells": [
   {
    "cell_type": "markdown",
-   "metadata": {},
+   "metadata": {
+    "deletable": true,
+    "editable": true
+   },
    "source": [
     "# Parameters in QCoDeS"
    ]
@@ -11,7 +14,9 @@
    "cell_type": "code",
    "execution_count": 1,
    "metadata": {
-    "collapsed": true
+    "collapsed": true,
+    "deletable": true,
+    "editable": true
    },
    "outputs": [],
    "source": [
@@ -21,7 +26,10 @@
   },
   {
    "cell_type": "markdown",
-   "metadata": {},
+   "metadata": {
+    "deletable": true,
+    "editable": true
+   },
    "source": [
     "QCoDeS provides 5 classes of parameter built in. Three base classes (which must be subclassed to use):\n",
     "- `Parameter` represents a single value at a time\n",
@@ -40,7 +48,10 @@
   },
   {
    "cell_type": "markdown",
-   "metadata": {},
+   "metadata": {
+    "deletable": true,
+    "editable": true
+   },
    "source": [
     "## Parameter\n",
     "Most of the time you can use `StandardParameter` directly; even if you have custom `get`/`set` functions, but sometimes it's useful to subclass `Parameter`:"
@@ -50,7 +61,9 @@
    "cell_type": "code",
    "execution_count": 2,
    "metadata": {
-    "collapsed": false
+    "collapsed": false,
+    "deletable": true,
+    "editable": true
    },
    "outputs": [
     {
@@ -94,7 +107,9 @@
    "cell_type": "code",
    "execution_count": 3,
    "metadata": {
-    "collapsed": false
+    "collapsed": false,
+    "deletable": true,
+    "editable": true
    },
    "outputs": [
     {
@@ -130,7 +145,9 @@
    "cell_type": "code",
    "execution_count": 4,
    "metadata": {
-    "collapsed": false
+    "collapsed": false,
+    "deletable": true,
+    "editable": true
    },
    "outputs": [
     {
@@ -166,7 +183,10 @@
   },
   {
    "cell_type": "markdown",
-   "metadata": {},
+   "metadata": {
+    "deletable": true,
+    "editable": true
+   },
    "source": [
     "## ArrayParameter\n",
     "For actions that create a whole array of values at once. When you use it in a `Loop`, it makes a single `DataArray` with the array returned by `get` nested inside extra dimension(s) for the loop.\n",
@@ -178,7 +198,9 @@
    "cell_type": "code",
    "execution_count": 5,
    "metadata": {
-    "collapsed": false
+    "collapsed": false,
+    "deletable": true,
+    "editable": true
    },
    "outputs": [
     {
@@ -223,7 +245,9 @@
    "cell_type": "code",
    "execution_count": 6,
    "metadata": {
-    "collapsed": false
+    "collapsed": false,
+    "deletable": true,
+    "editable": true
    },
    "outputs": [
     {
@@ -261,7 +285,9 @@
    "cell_type": "code",
    "execution_count": 7,
    "metadata": {
-    "collapsed": false
+    "collapsed": false,
+    "deletable": true,
+    "editable": true
    },
    "outputs": [
     {
@@ -336,7 +362,10 @@
   },
   {
    "cell_type": "markdown",
-   "metadata": {},
+   "metadata": {
+    "deletable": true,
+    "editable": true
+   },
    "source": [
     "## MultiParameter\n",
     "Return multiple items at once, where each item can be a single value or an array. When you use it in a `Loop`, it makes a separate `DataArray` for each item.\n",
@@ -350,7 +379,9 @@
    "cell_type": "code",
    "execution_count": 8,
    "metadata": {
-    "collapsed": false
+    "collapsed": false,
+    "deletable": true,
+    "editable": true
    },
    "outputs": [
     {
@@ -391,7 +422,9 @@
    "cell_type": "code",
    "execution_count": 9,
    "metadata": {
-    "collapsed": false
+    "collapsed": false,
+    "deletable": true,
+    "editable": true
    },
    "outputs": [
     {
@@ -427,7 +460,9 @@
    "cell_type": "code",
    "execution_count": 10,
    "metadata": {
-    "collapsed": false
+    "collapsed": false,
+    "deletable": true,
+    "editable": true
    },
    "outputs": [
     {
@@ -467,7 +502,9 @@
    "cell_type": "code",
    "execution_count": 11,
    "metadata": {
-    "collapsed": false
+    "collapsed": false,
+    "deletable": true,
+    "editable": true
    },
    "outputs": [
     {
@@ -546,7 +583,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.5.0"
+   "version": "3.5.2"
   }
  },
  "nbformat": 4,
diff --git a/docs/examples/Keithley_example.ipynb b/docs/examples/driver_examples/Keithley_example.ipynb
similarity index 100%
rename from docs/examples/Keithley_example.ipynb
rename to docs/examples/driver_examples/Keithley_example.ipynb
diff --git a/docs/examples/Qcodes example ATS_ONWORK.ipynb b/docs/examples/driver_examples/Qcodes example ATS_ONWORK.ipynb
similarity index 100%
rename from docs/examples/Qcodes example ATS_ONWORK.ipynb
rename to docs/examples/driver_examples/Qcodes example ATS_ONWORK.ipynb
diff --git a/docs/examples/Qcodes example with Agilent 34400A.ipynb b/docs/examples/driver_examples/Qcodes example with Agilent 34400A.ipynb
similarity index 100%
rename from docs/examples/Qcodes example with Agilent 34400A.ipynb
rename to docs/examples/driver_examples/Qcodes example with Agilent 34400A.ipynb
diff --git a/docs/examples/Qcodes example with Decadac.ipynb b/docs/examples/driver_examples/Qcodes example with Decadac.ipynb
similarity index 100%
rename from docs/examples/Qcodes example with Decadac.ipynb
rename to docs/examples/driver_examples/Qcodes example with Decadac.ipynb
diff --git a/docs/examples/Qcodes example with Ithaco.ipynb b/docs/examples/driver_examples/Qcodes example with Ithaco.ipynb
similarity index 100%
rename from docs/examples/Qcodes example with Ithaco.ipynb
rename to docs/examples/driver_examples/Qcodes example with Ithaco.ipynb
diff --git a/docs/examples/Qcodes example with Keithley 2600.ipynb b/docs/examples/driver_examples/Qcodes example with Keithley 2600.ipynb
similarity index 100%
rename from docs/examples/Qcodes example with Keithley 2600.ipynb
rename to docs/examples/driver_examples/Qcodes example with Keithley 2600.ipynb
diff --git a/docs/examples/Qcodes example with Mercury IPS (Magnet).ipynb b/docs/examples/driver_examples/Qcodes example with Mercury IPS (Magnet).ipynb
similarity index 100%
rename from docs/examples/Qcodes example with Mercury IPS (Magnet).ipynb
rename to docs/examples/driver_examples/Qcodes example with Mercury IPS (Magnet).ipynb
diff --git a/docs/examples/Qcodes example with QDac.ipynb b/docs/examples/driver_examples/Qcodes example with QDac.ipynb
similarity index 100%
rename from docs/examples/Qcodes example with QDac.ipynb
rename to docs/examples/driver_examples/Qcodes example with QDac.ipynb
diff --git a/docs/examples/Qcodes example with Rohde Schwarz ZN20.ipynb b/docs/examples/driver_examples/Qcodes example with Rohde Schwarz ZN20.ipynb
similarity index 100%
rename from docs/examples/Qcodes example with Rohde Schwarz ZN20.ipynb
rename to docs/examples/driver_examples/Qcodes example with Rohde Schwarz ZN20.ipynb
diff --git a/docs/examples/Qcodes example with Tektronix AWG5014C.ipynb b/docs/examples/driver_examples/Qcodes example with Tektronix AWG5014C.ipynb
similarity index 100%
rename from docs/examples/Qcodes example with Tektronix AWG5014C.ipynb
rename to docs/examples/driver_examples/Qcodes example with Tektronix AWG5014C.ipynb
diff --git a/docs/examples/Qcodes example with Triton.ipynb b/docs/examples/driver_examples/Qcodes example with Triton.ipynb
similarity index 100%
rename from docs/examples/Qcodes example with Triton.ipynb
rename to docs/examples/driver_examples/Qcodes example with Triton.ipynb
diff --git a/docs/examples/Triton1_thermometry.reg b/docs/examples/driver_examples/Triton1_thermometry.reg
similarity index 100%
rename from docs/examples/Triton1_thermometry.reg
rename to docs/examples/driver_examples/Triton1_thermometry.reg
diff --git a/docs/examples/testsweep/gates_chan0_set.dat b/docs/examples/testsweep/gates_chan0_set.dat
deleted file mode 100644
index 7a747e0d052..00000000000
--- a/docs/examples/testsweep/gates_chan0_set.dat
+++ /dev/null
@@ -1,404 +0,0 @@
-# gates_chan0_set	meter_amplitude
-# "Gate Channel 0 (mV)"	"Current (nA)"
-# 401
--20	0.117
--19.9	0.117
--19.8	0.115
--19.7	0.111
--19.6	0.106
--19.5	0.099
--19.4	0.092
--19.3	0.085
--19.2	0.077
--19.1	0.071
--19	0.064
--18.9	0.058
--18.8	0.053
--18.7	0.048
--18.6	0.044
--18.5	0.04
--18.4	0.037
--18.3	0.034
--18.2	0.031
--18.1	0.029
--18	0.027
--17.9	0.025
--17.8	0.023
--17.7	0.022
--17.6	0.02
--17.5	0.019
--17.4	0.018
--17.3	0.017
--17.2	0.016
--17.1	0.015
--17	0.014
--16.9	0.013
--16.8	0.013
--16.7	0.012
--16.6	0.011
--16.5	0.011
--16.4	0.01
--16.3	0.01
--16.2	0.01
--16.1	0.009
--16	0.009
--15.9	0.008
--15.8	0.008
--15.7	0.008
--15.6	0.007
--15.5	0.007
--15.4	0.007
--15.3	0.007
--15.2	0.006
--15.1	0.006
--15	0.006
--14.9	0.006
--14.8	0.006
--14.7	0.007
--14.6	0.007
--14.5	0.007
--14.4	0.007
--14.3	0.008
--14.2	0.008
--14.1	0.008
--14	0.009
--13.9	0.009
--13.8	0.01
--13.7	0.01
--13.6	0.01
--13.5	0.011
--13.4	0.011
--13.3	0.012
--13.2	0.013
--13.1	0.013
--13	0.014
--12.9	0.015
--12.8	0.016
--12.7	0.017
--12.6	0.018
--12.5	0.019
--12.4	0.02
--12.3	0.022
--12.2	0.023
--12.1	0.025
--12	0.027
--11.9	0.029
--11.8	0.031
--11.7	0.034
--11.6	0.037
--11.5	0.04
--11.4	0.044
--11.3	0.048
--11.2	0.053
--11.1	0.058
--11	0.064
--10.9	0.071
--10.8	0.077
--10.7	0.085
--10.6	0.092
--10.5	0.099
--10.4	0.106
--10.3	0.111
--10.2	0.115
--10.1	0.117
--10	0.117
--9.9	0.117
--9.8	0.115
--9.7	0.111
--9.6	0.106
--9.5	0.099
--9.4	0.092
--9.3	0.085
--9.2	0.077
--9.1	0.071
--9	0.064
--8.9	0.058
--8.8	0.053
--8.7	0.048
--8.6	0.044
--8.5	0.04
--8.4	0.037
--8.3	0.034
--8.2	0.031
--8.1	0.029
--8	0.027
--7.9	0.025
--7.8	0.023
--7.7	0.022
--7.6	0.02
--7.5	0.019
--7.4	0.018
--7.3	0.017
--7.2	0.016
--7.1	0.015
--7	0.014
--6.9	0.013
--6.8	0.013
--6.7	0.012
--6.6	0.011
--6.5	0.011
--6.4	0.01
--6.3	0.01
--6.2	0.01
--6.1	0.009
--6	0.009
--5.9	0.008
--5.8	0.008
--5.7	0.008
--5.6	0.007
--5.5	0.007
--5.4	0.007
--5.3	0.007
--5.2	0.006
--5.1	0.006
--5	0.006
--4.9	0.006
--4.8	0.006
--4.7	0.007
--4.6	0.007
--4.5	0.007
--4.4	0.007
--4.3	0.008
--4.2	0.008
--4.1	0.008
--4	0.009
--3.9	0.009
--3.8	0.01
--3.7	0.01
--3.6	0.01
--3.5	0.011
--3.4	0.011
--3.3	0.012
--3.2	0.013
--3.1	0.013
--3	0.014
--2.9	0.015
--2.8	0.016
--2.7	0.017
--2.6	0.018
--2.5	0.019
--2.4	0.02
--2.3	0.022
--2.2	0.023
--2.1	0.025
--2	0.027
--1.9	0.029
--1.8	0.031
--1.7	0.034
--1.6	0.037
--1.5	0.04
--1.4	0.044
--1.3	0.048
--1.2	0.053
--1.1	0.058
--1	0.064
--0.9	0.071
--0.8	0.077
--0.7	0.085
--0.6	0.092
--0.5	0.099
--0.4	0.106
--0.3	0.111
--0.2	0.115
--0.1	0.117
-0	0.117
-0.1	0.117
-0.2	0.115
-0.3	0.111
-0.4	0.106
-0.5	0.099
-0.6	0.092
-0.7	0.085
-0.8	0.077
-0.9	0.071
-1	0.064
-1.1	0.058
-1.2	0.053
-1.3	0.048
-1.4	0.044
-1.5	0.04
-1.6	0.037
-1.7	0.034
-1.8	0.031
-1.9	0.029
-2	0.027
-2.1	0.025
-2.2	0.023
-2.3	0.022
-2.4	0.02
-2.5	0.019
-2.6	0.018
-2.7	0.017
-2.8	0.016
-2.9	0.015
-3	0.014
-3.1	0.013
-3.2	0.013
-3.3	0.012
-3.4	0.011
-3.5	0.011
-3.6	0.01
-3.7	0.01
-3.8	0.01
-3.9	0.009
-4	0.009
-4.1	0.008
-4.2	0.008
-4.3	0.008
-4.4	0.007
-4.5	0.007
-4.6	0.007
-4.7	0.007
-4.8	0.006
-4.9	0.006
-5	0.006
-5.1	0.006
-5.2	0.006
-5.3	0.007
-5.4	0.007
-5.5	0.007
-5.6	0.007
-5.7	0.008
-5.8	0.008
-5.9	0.008
-6	0.009
-6.1	0.009
-6.2	0.01
-6.3	0.01
-6.4	0.01
-6.5	0.011
-6.6	0.011
-6.7	0.012
-6.8	0.013
-6.9	0.013
-7	0.014
-7.1	0.015
-7.2	0.016
-7.3	0.017
-7.4	0.018
-7.5	0.019
-7.6	0.02
-7.7	0.022
-7.8	0.023
-7.9	0.025
-8	0.027
-8.1	0.029
-8.2	0.031
-8.3	0.034
-8.4	0.037
-8.5	0.04
-8.6	0.044
-8.7	0.048
-8.8	0.053
-8.9	0.058
-9	0.064
-9.1	0.071
-9.2	0.077
-9.3	0.085
-9.4	0.092
-9.5	0.099
-9.6	0.106
-9.7	0.111
-9.8	0.115
-9.9	0.117
-10	0.117
-10.1	0.117
-10.2	0.115
-10.3	0.111
-10.4	0.106
-10.5	0.099
-10.6	0.092
-10.7	0.085
-10.8	0.077
-10.9	0.071
-11	0.064
-11.1	0.058
-11.2	0.053
-11.3	0.048
-11.4	0.044
-11.5	0.04
-11.6	0.037
-11.7	0.034
-11.8	0.031
-11.9	0.029
-12	0.027
-12.1	0.025
-12.2	0.023
-12.3	0.022
-12.4	0.02
-12.5	0.019
-12.6	0.018
-12.7	0.017
-12.8	0.016
-12.9	0.015
-13	0.014
-13.1	0.013
-13.2	0.013
-13.3	0.012
-13.4	0.011
-13.5	0.011
-13.6	0.01
-13.7	0.01
-13.8	0.01
-13.9	0.009
-14	0.009
-14.1	0.008
-14.2	0.008
-14.3	0.008
-14.4	0.007
-14.5	0.007
-14.6	0.007
-14.7	0.007
-14.8	0.006
-14.9	0.006
-15	0.006
-15.1	0.006
-15.2	0.006
-15.3	0.007
-15.4	0.007
-15.5	0.007
-15.6	0.007
-15.7	0.008
-15.8	0.008
-15.9	0.008
-16	0.009
-16.1	0.009
-16.2	0.01
-16.3	0.01
-16.4	0.01
-16.5	0.011
-16.6	0.011
-16.7	0.012
-16.8	0.013
-16.9	0.013
-17	0.014
-17.1	0.015
-17.2	0.016
-17.3	0.017
-17.4	0.018
-17.5	0.019
-17.6	0.02
-17.7	0.022
-17.8	0.023
-17.9	0.025
-18	0.027
-18.1	0.029
-18.2	0.031
-18.3	0.034
-18.4	0.037
-18.5	0.04
-18.6	0.044
-18.7	0.048
-18.8	0.053
-18.9	0.058
-19	0.064
-19.1	0.071
-19.2	0.077
-19.3	0.085
-19.4	0.092
-19.5	0.099
-19.6	0.106
-19.7	0.111
-19.8	0.115
-19.9	0.117
-20	0.117
diff --git a/docs/examples/testsweep/snapshot.json b/docs/examples/testsweep/snapshot.json
deleted file mode 100644
index 93ef979f99f..00000000000
--- a/docs/examples/testsweep/snapshot.json
+++ /dev/null
@@ -1,216 +0,0 @@
-{
-    "__class__": "qcodes.data.data_set.DataSet",
-    "arrays": {
-        "gates_chan0_set": {
-            "__class__": "qcodes.data.data_array.DataArray",
-            "action_indices": [],
-            "array_id": "gates_chan0_set",
-            "instrument": "toymodel.MockGates",
-            "instrument_name": "gates",
-            "is_setpoint": true,
-            "label": "Gate Channel 0 (mV)",
-            "name": "chan0",
-            "shape": [
-                401
-            ],
-            "units": ""
-        },
-        "meter_amplitude": {
-            "__class__": "qcodes.data.data_array.DataArray",
-            "action_indices": [
-                0
-            ],
-            "array_id": "meter_amplitude",
-            "instrument": "toymodel.MockMeter",
-            "instrument_name": "meter",
-            "is_setpoint": false,
-            "label": "Current (nA)",
-            "name": "amplitude",
-            "shape": [
-                401
-            ],
-            "units": ""
-        }
-    },
-    "formatter": "qcodes.data.gnuplot_format.GNUPlotFormat",
-    "io": "<DiskIO, base_location='/Users/alex/qdev/Qcodes/docs/examples'>",
-    "location": "testsweep",
-    "loop": {
-        "__class__": "qcodes.loops.ActiveLoop",
-        "actions": [
-            {
-                "__class__": "qcodes.instrument.parameter.StandardParameter",
-                "instrument": "toymodel.MockMeter",
-                "instrument_name": "meter",
-                "label": "Current (nA)",
-                "name": "amplitude",
-                "ts": "2016-06-15 22:18:12",
-                "units": "",
-                "value": 0.117
-            }
-        ],
-        "background": true,
-        "delay": 0.003,
-        "sweep_values": {
-            "parameter": {
-                "__class__": "qcodes.instrument.parameter.StandardParameter",
-                "instrument": "toymodel.MockGates",
-                "instrument_name": "gates",
-                "label": "Gate Channel 0 (mV)",
-                "name": "chan0",
-                "ts": "2016-06-15 22:18:10",
-                "units": "",
-                "value": 0.0
-            },
-            "values": [
-                {
-                    "first": -20.0,
-                    "last": 20.0,
-                    "num": 401,
-                    "type": "linear"
-                }
-            ]
-        },
-        "then_actions": [],
-        "ts_end": "2016-06-15 22:18:19",
-        "ts_start": "2016-06-15 22:18:16",
-        "use_data_manager": true,
-        "use_threads": true
-    },
-    "station": {
-        "components": {},
-        "default_measurement": [
-            {
-                "__class__": "qcodes.instrument.parameter.StandardParameter",
-                "instrument": "toymodel.MockMeter",
-                "instrument_name": "meter",
-                "label": "Current (nA)",
-                "name": "amplitude",
-                "ts": "2016-06-15 22:18:12",
-                "units": "",
-                "value": 0.117
-            }
-        ],
-        "instruments": {
-            "gates": {
-                "__class__": "toymodel.MockGates",
-                "functions": {
-                    "reset": {}
-                },
-                "name": "gates",
-                "parameters": {
-                    "IDN": {
-                        "__class__": "qcodes.instrument.parameter.StandardParameter",
-                        "instrument": "toymodel.MockGates",
-                        "instrument_name": "gates",
-                        "label": "IDN",
-                        "name": "IDN",
-                        "ts": "2016-06-15 22:18:10",
-                        "units": "",
-                        "value": {
-                            "firmware": null,
-                            "model": null,
-                            "serial": null,
-                            "vendor": null
-                        }
-                    },
-                    "chan0": {
-                        "__class__": "qcodes.instrument.parameter.StandardParameter",
-                        "instrument": "toymodel.MockGates",
-                        "instrument_name": "gates",
-                        "label": "Gate Channel 0 (mV)",
-                        "name": "chan0",
-                        "ts": "2016-06-15 22:18:10",
-                        "units": "",
-                        "value": 0.0
-                    },
-                    "chan1": {
-                        "__class__": "qcodes.instrument.parameter.StandardParameter",
-                        "instrument": "toymodel.MockGates",
-                        "instrument_name": "gates",
-                        "label": "Gate Channel 1 (mV)",
-                        "name": "chan1",
-                        "ts": "2016-06-15 22:18:10",
-                        "units": "",
-                        "value": 0.0
-                    },
-                    "chan2": {
-                        "__class__": "qcodes.instrument.parameter.StandardParameter",
-                        "instrument": "toymodel.MockGates",
-                        "instrument_name": "gates",
-                        "label": "Gate Channel 2 (mV)",
-                        "name": "chan2",
-                        "ts": "2016-06-15 22:18:10",
-                        "units": "",
-                        "value": 0.0
-                    }
-                }
-            },
-            "meter": {
-                "__class__": "toymodel.MockMeter",
-                "functions": {},
-                "name": "meter",
-                "parameters": {
-                    "IDN": {
-                        "__class__": "qcodes.instrument.parameter.StandardParameter",
-                        "instrument": "toymodel.MockMeter",
-                        "instrument_name": "meter",
-                        "label": "IDN",
-                        "name": "IDN",
-                        "ts": "2016-06-15 22:18:10",
-                        "units": "",
-                        "value": {
-                            "firmware": null,
-                            "model": null,
-                            "serial": null,
-                            "vendor": null
-                        }
-                    },
-                    "amplitude": {
-                        "__class__": "qcodes.instrument.parameter.StandardParameter",
-                        "instrument": "toymodel.MockMeter",
-                        "instrument_name": "meter",
-                        "label": "Current (nA)",
-                        "name": "amplitude",
-                        "ts": "2016-06-15 22:18:12",
-                        "units": "",
-                        "value": 0.117
-                    }
-                }
-            },
-            "source": {
-                "__class__": "toymodel.MockSource",
-                "functions": {},
-                "name": "source",
-                "parameters": {
-                    "IDN": {
-                        "__class__": "qcodes.instrument.parameter.StandardParameter",
-                        "instrument": "toymodel.MockSource",
-                        "instrument_name": "source",
-                        "label": "IDN",
-                        "name": "IDN",
-                        "ts": "2016-06-15 22:18:10",
-                        "units": "",
-                        "value": {
-                            "firmware": null,
-                            "model": null,
-                            "serial": null,
-                            "vendor": null
-                        }
-                    },
-                    "amplitude": {
-                        "__class__": "qcodes.instrument.parameter.StandardParameter",
-                        "instrument": "toymodel.MockSource",
-                        "instrument_name": "source",
-                        "label": "Source Amplitude (μV)",
-                        "name": "amplitude",
-                        "ts": "2016-06-15 22:18:10",
-                        "units": "",
-                        "value": 0.1
-                    }
-                }
-            }
-        },
-        "parameters": {}
-    }
-}
\ No newline at end of file
diff --git a/docs/user/tutorial.rst b/docs/user/tutorial.rst
index b1e646ddb8b..31ced303bc5 100644
--- a/docs/user/tutorial.rst
+++ b/docs/user/tutorial.rst
@@ -3,34 +3,23 @@
 Tutorial
 ========
 
-In this tutorial we'll walk through *****
-
-
-.. _driver :
-
+:Gw
 Writing a Driver
 ----------------
 
-Write a simple driver example
-with commented code
-- add parameter
-- add validator
-- add custom stuff
-- add doccstrings f.ex
-
-.. todo::  missing
+First look at what parameters are and how to create them: `qcodes parameter <https://github.com/QCoDeS/Qcodes/blob/master/docs/examples/Parameters.ipynb>`__ .
 
+Then check out the walk-through to write your first driver:  `qcodes instrument <https://github.com/QCoDeS/Qcodes/blob/master/docs/examples/Creating%20Instrument%20Drivers.ipynb>`__ .
 
 Measuring
 ---------
 
-.. todo::  missing
+Browse the   `example <https://github.com/QCoDeS/Qcodes/blob/master/docs/examples/Measure%20without%20a%20Loop.ipynb>`__ .
 
 .. _simulation :
 
 Simulation
 ----------
-Explain the mock mock
 
 .. todo::  missing
 

From e4544af18a204b2bd9ce8d3bf0d3f6e8f81de406 Mon Sep 17 00:00:00 2001
From: Giulio Ungaretti <giulioungaretti@me.com>
Date: Thu, 16 Mar 2017 12:25:05 +0100
Subject: [PATCH 24/36] fix: remove mp from config

---
 qcodes/config/qcodesrc.json        |  1 -
 qcodes/config/qcodesrc_schema.json |  7 +------
 qcodes/plots/base.py               | 10 +---------
 3 files changed, 2 insertions(+), 16 deletions(-)

diff --git a/qcodes/config/qcodesrc.json b/qcodes/config/qcodesrc.json
index d63cfbc2800..ca4a05aa88d 100644
--- a/qcodes/config/qcodesrc.json
+++ b/qcodes/config/qcodesrc.json
@@ -1,6 +1,5 @@
 {
     "core":{
-        "legacy_mp": false,
         "loglevel": "DEBUG",
         "default_fmt": "data/{date}/#{counter}_{name}_{time}"
     },
diff --git a/qcodes/config/qcodesrc_schema.json b/qcodes/config/qcodesrc_schema.json
index c3b7963ba21..bcaecc8e329 100644
--- a/qcodes/config/qcodesrc_schema.json
+++ b/qcodes/config/qcodesrc_schema.json
@@ -7,11 +7,6 @@
             "description": "controls core settings of qcodes",
             "type" : "object",
             "properties" : {
-                "legacy_mp": {
-                    "type" : "boolean",
-                    "description": "control legacy buggy multiprocess",
-                    "default": false
-                },
                 "default_fmt": {
                     "type" : "string",
                     "description": "default location formatter",
@@ -30,7 +25,7 @@
                     ]
                 }
             },
-            "required":[ "legacy_mp", "loglevel" ]
+            "required":["loglevel" ]
         },
         "gui" : {
             "type" : "object",
diff --git a/qcodes/plots/base.py b/qcodes/plots/base.py
index 724945d7aa2..00c255c2307 100644
--- a/qcodes/plots/base.py
+++ b/qcodes/plots/base.py
@@ -1,9 +1,7 @@
 """
 Live plotting in Jupyter notebooks
 """
-from IPython.display import display
 
-from qcodes import config
 
 class BasePlot:
 
@@ -24,13 +22,7 @@ def __init__(self, interval=1, data_keys='xyz'):
         self.data_keys = data_keys
         self.traces = []
         self.data_updaters = set()
-        # only import in name space if the gui is set to noebook
-        # and there is multiprocessing
         self.interval = interval
-        if config['gui']['notebook'] and config['core']['legacy_mp']:
-            from qcodes.widgets.widgets import HiddenUpdateWidget
-            self.update_widget = HiddenUpdateWidget(self.update, interval)
-            display(self.update_widget)
 
     def clear(self):
         """
@@ -81,7 +73,7 @@ def add(self, *args, updater=None, **kwargs):
                 into `x`, `y`, and optionally `z`, these are passed along to
                 self.add_to_plot.
                 To use custom labels and units pass for example:
-                    plot.add(x=set, y=amplitude, 
+                    plot.add(x=set, y=amplitude,
                              xlabel="set"
                              xunit="V",
                              ylabel= "Amplitude",

From cced6c7c4e2e59168e8c00f7fe7b022822ca423f Mon Sep 17 00:00:00 2001
From: Giulio Ungaretti <giulioungaretti@me.com>
Date: Thu, 16 Mar 2017 13:17:44 +0100
Subject: [PATCH 25/36] fix: Remove server references

---
 qcodes/instrument/ip.py | 19 -------------------
 1 file changed, 19 deletions(-)

diff --git a/qcodes/instrument/ip.py b/qcodes/instrument/ip.py
index 9799353e7eb..3b8df6a9883 100644
--- a/qcodes/instrument/ip.py
+++ b/qcodes/instrument/ip.py
@@ -28,12 +28,6 @@ class IPInstrument(Instrument):
         write_confirmation (bool): Whether the instrument acknowledges writes
             with some response we should read. Default True.
 
-        server_name (str): Name of the InstrumentServer to use. Defaults to
-            'IPInstruments'.
-
-            Use ``None`` to run locally - but then this instrument will not
-            work with qcodes Loops or other multiprocess procedures.
-
         metadata (Optional[Dict]): additional static metadata to add to this
             instrument's JSON snapshot.
 
@@ -59,19 +53,6 @@ def __init__(self, name, address=None, port=None, timeout=5,
 
         self.set_persistent(persistent)
 
-    @classmethod
-    def default_server_name(cls, **kwargs):
-        """
-        Get the default server name for this instrument.
-
-        Args:
-            **kwargs: All the kwargs supplied in the constructor.
-
-        Returns:
-            str: By default all IPInstruments go on the server 'IPInstruments'.
-        """
-        return 'IPInstruments'
-
     def set_address(self, address=None, port=None):
         """
         Change the IP address and/or port of this instrument.

From 145db4d2158b9f329701dd176457cbab04726665 Mon Sep 17 00:00:00 2001
From: Giulio Ungaretti <giulioungaretti@me.com>
Date: Thu, 16 Mar 2017 13:18:00 +0100
Subject: [PATCH 26/36] chore: Add todo

---
 qcodes/tests/instrument_mocks.py | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/qcodes/tests/instrument_mocks.py b/qcodes/tests/instrument_mocks.py
index 4de3c460dad..4c757a830e6 100644
--- a/qcodes/tests/instrument_mocks.py
+++ b/qcodes/tests/instrument_mocks.py
@@ -55,6 +55,7 @@ class MockMetaParabola(Instrument):
     '''
     Test for a meta instrument, has a tunable gain knob
     '''
+    # TODO (giulioungaretti) remove unneded shared_kwargs
     shared_kwargs = ['mock_parabola_inst']
 
     def __init__(self, name, mock_parabola_inst, **kw):
@@ -157,4 +158,4 @@ def __init__(self):
                          setpoint_units=setpoint_units)
 
     def get(self):
-        return np.zeros(5), np.ones(5)
\ No newline at end of file
+        return np.zeros(5), np.ones(5)

From cdc657f55603f31741d3e125131a1a70982c7f92 Mon Sep 17 00:00:00 2001
From: Giulio Ungaretti <giulioungaretti@me.com>
Date: Thu, 16 Mar 2017 13:21:32 +0100
Subject: [PATCH 27/36] fix: Remove server and metaclass

---
 qcodes/instrument/base.py      | 106 ++-------------------------------
 qcodes/instrument/metaclass.py |  46 --------------
 qcodes/instrument/visa.py      |   7 ---
 qcodes/tests/test_visa.py      |   9 ++-
 4 files changed, 9 insertions(+), 159 deletions(-)
 delete mode 100644 qcodes/instrument/metaclass.py

diff --git a/qcodes/instrument/base.py b/qcodes/instrument/base.py
index ff1ef079413..b12bb5aa7ed 100644
--- a/qcodes/instrument/base.py
+++ b/qcodes/instrument/base.py
@@ -20,27 +20,6 @@ class Instrument(Metadatable, DelegateAttributes):
         name (str): an identifier for this instrument, particularly for
             attaching it to a Station.
 
-        server_name (Optional[str]): If not ``None``, this instrument starts a
-            separate server process (or connects to one, if one already exists
-            with the same name) and all hardware calls are made there.
-
-            Default '', then we call classmethod ``default_server_name``,
-            passing in all the constructor kwargs, to determine the name.
-            If not overridden, this just gives 'Instruments'.
-
-            **see subclass constructors below for more on ``server_name``**
-
-            Use None to operate without a server - but then this Instrument
-            will not work with qcodes Loops or other multiprocess procedures.
-
-            If a server is used, the ``Instrument`` you asked for is
-            instantiated on the server, and the object you get in the main
-            process is actually a ``RemoteInstrument`` that proxies all method
-            calls, ``Parameters``, and ``Functions`` to the server.
-
-            The metaclass ``InstrumentMetaclass`` handles making either the
-            requested class or its RemoteInstrument proxy.
-
         metadata (Optional[Dict]): additional static metadata to add to this
             instrument's JSON snapshot.
 
@@ -77,7 +56,7 @@ class Instrument(Metadatable, DelegateAttributes):
 
     _all_instruments = {}
 
-    def __init__(self, name, server_name=None, **kwargs):
+    def __init__(self, name, **kwargs):
         self._t0 = time.time()
         super().__init__(**kwargs)
         self.parameters = {}
@@ -90,7 +69,6 @@ def __init__(self, name, server_name=None, **kwargs):
 
         self._meta_attrs = ['name']
 
-        self._no_proxy_methods = {'__getstate__'}
         self.record_instance(self)
 
     def get_idn(self):
@@ -191,10 +169,7 @@ def record_instance(cls, instance):
         that there are no other instruments with the same name.
 
         Args:
-            instance (Union[Instrument, RemoteInstrument]): Note: we *do not*
-                check that instance is actually an instance of ``cls``. This is
-                important, because a ``RemoteInstrument`` should function as an
-                instance of the instrument it proxies.
+            instance (Instrument): Instance to record
 
         Raises:
             KeyError: if another instance with the same name is already present
@@ -338,11 +313,6 @@ def add_parameter(self, name, parameter_class=StandardParameter,
 
             **kwargs: constructor arguments for ``parameter_class``.
 
-        Returns:
-            dict: attribute information. Only used if you add parameters
-                from the ``RemoteInstrument`` rather than at construction, to
-                properly construct the proxy for this parameter.
-
         Raises:
             KeyError: if this instrument already has a parameter with this
                 name.
@@ -352,10 +322,6 @@ def add_parameter(self, name, parameter_class=StandardParameter,
         param = parameter_class(name=name, instrument=self, **kwargs)
         self.parameters[name] = param
 
-        # for use in RemoteInstruments to add parameters to the server
-        # we return the info they need to construct their proxy
-        return param.get_attrs()
-
     def add_function(self, name, **kwargs):
         """
         Bind one Function to this instrument.
@@ -376,11 +342,6 @@ def add_function(self, name, **kwargs):
 
             **kwargs: constructor kwargs for ``Function``
 
-        Returns:
-            A dict of attribute information. Only used if you add functions
-            from the ``RemoteInstrument`` rather than at construction, to
-            properly construct the proxy for this function.
-
         Raises:
             KeyError: if this instrument already has a function with this
                 name.
@@ -390,10 +351,6 @@ def add_function(self, name, **kwargs):
         func = Function(name=name, instrument=self, **kwargs)
         self.functions[name] = func
 
-        # for use in RemoteInstruments to add functions to the server
-        # we return the info they need to construct their proxy
-        return func.get_attrs()
-
     def snapshot_base(self, update=False):
         """
         State of the instrument as a JSON-compatible dict.
@@ -444,7 +401,8 @@ def print_readable_snapshot(self, update=False, max_chars=80):
         print('{0:<{1}}'.format('\tparameter ', par_field_len) + 'value')
         print('-'*80)
         for par in sorted(snapshot['parameters']):
-            msg = '{0:<{1}}:'.format(snapshot['parameters'][par]['name'], par_field_len)
+            name = snapshot['parameters'][par]['name']
+            msg = '{0:<{1}}:'.format(name, par_field_len)
             val = snapshot['parameters'][par]['value']
             unit = snapshot['parameters'][par]['unit']
             if isinstance(val, floating_types):
@@ -454,7 +412,7 @@ def print_readable_snapshot(self, update=False, max_chars=80):
             if unit is not '':  # corresponds to no unit
                 msg += '({})'.format(unit)
             # Truncate the message if it is longer than max length
-            if len(msg) > max_chars and not max_chars==-1:
+            if len(msg) > max_chars and not max_chars == -1:
                 msg = msg[0:max_chars-3] + '...'
             print(msg)
 
@@ -590,60 +548,6 @@ def call(self, func_name, *args):
         """
         return self.functions[func_name].call(*args)
 
-    #
-    # info about what's in this instrument, to help construct the remote     #
-    #
-
-    def connection_attrs(self, new_id):
-        """
-        Collect info to reconstruct the instrument API in the RemoteInstrument.
-
-        Args:
-            new_id (int): The ID of this instrument on its server.
-                This is how the RemoteInstrument points its calls to the
-                correct server instrument when it calls the server.
-
-        Returns:
-            dict: Dictionary of name: str, id: int, parameters: dict,
-                functions: dict, _methods: dict
-                parameters, functions, and _methods are dictionaries of
-                name: List(str) of attributes to be proxied in the remote.
-        """
-        return {
-            'name': self.name,
-            'id': new_id,
-            'parameters': {name: p.get_attrs()
-                           for name, p in self.parameters.items()},
-            'functions': {name: f.get_attrs()
-                          for name, f in self.functions.items()},
-            '_methods': self._get_method_attrs()
-        }
-
-    def _get_method_attrs(self):
-        """
-        Construct a dict of methods this instrument has.
-
-        Returns:
-            dict: Dictionary of method names : list of attributes each method
-                has that should be proxied. As of now, this is just its
-                docstring, if it has one.
-        """
-        out = {}
-
-        for attr in dir(self):
-            value = getattr(self, attr)
-            if ((not callable(value)) or
-                    value is self.parameters.get(attr) or
-                    value is self.functions.get(attr) or
-                    attr in self._no_proxy_methods):
-                # Functions and Parameters are callable and they show up in
-                # dir(), but they have their own listing.
-                continue
-
-            out[attr] = ['__doc__'] if hasattr(value, '__doc__') else []
-
-        return out
-
     def __getstate__(self):
         """Prevent pickling instruments, and give a nice error message."""
         raise RuntimeError(
diff --git a/qcodes/instrument/metaclass.py b/qcodes/instrument/metaclass.py
deleted file mode 100644
index 3e4593a29d2..00000000000
--- a/qcodes/instrument/metaclass.py
+++ /dev/null
@@ -1,46 +0,0 @@
-"""Metaclass to choose between Instrument and RemoteInstrument"""
-
-import warnings
-
-from .remote import RemoteInstrument
-
-
-class InstrumentMetaclass(type):
-    def __call__(cls, *args, server_name=None, **kwargs):
-        """
-        Create either a real Instrument or a RemoteInstrument as requested.
-
-        This (metaclass.__call__) is what is actually executed when you
-        instantiate an instrument, and returns the fully initialized object
-        (unlike class.__new__ which returns before __init__) so we can use this
-        to determine if the object was successfully created and only then
-        record its instance.
-
-        Args:
-            cls (type): the specific instrument class you invoked
-
-            *args (List[Any]): positional args to the instrument constructor
-
-            server_name (Optional[Union[str, None]]): if ``None`` we construct
-                a local instrument (with the class you requested). If a string,
-                we construct this instrument on a server with that name, or the
-                default from the instrument's classmethod
-                ``default_server_name`` if a blank string is used)
-
-            **kwargs (Dict[Any]): the kwargs to the instrument constructor,
-                after omitting server_name
-        """
-        if server_name is None:
-            instrument = super().__call__(*args, **kwargs)
-        else:
-            warnings.warn('Multiprocessing is in beta, use at own risk',
-                          UserWarning)
-
-            instrument = RemoteInstrument(*args, instrument_class=cls,
-                                          server_name=server_name, **kwargs)
-
-            # for RemoteInstrument, we want to record this instance with the
-            # class that it proxies, not with RemoteInstrument itself
-            cls.record_instance(instrument)
-
-        return instrument
diff --git a/qcodes/instrument/visa.py b/qcodes/instrument/visa.py
index 8260c650fad..5d341ea7402 100644
--- a/qcodes/instrument/visa.py
+++ b/qcodes/instrument/visa.py
@@ -25,13 +25,6 @@ class VisaInstrument(Instrument):
 
         terminator: Read termination character(s) to look for. Default ''.
 
-        server_name (str): Name of the InstrumentServer to use. By default
-            uses 'GPIBServer' for all GPIB instruments, 'SerialServer' for
-            serial port instruments, and 'VisaServer' for all others.
-
-            Use ``None`` to run locally - but then this instrument will not
-            work with qcodes Loops or other multiprocess procedures.
-
         metadata (Optional[Dict]): additional static metadata to add to this
             instrument's JSON snapshot.
 
diff --git a/qcodes/tests/test_visa.py b/qcodes/tests/test_visa.py
index 76407afdc84..bbe6e92141a 100644
--- a/qcodes/tests/test_visa.py
+++ b/qcodes/tests/test_visa.py
@@ -81,7 +81,7 @@ class TestVisaInstrument(TestCase):
     ]
 
     def test_ask_write_local(self):
-        mv = MockVisa('Joe', server_name=None)
+        mv = MockVisa('Joe')
 
         # test normal ask and write behavior
         mv.state.set(2)
@@ -124,18 +124,17 @@ def open_resource(self, address):
 
         rm_mock.return_value = MockRM()
 
-        MockBackendVisaInstrument('name', server_name=None)
+        MockBackendVisaInstrument('name')
         self.assertEqual(rm_mock.call_count, 1)
         self.assertEqual(rm_mock.call_args, ((),))
         self.assertEqual(address_opened[0], None)
 
-        MockBackendVisaInstrument('name2', server_name=None, address='ASRL2')
+        MockBackendVisaInstrument('name2', address='ASRL2')
         self.assertEqual(rm_mock.call_count, 2)
         self.assertEqual(rm_mock.call_args, ((),))
         self.assertEqual(address_opened[0], 'ASRL2')
 
-        MockBackendVisaInstrument('name3', server_name=None,
-                                  address='ASRL3@py')
+        MockBackendVisaInstrument('name3', address='ASRL3@py')
         self.assertEqual(rm_mock.call_count, 3)
         self.assertEqual(rm_mock.call_args, (('@py',),))
         self.assertEqual(address_opened[0], 'ASRL3')

From f01050e8c6ba9eacfe05da9b352ef869c28c64b3 Mon Sep 17 00:00:00 2001
From: Giulio Ungaretti <giulioungaretti@me.com>
Date: Thu, 16 Mar 2017 13:36:02 +0100
Subject: [PATCH 28/36] add stuff

---
 qcodes/instrument/base.py       | 27 +++------------------------
 qcodes/tests/test_instrument.py | 10 +++++++---
 2 files changed, 10 insertions(+), 27 deletions(-)

diff --git a/qcodes/instrument/base.py b/qcodes/instrument/base.py
index b12bb5aa7ed..96ae487a45b 100644
--- a/qcodes/instrument/base.py
+++ b/qcodes/instrument/base.py
@@ -24,23 +24,6 @@ class Instrument(Metadatable, DelegateAttributes):
             instrument's JSON snapshot.
 
 
-    Any unpicklable objects that are inputs to the constructor must be set
-    on server initialization, and must be shared between all instruments
-    that reside on the same server. To make this happen, set the
-    ``shared_kwargs`` class attribute to a tuple of kwarg names that should
-    be treated this way.
-
-    It is an error to initialize two instruments on the same server with
-    different keys or values for ``shared_kwargs``, unless the later
-    instruments have NO ``shared_kwargs`` at all.
-
-    subclass constructors: ``server_name`` and any ``shared_kwargs`` must be
-    available as kwargs and kwargs ONLY (not positional) in all subclasses,
-    and not modified in the inheritance chain. This is because we need to
-    create the server before instantiating the actual instrument. The easiest
-    way to manage this is to accept ``**kwargs`` in your subclass and pass them
-    on to ``super().__init()``.
-
     Attributes:
         name (str): an identifier for this instrument, particularly for
             attaching it to a Station.
@@ -199,12 +182,8 @@ def instances(cls):
         You can use this to get the objects back if you lose track of them,
         and it's also used by the test system to find objects to test against.
 
-        Note:
-            Will also include ``RemoteInstrument`` instances that proxy
-            instruments of this class.
-
         Returns:
-            List[Union[Instrument, RemoteInstrument]]
+            List[Instrument]]
         """
         if getattr(cls, '_type', None) is not cls:
             # only instances of a superclass - we want instances of this
@@ -218,7 +197,7 @@ def remove_instance(cls, instance):
         Remove a particular instance from the record.
 
         Args:
-            instance (Union[Instrument, RemoteInstrument])
+            instance (Union[Instrument])
         """
         wr = weakref.ref(instance)
         if wr in cls._instances:
@@ -242,7 +221,7 @@ def find_instrument(cls, name, instrument_class=None):
                 you are looking for.
 
         Returns:
-            Union[Instrument, RemoteInstrument]
+            Union[Instrument]
 
         Raises:
             KeyError: if no instrument of that name was found, or if its
diff --git a/qcodes/tests/test_instrument.py b/qcodes/tests/test_instrument.py
index d02ccdcc254..61bd6d845d7 100644
--- a/qcodes/tests/test_instrument.py
+++ b/qcodes/tests/test_instrument.py
@@ -10,11 +10,10 @@ class TestInstrument(TestCase):
 
     def setUp(self):
         self.instrument = DummyInstrument(
-            name='testdummy', gates=['dac1', 'dac2', 'dac3'], server_name=None)
+            name='testdummy', gates=['dac1', 'dac2', 'dac3'])
 
     def tearDown(self):
-        # TODO (giulioungaretti) remove ( does nothing ?)
-        pass
+        del self.instrument
 
     def test_validate_function(self):
         instrument = self.instrument
@@ -40,3 +39,8 @@ def test_attr_access(self):
 
         # make sure the gate is removed
         self.assertEqual(hasattr(instrument, 'dac1'), False)
+
+    def test_repr(self):
+        idn = dict(zip(('vendor', 'model', 'serial', 'firmware'),
+                       [None, self.instrument.name, None, None]))
+        self.assertEqual(idn, self.instrument.get_idn())

From 71295e89f4e449199964da93f3214b7acece4f3f Mon Sep 17 00:00:00 2001
From: Giulio Ungaretti <giulioungaretti@me.com>
Date: Thu, 16 Mar 2017 13:55:43 +0100
Subject: [PATCH 29/36] fix: use right default for _instances

---
 qcodes/instrument/base.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/qcodes/instrument/base.py b/qcodes/instrument/base.py
index 96ae487a45b..460729fbb94 100644
--- a/qcodes/instrument/base.py
+++ b/qcodes/instrument/base.py
@@ -124,7 +124,7 @@ def __del__(self):
         """Close the instrument and remove its instance record."""
         try:
             wr = weakref.ref(self)
-            if wr in getattr(self, '_instances', {}):
+            if wr in getattr(self, '_instances', []):
                 self._instances.remove(wr)
             self.close()
         except:

From dc6274b8b4b9368e5f09eca2cfc1dc0c8254336d Mon Sep 17 00:00:00 2001
From: Giulio Ungaretti <giulioungaretti@me.com>
Date: Thu, 16 Mar 2017 13:56:03 +0100
Subject: [PATCH 30/36] bugs

---
 qcodes/tests/test_instrument.py | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/qcodes/tests/test_instrument.py b/qcodes/tests/test_instrument.py
index 61bd6d845d7..e924e588b68 100644
--- a/qcodes/tests/test_instrument.py
+++ b/qcodes/tests/test_instrument.py
@@ -9,11 +9,16 @@
 class TestInstrument(TestCase):
 
     def setUp(self):
+        print("yolo")
         self.instrument = DummyInstrument(
             name='testdummy', gates=['dac1', 'dac2', 'dac3'])
-
-    def tearDown(self):
+    
+    def test_del(self):
+        import pdb
+        pdb.set_trace()
         del self.instrument
+        pdb.set_trace()
+        #self.assertEqual(DummyInstrument._instances, [])
 
     def test_validate_function(self):
         instrument = self.instrument

From 37c6fa127f22c3ffee821df37d426b60dc3d0d20 Mon Sep 17 00:00:00 2001
From: Giulio Ungaretti <giulioungaretti@me.com>
Date: Thu, 16 Mar 2017 16:56:01 +0100
Subject: [PATCH 31/36] feature: add more tests

---
 qcodes/tests/test_instrument.py | 62 ++++++++++++++++++++++++++++-----
 1 file changed, 53 insertions(+), 9 deletions(-)

diff --git a/qcodes/tests/test_instrument.py b/qcodes/tests/test_instrument.py
index e924e588b68..1af54e4197b 100644
--- a/qcodes/tests/test_instrument.py
+++ b/qcodes/tests/test_instrument.py
@@ -2,23 +2,24 @@
 Test suite for  instument.*
 """
 from unittest import TestCase
-
-from .instrument_mocks import DummyInstrument
+from qcodes.instrument.base import Instrument
+from .instrument_mocks import DummyInstrument, MockParabola
+from qcodes.instrument.parameter import ManualParameter
+import gc
 
 
 class TestInstrument(TestCase):
 
     def setUp(self):
-        print("yolo")
         self.instrument = DummyInstrument(
             name='testdummy', gates=['dac1', 'dac2', 'dac3'])
-    
-    def test_del(self):
-        import pdb
-        pdb.set_trace()
+        self.instrument2 = MockParabola("parabola")
+
+    def tearDown(self):
+        # force gc run
         del self.instrument
-        pdb.set_trace()
-        #self.assertEqual(DummyInstrument._instances, [])
+        del self.instrument2
+        gc.collect()
 
     def test_validate_function(self):
         instrument = self.instrument
@@ -28,6 +29,14 @@ def test_validate_function(self):
         with self.assertRaises(Exception):
             instrument.validate_status()
 
+    def test_check_instances(self):
+        with self.assertRaises(KeyError):
+            DummyInstrument(name='testdummy', gates=['dac1', 'dac2', 'dac3'])
+
+        self.assertEqual(Instrument.instances(), [])
+        self.assertEqual(DummyInstrument.instances(), [self.instrument])
+        self.assertEqual(self.instrument.instances(), [self.instrument])
+
     def test_attr_access(self):
         instrument = self.instrument
 
@@ -49,3 +58,38 @@ def test_repr(self):
         idn = dict(zip(('vendor', 'model', 'serial', 'firmware'),
                        [None, self.instrument.name, None, None]))
         self.assertEqual(idn, self.instrument.get_idn())
+
+    def test_add_remove_f_p(self):
+        with self.assertRaises(KeyError):
+                self.instrument.add_parameter('dac1', get_cmd='foo')
+        self.instrument.add_function('function', call_cmd='foo')
+        with self.assertRaises(KeyError):
+                self.instrument.add_function('function', call_cmd='foo')
+
+        self.instrument.add_function('dac1', call_cmd='foo')
+        # test custom __get_attr__
+        self.instrument['function']
+        # by desgin one gets the parameter if a function exists and has same
+        # name
+        dac1 = self.instrument['dac1']
+        self.assertTrue(isinstance(dac1, ManualParameter))
+
+    def test_instances(self):
+        instruments = [self.instrument, self.instrument2]
+        for instrument in instruments:
+            for other_instrument in instruments:
+                instances = instrument.instances()
+                # check that each instrument is in only its own
+                if other_instrument is instrument:
+                    self.assertIn(instrument, instances)
+                else:
+                    self.assertNotIn(other_instrument, instances)
+
+                # check that we can find each instrument from any other
+                self.assertEqual(
+                    instrument,
+                    other_instrument.find_instrument(instrument.name))
+
+            # check that we can find this instrument from the base class
+            self.assertEqual(instrument,
+                             Instrument.find_instrument(instrument.name))

From 7bfb43b53581e0cceb3300c416ae9bad40d84f60 Mon Sep 17 00:00:00 2001
From: Giulio Ungaretti <giulioungaretti@me.com>
Date: Thu, 16 Mar 2017 16:56:44 +0100
Subject: [PATCH 32/36] Remove find_component

---
 qcodes/instrument/base.py | 28 ----------------------------
 1 file changed, 28 deletions(-)

diff --git a/qcodes/instrument/base.py b/qcodes/instrument/base.py
index 460729fbb94..5cda80f9da0 100644
--- a/qcodes/instrument/base.py
+++ b/qcodes/instrument/base.py
@@ -243,34 +243,6 @@ def find_instrument(cls, name, instrument_class=None):
 
         return ins
 
-    @classmethod
-    def find_component(cls, name_attr, instrument_class=None):
-        """
-        Find a component of an existing instrument by name and attribute.
-
-        Args:
-            name_attr (str): A string in nested attribute format:
-                <name>.<attribute>[.<subattribute>] and so on.
-                For example, <attribute> can be a parameter name,
-                or a method name.
-            instrument_class (Optional[class]): The type of instrument
-                you are looking for this component within.
-
-        Returns:
-            Any: The component requested.
-        """
-
-        if '.' in name_attr:
-            name, attr = name_attr.split('.', 1)
-            ins = cls.find_instrument(name, instrument_class=instrument_class)
-            return ins.getattr(attr)
-
-        else:
-            # allow find_component to return the whole instrument,
-            # if no attribute was specified, for maximum generality.
-            return cls.find_instrument(name_attr,
-                                       instrument_class=instrument_class)
-
     def add_parameter(self, name, parameter_class=StandardParameter,
                       **kwargs):
         """

From a9b49a94c4ce40aba3614ac57ad658b0beb7580d Mon Sep 17 00:00:00 2001
From: Giulio Ungaretti <giulioungaretti@me.com>
Date: Thu, 16 Mar 2017 17:09:19 +0100
Subject: [PATCH 33/36] fix vim typo

---
 docs/user/tutorial.rst | 1 -
 1 file changed, 1 deletion(-)

diff --git a/docs/user/tutorial.rst b/docs/user/tutorial.rst
index 31ced303bc5..41bc21a9d44 100644
--- a/docs/user/tutorial.rst
+++ b/docs/user/tutorial.rst
@@ -3,7 +3,6 @@
 Tutorial
 ========
 
-:Gw
 Writing a Driver
 ----------------
 

From b099a83b2e467f47d40b1a8a463ba91008b05504 Mon Sep 17 00:00:00 2001
From: Giulio Ungaretti <giulioungaretti@me.com>
Date: Fri, 17 Mar 2017 15:01:09 +0100
Subject: [PATCH 34/36] fix: Remove array getter

---
 qcodes/instrument/mock.py | 38 --------------------------------------
 1 file changed, 38 deletions(-)
 delete mode 100644 qcodes/instrument/mock.py

diff --git a/qcodes/instrument/mock.py b/qcodes/instrument/mock.py
deleted file mode 100644
index c53cf3e93a0..00000000000
--- a/qcodes/instrument/mock.py
+++ /dev/null
@@ -1,38 +0,0 @@
-"""Mock instruments for testing purposes."""
-
-from .parameter import MultiParameter
-from qcodes import Loop
-from qcodes.data.data_array import DataArray
-
-
-class ArrayGetter(MultiParameter):
-    """
-    Example parameter that just returns a single array
-
-    TODO: in theory you can make this an ArrayParameter with
-    name, label & shape (instead of names, labels & shapes) and altered
-    setpoints (not wrapped in an extra tuple) and this mostly works,
-    but when run in a loop it doesn't propagate setpoints to the
-    DataSet. This is a bug
-    """
-    def __init__(self, measured_param, sweep_values, delay):
-        name = measured_param.name
-        super().__init__(names=(name,),
-                         shapes=((len(sweep_values),),),
-                         name=name)
-        self._instrument = getattr(measured_param, '_instrument', None)
-        self.measured_param = measured_param
-        self.sweep_values = sweep_values
-        self.delay = delay
-        self.shapes = ((len(sweep_values),),)
-        set_array = DataArray(parameter=sweep_values.parameter,
-                              preset_data=sweep_values)
-        self.setpoints = ((set_array,),)
-        if hasattr(measured_param, 'label'):
-            self.labels = (measured_param.label,)
-
-    def get(self):
-        loop = Loop(self.sweep_values, self.delay).each(self.measured_param)
-        data = loop.run_temp()
-        array = data.arrays[self.measured_param.full_name]
-        return (array,)

From 3e3ae2a3aa450815581805f78eb6a157b650dfec Mon Sep 17 00:00:00 2001
From: Giulio Ungaretti <giulioungaretti@me.com>
Date: Fri, 17 Mar 2017 15:05:44 +0100
Subject: [PATCH 35/36] fix: remove timing

---
 qcodes/utils/timing.py | 89 ------------------------------------------
 1 file changed, 89 deletions(-)
 delete mode 100644 qcodes/utils/timing.py

diff --git a/qcodes/utils/timing.py b/qcodes/utils/timing.py
deleted file mode 100644
index a624bb640aa..00000000000
--- a/qcodes/utils/timing.py
+++ /dev/null
@@ -1,89 +0,0 @@
-import time
-import multiprocessing as mp
-
-
-sleep_time = 0.001
-
-_calibration = {
-    'sleep_delay': None,
-    'async_sleep_delay': None,
-    'mp_start_delay': None
-}
-
-
-def calibrate(quiet=False):
-    if _calibration['mp_start_delay'] is None:
-        if not quiet:  # pragma: no cover
-            print('multiprocessing startup delay and regular sleep delays:')
-        mp_res = mptest(quiet=quiet)
-        _calibration['blocking_time'] = abs(mp_res['blocking_time'])
-        _calibration['mp_start_delay'] = abs(mp_res['startup_time'])
-        _calibration['mp_finish_delay'] = abs(mp_res['finish_time'])
-        _calibration['sleep_delay'] = abs(mp_res['median'])
-
-    return _calibration
-
-
-def report(startup_time, deviations,
-           queue=None, quiet=False):  # pragma: no cover
-    deviations.sort()
-    mindev = deviations[0]
-    avgdev = sum(deviations) / len(deviations)
-    meddev = deviations[len(deviations) // 2]
-    maxdev = deviations[-1]
-    if not quiet:
-        print('startup time: {:.3e}'.format(startup_time))
-        print('min/med/avg/max dev: {:.3e}, {:.3e}, {:.3e}, {:.3e}'.format(
-            mindev, meddev, avgdev, maxdev))
-
-    out = {
-        'startup_time': startup_time,
-        'min': mindev,
-        'max': maxdev,
-        'avg': avgdev,
-        'median': meddev,
-        'finish_time': time.time()
-    }
-    if queue:
-        queue.put(out)
-    return out
-
-
-def sleeper(n, d, t0, timer, queue, quiet):  # pragma: no cover
-    times = []
-    startup_time = time.time() - t0
-    for i in range(n):
-        times.append(timer())
-        time.sleep(d)
-
-    deviations = [times[i] - times[i - 1] - d for i in range(1, len(times))]
-    return report(startup_time, deviations, queue, quiet)
-
-
-def mptest(n=100, d=0.001, timer=time.perf_counter, quiet=False):
-    '''
-    test time.sleep performance, and the time to start a multiprocessing
-    Process. start time uses time.time() because some other timers start
-    from zero in each new process
-
-    n: how many asyncio.sleep calls to use
-        default 100
-    d: delay per sleep
-        default 0.001
-    timer: which system timer to use
-        default time.perf_counter
-    quiet: don't print anything
-        default False
-    '''
-
-    q = mp.Queue()
-    start_time = time.time()
-    p = mp.Process(target=sleeper, args=(n, d, start_time, timer, q, quiet))
-    p.start()
-    blocking_time = time.time() - start_time
-    p.join()
-
-    out = q.get()
-    out['finish_time'] = time.time() - out['finish_time']
-    out['blocking_time'] = blocking_time
-    return out

From 59f33f70032ca362b4ae70bdc06e901a6c51e922 Mon Sep 17 00:00:00 2001
From: Giulio Ungaretti <giulioungaretti@me.com>
Date: Tue, 21 Mar 2017 10:27:39 +0100
Subject: [PATCH 36/36] feature: Allow for legacy code to run

This allows for no exception but just a warning.
The deprecated argument is ignored.
---
 qcodes/instrument/base.py | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/qcodes/instrument/base.py b/qcodes/instrument/base.py
index 5cda80f9da0..6c02d7c2738 100644
--- a/qcodes/instrument/base.py
+++ b/qcodes/instrument/base.py
@@ -1,8 +1,9 @@
 """Instrument base class."""
 import logging
+import numpy as np
 import time
+import warnings
 import weakref
-import numpy as np
 
 from qcodes.utils.metadata import Metadatable
 from qcodes.utils.helpers import DelegateAttributes, strip_attrs, full_class
@@ -41,6 +42,9 @@ class Instrument(Metadatable, DelegateAttributes):
 
     def __init__(self, name, **kwargs):
         self._t0 = time.time()
+        if kwargs.pop('server_name', False):
+            warnings.warn("server_name argument not supported any more",
+                          stacklevel=0)
         super().__init__(**kwargs)
         self.parameters = {}
         self.functions = {}