예제 #1
0
파일: menu.py 프로젝트: Ulm-IQO/qudi
    def __init__(self, modules):
        """ Create new menu from module tree.

            @param dict m: module tree
        """
        super().__init__()

        self.modules = []

        self.hwmenu = QtWidgets.QMenu('Hardware')
        self.logicmenu = QtWidgets.QMenu('Logic')
        self.guimenu = QtWidgets.QMenu('Gui')
        self.addMenu(self.hwmenu)
        self.addMenu(self.logicmenu)
        self.addMenu(self.guimenu)

        self.hwmenuitems = MenuItem(self.hwmenu)
        self.logicmenuitems = MenuItem(self.logicmenu)
        self.guimenuitems = MenuItem(self.guimenu)

        for module_path, module in natural_sort(modules['hardware'].items()):
            self.build_submenu(self.hwmenuitems, module_path, module)

        for module_path, module in natural_sort(modules['logic'].items()):
            self.build_submenu(self.logicmenuitems, module_path, module)

        for module_path, module in natural_sort(modules['gui'].items()):
            self.build_submenu(self.guimenuitems, module_path, module)
예제 #2
0
파일: menu.py 프로젝트: xieyong8410/qudi
    def __init__(self, modules):
        """ Create new menu from module tree.

            @param dict m: module tree
        """
        super().__init__()

        self.modules = []

        self.hwmenu = QtWidgets.QMenu('Hardware')
        self.logicmenu = QtWidgets.QMenu('Logic')
        self.guimenu = QtWidgets.QMenu('Gui')
        self.addMenu(self.hwmenu)
        self.addMenu(self.logicmenu)
        self.addMenu(self.guimenu)

        self.hwmenuitems = MenuItem(self.hwmenu)
        self.logicmenuitems = MenuItem(self.logicmenu)
        self.guimenuitems = MenuItem(self.guimenu)

        for module_path, module in natural_sort(modules['hardware'].items()):
            self.build_submenu(self.hwmenuitems, module_path, module)

        for module_path, module in natural_sort(modules['logic'].items()):
            self.build_submenu(self.logicmenuitems, module_path, module)

        for module_path, module in natural_sort(modules['gui'].items()):
            self.build_submenu(self.guimenuitems, module_path, module)
예제 #3
0
    def load_sequence(self, sequence_name):
        """ Loads a sequence to the channels of the device in order to be ready for playback.
        For devices that have a workspace (i.e. AWG) this will load the sequence from the device
        workspace into the channels.

        @param sequence_name:  str, name of the sequence to load

        @return (dict, str): Dictionary with keys being the channel number and values being the
                             respective asset loaded into the channel, string describing the asset
                             type ('waveform' or 'sequence')
        """
        if sequence_name not in self.sequence_dict:
            self.log.error(
                'Sequence loading failed. No sequence with name "{0}" found on device '
                'memory.'.format(sequence_name))
            return self.get_loaded_assets()

        # Determine if the device is purely digital and get all active channels
        analog_channels = natural_sort(chnl for chnl in self.activation_config
                                       if chnl.startswith('a'))
        digital_channels = natural_sort(chnl for chnl in self.activation_config
                                        if chnl.startswith('d'))
        pure_digital = len(analog_channels) == 0

        if pure_digital and len(
                digital_channels) != self.sequence_dict[sequence_name]:
            self.log.error(
                'Sequence loading failed. Number of active digital channels ({0:d}) does'
                ' not match the number of tracks in the sequence ({1:d}).'
                ''.format(len(digital_channels),
                          self.sequence_dict[sequence_name]))
            return self.get_loaded_assets()
        if not pure_digital and len(
                analog_channels) != self.sequence_dict[sequence_name]:
            self.log.error(
                'Sequence loading failed. Number of active analog channels ({0:d}) does'
                ' not match the number of tracks in the sequence ({1:d}).'
                ''.format(len(analog_channels),
                          self.sequence_dict[sequence_name]))
            return self.get_loaded_assets()

        new_loaded_assets = dict()
        if pure_digital:
            for track_index, chnl in enumerate(digital_channels):
                chnl_num = int(chnl.split('ch')[1])
                new_loaded_assets[chnl_num] = '{0}_{1:d}'.format(
                    sequence_name, track_index)
        else:
            for track_index, chnl in enumerate(analog_channels):
                chnl_num = int(chnl.split('ch')[1])
                new_loaded_assets[chnl_num] = '{0}_{1:d}'.format(
                    sequence_name, track_index)

        self.current_loaded_assets = new_loaded_assets
        return self.get_loaded_assets()
