Exemplo n.º 1
0
    def __init__(self, experiment, measurement, parent=None, output_guis=None):

        # Initialize parent class
        super().__init__(experiment,
                         measurement,
                         parent=parent,
                         output_guis=output_guis)
        logging.getLogger(__name__)
        self.experiment = experiment
        self.measurement = measurement

        self.output_guis = output_guis

        self.timer_interval_ms = 50

        # Make sure the plotting update flags exist:
        self.experiment.flag_new_spectral_data = False
        self.experiment.flag_new_camera_image = False

        self.timer_update_plotting = QTimer()
        self.timer_update_plotting.timeout.connect(self.update_plots)
        # Idea:
        # Have one thread that

        self.initialize_some_graphics()

        # To demonstrate that th gui can still be expanded, a button to swap x and y direction is added here
        button_swap_XY = QPushButton('Swap atto XY direction')
        button_swap_XY.clicked.connect(self.swap_XY)
        self.outer_layout.insertWidget(1, button_swap_XY)
Exemplo n.º 2
0
    def __init__(self, thorlabs_instrument, also_close_output=False):
        super().__init__()
        self.logger = logging.getLogger(__name__)

        self.overall_layout = QHBoxLayout()
        self.setLayout(self.overall_layout)

        self.motor = thorlabs_instrument
        self.logger.debug('You are connected to a {}'.format(self.motor.kind_of_device))
        self.title = 'Thorlabs {} GUI'.format(self.motor._name)

        self.saved_position = None
        self.current_position = None

        self.distance = 1.0*ur('mm')

        self.min_distance = -12.0 * ur('mm')
        self.max_distance = 12.0 * ur('mm')

        self.stop = self.stop_moving

        self.initUI()

        self.timer = QTimer()
        self.timer.timeout.connect(self.set_current_motor_position_label)
        self.timer.start(100)       #time in ms

        self.moving_thread = WorkThread(self.motor.move_absolute, self.current_position, True)
Exemplo n.º 3
0
    def __init__(
        self,
        settings={}
    ):  # note: usually it's not recommended to specify default value, but here I did because it's an empty dict
        # don't place the docstring here but above in the class definition
        super().__init__(settings)  # mandatory line
        self.logger = logging.getLogger(__name__)  # mandatory line
        self.logger.info('Class WinspecController created.')

        # force_threading_mode:
        #   True    Force it to use threading mode
        #   None    Automatic (default behaviour)
        #   False   Force it to not use threading mode
        if 'force_threading_mode' in settings:
            self._force_threading = settings['force_threading_mode']
        else:
            self._force_threading = None
        self._threading_mode = None

        # pythoncom.CoInitialize()                    # added this line for threading
        self.name = 'Winspec Controller'
        # self.ws = None
        self.params = {}
        self.params_exp = {}
        self.params_spt = {}
        # self.exp = None
        # self._spec_mgr = None
        # self.spt = None
        # I don't really understand this stuff, but after a very long search trying many things, this turns out to work for collecting spectral data
        self._variant_array = win32com.client.VARIANT(
            win32com.client.pythoncom.VT_BYREF
            | win32com.client.pythoncom.VT_ARRAY
            | win32com.client.pythoncom.VT_I4, [1, 2, 3, 4])
    def __init__(self, settings):
        """ | Usually, the super().__init__() would execute the init of the BaseController.
        | However, since the current class inherits from both core.Motor and BaseController, only the first init is executed.
        | So a few lines are copied from BaseController.

        :param settings: the class Motor needs a serial number
        :type settings: dict
        """

        self.logger = logging.getLogger(__name__)
        self._is_initialized = False

        self.logger.info('Class PI_motorcontroller is created')

        # Calls init of core.Motor, whose init is executed
        super().__init__()

        # There is one function that is outside of the Motor class in the core, which would be useful to have accessible.
        # That would be list_available_devices
        self.logger.debug("Done with motorcontroller")

        self.CONTROLLERNAME = str(settings['controllername'])
        print(self.CONTROLLERNAME)
        self.STAGES = (settings['stages'], )  # connect stages to axes
        self.REFMODE = (settings['refmode'],
                        )  # reference the connected stages
