Esempio n. 1
0
class AWG(InstrumentChannel):
    """Device-specific *AWG Core* for the *UHFQA*.

    Inherits from :class:`InstrumentChannel` and wraps around a `AWGCore` for
    *HDAWG* from :mod:`zhinst-toolkit`. This class adds Parameters from the
    :mod:`zhinst-toolkit` as *QCoDeS Parameters* and wraps all methods of the
    *toolkit's* `AWGCore`.

    Arguments:
        name (str): The name of the `AWG` submodule.
        parent_instr (:class:`qcodes.instrument.base.Instrument`): The QCoDeS
            parent instrument of the `InstrumentChannel`.
        parent_contr (:class:`zhinst.toolkit.BaseInstrument`): The `_controller`
            of the parent instrument that is used for getting and setting
            parameters.

    Attributes:
        output1 (:class:`Parameter`): The state
            of the output of channel 1. Can be one of {'on', 'off'}.
        output2 (:class:`Parameter`): The state
            of the output of channel 2. Can be one of {'on', 'off'}.
        gain1 (:class:`Parameter`): Gain of the
            output channel 1. The value must be between -1 and +1 (default: +1).
        gain2 (:class:`Parameter`): Gain of the
            output channel 2. The value must be between -1 and +1 (default: +1).
        waveforms (list): A list of `Waveforms` that respresent the queue of
            waveforms to upload to the device when the sequence type is
            *'Simple'*.
        is_running (bool): A flag that shows if the `AWG Core` is currently
            running or not.
        index (int): The index of the `AWG Core` in the list of *awgs*.

    """
    def __init__(self, name: str, parent_instr, parent_contr) -> None:
        super().__init__(parent_instr, name)
        self._awg = UHFQA_AWG(parent_contr, 0)
        self._awg._setup()
        self._awg._init_awg_params()
        self._add_qcodes_awg_params()

    def _add_qcodes_awg_params(self):
        # add custom parameters as QCoDeS parameters
        self.add_parameter(
            "output1",
            unit=self._awg.output1._unit,
            docstring=self._awg.output1.__repr__(),
            get_cmd=self._awg.output1,
            set_cmd=self._awg.output1,
            label="Output Ch 1",
        )
        self.add_parameter(
            "output2",
            unit=self._awg.output2._unit,
            docstring=self._awg.output2.__repr__(),
            get_cmd=self._awg.output2,
            set_cmd=self._awg.output2,
            label="Output Ch 2",
        )
        self.add_parameter(
            "gain1",
            unit=self._awg.gain1._unit,
            docstring=self._awg.gain1.__repr__(),
            get_cmd=self._awg.gain1,
            set_cmd=self._awg.gain1,
            label="Gain Ch 1",
        )
        self.add_parameter(
            "gain2",
            unit=self._awg.gain2._unit,
            docstring=self._awg.gain2.__repr__(),
            get_cmd=self._awg.gain2,
            set_cmd=self._awg.gain2,
            label="Gain Ch 2",
        )
        self.add_parameter(
            "single",
            unit=self._awg.single._unit,
            docstring=self._awg.single.__repr__(),
            get_cmd=self._awg.single,
            set_cmd=self._awg.single,
            label="AWG Single Shot Mode",
        )

    def outputs(self, value=None):
        """Sets both signal outputs simultaneously.

        Arguments:
            value (tuple): Tuple of values {'on', 'off'} for channel 1
                and 2 (default: None).

        Returns:
            A tuple with the states {'on', 'off'} for the two output
            channels if the keyword argument is not given.

        Raises:
            ValueError: If the `value` argument is not a list or tuple
                of length 2.

        """
        return self._awg.outputs(value=value)

    def run(self, sync=True) -> None:
        """Run the AWG Core.

        Arguments:
            sync (bool): A flag that specifies if a synchronisation
                should be performed between the device and the data
                server after enabling the AWG Core (default: True).

        """
        self._awg.run(sync=sync)

    def stop(self, sync=True) -> None:
        """Stop the AWG Core.

        Arguments:
            sync (bool): A flag that specifies if a synchronisation
                should be performed between the device and the data
                server after disabling the AWG Core (default: True).

        """
        self._awg.stop(sync=sync)

    def wait_done(self,
                  timeout: float = 10,
                  sleep_time: float = 0.005) -> None:
        """Wait until the AWG Core is finished.

        Arguments:
            timeout (float): The maximum waiting time in seconds for the
                AWG Core (default: 10).
            sleep_time (float): Time in seconds to wait between
                requesting AWG state

        Raises:
            ToolkitError: If the AWG is running in continuous mode.
            TimeoutError: If the AWG is not finished before the timeout.

        """
        self._awg.wait_done(timeout=timeout, sleep_time=sleep_time)

    def compile(self) -> None:
        """Compiles the current SequenceProgram on the AWG Core.

        Raises:
            ToolkitConnectionError: If the AWG Core has not been set up
                yet
            ToolkitError: if the compilation has failed or the ELF
                upload is not successful.
            TimeoutError: if the program upload is not completed before
                timeout.

        """
        self._awg.compile()

    def reset_queue(self) -> None:
        """Resets the waveform queue to an empty list."""
        self._awg.reset_queue()

    def queue_waveform(
        self,
        wave1: Union[List, np.array],
        wave2: Union[List, np.array],
        delay: float = 0,
    ) -> None:
        """Queues up a waveform to the *AWG Core*.

        Uploading custom waveforms is only possible when using the
        *'Simple'* or *'Custom'* sequence types. The waveform is
        specified with two numpy arrays for the two channels of the
        *AWG Core*. The waveform will then automatically align them to
        the correct minimum waveform length, sample granularity and
        scaling. An individual delay can be specified to shift the
        individual waveform with respect to the time origin of the
        period.

        Arguments:
            wave1 (array like): A list or array of samples in the
                waveform to be queued for channel 1. An empty list '[]'
                will upload zeros of the minimum waveform length.
            wave2 (array like): A list or array of samples in the
                waveform to be queued for channel 2. An empty list '[]'
                will upload zeros of the minimum waveform length.
            delay (float): An individual delay for the queued sequence
                with respect to the time origin. Positive values shift
                the start of the waveform forwards in time. (default: 0)

        Raises:
            ToolkitError: If the sequence is not of type *'Simple'* or
                *'Custom'*.

        """
        self._awg.queue_waveform(wave1, wave2, delay=delay)

    def replace_waveform(
        self,
        wave1: Union[List, np.array],
        wave2: Union[List, np.array],
        i: int = 0,
        delay: float = 0,
    ) -> None:
        """Replaces the data in a waveform in the queue.

        The new data must have the same length as the previous data
        s.t. the waveform data can be replaced without recompilation of
        the sequence program.

        Arguments:
            wave1 (array): Waveform to replace current wave for
                Channel 1.
            wave2 (array): Waveform to replace current wave for
                Channel 2.
            i (int): The index of the waveform in the queue to be
                replaced.
            delay (int): An individual delay in seconds for this
                waveform w.r.t. the time origin of the sequence
                (default: 0).

        Raises:
            ValueError: If the given index is out of range.

        """
        self._awg.replace_waveform(wave1, wave2, i=i, delay=delay)

    def upload_waveforms(self) -> None:
        """Uploads all waveforms in the queue to the AWG Core.

        This method only works as expected if the Sequence Program is in
        'Simple' or 'Custom' modes and has been compiled beforehand.
        See :func:`compile_and_upload_waveforms(...)`.
        """
        self._awg.upload_waveforms()

    def compile_and_upload_waveforms(self) -> None:
        """Compiles the Sequence Program and uploads the queued waveforms.

        Simply combines the two methods to make sure the sequence is compiled
        before the waveform queue is uplaoded.
        """
        self._awg.compile_and_upload_waveforms()

    def set_sequence_params(self, **kwargs) -> None:
        """Sets the parameters of the *Sequence Program*.

        Passes all the keyword arguments to the `set_param(...)` method of the
        *Sequence Program*. The available sequence parameters may vary between
        different sequences. For a list of all current sequence parameters see
        the method `sequence_params()`.

        They include:
            *'sequence_type', 'period', 'repetitions', 'trigger_mode',
            'trigger_delay', ...*

            >>> hdawg.awgs[0].set_sequence_params(
            >>>     sequence_type="Simple",
            >>>     trigger_mode="Send Trigger",
            >>>     repetitions=1e6,
            >>>     alignemnt="Start with Trigger"
            >>> )

        """
        self._awg.set_sequence_params(**kwargs)

    def sequence_params(self) -> None:
        """Returns the current seuence parameters.

        Returns:
            A dictionary with the current sequence parameters.

        """
        return self._awg.sequence_params

    @property
    def waveforms(self):
        return self._awg.waveforms

    @property
    def is_running(self):
        return self._awg.is_running

    @property
    def index(self):
        return self._awg.index