예제 #4
0
    def __init__(self, pulsedmeasurementlogic):
        # Init base class
        super().__init__(pulsedmeasurementlogic)

        # Dictionaries holding references to the extraction methods
        self._gated_extraction_methods = dict()
        self._ungated_extraction_methods = dict()
        # dictionary containing all possible parameters that can be used by the extraction methods
        self._parameters = dict()
        # Currently selected extraction method
        self._current_extraction_method = None

        # import path for extraction modules from default directory (logic.pulse_extraction_methods)
        path_list = [
            os.path.join(get_main_dir(), 'logic', 'pulsed',
                         'pulse_extraction_methods')
        ]
        # import path for extraction modules from non-default directory if a path has been given
        if isinstance(pulsedmeasurementlogic.extraction_import_path, str):
            path_list.append(pulsedmeasurementlogic.extraction_import_path)

        # Import extraction modules and get a list of extractor classes
        extractor_classes = self.__import_external_extractors(paths=path_list)

        # create an instance of each class and put them in a temporary list
        extractor_instances = [
            cls(pulsedmeasurementlogic) for cls in extractor_classes
        ]

        # add references to all extraction methods in each instance to a dict
        self.__populate_method_dicts(instance_list=extractor_instances)

        # populate "_parameters" dictionary from extraction method signatures
        self.__populate_parameter_dict()

        # Set default extraction method
        if self.is_gated:
            self._current_extraction_method = natural_sort(
                self._gated_extraction_methods)[0]
        else:
            self._current_extraction_method = natural_sort(
                self._ungated_extraction_methods)[0]

        # Update from parameter_dict if handed over
        if isinstance(pulsedmeasurementlogic.extraction_parameters, dict):
            # Delete unused parameters
            params = [
                p for p in pulsedmeasurementlogic.extraction_parameters
                if p not in self._parameters and p != 'method'
            ]
            for param in params:
                del pulsedmeasurementlogic.extraction_parameters[param]
            # Update parameter dict and current method
            self.extraction_settings = pulsedmeasurementlogic.extraction_parameters
        return
예제 #5
0
파일: poimangui.py 프로젝트: rmblror/qudi
    def update_poi(self, old_name, new_name, position):
        # Handle changed names and deleted/added POIs
        if old_name != new_name:
            self._mw.active_poi_ComboBox.blockSignals(True)
            # Remember current text
            text_active_poi = self._mw.active_poi_ComboBox.currentText()
            # sort POI names and repopulate ComboBoxes
            self._mw.active_poi_ComboBox.clear()
            poi_names = natural_sort(self.poimanagerlogic().poi_names)
            self._mw.active_poi_ComboBox.addItems(poi_names)
            if text_active_poi == old_name:
                self._mw.active_poi_ComboBox.setCurrentText(new_name)
            else:
                self._mw.active_poi_ComboBox.setCurrentText(text_active_poi)
            self._mw.active_poi_ComboBox.blockSignals(False)

        # Delete/add/update POI marker to image
        if not old_name:
            # POI has been added
            self._add_poi_marker(name=new_name, position=position)
        elif not new_name:
            # POI has been deleted
            self._remove_poi_marker(name=old_name)
        else:
            # POI has been renamed and/or changed position
            size = self.poimanagerlogic().optimise_xy_size * np.sqrt(2)
            self._markers[old_name].set_name(new_name)
            self._markers[new_name] = self._markers.pop(old_name)
            self._markers[new_name].setSize((size, size))
            self._markers[new_name].set_position(position[:2])

        active_poi = self._mw.active_poi_ComboBox.currentText()
        if active_poi:
            self._markers[active_poi].select()
        return
예제 #6
0
파일: poimangui.py 프로젝트: Ulm-IQO/qudi
    def update_poi(self, old_name, new_name, position):
        # Handle changed names and deleted/added POIs
        if old_name != new_name:
            self._mw.active_poi_ComboBox.blockSignals(True)
            # Remember current text
            text_active_poi = self._mw.active_poi_ComboBox.currentText()
            # sort POI names and repopulate ComboBoxes
            self._mw.active_poi_ComboBox.clear()
            poi_names = natural_sort(self.poimanagerlogic().poi_names)
            self._mw.active_poi_ComboBox.addItems(poi_names)
            if text_active_poi == old_name:
                self._mw.active_poi_ComboBox.setCurrentText(new_name)
            else:
                self._mw.active_poi_ComboBox.setCurrentText(text_active_poi)
            self._mw.active_poi_ComboBox.blockSignals(False)

        # Delete/add/update POI marker to image
        if not old_name:
            # POI has been added
            self._add_poi_marker(name=new_name, position=position)
        elif not new_name:
            # POI has been deleted
            self._remove_poi_marker(name=old_name)
        else:
            # POI has been renamed and/or changed position
            size = self.poimanagerlogic().optimise_xy_size * np.sqrt(2)
            self._markers[old_name].set_name(new_name)
            self._markers[new_name] = self._markers.pop(old_name)
            self._markers[new_name].setSize((size, size))
            self._markers[new_name].set_position(position[:2])

        active_poi = self._mw.active_poi_ComboBox.currentText()
        if active_poi:
            self._markers[active_poi].select()
        return
예제 #7
0
    def load_waveform(self, load_dict):
        """ Loads a waveform to the specified channel of the pulsing device.

        @param load_dict:  dict|list, a dictionary with keys being one of the available channel

        @return dict: Dictionary containing the actually loaded waveforms per channel.
        """
        if isinstance(load_dict, list):
            new_dict = dict()
            for waveform in load_dict:
                channel = int(waveform.rsplit('_ch', 1)[1])
                new_dict[channel] = waveform
            load_dict = new_dict

        # Get all active channels
        chnl_activation = self.get_active_channels()
        analog_channels = natural_sort(
            chnl for chnl in chnl_activation if chnl.startswith('a') and chnl_activation[chnl])

        # Load waveforms into channels
        for chnl_num, waveform in load_dict.items():
            self.loaded_waveforms[chnl_num] = waveform

        self.last_sequence = None
        return self.get_loaded_assets()