Exemplo n.º 5
0
    def __init__(self, settings={}):
        """ Init for the class

        """
        self.logger = logging.getLogger(__name__)
        self._is_initialized = False
        self._settings = settings
Exemplo n.º 6
0
    def __init__(self, settings):
        """ init of the class"""
        super().__init__(settings)
        self.logger = logging.getLogger(__name__)
        self.attocube_piezo_dict = {}
        self.Amplitude = np.zeros(
            3)  #here we will remember which amplitudes are set on the steppers
        self.Stepwidth = np.zeros(
            3
        )  #here we will remember what the amplitudes means in terms of stepsize
        self.Frequency = np.zeros(3)
        self.Speed = np.zeros(3)

        if 'temperature' in settings:
            self.temperature = settings['temperature']
        else:
            self.temperature = 300

        self.stop = False

        self.logger.info('Welcome to the instrument of the Attocube')

        self.current_positions = {
            'XPiezoStepper': 'unavailable',
            'YPiezoStepper': 'unavailable',
            'ZPiezoStepper': 'unavailable',
            'XPiezoScanner': 'unavailable',
            'YPiezoScanner': 'unavailable',
            'ZPiezoScanner': 'unavailable'
        }
        self.initialize()
Exemplo n.º 7
0
    def __init__(self, variable_waveplate_ins):
        """
        Init of the VariableWaveplateGui

        :param variable_waveplate_ins: instrument
        :type an instance of the variable_waveplate instrument
        """
        super().__init__()
        self.logger = logging.getLogger(__name__)
        self.test = QDoubleSpinBox()  # to be removed

        # to load from the UI file
        gui_file = os.path.join(root_dir, 'view', 'polarization',
                                'variable_waveplate_instrument.ui')
        self.logger.info('Loading the GUI file: {}'.format(gui_file))
        self.gui = uic.loadUi(gui_file, self)
        # define internal variables to update the GUI
        self._output = None
        self._mode = None
        self._analog_value_1 = None
        self._analog_value_2 = None

        # setup the gui
        self.variable_waveplate_ins = variable_waveplate_ins
        self.customize_gui()
        self.get_device_state()
        self.set_device_state_to_gui()
        self.show()
Exemplo n.º 8
0
    def __init__(self, settings):
        """
        Init of the class.

        It needs a settings dictionary that contains the following fields (mandatory)

            * port: COM port name where the AaAotf is connected
            * controller: this should point to the controller to use and with / add the name of the class to use
            * apply_defaults: logical to indicate if the default settings should be applied at the init

        """
        super().__init__(settings)
        self.logger = logging.getLogger(__name__)
        self._port = settings['port']
        self.dummy = settings['dummy']

        #
        self.channel_in_use = None
        self.logger.info('Initializing device AOTF with Aotf_model at port = {}'.format(self._port))
        self.controller = AaModd18012(settings)
        self.controller.initialize()

        # loads the calibration file to transform freq to wavelength.
        cal_file = os.path.join(os.path.dirname(__file__), 'lookup_table_cal_aotf_2019-02-05.txt')
        self.logger.info('Using freq to wavelength calibration for aotf from file {}'.format(cal_file))
        self.load_calibration(cal_file)

        # turn off all channels:
        if 'apply_defaults' in settings.keys():
            if settings['apply_defaults']:
                self.logger.info('Applying defaults to AaAOTF')
                # apply defaults to all values
                for i in range(8):
                    self.set_defaults(i+1)
                self.blanking(True, 'internal')
Exemplo n.º 9
0
    def __init__(self, settings):  # passing settings is required !
        """ Init for the class

        """
        self.logger = logging.getLogger(__name__)
        self.logger.info(
            'Class BaseInstrument created with settings: {}'.format(settings))
        self.settings = settings

        if 'dummy' in settings and settings['dummy'] == True:
            if 'controller' in settings:
                if len(settings['controller']
                       ) < 5 or settings['controller'][-4] != 'Dummy':
                    settings['controller'] += 'Dummy'

        self.controller_class = self.load_controller(settings)
        self.logger.debug('Controller class: {}'.format(self.controller_class))
        if 'via_serial' in settings:
            port = settings['via_serial'].split('COM')[-1]
            self.controller = self.controller_class.via_serial(port)
        elif 'via_gpib' in settings:
            self.logger.warning('NOT TESTED')
            port = settings['via_gpib'].split('COM')[-1]
            self.controller = self.controller_class.via_gpib(port)  # to do
        elif 'via_usb' in settings:
            self.logger.warning('NOT TESTED')
            port = settings['via_usb'].split('COM')[-1]
            self.controller = self.controller_class.via_usb(port)  # to do
        else:
            self.controller = self.controller_class(settings)
