diff --git a/docs/conf.py b/docs/conf.py
index af98825d4b14976517cd8c63be081212c0bd4c0b..b751183b4770f5fa41aa79debed0016ac6353d53 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -16,6 +16,7 @@ import os
 import sys
 sys.path.insert(0, os.path.abspath('../'))
 
+#import sphinx_rtd_theme
 
 # -- Project information -----------------------------------------------------
 
@@ -24,9 +25,9 @@ copyright = '2019, Stephan Philips'
 author = 'Stephan Philips'
 
 # The short X.Y version
-version = ''
+version = '1.3'
 # The full version, including alpha/beta/rc tags
-release = '0.2 alpha'
+release = '1.3'
 
 
 # -- General configuration ---------------------------------------------------
@@ -44,6 +45,8 @@ extensions = [
     'sphinx.ext.mathjax',
     'sphinx.ext.viewcode',
     'sphinx.ext.githubpages',
+    'sphinx.ext.napoleon',
+    #'sphinx_rtd_theme',
 ]
 
 # Add any paths that contain templates here, relative to this directory.
@@ -80,6 +83,7 @@ pygments_style = None
 # a list of builtin themes.
 #
 html_theme = 'sphinx_rtd_theme'
+#html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
 
 # Theme options are theme-specific and customize the look and feel of a theme
 # further.  For a list of options available for each theme, see the
diff --git a/docs/img/DC_compensation_pulses.png b/docs/img/DC_compensation_pulses.png
new file mode 100644
index 0000000000000000000000000000000000000000..558efdbac42966743e75ad06a239123e12e7640f
Binary files /dev/null and b/docs/img/DC_compensation_pulses.png differ
diff --git a/docs/img/Drawings.pptx b/docs/img/Drawings.pptx
new file mode 100644
index 0000000000000000000000000000000000000000..7033cc6f6c335c33dae6d4c278b5cf86f42b376f
Binary files /dev/null and b/docs/img/Drawings.pptx differ
diff --git a/docs/img/IQ_gain_error.png b/docs/img/IQ_gain_error.png
new file mode 100644
index 0000000000000000000000000000000000000000..361f817374ef90cb6757a46b82ae1d22bfa67dbb
Binary files /dev/null and b/docs/img/IQ_gain_error.png differ
diff --git a/docs/img/IQ_mixing.png b/docs/img/IQ_mixing.png
new file mode 100644
index 0000000000000000000000000000000000000000..fa409944808d8c110454b9e9802c8dc3cade3f6a
Binary files /dev/null and b/docs/img/IQ_mixing.png differ
diff --git a/docs/img/IQ_offset_error.png b/docs/img/IQ_offset_error.png
new file mode 100644
index 0000000000000000000000000000000000000000..a7d1b6701b0069f5b7c8645376b48269bdfc0284
Binary files /dev/null and b/docs/img/IQ_offset_error.png differ
diff --git a/docs/img/bias_T.png b/docs/img/bias_T.png
new file mode 100644
index 0000000000000000000000000000000000000000..5b2a5a938a1a21b8040c34d27ac8b059813c3de8
Binary files /dev/null and b/docs/img/bias_T.png differ
diff --git a/docs/img/bias_T_block_pulse.png b/docs/img/bias_T_block_pulse.png
new file mode 100644
index 0000000000000000000000000000000000000000..4acac2997e341485dacd923475e83342cb2e6816
Binary files /dev/null and b/docs/img/bias_T_block_pulse.png differ
diff --git a/docs/img/bias_T_sequence.png b/docs/img/bias_T_sequence.png
new file mode 100644
index 0000000000000000000000000000000000000000..52c624dc6fadccba498956777a379fc428765488
Binary files /dev/null and b/docs/img/bias_T_sequence.png differ
diff --git a/docs/img/ideal_modulation.png b/docs/img/ideal_modulation.png
new file mode 100644
index 0000000000000000000000000000000000000000..d1646b0c4e135087c4149d21c6bb51b1f15be339
Binary files /dev/null and b/docs/img/ideal_modulation.png differ
diff --git a/docs/img/long_pulses.png b/docs/img/long_pulses.png
new file mode 100644
index 0000000000000000000000000000000000000000..a7e29b74e18bb1eb4a2288e2f9b134c0b55a8193
Binary files /dev/null and b/docs/img/long_pulses.png differ
diff --git a/docs/img/long_pulses_with_compensation.png b/docs/img/long_pulses_with_compensation.png
new file mode 100644
index 0000000000000000000000000000000000000000..3962820a22476a9708bb1e5b8f95672705efa745
Binary files /dev/null and b/docs/img/long_pulses_with_compensation.png differ
diff --git a/docs/img/real_modulation.png b/docs/img/real_modulation.png
new file mode 100644
index 0000000000000000000000000000000000000000..c3a82ae723388397cf4d39305a8a26c76acb6d72
Binary files /dev/null and b/docs/img/real_modulation.png differ
diff --git a/docs/index.rst b/docs/index.rst
index 81efd7c614d3d3c96d6d045d22ace1cbf6317ab8..1989e1dba234531435caa0183b1872dcb9f6f236 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -3,28 +3,81 @@
    You can adapt this file completely to your liking, but it should at least
    contain the root `toctree` directive.
 