예제 #8
0
    def update_roi(self, old_name, new_name, position):
        # Handle changed names and deleted/added POIs
        if old_name != new_name:
            self._mw.active_roi_ComboBox.blockSignals(True)
            # Remember current text
            text_active_roi = self._mw.active_roi_ComboBox.currentText()
            # sort ROI names and repopulate ComboBoxes
            self._mw.active_roi_ComboBox.clear()
            roi_names = natural_sort(self.roi_logic().roi_names)
            self._mw.active_roi_ComboBox.addItems(roi_names)
            if text_active_roi == old_name:
                self._mw.active_roi_ComboBox.setCurrentText(new_name)
            else:
                self._mw.active_roi_ComboBox.setCurrentText(text_active_roi)
            self._mw.active_roi_ComboBox.blockSignals(False)

        # Delete/add/update ROI marker to image
        if not old_name:
            # ROI has been added
            self._add_roi_marker(name=new_name, position=position)
        elif not new_name:
            # ROI has been deleted
            self._remove_roi_marker(name=old_name)
        else:
            # ROI has been renamed and/or changed position
            size = self.roi_logic.roi_width  # check if width should be changed again
            self._markers[old_name].set_name(new_name)
            self._markers[new_name] = self._markers.pop(old_name)
            self._markers[new_name].setSize((size, size))
            self._markers[new_name].set_position(position[:2])

        active_roi = self._mw.active_roi_ComboBox.currentText()
        if active_roi:
            self._markers[active_roi].select()
예제 #9
0
    def load_waveform(self, load_dict):
        """ Loads a waveform to the specified channel of the pulsing device.

        @param load_dict:  dict|list, a dictionary with keys being one of the available channel

        @return dict: Dictionary containing the actually loaded waveforms per channel.
        """
        if isinstance(load_dict, list):
            new_dict = dict()
            for waveform in load_dict:
                channel = int(waveform.rsplit('_ch', 1)[1])
                new_dict[channel] = waveform
            load_dict = new_dict

        # Get all active channels
        chnl_activation = self.get_active_channels()
        analog_channels = natural_sort(
            chnl for chnl in chnl_activation if chnl.startswith('a') and chnl_activation[chnl])

        # Load waveforms into channels
        for chnl_num, waveform in load_dict.items():
            self.loaded_waveforms[chnl_num] = waveform

        self.last_sequence = None
        return self.get_loaded_assets()
예제 #10
0
파일: poimangui.py 프로젝트: rmblror/qudi
    def _update_pois(self, poi_dict):
        """ Populate the dropdown box for selecting a poi. """
        self._mw.active_poi_ComboBox.blockSignals(True)

        self._mw.active_poi_ComboBox.clear()

        poi_names = natural_sort(poi_dict)
        self._mw.active_poi_ComboBox.addItems(poi_names)

        # Get two list of POI names. One of those to delete and one of those to add
        old_poi_names = set(self._markers)
        new_poi_names = set(poi_names)
        names_to_delete = list(old_poi_names.difference(new_poi_names))
        names_to_add = list(new_poi_names.difference(old_poi_names))

        # Delete markers accordingly
        for name in names_to_delete:
            self._remove_poi_marker(name)
        # Update positions of all remaining markers
        size = self.poimanagerlogic().optimise_xy_size * np.sqrt(2)
        for name, marker in self._markers.items():
            marker.setSize((size, size))
            marker.set_position(poi_dict[name])
        # Add new markers
        for name in names_to_add:
            self._add_poi_marker(name=name, position=poi_dict[name])

        # If there is no active POI, set the combobox to nothing (-1)
        active_poi = self.poimanagerlogic().active_poi
        if active_poi in poi_names:
            self._mw.active_poi_ComboBox.setCurrentText(active_poi)
            self._markers[active_poi].select()
            active_poi_pos = poi_dict[active_poi]
            self._mw.poi_coords_label.setText(
                '({0:.2r}m, {1:.2r}m, {2:.2r}m)'.format(
                    ScaledFloat(active_poi_pos[0]),
                    ScaledFloat(active_poi_pos[1]),
                    ScaledFloat(active_poi_pos[2])))
        else:
            self._mw.active_poi_ComboBox.setCurrentIndex(-1)

        self._mw.active_poi_ComboBox.blockSignals(False)
        return
예제 #11
0
    def __init__(self, pulsedmeasurementlogic):
        # Init base class
        super().__init__(pulsedmeasurementlogic)

        # Dictionary holding references to all analysis methods
        self._analysis_methods = dict()
        # dictionary containing all possible parameters that can be used by the analysis methods
        self._parameters = dict()
        # Currently selected analysis method
        self._current_analysis_method = None

        # import path for analysis modules from default directory (logic.pulse_analysis_methods)
        path_list = [os.path.join(get_main_dir(), 'logic', 'pulsed', 'pulsed_analysis_methods')]
        # import path for analysis modules from non-default directory if a path has been given
        if isinstance(pulsedmeasurementlogic.analysis_import_path, str):
            path_list.append(pulsedmeasurementlogic.analysis_import_path)

        # Import analysis modules and get a list of analyzer classes
        analyzer_classes = self.__import_external_analyzers(paths=path_list)

        # create an instance of each class and put them in a temporary list
        analyzer_instances = [cls(pulsedmeasurementlogic) for cls in analyzer_classes]

        # add references to all analysis methods in each instance to a dict
        self.__populate_method_dict(instance_list=analyzer_instances)

        # populate "_parameters" dictionary from analysis method signatures
        self.__populate_parameter_dict()

        # Set default analysis method
        self._current_analysis_method = natural_sort(self._analysis_methods)[0]

        # Update from parameter_dict if handed over
        if isinstance(pulsedmeasurementlogic.analysis_parameters, dict):
            # Delete unused parameters
            params = [p for p in pulsedmeasurementlogic.analysis_parameters if
                      p not in self._parameters and p != 'method']
            for param in params:
                del pulsedmeasurementlogic.analysis_parameters[param]
            # Update parameter dict and current method
            self.analysis_settings = pulsedmeasurementlogic.analysis_parameters
        return