Exemplo n.º 10
0
    def __init__(self, settings):
        """ | Usually, the super().__init__() would execute the init of the BaseController.
        | However, since the current class inherits from both core.Motor and BaseController, only the first init is executed.
        | So a few lines are copied from BaseController.

        :param settings: the class Motor needs a serial number
        :type settings: dict
        """

        self.logger = logging.getLogger(__name__)
        self._is_initialized = False

        self.logger.info('Class TDC001_cube (Thorlabs motors) is created.')
        self.name = 'TDC001_cube'

        #These lines are a copy of the init of BaseController, that is not executed because it is the second inheritance
        self._settings = settings
        if 'serial' in settings:
            self.serial = settings['serial']
            self.logger.debug("Serial = {}".format(self.serial))
        else:
            self.logger.error("No serial specified in settings")
        self._is_initialized = True

        # Calls init of core.Motor, whose init is executed
        super().__init__(self.serial)

        # There is one function that is outside of the Motor class in the core, which would be useful to have accessible.
        # That would be list_available_devices.
        self.core = core
        self.logger.debug("Done with motorcontroller")
Exemplo n.º 11
0
    def __init__(self, settings):
        """ Init method for the class

        """
        super().__init__()  # runs the init of the base_controller class.
        self.logger = logging.getLogger(__name__)
        self.name = 'SK polarization'
        self.logger.debug('Is initialized state: {}'.format(self._is_initialized))

        # get the path for the dll
        if 'dll_path' in settings.keys():
            path = settings['dll_path']
        else:
            path = 'D:/mcaldarola/surfdrive/NanoCD/Setup/SK/SKPolarimeterMFC_VS2015_x64/x64/Release/'

        name = settings['dll_name']
        self.logger.debug('DLL to use: {}.dll'.format(path + name))
        self.dll = ctypes.CDLL(path + name)
        self.logger.debug('DLL: {}'.format(self.dll))

        # this is the info needed to get the measurement point
        self.time_out = 300  # in ms
        self.vector_length = 13
        self.get_data_delay = 0.7   # in sec
        self.start_measurement_time = 0  # initialize the value
Exemplo n.º 12
0
    def __init__(self, settings):
        super().__init__(settings)  # mandatory line
        self.logger = logging.getLogger(__name__)
        self.logger.info('Class Lock-in created.')
        self.name = 'Lock-in Controller'

        self._rm = visa.ResourceManager()
        self._resource_list = self._rm.list_resources()
        self._osa = None
        #these are @properties variables
        self._start_wav = None
        self._end_wav = None
        self._optical_resolution = None
        self._sample_points = None
        self._sensitivity = None  # will match value of OSA (1-6)
        self._settings = settings
        if 'port' in self._settings:
            self._port = self._settings['port']
        else:
            self._port = 'AUTO'
        self._sensitivities = [
            'high1', 'high2', 'high3', 'norm_hold', 'norm_auto', 'mid'
        ]
        self._time_constants = [0.02, 0.12, 1.125, 0.001, 0.001, 0.002]
        self._sens_commands = ['SH1', 'SH2', 'SH3', 'SNHD', 'SNAT', 'SMID']
Exemplo n.º 13
0
 def __init__(self, settings,
              sub_instruments):  # passing settings is required !
     self.logger = logging.getLogger(__name__)
     self.logger.info(
         'Class BaseInstrument created with settings: {}'.format(settings))
     self.settings = settings
     self.sub_instruments = sub_instruments