Esempio n. 2
0
class AWG(InstrumentChannel):
    """Device-specific *AWG Core* for the *UHFQA*. 
    
    Inherits from :class:`InstrumentChannel` and wraps around a `AWGCore` for 
    *HDAWG* from :mod:`zhinst-toolkit`. This class adds Parameters from the 
    :mod:`zhinst-toolkit` as *QCoDeS Parameters* and wraps all methods of the 
    *toolkit's* `AWGCore`. 

    Arguments:
        name (str): The name of the `AWG` submodule.
        parent_instr (:class:`qcodes.instrument.base.Instrument`): The QCoDeS 
            parent instrument of the `InstrumentChannel`.
        parent_contr (:class:`zhinst.toolkit.BaseInstrument`): The `_controller` 
            of the parent instrument that is used for getting and setting 
            parameters. 

    Attributes:
        output1 (:class:`Parameter`): The state 
            of the output of channel 1. Can be one of {'on', 'off'}.
        output2 (:class:`Parameter`): The state 
            of the output of channel 2. Can be one of {'on', 'off'}.
        gain1 (:class:`Parameter`): Gain of the 
            output channel 1. The value must be between -1 and +1 (default: +1).
        gain2 (:class:`Parameter`): Gain of the 
            output channel 2. The value must be between -1 and +1 (default: +1).
        waveforms (list): A list of `Waveforms` that respresent the queue of 
            waveforms to upload to the device when the sequence type is 
            *'Simple'*.
        is_running (bool): A flag that shows if the `AWG Core` is currently 
            running or not.
        index (int): The index of the `AWG Core` in the list of *awgs*.
    
    """
    def __init__(self, name: str, parent_instr, parent_contr) -> None:
        super().__init__(parent_instr, name)
        self._awg = UHFQA_AWG(parent_contr, 0)
        self._awg._setup()
        # add custom parameters as QCoDeS parameters
        self.add_parameter(
            "output1",
            unit=self._awg.output1._unit,
            docstring=self._awg.output1.__repr__(),
            get_cmd=self._awg.output1,
            set_cmd=self._awg.output1,
            label="Output Ch 1",
            vals=vals.OnOff(),
        )
        self.add_parameter(
            "output2",
            unit=self._awg.output2._unit,
            docstring=self._awg.output2.__repr__(),
            get_cmd=self._awg.output2,
            set_cmd=self._awg.output2,
            label="Output Ch 2",
            vals=vals.OnOff(),
        )
        self.add_parameter(
            "gain1",
            unit=self._awg.gain1._unit,
            docstring=self._awg.gain1.__repr__(),
            get_cmd=self._awg.gain1,
            set_cmd=self._awg.gain1,
            label="Gain Ch 1",
            vals=vals.Numbers(-1, 1),
        )
        self.add_parameter(
            "gain2",
            unit=self._awg.gain2._unit,
            docstring=self._awg.gain2.__repr__(),
            get_cmd=self._awg.gain2,
            set_cmd=self._awg.gain2,
            label="Gain Ch 2",
            vals=vals.Numbers(-1, 1),
        )

    def run(self) -> None:
        """Runs the *AWG Core*."""
        self._awg.run()

    def stop(self) -> None:
        """Stops the *AWG Core*."""
        self._awg.stop()

    def wait_done(self, timeout: float = 100) -> None:
        """Waits until the *AWG Core* is finished running. 
        
        Keyword Arguments:
            timeout (int): A timeout in seconds after which the AWG is stopped 
                (default: 100)

        """
        self._awg.wait_done(timeout=timeout)

    def compile(self) -> None:
        """Compiles the current *Sequence Program* on the *AWG Core*.
        
        Raises:
            `ToolkitError`: If the *AWG Core* has not been set up yet.
            `ToolkitError`: If the compilation has failed.
            `Warning`: If the compilation has finished with a warning.

        """
        self._awg.compile()

    def reset_queue(self) -> None:
        """Resets the waveform queue to an empty list."""
        self._awg.reset_queue()

    def queue_waveform(
        self,
        wave1: Union[List, np.array],
        wave2: Union[List, np.array],
        delay: float = 0,
    ) -> None:
        """Queues up a waveform to the *AWG Core*. 
        
        Uploading custom waveforms is only possible when using the *'Simple'* 
        sequence type. The waveform is specified with two numpy arrays for the 
        two channels of the *AWG Core*. The waveform will then automatically 
        align them to the correct minimum waveform length, sample granularity 
        and scaling. An individual delay can be specified to shift the 
        individual waveform with respect to the time origin of the period.
        
        Arguments:
            wave1 (array like): A list or array of samples in the waveform to be 
                queued for channel 1. An empty list '[]' will upload zeros of 
                the minimum waveform length.
            wave2 (array like): A list or array of samples in the waveform to be 
                queued for channel 2. An empty list '[]' will upload zeros of 
                the minimum waveform length.
        
        Keyword Arguments:
            delay (float): An individual delay for the queued sequence with 
                respect to the time origin. Positive values shift the start of 
                the waveform forwards in time. (default: 0)

        """
        self._awg.queue_waveform(wave1, wave2, delay=delay)

    def replace_waveform(
        self,
        wave1: Union[List, np.array],
        wave2: Union[List, np.array],
        i: int = 0,
        delay: float = 0,
    ) -> None:
        """Replaces the data in a waveform in the queue. 
        
        The new data must have the same length as the previous data s.t. the 
        waveform data can be replaced without recompilation of the sequence 
        program.
        
        Arguments:
            wave1 (array): Waveform to replace current wave for Channel 1.
            wave2 (array): Waveform to replace current wave for Channel 2.
        
        Keyword Arguments:
            i (int): The index of the waveform in the queue to be replaced.
            delay (int): An individual delay in seconds for this waveform w.r.t. 
                the time origin of the sequence. (default: 0)
        
        """
        self._awg.replace_waveform(wave1, wave2, i=i, delay=delay)

    def upload_waveforms(self) -> None:
        """Uploads all waveforms in the queue to the AWG Core.

        This method only works as expected if the Sequence Program is in 
        'Simple' mode and has been compiled beforehand.
        
        """
        self._awg.upload_waveforms()

    def compile_and_upload_waveforms(self) -> None:
        """Compiles the Sequence Program and uploads the queued waveforms.

        Simply combines the two methods to make sure the sequence is compiled 
        before the waveform queue is uplaoded.
        
        """
        self._awg.compile_and_upload_waveforms()

    def set_sequence_params(self, **kwargs) -> None:
        """Sets the parameters of the *Sequence Program*.

        Passes all the keyword arguments to the `set_param(...)` method of the 
        *Sequence Program*. The available sequence parameters may vary between 
        different sequences. For a list of all current sequence parameters see 
        the method `sequence_params()`. 

        They include:
            *'sequence_type', 'period', 'repetitions', 'trigger_mode', 
            'trigger_delay', ...*

            >>> hdawg.awgs[0].set_sequence_params(
            >>>     sequence_type="Simple",
            >>>     trigger_mode="Send Trigger",
            >>>     repetitions=1e6,
            >>>     alignemnt="Start with Trigger"
            >>> )
              
        """
        self._awg.set_sequence_params(**kwargs)

    def sequence_params(self) -> None:
        """Returns the current seuence parameters.
        
        Returns:
            A dictionary with the current sequence parameters.
            
        """
        return self._awg.sequence_params

    @property
    def waveforms(self):
        return self._awg.waveforms

    @property
    def is_running(self):
        return self._awg.is_running

    @property
    def index(self):
        return self._awg.index