예제 #12
0
파일: poimangui.py 프로젝트: Ulm-IQO/qudi
    def _update_pois(self, poi_dict):
        """ Populate the dropdown box for selecting a poi. """
        self._mw.active_poi_ComboBox.blockSignals(True)

        self._mw.active_poi_ComboBox.clear()

        poi_names = natural_sort(poi_dict)
        self._mw.active_poi_ComboBox.addItems(poi_names)

        # Get two list of POI names. One of those to delete and one of those to add
        old_poi_names = set(self._markers)
        new_poi_names = set(poi_names)
        names_to_delete = list(old_poi_names.difference(new_poi_names))
        names_to_add = list(new_poi_names.difference(old_poi_names))

        # Delete markers accordingly
        for name in names_to_delete:
            self._remove_poi_marker(name)
        # Update positions of all remaining markers
        size = self.poimanagerlogic().optimise_xy_size * np.sqrt(2)
        for name, marker in self._markers.items():
            marker.setSize((size, size))
            marker.set_position(poi_dict[name])
        # Add new markers
        for name in names_to_add:
            self._add_poi_marker(name=name, position=poi_dict[name])

        # If there is no active POI, set the combobox to nothing (-1)
        active_poi = self.poimanagerlogic().active_poi
        if active_poi in poi_names:
            self._mw.active_poi_ComboBox.setCurrentText(active_poi)
            self._markers[active_poi].select()
            active_poi_pos = poi_dict[active_poi]
            self._mw.poi_coords_label.setText(
                '({0:.2r}m, {1:.2r}m, {2:.2r}m)'.format(ScaledFloat(active_poi_pos[0]),
                                                        ScaledFloat(active_poi_pos[1]),
                                                        ScaledFloat(active_poi_pos[2])))
        else:
            self._mw.active_poi_ComboBox.setCurrentIndex(-1)

        self._mw.active_poi_ComboBox.blockSignals(False)
        return
예제 #13
0
    def _update_rois(self, roi_dict):
        """ Populate the dropdown box for selecting a roi. """
        self._mw.active_roi_ComboBox.blockSignals(True)

        self._mw.active_roi_ComboBox.clear()

        roi_names = natural_sort(roi_dict)
        self._mw.active_roi_ComboBox.addItems(roi_names)

        # Get two lists of ROI names. One of those to delete and one of those to add
        old_roi_names = set(self._markers)
        new_roi_names = set(roi_names)
        names_to_delete = list(old_roi_names.difference(new_roi_names))
        names_to_add = list(new_roi_names.difference(old_roi_names))

        # Delete markers accordingly
        for name in names_to_delete:
            self._remove_roi_marker(name)
        # Update positions of all remaining markers
        size = self.roi_logic(
        ).roi_width  # self.roi_logic().optimise_xy_size * np.sqrt(2)
        for name, marker in self._markers.items():
            marker.setSize((size, size))
            marker.set_position(roi_dict[name])
        # Add new markers
        for name in names_to_add:
            self._add_roi_marker(name=name, position=roi_dict[name])

        # If there is no active ROI, set the combobox to nothing (-1)
        active_roi = self.roi_logic().active_roi
        if active_roi in roi_names:
            self._mw.active_roi_ComboBox.setCurrentText(active_roi)
            self._markers[active_roi].select()
            active_roi_pos = roi_dict[active_roi]

            self._mw.roi_coords_label.setText('x={0}, y={1}, z={2}'.format(
                active_roi_pos[0], active_roi_pos[1], active_roi_pos[2]))
        else:
            self._mw.active_roi_ComboBox.setCurrentIndex(-1)
            self._mw.roi_coords_label.setText('')  # no roi active

        self._mw.active_roi_ComboBox.blockSignals(False)