Exemplo n.º 14
0
    def __init__(self, settings):                   # not specifying a default value for settings is less confusing for novice users
        # don't place the docstring here but above in the class definition
        super().__init__(settings)                  # mandatory line
        self.logger = logging.getLogger(__name__)   # mandatory line
        self.logger.info('Class ExampleInstrument created.')
        self.settings = settings
        self.default_name = 'temp.SPE'

        self._timing_modes = self._remove_unavailable('timing_modes', [0, 'Free Run', 2, 'External Sync'])
        self._shutter_controls = self._remove_unavailable('shutter_controls', [0, 'Normal', 'Closed', 'Opened'])
        self._fast_safe = self._remove_unavailable('fast_safe', ['Fast', 'Safe'])
        self._ccd = self._remove_unavailable('ccd', ['Full', 'ROI'])
        self._autosave = self._remove_unavailable('autosave', ['Ask', 'Auto', 'No'])
        self._accums = 1

        if 'horz_width_multiple' in self.settings:
            self._horz_width_multiple = self.settings['horz_width_multiple']  # This parameter specifies if camera requires horizontal range of certain interval
        else:
            self._horz_width_multiple = 1   # This parameter specifies if camera requires horizontal range of certain interval

        self.initialize()   # ! required to do this in the __init__

        # self._is_acquiring = False
        self._is_moving = False

        self.frame = []

        # bug fix:
        self.ccd = 'Full'
        # Changed exp_get('XDIM')[0] to exp_get('XDIMDET')[0]
        self.controller.xdim = self.controller.exp_get('XDIMDET')[0]
        self.controller.ydim = self.controller.exp_get('YDIMDET')[0]
        self.ccd = 'ROI'
Exemplo n.º 15
0
def array_from_settings_dict(sweep_dict):
    """
    Wrapper around array_from_string_quantities().
    sweep_dict should contain 'start' and 'stop' key. And either 'step' or 'num' key.
    The values may have units (that can be interpreted by pint).
    See array_from_string_quantities() and array_from_pint_quantities() for further details.

    :param sweep_dict: Dictionary containing start, stop and step or num keys
    :return: (numpy.array, pint.unit)
    """
    logger = logging.getLogger(__name__)
    if 'start' not in sweep_dict:
        logger.error('sweep dictionary should contain key start')
    if 'stop' not in sweep_dict:
        logger.error('sweep dictionary should contain key stop')
    if 'step' in sweep_dict:
        return array_from_string_quantities(sweep_dict['start'],
                                            sweep_dict['stop'],
                                            step=sweep_dict['step'])
    elif 'num' in sweep_dict:
        return array_from_string_quantities(sweep_dict['start'],
                                            sweep_dict['stop'],
                                            num=sweep_dict['num'])
    else:
        return array_from_string_quantities(sweep_dict['start'],
                                            sweep_dict['stop'])
Exemplo n.º 16
0
    def __init__(self, anc350_instrument, also_close_output=False):
        """Attocube
        """
        super().__init__()
        self.logger = logging.getLogger(__name__)
        self.title = 'Attocube GUI'
        self.anc350_instrument = anc350_instrument

        name = 'attocube.ui'
        gui_folder = os.path.dirname(os.path.abspath(__file__))
        gui_file = os.path.join(gui_folder, name)
        self.logger.debug('Loading the GUI file: {}'.format(gui_file))
        self.gui = uic.loadUi(gui_file, self)

        self.max_amplitude_V = 60
        self.max_frequency = 2000
        self.max_dclevel_V = 60 * ur(
            'V')  #Pay attention: this max only goes for 4K,
        self.max_dcLevel_mV_300K = 60 * ur(
            'V')  #at room temperature use 60V as max
        self.max_distance = 5 * ur('mm')

        self.current_positions = {}

        self.current_axis = 'X,Y Piezo Stepper'
        self.current_move = 'step'
        self.direction = 'left'
        self.distance = 0 * ur('um')

        self.settings = {
            'amplitudeX': 30,
            'amplitudeY': 40,
            'amplitudeZ': 30,
            'frequencyX': 1000,
            'frequencyY': 1000,
            'frequencyZ': 1000
        }

        self.temperature = 300

        self.scanner_unitX = 'V'
        self.scanner_unitY = 'V'
        self.scanner_unitZ = 'V'

        self.dcX = 1 * ur(self.scanner_unitX)
        self.dcY = 1 * ur(self.scanner_unitY)
        self.dcZ = 0 * ur(self.scanner_unitZ)

        self.stop = self.stop_moving

        self.initUI()

        #This one is to continuously (= every 100ms) show the position of the axes
        self.timer = QTimer()
        self.timer.timeout.connect(self.show_position)
        self.timer.start(100)  #time in ms

        self.moving_thread = WorkThread(self.anc350_instrument.move_to,
                                        self.current_axis, self.distance)