-Welcome to pulse lib's documentation
-====================================
-This is a pulse library designed to provide all the control signals that are needed control spin qubits coherenly.
-A lot of attention is given to performance, structure and ease of use.
+Pulse_lib
+=========
 
-Features now include:
-	- Support for arbitrary pulse/sine wave based sequences (phase coherent atm).
-	- Fully multidimensional. Execute any command as a loop in any dimension.
-	- Short and clean syntax. No sympy.
-	- Native support for virtual gates.
-	- IQ toolkit and IQ virtual channels -- Full suppport for single sideband modulation (Along with PM/AM/FM).
-	- Automatic compenstation for DC offsets.
-	- High speed uploader for Keysight PXI systems which supports upload during playback.
+Pulse_lib is a library to control multi-channel AWG pulse sequences and digitizer acquisitions
+with a simple API using physical units. It is designed to control qubit experiments, especially quantum dot
+and spin qubit experiments.
 
-Getting started:
+Sequences can contain direct voltage pulses, phase coherent microwave (MW) pulses, digital markers, triggers,
+and digitizer acquisitions. Parameters of the pulses in a sequence can be swept across a range of values. This turns the sequence in a
+multi-dimensional measurement.
 
-	- :ref:`struct_lib`
-	- :ref:`init_lib`
-	- :ref:`simple_pulse`
+Pulse_lib translates the specified pulse sequence to output signals of the AWG. It takes care of:
+
+* Phase coherence of pulses per qubit
+* Capacitive coupling of plunger and barrier gates of quantum dots using a virtual matrix
+* Signal delays due to vector signal generator and cables
+* MW up conversion by vector signal generator
+* Attenuators between AWG and target device
+* DC charging of bias-T, which acts as a high pass filter for AWG signals
+
+Pulses can be conditional on a measurement in the same sequence. However, this feature
+is currently only supported by the QuTech QuantumSequencer for Keysight PXI.
+
+Pulse_lib supports the following hardware:
+
+* Keysight PXI M3202A AWG and M3201A digitizer
+* Tektronix AWG5014 with Spectrum M4i digitizer
+* Qblox Pulsar QCM and QRM
+* QuTech QuantumSequencer for Keysight PXI
+
+
+.. toctree::
+	:maxdepth: 2
+	:caption: Getting started
+	:name: getting_started
+
+	introduction
+	installation
+	tutorials/basic_example
+
+.. toctree::
+	:maxdepth: 2
+	:caption: Signal physics
+
+	signals/delays
+	signals/attenuation
+	signals/bias_T
+	signals/cross_capacitance
+	signals/iq_modulation
+
+.. toctree::
+	:maxdepth: 1
+	:caption: User Guide
+
+	user/configuration
+	user/segments
+	user/timeline
+	user/voltage_channels
+	user/mw_channels
+	user/marker_channels
+	user/digitizer_channels
+	user/parameter_sweep
+	user/plotting_segments
+	user/acquisition_parameter
+	user/executing_sequence
+
+*TODO:*
+
+
+.. Getting started:
+
+..	- :ref:`struct_lib`
+..	- :ref:`init_lib`
+..	- :ref:`simple_pulse`
 
-..    :caption: Getting started
-..    :titlesonly:
 
 ..    struct
 ..    tutorials/init_lib
@@ -36,23 +89,6 @@ Getting started:
 ..    tutorials/example_PT
 ..    tutorials/example_RB
 
-When using the library in combination with the keysight PXI AWG's, playback of the waveforms is also supported:
-	- How does a upload work? What are the different steps?
-	- Your first simple upload.
-	- Integrating HVI.
-	- More advanced upload options, running uploads at high speeds.
-
-An overview of all the functions in the classes can be found at
-	- sequence
-	- segment containers
-	- segment base
-	- segment IQ
-
-API documentation for developers
-	- Requesting data from the sequence object.
-
-
-
 
 Indices and tables
 ==================