예제 #14
0
    def write_waveform(self, name, analog_samples, digital_samples, is_first_chunk, is_last_chunk,
                       total_number_of_samples):
        """
        Write a new waveform or append samples to an already existing waveform on the device memory.

        @param name: str, waveform name, human readabla
        @param analog_samples: numpy.ndarray of type float32 containing the voltage samples
        @param digital_samples: numpy.ndarray of type bool containing the marker states
                                (if analog channels are active, this must be the same length as
                                analog_samples)
        @param is_first_chunk: bool, flag indicating if it is the first chunk to write.
                                     If True this method will create a new empty wavveform.
                                     If False the samples are appended to the existing waveform.
        @param is_last_chunk: bool, flag indicating if it is the last chunk to write.
                                    Some devices may need to know when to close the appending wfm.
        @param total_number_of_samples: int, The number of sample points for the entire waveform
                                        (not only the currently written chunk)

        @return: (int, list) number of samples written (-1 indicates failed process) and list of
                             created waveform names
        """
        tstart = datetime.datetime.now()
        self.log.debug('@{} write wfm: {} first: {} last: {} {}'.format(
            datetime.datetime.now() - tstart, name, is_first_chunk, is_last_chunk,
            total_number_of_samples))
        waveforms = list()
        min_samples = 30

        if not (is_first_chunk and is_last_chunk):
            self.log.error('Chunked Write not supported by this device.')
            return -1, waveforms

        # Sanity checks
        if len(analog_samples) == 0:
            self.log.error('No analog samples passed to write_waveform.')
            return -1, waveforms

        if total_number_of_samples < min_samples:
            self.log.error('Unable to write waveform.'
                           '\nNumber of samples to write ({0:d}) is '
                           'smaller than the allowed minimum waveform length ({1:d}).'
                           ''.format(total_number_of_samples, min_samples))
            return -1, waveforms

        # determine active channels
        activation_dict = self.get_active_channels()
        active_channels = {chnl for chnl in activation_dict if activation_dict[chnl]}
        active_analog = natural_sort(chnl for chnl in active_channels if chnl.startswith('a'))

        # Sanity check of channel numbers
        if active_channels != set(analog_samples.keys()).union(set(digital_samples.keys())):
            self.log.error('Mismatch of channel activation and sample array dimensions for '
                           'waveform creation.\nChannel activation is: {0}\nSample arrays have: '
                           ''.format(active_channels,
                                     set(analog_samples.keys()).union(set(digital_samples.keys()))))
            return -1, waveforms

        for a_ch in active_analog:
            a_ch_num = self.__ch_map[a_ch]
            wfm_name = '{0}_ch{1:d}'.format(name, a_ch_num)
            wfm = ksd1.SD_Wave()
            analog_samples[a_ch] = analog_samples[a_ch].astype('float64') / 2

            self.log.debug('wfmobj: {} {} {} min: {} max: {}'.format(
                a_ch, name, wfm_name, np.min(analog_samples[a_ch]), np.max(analog_samples[a_ch])))

            self.log.debug('@{} Before new wfm {}'.format(datetime.datetime.now() - tstart, a_ch))
            wfmid = self._fast_newFromArrayDouble(
                wfm, ksd1.SD_WaveformTypes.WAVE_ANALOG, analog_samples[a_ch])
            self.log.debug('@{} After new wfm {}'.format(datetime.datetime.now() - tstart, a_ch))

            if wfmid < 0:
                self.log.error('Device error when creating waveform {} ch: {}: {} {}'
                               ''.format(wfm_name, a_ch, wfmid, ksd1.SD_Error.getErrorMessage(wfmid)))
                return -1, waveforms

            if len(self.written_waveforms) > 0:
                wfm_nr = max(set(self.written_waveforms.values())) + 1
            else:
                wfm_nr = 1

            self.log.debug('@{} Before loading wfm {} '.format(datetime.datetime.now() - tstart, a_ch))
            written = self.awg.waveformLoad(wfm, wfm_nr)
            self.log.debug('@{} Samples written: {} {} '.format(datetime.datetime.now() - tstart, a_ch, wfm, written))
            if written < 0:
                self.log.error('Device error when uploading waveform {} id: {}: {} {}'
                               ''.format(wfm, wfm_nr, written, ksd1.SD_Error.getErrorMessage(written)))
                return -1, waveforms
            self.written_waveforms[wfm_name] = wfm_nr
            waveforms.append(wfm_name)

        self.log.debug('@{} Finished writing waveforms'.format(datetime.datetime.now() - tstart))
        return total_number_of_samples, waveforms