Exemplo n.º 17
0
    def __init__(self, settings):
        """ init of the class"""
        super().__init__(settings)
        self.logger = logging.getLogger(__name__)
        self.logger.info('Class CoboltLaser Instrument created.')

        self.initialize()
        self.DEFAULTS = {}
Exemplo n.º 18
0
 def __init__(self, settings):
     super().__init__()
     self.logger = logging.getLogger(__name__)
     self.rsc = None
     self.instrument_id = settings['instrument_id']
     self.dummy = settings['dummy']
     self.logger.info(
         'Created controller class for Agilent33522A with id: {}'.format(
             self.instrument_id))
     self.logger.info('Dummy mode: {}'.format(self.dummy))
    def __init__(self, settings):
        """ initialize the unit_test class

        """
        self.logger = logging.getLogger(__name__)
        self.logger.info('Created UTestVariableWaveplate class.')
        self.logger.info('Testing in dummy={}'.format(settings['dummy']))
        self.dummy = settings['dummy']
        self.inst = CoboltLaser(settings)
        sleep(1)
Exemplo n.º 20
0
 def __init__(self):
     super().__init__()
     self.logger = logging.getLogger(__name__)
     self.logger.debug('Creating the BaseGraph ')
     self.title = 'BaseGraph Plot'
     self.left = 50
     self.top = 50
     self.width = 640
     self.height = 480
     self.plot_title = None
Exemplo n.º 21
0
    def __init__(self, settings):
        """ initialize the unit_test class

        """
        self.logger = logging.getLogger(__name__)
        self.logger.info('Created UTestFunGen class.')
        self.logger.info('UTesting in dummy = {}'.format(settings['dummy']))
        self.dummy = settings['dummy']
        self.inst = FunGen(settings)
        sleep(1)
Exemplo n.º 22
0
    def __init__(self, settings):
        """
        Init of the class.

        It needs a settings dictionary that contains the following fields (mandatory)

            * port: COM port name where the LCC25 is connected
            * enable: logical to say if the initialize enables the output
            * dummy: logical to say if the connection is real or dummy (True means dummy)
            * controller: this should point to the controller to use and with / add the name of the class to use

        Note: When you set the setting 'dummy' = True, the controller to be loaded is the dummy one by default,
        i.e. the class will automatically overwrite the 'controller' with 'hyperion.controller.thorlabs.lcc25/LccDummy'

        Example:

            settings = {'port':'COM8', 'enable': None, 'dummy' : True,
                                   'controller': 'hyperion.controller.thorlabs.lcc25/Lcc'}


        """
        super().__init__(settings)
        self.logger = logging.getLogger(__name__)
        self._port = settings['port']

        # property
        self._output = settings['enable']
        self._mode = None
        self._freq = None
        self._wavelength = 532 * ur('nm')  # default wavelength
        self.MODES = ['Modulation', 'Voltage1', 'Voltage2', 'QWP']

        self.logger.info(
            'Initializing Variable Waveplate with settings: {}'.format(
                settings))
        # this is to load the calibration file
        self.calibration = {}
        self.logger.debug('Get the source path')
        cal_file = os.path.join(
            package_path, 'instrument', 'polarization',
            'lookup_table_qwp_voltage_calibration_2019-03-15.txt')
        self.logger.info(
            'Using Variable Waveplate QWP calibration file: {}'.format(
                cal_file))
        self.load_calibration(cal_file)

        # initialize
        self.initialize()  # mandatory!
        if self._output is None:
            self._output = self.output
        else:
            self.output = self._output

        # mode
        self._mode = self.mode