diff --git a/docs/installation.rst b/docs/installation.rst
new file mode 100644
index 0000000000000000000000000000000000000000..d1b663fda4d5518cd981f5a737a1d538eb4e7123
--- /dev/null
+++ b/docs/installation.rst
@@ -0,0 +1,62 @@
+.. title:: Installation
+
+Installation
+============
+
+Pulse_lib
+---------
+
+Clone the `sources of Pulse_lib <https://github.com/stephanlphilips/pulse_lib>`_ from GitHub.
+
+.. code-block:: console
+
+	pip install ./pulse_lib
+
+or
+
+.. code-block:: console
+
+	python3 setup.py install
+
+Pulse_lib uses the packages qcodes and qcodes_contrib_drivers.
+
+
+Keysight PXI
+------------
+
+To use pulse_lib with Keysight M3202A AWG and M3102A digitizer you have to install:
+
+* Keysight SD1 software
+* Keysight FPGA Test Sync Executive
+* Git clone `hvi2-script <https://github.com/QuTech-Delft/hvi2_script>`_ branch SD1_3.1
+* Git clone `core tools <https://github.com/stephanlphilips/core_tools>`_
+
+The core tools package contains the HVI2 schedules required to trigger the AWGs and digitzers.
+It contains the schedules for video mode and single shot measurements.
+
+The core tools package also contains a driver for the M3102A digitizer.
+
+
+Tektronix AWG5014
+-----------------
+
+No additional software is needed to use pulse_lib with AWG5014.
+
+A schedule to use AWG5014 with Spectrum M4i digitizer and Zurich Instruments UHFLI is included in pulse_lib.
+
+
+Qblox Pulsar QCM and QRM
+------------------------
+
+Note: Support for Qblox is still in development on a separate branch of pulse_lib.
+
+To use pulse_lib with Qblox you have to install:
+
+* package qblox_instruments (available on PyPi)
+* `Q1Pulse<https://github.com/sldesnoo-Delft/q1pulse>`_
+
+
+QuTech QuantumSequencer
+-----------------------
+
+The QuantumSequencer uses QuTech developed FPGA images for Keysight M3202A and M3102A.
diff --git a/docs/introduction.rst b/docs/introduction.rst
new file mode 100644
index 0000000000000000000000000000000000000000..01f81b4e2f9c0c9a70abb06da6c25f9f548f0856
--- /dev/null
+++ b/docs/introduction.rst
@@ -0,0 +1,122 @@
+.. title:: Introduction
+
+Introduction
+============
+
+Pulse_lib is a library to control multi-channel AWG pulse sequences and digitizer acquisitions
+with a simple API using physical units. It is designed to control qubit experiments, especially quantum dot
+and spin qubit experiments.
+
+
+Pulses are specified on user-defined channels. A channel can be used for either voltage pulses,
+microwave (MW) pulses, marker on-off pulses, or digitizer acquisition.
+
+
+Gates (voltage channels)
+------------------------
+
+A gate is used to apply voltage pulses on the target device. The pulses are output to one AWG channel, or in
+the case of a virtual gate to multiple AWG channels.
+A virtual gate is a combination of channels that can be used to compensate capacitive coupling.
+A virtual gate can also be a combination of other virtual gates, e.g. to define a detuning voltage.
+
+Voltage pulses are additive, i.e. pulses which overlap in time are summed.
+The following pulses can be added to a sequence on a (virtual) gate:
+
+* block pulses
+* ramps
+* sinusoidal pulses
+* custom pulses of arbitrary shape
+
+The pulse_lib configuration has settings to compensate the voltage pulses for:
+
+* Signal delays due to cables and filters
+* Attenuation between AWG and target device
+* DC charging of bias-T, which acts as a high pass filter for AWG signals
+* Capacitive coupling of plunger and barrier gates of quantum dots using a virtual matrix
+
+
+Qubit (MW) channels
+-------------------
+
+A qubit channel is used to apply phase coherent MW pulses to the target device.
+It should be assigned to an IQ output pair of the AWG. Multiple qubit channels can be assigned
+to one IQ output pair. (See hardware for limitations.)
+
+Every qubit channel has a reference frequency (or resonance frequency) used track the
+signal phase between pulses.
+
+The following pulses can be added to a sequence on a qubit channel:
+
+* MW pulse with optional envelope for amplitude and phase modulation
+* phase shift for virual-Z gates or phase correction after another gate
+* Frequency chirps
+
+The pulse_lib configuration has settings to compensate the MW pulses for:
+
+* Signal delays due to vector signal generator and cables
+* MW up conversion by vector signal generator
+* IQ mixer phase and amplitude errors
+
+
+Marker channels
+---------------
+
+A marker channel is a digital I/O or an AWG output channel used for example to trigger
+another instrument or to mute/unmute a signal.
+
+A marker channel can be linked to a MW channel to automatically mute/unmute the output of the MW source.
+It can be offset in time to unmute the MW source ahead of the MW pulse.
+
+
+Acquisition channels
+--------------------
+
+Acquisition channels are used to add acquisitions to a sequence. The input for the acquisition channel
+can be single digitizer input channel, or an input pair representing I and Q inputs.
+The input can be demodulated and phase shifted.
+
+The acquisition can specify to return averaged the data or a down-sampled time trace.
+A threshold can be set on the averaged value to convert it to a qubit state measurement.
+
+
+Physical units
+--------------
+
+Pulses in pulse_lib are specified in physical units like they should arrive on the target device:
+
+* Amplitudes are specified in millivolts
+* Time is specified in nanoseconds
+* MW pulses are specified for a specific qubit and resonance and drive frequency in Hz
+* Channels are identified with a logical name
+
+Parameter sweeps
+----------------
+
+Parameters of the pulses in a sequence can be swept across a range of values. This turns the sequence in a
+multi-dimensional measurement.
+
+Conditional pulses
+------------------
+
+Pulses can be made conditional on one or more measurements in the same sequence.
+The conditional pulses can be used to create classical controlled qubit gates.
+
+This feature is currently only supported by the QuTech QuantumSequencer for Keysight PXI.
+
+Supported hardware
+------------------
+
+Pulse_lib supports the following hardware:
+
+* Keysight PXI M3202A AWG and M3201A digitizer
+* Tektronix AWG5014 with Spectrum M4i digitizer, AlazarTech ATS or Zurich Instruments UHFLI
+* Qblox Pulsar QCM and QRM
+* QuTech QuantumSequencer for Keysight PXI
+
+See the hardware specific sections for supported features and limitations.
+
+The communication with the AWGs has been optimized to minimize the overhead between measurements.
+The compilation of pulse sequences and the communication with the AWGs will be further optimized
+with every new release of the software.
+
diff --git a/docs/signals/attenuation.rst b/docs/signals/attenuation.rst
new file mode 100644
index 0000000000000000000000000000000000000000..b83b31fa148bbc67cf03e5bff3740fb63cf57a63
--- /dev/null
+++ b/docs/signals/attenuation.rst
@@ -0,0 +1,19 @@
+.. title: Attenuation
+
+Signal attenuation
+==================
+
+The signal from AWG to device is electrically attenuated to reduce the amount of noise on the device.
+The signal-to-noise ratio of the AWG is high when the signal has a high amplitude. On the device the
+required signal amplitude is much lower and must be attenuated.
+
+Pulselib compensates for this attenuation. The value should be specified as the fraction of the signal
+transmitted to the device.
+
+Example:
+  If the attenuation is 12 dB, then the amplitude at the device will be 0.25 of the amplitude at the AWG.
+  An attenuation of 0.25 should be specified for the channel.
+
+  .. code-block:: python
+
+      pl.add_channel_attenuation('P1', 0.25)
diff --git a/docs/signals/bias_T.rst b/docs/signals/bias_T.rst
new file mode 100644
index 0000000000000000000000000000000000000000..758c3556edc05f8b1a4cbc8966f296c1b774c9c3
--- /dev/null
+++ b/docs/signals/bias_T.rst
@@ -0,0 +1,90 @@
+.. title: Bias-T
+
+Bias-T
+======
+
+The plunger and barrier gates of quantum dots have a DC voltage offset to maintain the desired operational regime.
+The gates are pulsed for the initialization, manipulation and readout of the qubit state.
+The DC voltage source and the AWG-generated pulses are combined by means of a bias-T.
+
+.. figure:: /img/bias_T.png
+    :scale: 50%
+
+    Bias-T connecting the high frequency AWG and the low frequency DAC to the device.
+
+The bias-T is a T-like component which acts as a high-pass filter for the AWG pulses and as a low-pass filter
+for the DC voltage. It consists of a resistor and a capacitor with values in the order of 1 MOhm and 100 nF
+giving an RC-time in the order of 0.1 s.
+The a cut-off frequency :math:`f_c = 1/2\pi R C` is in the order of a few Hz.
+
+he high-pass filter on the AWG signal results in amplitude decays for long pulses and
+accumulation of an offset when the average voltage of a sequence is not zero.
+This offset will grow with every repetition of the sequence until the offset is has the negative voltage
+of the average of the sequence.
+
+.. figure:: /img/bias_T_block_pulse.png
+    :scale: 75%
+
+    Decay of the amplitude of a long block pulse due to the bias-T high pass filtering with RC-time = 0.1 s.
+
+
+.. figure:: /img/bias_T_sequence.png
+    :scale: 90%
+
+    The deviation after 2 pulses of ~0.5 ms is only 1.6 mV. After 100 repetitions the deviation is > 50 mV.
+
+
+DC-compensation
+---------------
+
+The average voltage of a sequence should be 0.0 V to avoid a growing voltage offset due to the bias-T
+high pass filtering.
+Pulse_lib will automatically add a DC-compensation pulse when the average of a sequence is not zero.
+This DC-compensation is enabled for all channels where the channel compensation limits are set.
+
+Note: Contrary to all other settings, the compensation limits are set in AWG voltage, not the device voltage.
+
+Example:
+  Enable DC-compensation for channels P1 and P2 with limits of -200 and +500 mV.
+
+  .. code-block:: python
+
+    pl.add_channel_compensation_limit('P1', (-200, 500))
+    pl.add_channel_compensation_limit('P2', (-200, 500))
+
+.. figure:: /img/DC_compensation_pulses.png
+    :scale: 75%
+
+    DC compensation with automatically added pulses of -200 mV at the end of the sequence.
+
+
+Bias-T compensation
+-------------------
+
+Sequences with long pulses or long sequences with the average voltage not equal to zero will
+be distorted by the bias-T when the duration exceeds a few percent of the RC-time.
+Pulse_lib will compensate for the bias-T high-pass filtering when the bias-T time compensation is
+configured.
+This bias-T correction will increase the sequence compilation time with a small percentage.
+
+The bias-T compensation can correct pulses with a duration in the order of the RC-time.
+Pulses that are longer than a few times the RC-time will eventually hit the limits of the AWG output range,
+because the bias-T compensation increases the amplitude of the signal.
+A good correction of long pulses is only possible when the configured RC-time is accurate enough.
+An error of 2% in the configured RC-time gives an error of 10% in the amplitude at the end of a pulse
+with a duration of 5 times the RC-time.
+
+Note: The time of the bias-T is specified in seconds!
+
+Example:
+  Enable bias-T compensation for channels P1 and P2.
+
+  .. code-block:: python
+
+        pulse.add_channel_bias_T_compensation('P1', 0.102)
+        pulse.add_channel_bias_T_compensation('P2', 0.106)
+
+.. figure:: /img/long_pulses_with_compensation.png
+    :scale: 75%
+
+    Bias-T compensated pulses. The dashed lines show the signal after bias-T with the desired rectangular pulses.
diff --git a/docs/signals/cross_capacitance.rst b/docs/signals/cross_capacitance.rst
new file mode 100644
index 0000000000000000000000000000000000000000..8cbc09d6b2fe1732ad0e1111a4b2a1d8bc747034
--- /dev/null
+++ b/docs/signals/cross_capacitance.rst
@@ -0,0 +1,91 @@
+.. title: Cross-capacitance
+
+Cross-capacitance
+=================
+The chemical potential of the quantum dots used in spin-qubit devices determines the amount of electrons that
+will be loaded in the quantum dot. The chemical potential is controlled by a plunger gate close to the quantum dot.
+However, due to the small distance between quantum dots the potential of a quantum dot is also affected
+by neighbouring plunger and barrier gates. This is the capacitive cross-talk, or cross-capacitance, from a gate to
+other quantum dots. This cross-capacitance is classical in nature and can be corrected by pulse_lib using
+"virtual gates".
+
+A virtual gate is a pulse_lib channel that outputs a pulse sequence on multiple AWG channels
+such that only a single chemical potential or single tunnel coupling will be affected by the pulses.
+Virtual gates are defined by a virtual gate matrix.
+
+
+Virtual Gate Matrix
+===================
+
+A virtual gate matrix is a matrix that relates the virtual gate voltages to the real voltages.
+
+	:math:`\begin{pmatrix} vP1 \\ vP2 \\ vP3 \end{pmatrix} = M \begin{pmatrix} P1 \\ P2 \\ P3 \end{pmatrix}`
+
+When there would me no cross effects, this matrix would look like:
+
+	:math:`M = \begin{pmatrix} 1  & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \end{pmatrix}`
+
+Which gives a one to one map of the virtual gate voltages to the real voltages.
+In reality, this will not be the case. There will be cross-capacitances.
+
+	:math:`M = \begin{pmatrix} 1  & C_{12} & C_{13} \\ C_{21} & 1 & C_{23} \\ C_{31} & C_{32} & 1 \end{pmatrix}`
+
+The values on the diagonal are kept equal to 1. The lever arm of :math:`vP1` will then be equal to the lever
+arm of :math:`P1`.
+A correct virtual matrix will remove the slant from the lines in the charge stability diagram without stretching it.
+
+See *Loading a quantum-dot based "Qubyte" register*, C. Volk (2019), for a detailed description
+of cross-capacitance and virtual gates.
+
+
+Virtual gate matrix in pulse_lib
+--------------------------------
+
+Pulse_lib inverts cross-capacitance matrix :math:`M` to calculate the voltages on the output channels.
+
+	:math:`\begin{pmatrix} P1 \\ P2 \\ P3 \end{pmatrix} = M^{-1} \begin{pmatrix} vP1 \\ vP2 \\ vP3 \end{pmatrix}`
+
+The cross-capacitance matrix (real-to-virtual) can be passed to pulse_lib, but also the inverted
+matrix (virtual-to-real) can be passed. The cross-capacitance matrix has to be a square matrix, because it
+must be invertible. The virtual-to-real matrix doesn't have to be square.
+
+Example:
+  .. code-block:: python
+
+      pl.add_virtual_matrix(
+        name='virtual-gates',
+        real_gate_names=['B0', 'P1', 'B1', 'P2', 'B2'],
+        virtual_gate_names=['vB0', 'vP1', 'vB1', 'vP2', 'vB2'],
+        matrix=[
+            [1.00, 0.25, 0.05, 0.00, 0.00],
+            [0.14, 1.00, 0.12, 0.02, 0.00],
+            [0.05, 0.16, 1.00, 0.11, 0.01],
+            [0.02, 0.09, 0.18, 1.00, 0.16],
+            [0.00, 0.01, 0.013 0.21, 1.00]
+            ],
+        real2virtual=True)
+
+
+Combining virtual gates to a combined parameter
+-----------------------------------------------
+
+The use of the virtual matrix is not restricted to the definition of virtual gates to compensate
+for the cross-capacitance. It can also be used to define a new channel for voltage pulses that is
+a linear combination of virtual gates, e.g. to define a detuning parameter.
+
+Example:
+  A detuning parameter e12 and a energy parameter U12 is defined using a virtual-to-real matrix.
+
+  .. code-block:: python
+
+      pl.add_virtual_matrix(
+        name='detuning12',
+        real_gate_names=['vP1', 'vP2'],
+        virtual_gate_names=['e12', 'U12'],
+        matrix=[
+            [+0.5, +1.0],
+            [-0.5, +1.0],
+            ],
+        real2virtual=False)
+
+
diff --git a/docs/signals/delays.rst b/docs/signals/delays.rst
new file mode 100644
index 0000000000000000000000000000000000000000..54c32b617a57791c98ddbf31c5c205a6fe7411fa
--- /dev/null
+++ b/docs/signals/delays.rst
@@ -0,0 +1,36 @@
+.. title: Signal delay
+
+Signal delays
+=============
+
+It takes time for a signal to get from the AWG to the target device and from the device to the digitizer.
+Pulses with equal start time but on different channels should arrive at the same time on the target device.
+This is not by default true, because signals travel along different paths with different travel times.
+Pulse_lib can compensate for these difference in signal delays.
+
+Signal delays in pulse and acquisition paths are caused by:
+
+* propagation through cables, which is approximately 3 ns / m.
+* propagation through vector signal generator, which takes 20 - 50 ns.
+* propagation through RF up-convertor, down-converter.
+* processing time in AWG
+* processing time in digitizer
+
+The delay can be specified per channel. It is specified as the delay added to the channel.
+
+Example:
+ If the MW signal is delayed by the VSG and arrives 45 ns later than the signals of gates P1 and P2,
+ then you can add 45 ns to the gates P1 and P2.
+
+ .. code-block:: python
+
+     pl.add_channel_delay('P1', 45)
+     pl.add_channel_delay('P2', 45)
+
+ Alternatively, you can also subtract 45 ns for the I and Q channel.
+
+ .. code-block:: python
+
+     pl.add_channel_delay('I1', -45)
+     pl.add_channel_delay('Q1', -45)
+
diff --git a/docs/signals/iq_modulation.rst b/docs/signals/iq_modulation.rst
new file mode 100644
index 0000000000000000000000000000000000000000..5fc5498b9f06631e85acacc4c593ce2fc2b50235
--- /dev/null
+++ b/docs/signals/iq_modulation.rst
@@ -0,0 +1,152 @@
+.. title: IQ modulation
+
+IQ Modulation
+=============
+
+Spin qubit resonant frequencies are typically 2 to 20 GHz. This is much higher than the bandwidth of the AWGs.
+In experiments microwave (MW) sources are used to manipulate the qubits. The microwave signals must be amplitude
+and phase modulated for full qubit control.
+A common solution for this modulation of MW signals is in-phase and quadrature (IQ) modulation.
+The in-phase and quadrature MW sinusoids are mixed with an IQ modulation pair from the AWG.
+See `In-phase and quadrature components <https://en.wikipedia.org/wiki/In-phase_and_quadrature_components>`_.
+
+  .. figure:: /img/IQ_mixing.png
+     :scale: 80 %
+
+     IQ mixing with carrier frequency :math:`f_c`
+
+The output of this mixer is:
+
+	:math:`y(t) = I(t) cos(\omega_c t) - Q(t) sin(\omega_c t)`
+
+
+IQ modulation can be used to create a single frequency output signal which is higher of lower in frequency
+than the MW source. For this the IQ modulation signals should be sinusoids with a 90 degrees shift.
+
+	:math:`I(t) = A(t) cos(\omega_m t + \phi(t))`
+
+	:math:`Q(t) = A(t) sin(\omega_m t + \phi(t))`
+
+	:math:`y(t) = A(t) [cos(\omega_m t + \phi(t)) cos(\omega_c t) - sin(\omega_m t + \phi(t)) sin(\omega_c t)]`
+
+	:math:`y(t) = A(t) cos((\omega_c + \omega_m) t + \phi(t))`
+
+
+IQ modulation allows frequency multiplexing, because it is a linear operation. The I and Q components can
+contain multiple frequencies which will all be shifted with :math:`f_c`.
+IQ modulation can also be used for fast chirps (frequency sweeps), because phase and frequency of the
+I and Q components can be swiftly changed by the AWG.
+
+
+IQ modulation in pulse_lib
+--------------------------
+Users of pulse_lib don't have to care about the calculation of I and Q outputs.
+They can specify the desired MW pulses after IQ modulation and pulse_lib calculates the I and Q output signals
+for the AWG.
+
+The user has to specify the I and Q output channels of the AWG as an IQ pair and pass the frequency of the
+vector signal generator, the LO frequency.
+For coherent qubit control every qubit needs a channel with the resonant frequency of the qubit.
+
+Example:
+  .. code-block:: python
+
+    pl.define_channel('I1','AWG1', 3)
+    pl.define_channel('Q1','AWG1', 4)
+
+    # define IQ output pair
+    IQ_pair_1 = IQ_channel_constructor(pl)
+    IQ_pair_1.add_IQ_chan("I1", "I")
+    IQ_pair_1.add_IQ_chan("Q1", "Q")
+    # frequency of the MW source
+    IQ_pair_1.set_LO(2.40e9)
+
+    # add 1 qubit: q1
+    IQ_pair_1.add_virtual_IQ_channel("q1", 2.415e6)
+
+
+IQ modulation errors
+--------------------
+
+Idealy the IQ mixer creates single side-band signal.
+
+.. figure:: /img/ideal_modulation.png
+
+   Ideal IQ modulation
+
+In practice the signals and electrical components are not perfect. Small differences between amplifiers,
+filters and path length result in small errors in the IQ output.
+
+The I and Q output of the AWG can have a voltage offset, a (frequency dependent) gain difference and
+a (frequency dependent) phase difference. The output signal after modulation will contain the carrier frequency
+and the mirror side-band.
+
+.. figure:: /img/real_modulation.png
+
+   IQ modulation in practice with remainder of the carrier frequency and a mirrored side-band.
+
+Offset error
+~~~~~~~~~~~~
+
+A voltage offset in the AWG output results in the output of the carrier frequency.
+
+	:math:`y(t) = [a+cos(\omega_m t)] cos(\omega_c t) - [b + sin(\omega_m t)] sin(\omega_c t)]`
+
+	:math:`y(t) = cos((\omega_c + \omega_m) t) + a \cdot cos(\omega_c t) - b \cdot sin(\omega_c t)`
+
+.. figure:: /img/IQ_offset_error.png
+
+   Remainder of carrier frequency due to offset error.
+
+
+Gain error
+~~~~~~~~~~
+
+A difference in gain between I and Q components add the mirrored side-band frequency,
+:math:`f_c - f_m`, to the output.
+
+	:math:`y(t) = (1 + a) cos(\omega_m t) cos(\omega_c t) - sin(\omega_m t) sin(\omega_c t)`
+
+	:math:`y(t) = (1+\frac{a}{2}) cos((\omega_c + \omega_m) t) + \frac{a}{2} cos((\omega_c - \omega_m) t)`
+
+
+.. figure:: /img/IQ_gain_error.png
+
+   Mirrored side-band due to gain error.
+
+Phase error
+~~~~~~~~~~~
+
+When the phase difference between the I and Q components is not exactly 90 degrees then the mirrored
+side-band frequency is output as well. The resulting output is similar to the output with a gain error.
+
+	:math:`y(t) = cos(\omega_m t + \frac{a}{2}) cos(\omega_c t) - sin(\omega_m t - \frac{a}{2}) sin(\omega_c t)`
+
+	:math:`y(t) = cos(\frac{a}{2}) cos((\omega_c + \omega_m) t) - sin(\frac{a}{2}) sin((\omega_c - \omega_m) t)`
+
+
+
+IQ corrections in pulse_lib
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A vector signal generator will have options to correct the offset, phase and gain error of the IQ input, but
+only with a frequency independent correction.
+Pulse_lib can also correct for these errors, where gain and phase corrections are frequency dependent.
+
+Example:
+  Add offset correction to I and Q components.
+
+  .. code-block:: python
+
+    pl.add_channel_offset('I1', 10)
+    pl.add_channel_offset('Q1', -5)
+
+  Add gain and phase offset to qubit channels.
+
+  .. code-block:: python
+
+    IQ_pair_1.add_virtual_IQ_channel("q2", 2.421e9,
+                                     correction_gain=(1.0, 0.9))
+    IQ_pair_1.add_virtual_IQ_channel("q3", 2.473e9,
+                                     correction_gain=(0.98, 1.0),
+                                     correction_phase=0.3)
diff --git a/docs/tutorials/basic_example.rst b/docs/tutorials/basic_example.rst
new file mode 100644
index 0000000000000000000000000000000000000000..4c09bada5d37e97663d67a501f10fef5a119a030
--- /dev/null
+++ b/docs/tutorials/basic_example.rst
@@ -0,0 +1,106 @@
+.. title: Basic example
+
+Basic example
+=============
+
+
+
+Configure pulse_lib
+-------------------
+
+Create a pulse_lib object with gates for voltage pulses and 2 qubit channels for MW pulses.
+
+.. code-block:: python
+
+    pl = pulse_lib(backend='Keysight')
+
+    # add AWGs and digitizers
+    pl.add_awg(awg1)
+    p1.add_digitizer(digitizer)
+
+    # gates (voltage channels)
+    pl.define_channel('P1', awg1, 1)
+    pl.define_channel('P2', awg1, 2)
+
+    # IQ output pair
+    pl.define_channel('I1', awg1, 3)
+    pl.define_channel('Q1', awg1, 4)
+    IQ_pair_1 = IQ_channel_constructor(pl)
+    IQ_pair_1.add_IQ_chan("I1", "I")
+    IQ_pair_1.add_IQ_chan("Q1", "Q")
+
+    # set frequency of the MW source for down-conversion
+    IQ_pair_1.set_LO(mw_source.freq)
+
+    # add qubit channels
+    IQ_pair_1.add_virtual_IQ_channel("q1", q1_freq)
+    IQ_pair_1.add_virtual_IQ_channel("q2", q2_freq)
+
+    # acquisition channel
+    pl.define_digitizer_channel('S1', digitizer, 1)
+
+    pl.finish_init()
+
+
+Create a sequence
+-----------------
+
+A sequence is made of one or more segments. Here we use a single segment.
+
+.. code-block:: python
+
+    seg = pl.create_segment()
+
+Initialize the qubit with a voltage pulse on the gates.
+After the pulse the voltage returns to (0.0, 0.0)
+
+Voltage pulses on multiple channels can be added with ``add_block`` and ``add_ramp`` on the segment.
+The start and end time of a pulse are relative to a reference time in the segment.
+The reference time is moved to the end of the last pulse with reset_time.
+
+.. code-block:: python
+
+    gates = ['P1','P2']
+    # initialize qubit with 200 ns pulse of P1,P2 to v_init
+    v_init = (46.0, 25.5)
+    seg.add_block(0, 200, gates, v_init, reset_time=True)
+    seg.wait(40, reset_time=True)
+
+Generate a Ramsey pulse sequence with two MW pulses for qubit 1 with a wait time in between.
+Channels can be accessed as an attribute of the segment (``seg.q1``), and as an index in the segment (``seg['q1']``).
+
+.. code-block:: python
+
+    seg.q1.add_MW_pulse(0, q1_X90_t, q1_X90_amplitude)
+    seg.q1.wait(t_wait, reset_time=True)
+    seg.q1.add_MW_pulse(0, q1_X90_t, q1_X90_amplitude)
+    seg.wait(20, reset_time=True)
+
+Move the qubit to the readout point and start measurement 140 ns after start of the block pulse.
+
+.. code-block:: python
+
+    v_readout = (46.0, 25.5)
+    seg.add_ramp(0, 200, gates, (0.0, 0.0), v_readout, reset_time=True)
+    seg.S1.acquire(140, t_measure=1500)
+    seg.add_block(0, 1700, gates, v_readout, reset_time=True)
+
+Execute the sequence
+--------------------
+
+The segments have to be compiled to a sequence. The sequence has to be uploaded to the AWGs before execution.
+The acquired data can be retrieved with the acquisition parameter. This is a qcodes MultiParameter.
+
+.. code-block:: python
+
+    seq = pl.make_sequence([seg])
+    acq_param = seq.get_acquisition_param()
+
+    # upload sequence data to AWG
+    seq.upload()
+    # play the sequence
+    seq.play()
+
+    # retrieve measurement data
+    data = acq_param()
+
diff --git a/docs/user/configuration.rst b/docs/user/configuration.rst
new file mode 100644
index 0000000000000000000000000000000000000000..b39293066a2b03db6a3cd0ec74ade282f216a385
--- /dev/null
+++ b/docs/user/configuration.rst
@@ -0,0 +1,142 @@
+.. title: pulse_lib configuration
+
+Configuration
+=============
+
+The configuration of pulse_lib is stored in a pulselib object.
+This object is needed to create segments and sequences.
+
+Create pulselib object with specific backend
+---------------------------------------------
+
+A pulselib object must created for a specific backend for the hardware.
+
+.. code-block:: python
+
+    from pulse_lib.base_pulse import pulselib
+
+    pl = pulselib('Keysight')
+
+    # Add channels ...
+    # Configure channels ....
+
+At the end, after adding and configuring all channels, ``pl.finish_init()``
+must be called to complete the initialization.
+
+
+Add AWGs and digitizers
+-----------------------
+
+.. code-block:: python
+
+    pl.add_awg(awg1)
+    pl.add_awg(awg2)
+    pl.add_digitizer(digitizer)
+
+Note: Qblox QRM should be added as a digitizer. See @@@
+
+Gates (voltage channels)
+------------------------
+
+Gates (voltage channels) should be defined with a name for the channel and
+a name and channel number of the AWG.
+
+The channel delay specifies the amount of delay that should be added to the signal.
+The channel attenuation is expressed in the fraction of the amplitude after attenuation.
+The DC compensation limits are specified in AWG voltage before attenuation.
+
+.. code-block:: python
+
+    pl.add_channel("P1', awg1.name, 1)
+    pl.add_channel_delay('P1', 17)
+
+    # 0.01 = -20 dB attenuation
+    pl.add_channel_attenuation('P1', 0.01)
+
+    # Add limits on voltages for DC channel compensation.
+    # When no limit is specified then no DC compensation is performed.
+    # Limits are specified in AWG voltage before attenuation.
+    pl.add_channel_compensation_limit('P1', (-200, 500))
+
+    # Add compensation for bias-T with RC-time of 0.109 s
+    pl.add_channel_bias_T_compensation('P1', 0.109)
+
+Virtual matrix
+--------------
+
+``keep_square`` and @@@ are optional parameters that can only be set when ``real2virtual=True``. ???
+
+.. code-block:: python
+
+      pl.add_virtual_matrix(
+        name='virtual-gates',
+        real_gate_names=['B0', 'P1', 'B1', 'P2', 'B2'],
+        virtual_gate_names=['vB0', 'vP1', 'vB1', 'vP2', 'vB2'],
+        matrix=[
+            [1.00, 0.25, 0.05, 0.00, 0.00],
+            [0.14, 1.00, 0.12, 0.02, 0.00],
+            [0.05, 0.16, 1.00, 0.11, 0.01],
+            [0.02, 0.09, 0.18, 1.00, 0.16],
+            [0.00, 0.01, 0.013 0.21, 1.00]
+            ],
+        real2virtual=True,
+        keep_square=Tue,
+        @@@)
+
+      pl.add_virtual_matrix(
+        name='detuning12',
+        real_gate_names=['vP1', 'vP2'],
+        virtual_gate_names=['e12', 'U12'],
+        matrix=[
+            [+0.5, +1.0],
+            [-0.5, +1.0],
+            ],
+        real2virtual=False)
+
+Qubit channels (MW channels)
+----------------------------
+
+.. code-block:: python
+
+    from pulse_lib.virtual_channel_constructors import IQ_channel_constructor
+
+    pl.add_channel("I1', awg2.name, 3)
+    pl.add_channel("Q1', awg2.name, 4)
+    pl.add_channel_delay('I1', -52)
+    pl.add_channel_delay('Q1', -52)
+
+    # define IQ output pair
+    IQ_pair_1 = IQ_channel_constructor(pulse)
+    IQ_pair_1.add_IQ_chan("I1", "I")
+    IQ_pair_1.add_IQ_chan("Q1", "Q")
+
+    # frequency of the MW source
+    IQ_pair_1.set_LO(lo_freq)
+
+    # add channel for qubit q1
+    IQ_pair_1.add_virtual_IQ_channel("q1", 3.213e9)
+
+IQ phase-gain compensation
+Offset
+add marker
+
+
+Marker channels
+---------------
+
+delay
+
+
+Digitizer channels
+------------------
+
+Note: Digitizers  triggers
+
+.. code-block:: python
+
+    pl.define_digitizer_channel('SD1', digitizer.name, 1)
+
+IQ input pair
+
+RF-source
+