예제 #15
0
    def write_sequence(self, name, sequence_parameter_list):
        """
        Write a new sequence on the device memory.

        @param name: str, the name of the waveform to be created/append to
        @param sequence_parameter_list:  list, contains the parameters for each sequence step and
                                        the according waveform names.
        @return: int, number of sequence steps written (-1 indicates failed process)
        """
        steps_written = 0
        wfms_added = {}

        # Check if all waveforms are present on device memory
        avail_waveforms = set(self.get_waveform_names())
        for waveform_tuple, param_dict in sequence_parameter_list:
            if not avail_waveforms.issuperset(waveform_tuple):
                self.log.error('Failed to create sequence "{0}" due to waveforms "{1}" not '
                               'present in device memory.'.format(name, waveform_tuple))
                return -1

        active_analog = natural_sort(chnl for chnl in self.get_active_channels() if chnl.startswith('a'))
        num_tracks = len(active_analog)
        num_steps = len(sequence_parameter_list)

        for a_ch in active_analog:
            self.awg.AWGflush(self.__ch_map[a_ch])
            self.awg.channelWaveShape(self.__ch_map[a_ch], ksd1.SD_Waveshapes.AOU_AWG)

        # Fill in sequence information
        for step, (wfm_tuple, seq_params) in enumerate(sequence_parameter_list, 1):
            # Set waveforms to play
            if num_tracks == len(wfm_tuple):
                for track, waveform in enumerate(wfm_tuple, 1):
                    # Triggers !!!
                    wfm_nr = self.written_waveforms[waveform]
                    if seq_params['wait_for'] == 'SOFT':
                        trig = ksd1.SD_TriggerModes.SWHVITRIG
                        self.log.debug('Ch{} Trig SOFT'.format(track))
                    elif seq_params['wait_for'] == 'EXT':
                        trig = ksd1.SD_TriggerModes.EXTTRIG
                        self.log.debug('Ch{} Trig EXT'.format(track))
                    elif seq_params['wait_for'] == 'SOFT_CYCLE':
                        trig = ksd1.SD_TriggerModes.SWHVITRIG_CYCLE
                        self.log.debug('Ch{} Trig SOFT_CYCLE'.format(track))
                    elif seq_params['wait_for'] == 'EXT_CYCLE':
                        trig = ksd1.SD_TriggerModes.EXTTRIG_CYCLE
                        self.log.debug('Ch{} Trig EXT_CYCLE'.format(track))
                    else:
                        self.log.debug('Ch{} TrigAuto'.format(track))
                        trig = ksd1.SD_TriggerModes.AUTOTRIG
                    cycles = seq_params['repetitions'] + 1
                    prescale = 0
                    delay = 0
                    ret = self.awg.AWGqueueWaveform(track, wfm_nr, trig, delay, cycles, prescale)
                    self.log.debug('Sequence: {} Ch{} {} No{}'.format(
                        name, track, waveform, wfm_nr)
                    )
                    self.log.debug('Sequence Step: {0} Ch{1} No{2} Trig: {3} Del: {4} Rep: {5} Pre: {6} -> {7}'.format(
                        step, track, wfm_nr, trig, delay, cycles, prescale, ret)
                    )
                    if ret < 0:
                        self.log.error('Error queueing wfm: {} {}'.format(ret, ksd1.SD_Error.getErrorMessage(ret)))
                        return steps_written

                    wfms_added[track] = '{0}_{1:d}'.format(name, track)
                steps_written += 1
            else:
                self.log.error(
                    'Unable to write sequence.\nLength of waveform tuple "{0}" does not '
                    'match the number of sequence tracks.'.format(wfm_tuple)
                )
                return -1

        # more setup
        for a_ch in active_analog:
            self.log.debug('QueueConfig {}'.format(
                self.awg.AWGqueueConfig(self.__ch_map[a_ch], 1)))
            self.log.debug('channelAmpliude {}'.format(
                self.awg.channelAmplitude(self.__ch_map[a_ch], self.analog_amplitudes[a_ch])))


        if num_steps == steps_written:
            self.last_sequence = name
            self.loaded_waveforms = wfms_added

        self.set_channel_triggers(active_analog, sequence_parameter_list)

        return steps_written
예제 #16
0
    def write_waveform(self, name, analog_samples, digital_samples, is_first_chunk, is_last_chunk,
                       total_number_of_samples):
        """
        Write a new waveform or append samples to an already existing waveform on the device memory.

        @param name: str, waveform name, human readabla
        @param analog_samples: numpy.ndarray of type float32 containing the voltage samples
        @param digital_samples: numpy.ndarray of type bool containing the marker states
                                (if analog channels are active, this must be the same length as
                                analog_samples)
        @param is_first_chunk: bool, flag indicating if it is the first chunk to write.
                                     If True this method will create a new empty wavveform.
                                     If False the samples are appended to the existing waveform.
        @param is_last_chunk: bool, flag indicating if it is the last chunk to write.
                                    Some devices may need to know when to close the appending wfm.
        @param total_number_of_samples: int, The number of sample points for the entire waveform
                                        (not only the currently written chunk)

        @return: (int, list) number of samples written (-1 indicates failed process) and list of
                             created waveform names
        """
        tstart = datetime.datetime.now()
        self.log.debug('@{} write wfm: {} first: {} last: {} {}'.format(
            datetime.datetime.now() - tstart, name, is_first_chunk, is_last_chunk,
            total_number_of_samples))
        waveforms = list()
        min_samples = 30

        if not (is_first_chunk and is_last_chunk):
            self.log.error('Chunked Write not supported by this device.')
            return -1, waveforms

        # Sanity checks
        if len(analog_samples) == 0:
            self.log.error('No analog samples passed to write_waveform.')
            return -1, waveforms

        if total_number_of_samples < min_samples:
            self.log.error('Unable to write waveform.'
                           '\nNumber of samples to write ({0:d}) is '
                           'smaller than the allowed minimum waveform length ({1:d}).'
                           ''.format(total_number_of_samples, min_samples))
            return -1, waveforms

        # determine active channels
        activation_dict = self.get_active_channels()
        active_channels = {chnl for chnl in activation_dict if activation_dict[chnl]}
        active_analog = natural_sort(chnl for chnl in active_channels if chnl.startswith('a'))

        # Sanity check of channel numbers
        if active_channels != set(analog_samples.keys()).union(set(digital_samples.keys())):
            self.log.error('Mismatch of channel activation and sample array dimensions for '
                           'waveform creation.\nChannel activation is: {0}\nSample arrays have: '
                           ''.format(active_channels,
                                     set(analog_samples.keys()).union(set(digital_samples.keys()))))
            return -1, waveforms

        for a_ch in active_analog:
            a_ch_num = self.__ch_map[a_ch]
            wfm_name = '{0}_ch{1:d}'.format(name, a_ch_num)
            wfm = ksd1.SD_Wave()
            analog_samples[a_ch] = analog_samples[a_ch].astype('float64') / 2

            self.log.debug('wfmobj: {} {} {} min: {} max: {}'.format(
                a_ch, name, wfm_name, np.min(analog_samples[a_ch]), np.max(analog_samples[a_ch])))

            self.log.debug('@{} Before new wfm {}'.format(datetime.datetime.now() - tstart, a_ch))
            wfmid = self._fast_newFromArrayDouble(
                wfm, ksd1.SD_WaveformTypes.WAVE_ANALOG, analog_samples[a_ch])
            self.log.debug('@{} After new wfm {}'.format(datetime.datetime.now() - tstart, a_ch))

            if wfmid < 0:
                self.log.error('Device error when creating waveform {} ch: {}: {} {}'
                               ''.format(wfm_name, a_ch, wfmid, ksd1.SD_Error.getErrorMessage(wfmid)))
                return -1, waveforms

            if len(self.written_waveforms) > 0:
                wfm_nr = max(set(self.written_waveforms.values())) + 1
            else:
                wfm_nr = 1

            self.log.debug('@{} Before loading wfm {} '.format(datetime.datetime.now() - tstart, a_ch))
            written = self.awg.waveformLoad(wfm, wfm_nr)
            self.log.debug('@{} Samples written: {} {} '.format(datetime.datetime.now() - tstart, a_ch, wfm, written))
            if written < 0:
                self.log.error('Device error when uploading waveform {} id: {}: {} {}'
                               ''.format(wfm, wfm_nr, written, ksd1.SD_Error.getErrorMessage(written)))
                return -1, waveforms
            self.written_waveforms[wfm_name] = wfm_nr
            waveforms.append(wfm_name)

        self.log.debug('@{} Finished writing waveforms'.format(datetime.datetime.now() - tstart))
        return total_number_of_samples, waveforms