Exemplo n.º 23
0
    def __init__(self, settings):
        super().__init__(settings)
        self.logger = logging.getLogger(__name__)
        self.logger.debug('Class BeamFlags created.')
        self.settings = settings

        if 'start_up_delay' not in settings:
            self._start_up_delay = 1.5
        else:
            self._start_up_delay = settings['start_up_delay']

        # Create and add flag_names to the settings dictionary.
        # Note that flag names need to be 1 character long.
        if 'flag_names' not in self.settings:
            if 'gui_flags' in self.settings:
                self.settings['flag_names'] = list(
                    self.settings['gui_flags'].keys())
            else:
                self.settings['flag_names'] = [
                    '1', '2'
                ]  # hardcoded default value for this arduino device

        # Create and add states to the settings dictionary.
        # Note that flag states need to be 1 character long.
        if 'states' not in self.settings:
            if 'flag_states' in self.settings and 'red' in self.settings[
                    'flag_states'] and 'green' in self.settings['flag_states']:
                self.settings['states'] = [
                    self.settings['flag_states']['red'],
                    self.settings['flag_states']['green']
                ]
            else:
                self.settings['states'] = ['r', 'g']
                # hardcoded default value for this arduino device

        # Dict that represents state of the beam flags.
        # Can be outdated due to manual changes. Use update_all_states() to make sure it's updated.
        self.flag_states = {}
        for name in self.settings['flag_names']:
            self.flag_states[name] = None

        if 'actuator_timeout' not in self.settings:
            self.settings['actuator_timeout'] = 0.3
            # not used

        # In order to keep track of the state of the flags (because they can be altered manually,
        # outside the control of the python code), one could keep sending queries to the device,
        # bu I recommend this alternative method:
        # If self._use_passive_queries is True, the Arduino will send new state info when the
        # state is altered through toggle button. This instrument will then read this state
        # information from the Serial Buffer In whenever the state is required.
        self._use_passive_queries = True  # True recommended

        self.initialize()
Exemplo n.º 24
0
def pint_to_spin_combo(pint_quantity, doubleSpinBox, comboBox_units):
    """
    When a GUI has a combination of a Q(Double)SpinBox and a QComboBox that hold the numeric value and the unit
    respectively, this function can be used to easily put a pint quantity into  that combination.
    It is strongly recommended to use add_pint_to_combo(comboBox_units) before using this function!
    Complementary function is spin_combo_to_pint_apply_limits()

    :param pint_quantity: the pint quantity to write into the gui objects
    :type pint_quantity: pint quantity
    :param doubleSpinBox: the QDoubleSpinBox (or QSpinBox?) that holds the numeric value
    :type doubleSpinBox: QDoubleSpinBox (Maybe QSpinBox also works. Not tested)
    :param comboBox_units: the QComboBox that holds the units
    :type comboBox_units: QComboBox
    """
    logger = logging.getLogger(__name__)

    if hasattr(comboBox_units, 'pint_units'):
        pint_units = comboBox_units.pint_units
    else:
        # otherwise try to create it on the fly:
        pint_units = [
            Q_(comboBox_units.itemText(i)).units
            for i in range(comboBox_units.count())
        ]

    # Try to convert the pint quantity to one of the units in the comboBox.
    # If that succeeds set the combobox unit and the value in the doubleSpinBox
    try:
        # First try to match the combo unit to the one of pint_quantity:
        combo_index = pint_units.index(pint_quantity.units)
        value = pint_quantity.m_as(pint_units[combo_index])
    except ValueError:
        # If that fails find the unit that comes closest:
        v = list(log10([pint_quantity.m_as(un) for un in pint_units
                        ]))  # log10 of values converted to the combo units
        vp = [n for n in v if n >= 0
              ]  # only the positive ones (i.e. prefer 200ms over 0.2s )
        if len(vp) == 0:  # if there are none, add the largest negative one
            vp = max(v)
        combo_index = v.index(min(vp))  # get the corresponding index

        # If that fails try to convert to one of the units in the middle of the list:
        # combo_index = int((len(combo_index) - 1) / 2) # OLD CODE
        try:
            value = pint_quantity.m_as(
                pint_units[combo_index]
            )  # this will raise an error if the pint quantity is different dimensionality
        except ValueError:
            logger.error('Could not convert {} to one of: {}'.format(
                pint_quantity, units_pint))
            raise ValueError

    doubleSpinBox.setValue(value)
    comboBox_units.setCurrentIndex(combo_index)
