<jupyter_start><jupyter_text>Qcodes example with DelegateInstrument driverThis notebooks explains how to use the `DelegateInstrument` driver. AboutThe goal of the `DelegateInstrument` driver is to make it easier to combine different parameters together into a new "virtual" instrument. Each parameter on a `DelegateInstrument` can point to one or more parameters on other instruments in the station. UsageThe way it's used is mainly by specifying an entry in the station YAML. For instance, let's say you want to use a magnetic field coil. The driver has a method set_field(value, block), that by default is set to block=True, which means the field is ramped in a way that blocks further execution until the desired value is reached. However, let's say you are creating a measurement in which you want the parameter to be set, and while the value is ramping, you want to measure other parameters. This can be done by using `DelegateInstrument` and specifying a custom `setter` for the parameter that gets and sets the magnetic field.By default, each parameter is represented by a `DelegateParameter`. The `DelegateInstrument` also supports passing multiple source parameters to a given parameter. In order to do this, simply specify multiple parameters in the dictionary values  under the `parameters` key.<jupyter_code>%%writefile example.yaml

instruments:
  field_X:
    type: qcodes.tests.instrument_mocks.MockField

  field:
    type: qcodes.instrument.delegate.DelegateInstrument
    init:
      parameters:
        X:
          - field_X.field
        ramp_rate:
          - field_X.ramp_rate
        combined:
          - field_X.field
          - field_X.ramp_rate
      set_initial_values_on_load: true
      initial_values:
        ramp_rate: 1.0
      setters:
        X:
          method: field_X.set_field
          block: false
import qcodes as qc
station = qc.Station(config_file="example.yaml")
field_X = station.load_field_X()
field = station.load_field(station=station)
field.X()
field.X(1.)
field.X()
field.X()
field.X()
field.X()<jupyter_output><empty_output><jupyter_text>As you can see, the field is now ramped in the background with the specified ramp rate. Now, let's try to create a measurement that uses this ability, and ramps the field in the background while measuring:<jupyter_code>field.ramp_rate(10.)
field_X.field(0.0)
field.X()
import time
meas = qc.Measurement(station=station)
meas.register_parameter(field.X)

with meas.run() as datasaver:
    for B in [0.1, 0.0]:
        field.X(B)
        while field.X() != B:
            datasaver.add_result((field.X, field.X()))
            time.sleep(0.01)
    datasaver.flush_data_to_database()
datasaver.dataset.to_pandas_dataframe().plot()<jupyter_output><empty_output><jupyter_text>When specifying multiple source parameters on a given parameter, the grouped parameter will automatically return a `namedtuple` that returns both values.<jupyter_code>field.combined()<jupyter_output><empty_output><jupyter_text>We can now also create a custom parameter that does a simple calculation based on the current parameters.<jupyter_code>import numpy as np

def calculate_ramp_time(X, ramp_rate):
    """Calculate ramp time in seconds"""
    dfield = np.abs(field.target_field - X)
    return 60. * dfield/ramp_rate
field._create_and_add_parameter(
    group_name="ramp_time",
    station=station,
    paths=["field_X.field", "field_X.ramp_rate"],
    formatter=calculate_ramp_time
)
field.ramp_rate(1.0)
field.target_field = 0.1
field.ramp_time()
field.X(0.1)
field.ramp_time()
import time
time.sleep(1.)
field.ramp_time()
import time
time.sleep(1.)
field.ramp_time()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.08117679106510488, 'fraction_numerical': 0.006537728139471534, 'mean_word_length': 4.2457142857142856, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '4', 'dir': 'jupyter-structured-clean-dedup', 'id': '236327', 'license': 'MIT', 'n_tokens_mistral': 1110, 'n_tokens_neox': 1084, 'n_words': 378, 'path': 'docs/examples/driver_examples/QCoDeS example with DelegateInstrument.ipynb', 'repo_name': 'dbwz8/Qcodes', 'size': '3671'}