예제 #17
0
    def on_activate(self):
        """
        Starts up the NI-card and performs sanity checks.
        """
        # Sanity check ConfigOptions
        if not self._digital_channels and not self._analog_channels:
            raise Exception(
                'Not a single analog or digital channel provided in ConfigOptions.'
            )
        self._digital_channels = natural_sort(
            str(chnl) for chnl in self._digital_channels)
        self._analog_channels = natural_sort(
            str(chnl) for chnl in self._analog_channels)

        if self._digital_channels:
            try:
                if len(self._digital_channels) != len(
                        self._digital_event_rates):
                    if len(self._digital_event_rates) == 1:
                        tmp = self._digital_event_rates[0]
                        self._digital_event_rates = [
                            i * tmp
                            for i, _ in enumerate(self._digital_channels, 1)
                        ]
                    else:
                        raise Exception(
                            'ConfigOption "digital_event_rates" must have same length '
                            'as "digital_channels" or just be a single value.')
            except TypeError:
                self._digital_event_rates = [
                    i * self._digital_event_rates
                    for i, _ in enumerate(self._digital_channels, 1)
                ]
        if self._analog_channels:
            try:
                if len(self._analog_channels) != len(self._analog_amplitudes):
                    if len(self._analog_amplitudes) == 1:
                        tmp = self._analog_amplitudes[0]
                        self._analog_amplitudes = [
                            i * tmp
                            for i, _ in enumerate(self._analog_channels, 1)
                        ]
                    else:
                        raise Exception(
                            'ConfigOption "analog_amplitudes" must have same length '
                            'as "analog_channels" or just be a single value.')
            except TypeError:
                self._analog_amplitudes = [
                    i * self._analog_amplitudes
                    for i, _ in enumerate(self._analog_channels, 1)
                ]

        # Create constraints
        self._constraints = DataInStreamConstraints()
        self._constraints.digital_channels = tuple(
            StreamChannel(
                name=ch, type=StreamChannelType.DIGITAL, unit='counts')
            for ch in self._digital_channels)
        self._constraints.analog_channels = tuple(
            StreamChannel(name=ch, type=StreamChannelType.ANALOG, unit='V')
            for ch in self._analog_channels)
        self._constraints.analog_sample_rate.min = 1
        self._constraints.analog_sample_rate.max = 2**31 - 1
        self._constraints.analog_sample_rate.step = 1
        self._constraints.analog_sample_rate.unit = 'Hz'
        self._constraints.digital_sample_rate.min = 1
        self._constraints.digital_sample_rate.max = 2**31 - 1
        self._constraints.digital_sample_rate.step = 1
        self._constraints.digital_sample_rate.unit = 'Hz'
        self._constraints.combined_sample_rate = self._constraints.analog_sample_rate

        self._constraints.read_block_size.min = 1
        self._constraints.read_block_size.max = 1000000
        self._constraints.read_block_size.step = 1

        # TODO: Implement FINITE streaming mode
        self._constraints.streaming_modes = (StreamingMode.CONTINUOUS,
                                             )  # , StreamingMode.FINITE)
        self._constraints.data_type = np.float64
        self._constraints.allow_circular_buffer = True

        self.__sample_rate = self._constraints.combined_sample_rate.min
        self.__data_type = np.float64
        self.__stream_length = 0
        self.__buffer_size = 1000
        self.__use_circular_buffer = False
        self.__streaming_mode = StreamingMode.CONTINUOUS
        self.__active_channels = tuple()

        # Reset data buffer
        self._data_buffer = np.empty(0, dtype=self.__data_type)
        self._has_overflown = False
        self._is_running = False
        self._last_read = None
        self._start_time = None
        return