Exemplo n.º 25
0
    def __init__(self, settings):
        """ INIT of the class


        """
        super().__init__()  # runs the init of the base_controller class.
        self.logger = logging.getLogger(__name__)
        self.name = 'AaModd18012'
        self._port = settings['port']
        self.dummy = settings['dummy']
        self.rsc = None
        self.logger.info('Class Aa_modd18012 init. Created object.')
Exemplo n.º 26
0
def array_from_pint_quantities(start, stop, step=None, num=None):
    """
    Generates an array from pint values.
    Use either step or num to divide the range up in steps. (If both are specified, step is used)
    Using num works similar to numpy.linspace(start, stop, num).
    Using step works somewhat similar numpy.arange(start, stop, step). Modifications are that the sign of step will be
    interpreted automatically. And the issue of a missing endpoint due to tiny floating point errors is mitigated.
    It returns a numpy array and the pint unit.

    :param start: The start value of the array
    :type start: pint.quantity
    :param stop: The end value for determining the array
    :type stop: pint.quantity
    :param step: The stepsize between points
    :type step: pint.quantity
    :param num: Number of points generate
    :type num: int
    :return: a, b
    :rtype: (numpy.array, pint.unit)
    """
    logger = logging.getLogger(__name__)

    unit = start.u
    sta = start.m_as(unit)
    sto = stop.m_as(
        unit
    )  # if stop doesn't have the same units as start it will result in an error

    if step != None:
        ste = step.m_as(
            unit
        )  # if step doesn't have the same units as start it will result in an error
        # fixing sign:
        if sto < sta and ste > 0:
            ste = -ste

        # Tiny floating point errors sometimes cause the end-point not to be included. To mitigate this add a tiny
        # fraction times the step to the endpoint:
        beyond_stop = sto + ste / 1e9
        arr = np.arange(sta, beyond_stop, ste, float)

        # If the endpoint is almost equal to stop, just replace it with stop:
        if abs(sto - arr[-1]) < abs(ste * 1e-9):
            arr[-1] = sto

    else:
        if num == None:
            logger.warning('Specify either step or num')
            arr = np.array([sta, sto])
        else:
            arr = np.linspace(sta, sto, num)

    return arr, unit
Exemplo n.º 27
0
def spin_combo_to_pint_apply_limits(doubleSpinBox,
                                    comboBox_units,
                                    pint_lower_limit=None,
                                    pint_upper_limit=None):
    """
    When a GUI has a combination of a Q(Double)SpinBox and a QComboBox that hold the numeric value and the unit
    respectively, this function can be used to convert the combined values to a pint quantity.
    In addition it applies limits if they are specified.
    Typically you'll make one function limit_and_apply_X in your gui code, and connect both

        >>> doubleSpinBox.valueChanged.connect(limit_and_apply_X)
        >>> comboBox_units.currentIndexChanged.connect(limit_and_apply_X)

    to this function. Inside limit_and_apply_X() you would use this function spin_combo_to_pint_apply_limits() to apply
    limits and convert it to a pint quantity

    It is strongly recommended to use add_pint_to_combo(comboBox_units) before using this function!
    Complementary function is pint_to_spin_combo()

    :param doubleSpinBox: Q(Double)SpinBox that holds the numeric value
    :param comboBox_units: QComboBox that holds the units
    :param pint_lower_limit: OPTIONAL pint quantity for the lower limit to apply
    :param pint_upper_limit: OPTIONAL pint quantity for the upper limit to apply
    :returns: pint quantity
    """
    logger = logging.getLogger(__name__)

    value = doubleSpinBox.value()
    combo_index = comboBox_units.currentIndex()

    # If available use the units_pint stored inside comboBox_units object (by pint_to_doubleSpin_plus_unit_combo)
    if hasattr(comboBox_units, 'pint_units'):
        pint_units = comboBox_units.pint_units
    else:
        # otherwise try to create it on the fly:
        pint_units = [
            Q_(comboBox_units.itemText(i)).units
            for i in range(comboBox_units.count())
        ]

    new_quantity = value * pint_units[combo_index]
    logger.debug('new pint quantity: {}'.format(new_quantity))

    if pint_upper_limit is not None and new_quantity > pint_upper_limit:
        new_quantity = pint_upper_limit
        pint_to_spin_combo(new_quantity, doubleSpinBox, comboBox_units)

    if pint_lower_limit is not None and new_quantity < pint_lower_limit:
        new_quantity = pint_lower_limit
        pint_to_spin_combo(new_quantity, doubleSpinBox, comboBox_units)

    return new_quantity