예제 #18
0
파일: dtg5334.py 프로젝트: xieyong8410/qudi
    def get_sequence_names(self):
        """ Retrieve the names of all uploaded sequence on the device.

        @return list: List of all uploaded sequence name strings in the device workspace.
        """
        return list(natural_sort(self.sequence_names))
예제 #19
0
파일: dtg5334.py 프로젝트: xieyong8410/qudi
    def get_waveform_names(self):
        """ Retrieve the names of all uploaded waveforms on the device.

        @return list: List of all uploaded waveform name strings in the device workspace.
        """
        return list(natural_sort(self.waveform_names))
예제 #20
0
    def write_sequence(self, name, sequence_parameter_list):
        """
        Write a new sequence on the device memory.

        @param name: str, the name of the waveform to be created/append to
        @param sequence_parameter_list:  list, contains the parameters for each sequence step and
                                        the according waveform names.
        @return: int, number of sequence steps written (-1 indicates failed process)
        """
        steps_written = 0
        wfms_added = {}
        # Check if device has sequencer option installed
        if not self.has_sequence_mode():
            self.log.error('Direct sequence generation in AWG not possible. Sequencer option not '
                           'installed.')
            return -1

        # Check if all waveforms are present on device memory
        avail_waveforms = set(self.get_waveform_names())
        for waveform_tuple, param_dict in sequence_parameter_list:
            if not avail_waveforms.issuperset(waveform_tuple):
                self.log.error('Failed to create sequence "{0}" due to waveforms "{1}" not '
                               'present in device memory.'.format(name, waveform_tuple))
                return -1

        active_analog = natural_sort(chnl for chnl in self.get_active_channels() if chnl.startswith('a'))
        num_tracks = len(active_analog)
        num_steps = len(sequence_parameter_list)

        for a_ch in active_analog:
            self.awg.AWGflush(self.__ch_map[a_ch])
            self.awg.channelWaveShape(self.__ch_map[a_ch], ksd1.SD_Waveshapes.AOU_AWG)

        # Fill in sequence information
        for step, (wfm_tuple, seq_params) in enumerate(sequence_parameter_list, 1):
            # Set waveforms to play
            if num_tracks == len(wfm_tuple):
                for track, waveform in enumerate(wfm_tuple, 1):
                    # !!!
                    wfm_nr = self.written_waveforms[waveform]
                    if seq_params['wait_for'] == 'EXT':
                        trig = ksd1.SD_TriggerModes.EXTTRIG
                        self.log.debug('Ch{} Trig EXT'.format(track))

                    elif seq_params['wait_for'] == 'CYCLE':
                        trig = ksd1.SD_TriggerModes.EXTTRIG_CYCLE
                        self.log.debug('Ch{} Trig EXT_CYCLE'.format(track))
                    else:
                        self.log.debug('Ch{} TrigAuto'.format(track))
                        trig = ksd1.SD_TriggerModes.AUTOTRIG
                    cycles = seq_params['repetitions'] + 1
                    prescale = 0
                    delay = 0
                    ret = self.awg.AWGqueueWaveform(track, wfm_nr, trig, delay, cycles, prescale)
                    self.log.debug('Sequence: {} Ch{} {} No{}'.format(
                        name, track, waveform, wfm_nr)
                    )
                    self.log.debug('Sequence Step: {0} Ch{1} No{2} Trig: {3} Del: {4} Rep: {5} Pre: {6} -> {7}'.format(
                        step, track, wfm_nr, trig, delay, cycles, prescale, ret)
                    )
                    if ret < 0:
                        self.log.error('Error queueing wfm: {} {}'.format(ret, ksd1.SD_Error.getErrorMessage(ret)))
                        return steps_written

                    wfms_added[track] = '{0}_{1:d}'.format(name, track)
                steps_written += 1
            else:
                self.log.error(
                    'Unable to write sequence.\nLength of waveform tuple "{0}" does not '
                    'match the number of sequence tracks.'.format(wfm_tuple)
                )
                return -1

        # more setup
        for a_ch in active_analog:
            self.log.debug('QueueConfig {}'.format(
                self.awg.AWGqueueConfig(self.__ch_map[a_ch], 1)))
            self.log.debug('channelAmpliude {}'.format(
                self.awg.channelAmplitude(self.__ch_map[a_ch], self.analog_amplitudes[a_ch])))


        if num_steps == steps_written:
            self.last_sequence = name
            self.loaded_waveforms = wfms_added

        self.set_channel_triggers(active_analog, sequence_parameter_list)

        return steps_written
예제 #21
0
파일: dtg5334.py 프로젝트: Ulm-IQO/qudi
    def get_sequence_names(self):
        """ Retrieve the names of all uploaded sequence on the device.

        @return list: List of all uploaded sequence name strings in the device workspace.
        """
        return list(natural_sort(self.sequence_names))
예제 #22
0
파일: dtg5334.py 프로젝트: Ulm-IQO/qudi
    def get_waveform_names(self):
        """ Retrieve the names of all uploaded waveforms on the device.

        @return list: List of all uploaded waveform name strings in the device workspace.
        """
        return list(natural_sort(self.waveform_names))