Exemplo n.º 28
0
    def __init__(self,
                 main_dict,
                 default_dict={},
                 ReturnNoneForMissingKey=False):
        # self.logger = logging.getLogger(__name__)
        self.__ReturnNoneForMissingKey = ReturnNoneForMissingKey
        self.__logger = logging.getLogger(__name__)
        combined = copy.deepcopy(default_dict)
        combined.update(main_dict)
        super().__init__(combined)

        self.main_dict = main_dict
        self.default_dict = copy.deepcopy(default_dict)
Exemplo n.º 29
0
    def __init__(self, beam_flags_instr, also_close_output=False):
        """
        Gui for beam blocker flags.

        :param beam_flags_instr: The beam flags instrument object to create the gui for
        :type beam_flags_instr: BeamFlagsInstr object
        """
        super().__init__()
        self.logger = logging.getLogger(__name__)

        self.left = 400
        self.top = 400
        self.width = 240
        self.height = 80

        self.bfi = beam_flags_instr
        self.bf_settings = self.bfi.settings['gui_flags']

        self.all_labels = {}

        if 'name' in self.bfi.settings:
            self.title = self.bfi.settings['name']
        else:
            self.title = 'Beam Flags'

        self.red_char = self.bfi.settings['flag_states']['red']
        self.green_char = self.bfi.settings['flag_states']['green']
        self.red_color = self.bfi.settings['gui_red_color']
        self.green_color = self.bfi.settings['gui_green_color']

        self.initUI()

        # Start timer to repeatedly pull the current state of the toggle switches:
        self.logger.info('Starting timer thread')
        # self._busy = False
        if 'gui_state_update_ms' in self.bfi.settings:
            self.indicator_update_time = self.bfi.settings[
                'gui_state_update_ms']
        else:
            self.indicator_update_time = 100  # ms

        #Pay attention: using the Qtimer makes the gui very slow
        #Instead, use a workthread
        self.timer_mode = False
        if self.timer_mode:
            self.timer = QTimer()
            self.timer.timeout.connect(self.update_label_states)
            self.timer.start(self.indicator_update_time)
        else:
            self._thread = WorkThread(self.update_wrapper)
            self._thread.start(priority=QThread.LowestPriority)
Exemplo n.º 30
0
    def __init__(self, hydra_instrument, draw=None, also_close_output=False):
        super().__init__()
        self.logger = logging.getLogger(__name__)
        self.title = 'Hydraharp400 correlator gui'
        self.left = 50
        self.top = 50
        self.width = 320
        self.height = 200
        self.histogram_number = 0
        self.grid_layout = QGridLayout()
        self.setLayout(self.grid_layout)

        self.hydra_instrument = hydra_instrument

        if type(draw) is dict:
            self.draw = list(draw.values())[0]
        else:
            self.draw = draw

        #default values, could be put in a yml file as well
        self.array_length = 65536
        self.resolution = "1ps"
        self.integration_time = 5 * ur('s')
        self.channel = '0'
        self.time_passed = 0 * ur(
            's')  #which also makes sure that the units are the same

        self.max_time = 24 * ur('hour')
        self.max_length = 65536

        self.endtime = []
        self.time_axis = []
        self.units = 's'

        self.hydra_instrument.configurate()
        self.initUI()

        #This one is to continuously (= every 100ms) show the remaining time
        self.timer = QTimer()
        self.timer.timeout.connect(self.show_time_passed)

        # timer to update
        self.timer_plot = QTimer()
        self.timer_plot.timeout.connect(self.update_plot)

        self.histogram_thread = WorkThread(
            self.hydra_instrument.make_histogram, self.integration_time,
            self.channel)

        self.stop = self.stop_histogram