예제 #1
0
    def __init__(self, config, project):
        self.config = config
        self.project = project
        super(ExperimentUi, self).__init__()
        self.settings = FPGASettings()
        self.loggingLevel = config.get('Settings.loggingLevel',logging.INFO)
        self.consoleMaximumLines = config.get('Settings.consoleMaximumLinesNew',100)
        self.consoleEnable = config.get('Settings.consoleEnable',False)
        self.shutterNameDict = config.get('Settings.ShutterNameDict', ChannelNameDict())
        if self.shutterNameDict.__class__.__name__ == 'ChannelNameMap':
            self.shutterNameDict = ChannelNameDict( self.shutterNameDict.names )
        if self.shutterNameDict.customDict.__class__.__name__ == 'ChannelNameMap':
            self.shutterNameDict = ChannelNameDict(self.shutterNameDict.customDict._fwd, self.shutterNameDict.defaultDict )

        self.shutterNameSignal = DataChanged()
        self.triggerNameDict = config.get('Settings.TriggerNameDict', ChannelNameDict())
        if self.triggerNameDict.__class__.__name__ == 'ChannelNameMap':
            self.triggerNameDict = ChannelNameDict( self.triggerNameDict.names )
        self.triggerNameSignal = DataChanged()
        if self.loggingLevel not in self.levelValueList: self.loggingLevel = logging.INFO
        self.dbConnection = project.dbConnection
        self.objectListToSaveContext = list()
        self.voltageControlWindow = None

        localpath = getProject().configDir+'/UserFunctions/'
        for filename in Path(localpath.replace('\\','/')).glob('**/*.py'):
            try:
                importlib.machinery.SourceFileLoader("CustomFunctions", str(filename).replace('\\','/')).load_module()
            except SyntaxError as e:
                SyntaxError('Failed to load {0}'.format(str(filename)))
예제 #2
0
 def __init__(self, deviceClass, config, globalDict, parent=None):
     AWGBase.__init__(self, parent)
     AWGForm.__init__(self)
     self.config = config
     self.configname = 'AWGUi.' + deviceClass.displayName
     self.globalDict = globalDict
     self.autoSave = self.config.get(self.configname+'.autoSave', True)
     self.waveformCache = OrderedDict()
     self.settingsDict = self.config.get(self.configname+'.settingsDict', dict())
     self.settingsName = self.config.get(self.configname+'.settingsName', '')
     # self.settingsDict=dict()
     # self.settingsName=''
     self.recentFiles = self.config.get(self.configname+'.recentFiles', dict()) #dict of form {basename: filename}, where filename has path and basename doesn't
     self.lastDir = self.config.get(self.configname+'.lastDir', getProject().configDir)
     Settings.deviceProperties = deviceClass.deviceProperties
     Settings.saveIfNecessary = self.saveIfNecessary
     Settings.replot = self.replot
     for settings in list(self.settingsDict.values()): #make sure all pickled settings are consistent with device, in case it changed
         for channel in range(deviceClass.deviceProperties['numChannels']):
             if channel >= len(settings.channelSettingsList): #create new channels if it's necessary
                 settings.channelSettingsList.append({
                     'segmentDataRoot':AWGSegmentNode(None),
                     'segmentTreeState':None,
                     'plotEnabled':True,
                     'plotStyle':Settings.plotStyles.lines})
             else:
                 settings.channelSettingsList[channel].setdefault('segmentDataRoot', AWGSegmentNode(None))
                 settings.channelSettingsList[channel].setdefault('segmentTreeState', None)
                 settings.channelSettingsList[channel].setdefault('plotEnabled', True)
                 settings.channelSettingsList[channel].setdefault('plotStyle', Settings.plotStyles.lines)
     self.settings = Settings() #we always run settings through the constructor
     if self.settingsName in self.settingsDict:
         self.settings.update(self.settingsDict[self.settingsName])
     self.device = deviceClass(self.settings)
예제 #3
0
 def __init__(self,config,parent=None):
     VoltageFilesForm.__init__(self)
     VoltageFilesBase.__init__(self, parent)
     self.config = config
     self.configname = 'VoltageFiles.Files'
     self.files = self.config.get(self.configname, Files())
     self.lastDir = getProject().configDir
예제 #4
0
 def __init__(self, settings):
     self.settings = settings
     self.settings.deviceSettings.setdefault('programOnScanStart', False)
     self.settings.deviceSettings.setdefault('useCalibration', False)
     self.waveforms = []
     for channel in range(self.deviceProperties['numChannels']):
         self.waveforms.append(None)
         if channel >= len(self.settings.channelSettingsList
                           ):  #create new channels if it's necessary
             self.settings.channelSettingsList.append({
                 'segmentDataRoot':
                 AWGSegmentNode(None, ''),
                 'segmentTreeState':
                 None,
                 'plotEnabled':
                 True,
                 'plotStyle':
                 self.settings.plotStyles.lines
             })
     self.project = getProject()
     awgConfigDict = list(
         self.project.hardware[self.displayName].values())[0]
     sampleRateText = awgConfigDict['sampleRate']
     sampleRate = self.expression.evaluateAsMagnitude(sampleRateText)
     self.deviceProperties['sampleRate'] = sampleRate
     sample = 1 / self.deviceProperties['sampleRate']
     #new_mag('sample', sample)  # TODO: check whether the added samples = count / second in modules/quantity_units.txt
     #new_mag('samples', sample)  # replaces this
     if not self.project.isEnabled('hardware', self.displayName):
         self.enabled = False
     else:
         self.open()
예제 #5
0
 def __init__(self, config, parent=None):
     VoltageFilesForm.__init__(self)
     VoltageFilesBase.__init__(self, parent)
     self.config = config
     self.configname = 'VoltageFiles.Files'
     self.files = self.config.get(self.configname, Files())
     self.lastDir = getProject().configDir
예제 #6
0
 def __init__(self, config, parameterdict, channelNameData):
     PulseProgramWidget.__init__(self)
     PulseProgramBase.__init__(self)
     self.dependencyGraph = DiGraph()
     self.pulseProgram = PulseProgram.PulseProgram()
     self.sourceCodeEdits = dict()
     self.pppCodeEdits = dict()
     self.config = config
     self.variableTableModel = None
     self.globalVariablesChanged = None
     self.channelNameData = channelNameData
     self.pppCompileException = None
     self.globaldict = parameterdict
     self.project = getProject()
     self.defaultPPPDir = self.project.configDir+'/PulseProgramsPlus'
     if not os.path.exists(self.defaultPPPDir):
         os.makedirs(self.defaultPPPDir)
         examplePPPDir = os.path.realpath(os.path.join(os.path.dirname(__file__), '..', 'config/PulseProgramsPlus')) #/IonControl/config/PulseProgramsPlus directory
         for basename in os.listdir(examplePPPDir):
             if basename.endswith('.ppp'):
                 pathname = os.path.join(examplePPPDir, basename)
                 if os.path.isfile(pathname):
                     shutil.copy(pathname, self.defaultPPPDir) #Copy over all example PPP pulse programs
     self.defaultRAMDir = self.project.configDir+'/RAMFiles'
     if not os.path.exists(self.defaultRAMDir):
         exampleRAMDir = os.path.realpath(os.path.join(os.path.dirname(__file__), '..', 'config/RAMFiles')) #/IonControl/config/RAMFiles directory
         shutil.copytree(exampleRAMDir, self.defaultRAMDir) #Copy over all example RAM files
예제 #7
0
 def __init__(self, config, globalDict, parentname, plotnames=None, parent=None, analysisNames=None, counterNames=None):
     logger = logging.getLogger(__name__)
     ControlForm.__init__(self)
     ControlBase.__init__(self, parent)
     self.config = config
     self.configname = 'EvaluationControl.'+parentname
     self.globalDict = globalDict
     self.ppDict = None
     self.counterNames = counterNames
     # History and Dictionary
     try:
         self.settingsDict = self.config.get(self.configname+'.dict', dict())
     except (TypeError, UnpicklingError):
         logger.info( "Unable to read scan control settings dictionary. Setting to empty dictionary." )
         self.settingsDict = dict()
     self.evaluationConfigurationChanged.emit( self.settingsDict )
     try:
         self.settings = self.config.get(self.configname, Evaluation())
     except TypeError:
         logger.info( "Unable to read scan control settings. Setting to new scan." )
         self.settings = Evaluation()
     self.settingsName = self.config.get(self.configname+'.settingsName', None)
     self.evalAlgorithmList = list()
     self.plotnames = plotnames
     self.analysisNames = analysisNames
     self.pulseProgramUi = None
     self.parameters = self.config.get( self.configname+'.parameters', EvaluationControlParameters() )
     self.project = getProject()
     self.timestampsEnabled = self.project.isEnabled('software', 'Timestamps')
예제 #8
0
 def __init__(self, lastDir=None, plotstyle=0):
     if lastDir is None:
         self.lastDir = getProject().projectDir
     else:
         self.lastDir = lastDir
     self.plotstyle = plotstyle
     self.unplotLastTrace = True
     self.collapseLastTrace = False
     self.expandNew = True
예제 #9
0
 def __init__(self, lastDir=None, plotstyle=0):
     if lastDir is None:
         self.lastDir = getProject().projectDir
     else:
         self.lastDir = lastDir
     self.plotstyle = plotstyle
     self.unplotLastTrace = True
     self.collapseLastTrace = False
     self.expandNew = True
 def __init__(self, config, traceui, plotDict, parent=None):
     Base.__init__(self, parent)
     Form.__init__(self)
     self.config = config
     self.parameters = self.config.get("InstrumentLoggerQueryUi", Parameters())
     self.traceui = traceui
     self.unsavedTraceCount = 0
     self.plotDict = plotDict
     self.project = getProject()
     self.connection = ValueHistoryStore(self.project.dbConnection)
     self.connection.open_session()
     self.cache = dict()
예제 #11
0
 def __init__(self, deviceClass, config, globalDict, parent=None):
     AWGBase.__init__(self, parent)
     AWGForm.__init__(self)
     self.config = config
     self.configname = 'AWGUi.' + deviceClass.displayName
     self.globalDict = globalDict
     self.autoSave = self.config.get(self.configname + '.autoSave', True)
     self.waveformCache = OrderedDict()
     self.settingsDict = self.config.get(self.configname + '.settingsDict',
                                         dict())
     self.settingsName = self.config.get(self.configname + '.settingsName',
                                         '')
     # self.settingsDict=dict()
     # self.settingsName=''
     self.recentFiles = self.config.get(
         self.configname + '.recentFiles', dict()
     )  #dict of form {basename: filename}, where filename has path and basename doesn't
     self.lastDir = self.config.get(self.configname + '.lastDir',
                                    getProject().configDir)
     Settings.deviceProperties = deviceClass.deviceProperties
     Settings.saveIfNecessary = self.saveIfNecessary
     Settings.replot = self.replot
     for settings in list(
             self.settingsDict.values()
     ):  #make sure all pickled settings are consistent with device, in case it changed
         for channel in range(deviceClass.deviceProperties['numChannels']):
             if channel >= len(settings.channelSettingsList
                               ):  #create new channels if it's necessary
                 settings.channelSettingsList.append({
                     'segmentDataRoot':
                     AWGSegmentNode(None),
                     'segmentTreeState':
                     None,
                     'plotEnabled':
                     True,
                     'plotStyle':
                     Settings.plotStyles.lines
                 })
             else:
                 settings.channelSettingsList[channel].setdefault(
                     'segmentDataRoot', AWGSegmentNode(None))
                 settings.channelSettingsList[channel].setdefault(
                     'segmentTreeState', None)
                 settings.channelSettingsList[channel].setdefault(
                     'plotEnabled', True)
                 settings.channelSettingsList[channel].setdefault(
                     'plotStyle', Settings.plotStyles.lines)
     self.settings = Settings(
     )  #we always run settings through the constructor
     if self.settingsName in self.settingsDict:
         self.settings.update(self.settingsDict[self.settingsName])
     self.device = deviceClass(self.settings)
예제 #12
0
 def __init__(self, config, traceui, plotDict, parent=None):
     Base.__init__(self, parent)
     Form.__init__(self)
     self.config = config
     self.parameters = self.config.get("InstrumentLoggerQueryUi",
                                       Parameters())
     self.traceui = traceui
     self.unsavedTraceCount = 0
     self.plotDict = plotDict
     self.project = getProject()
     self.connection = ValueHistoryStore(self.project.dbConnection)
     self.connection.open_session()
     self.cache = dict()
예제 #13
0
 def __init__(self, experimentUi):
     ScriptingWidget.__init__(self)
     ScriptingBase.__init__(self)
     self.config = experimentUi.config
     self.experimentUi = experimentUi
     self.recentFiles = dict() #dict of form {shortname: fullname}, where fullname has path and shortname doesn't
     self.script = Script() #encapsulates the script
     self.scriptHandler = ScriptHandler(self.script, experimentUi) #handles interface to the script
     self.revert = False
     self.initcode = ''
     self.defaultDir = getProject().configDir+'/Scripts'
     if not os.path.exists(self.defaultDir):
         defaultScriptsDir = os.path.realpath(os.path.join(os.path.dirname(__file__), '..', 'config/Scripts')) #/IonControl/config/Scripts directory
         shutil.copytree(defaultScriptsDir, self.defaultDir) #Copy over all example scripts
예제 #14
0
 def __init__(self,
              config,
              globalDict=None,
              dacController=None,
              parent=None):
     VoltageControlForm.__init__(self)
     VoltageControlBase.__init__(self, parent)
     self.config = config
     self.configname = 'VoltageControl.Settings'
     self.settings = self.config.get(self.configname, Settings())
     self.dacController = dacController
     self.voltageBlender = VoltageBlender.VoltageBlender(
         globalDict, dacController)
     self.globalDict = globalDict
     self.project = getProject()
예제 #15
0
 def __init__(self, settings):
     self.project = getProject()
     self.settings = settings
     if not self.project.isEnabled('hardware', self.displayName):
         self.enabled = False
     else:
         dllName = list(self.project.hardware[self.displayName].values())[0]['DLL']
         try:
             self.lib = WinDLL(dllName)
             self.enabled = True
         except Exception:
             logging.getLogger(__name__).info("{0} unavailable. Unable to open {1}.".format(self.displayName, dllName))
             self.enabled = False
     self.settings.deviceSettings.setdefault('continuous', False)
     super(ChaseDA12000, self).__init__(settings)
예제 #16
0
 def __init__(self, experimentUi):
     ScriptingWidget.__init__(self)
     ScriptingBase.__init__(self)
     self.config = experimentUi.config
     self.experimentUi = experimentUi
     self.recentFiles = dict() #dict of form {shortname: fullname}, where fullname has path and shortname doesn't
     self.defaultDir = Path(getProject().configDir+'/Scripts')
     self.script = Script(homeDir=self.defaultDir) #encapsulates the script
     self.scriptHandler = ScriptHandler(self.script, experimentUi) #handles interface to the script
     self.revert = False
     self.allowFileViewerLoad = True
     self.initcode = ''
     if not self.defaultDir.exists():
         defaultScriptsDir = os.path.realpath(os.path.join(os.path.dirname(__file__), '..', 'config/Scripts')) #/IonControl/config/Scripts directory
         shutil.copytree(defaultScriptsDir, str(self.defaultDir)) #Copy over all example scripts
예제 #17
0
 def __init__(self, experimentUi, globalDict):
     super().__init__()
     self.config = experimentUi.config
     self.experimentUi = experimentUi
     self.globalDict = globalDict
     self.recentFiles = dict(
     )  #dict of form {shortname: fullname}, where fullname has path and shortname doesn't
     self.script = UserCode()  #carries around code body and filepath info
     self.defaultDir = getProject().configDir + '/UserFunctions'
     if not os.path.exists(self.defaultDir):
         defaultScriptsDir = os.path.realpath(
             os.path.join(os.path.dirname(__file__), '..',
                          'config/UserFunctions')
         )  #/IonControl/config/UserFunctions directory
         shutil.copytree(defaultScriptsDir,
                         self.defaultDir)  #Copy over all example scripts
예제 #18
0
 def __init__(self, settings):
     self.project = getProject()
     self.settings = settings
     if not self.project.isEnabled('hardware', self.displayName):
         self.enabled = False
     else:
         dllName = list(
             self.project.hardware[self.displayName].values())[0]['DLL']
         try:
             self.lib = WinDLL(dllName)
             self.enabled = True
         except Exception:
             logging.getLogger(__name__).info(
                 "{0} unavailable. Unable to open {1}.".format(
                     self.displayName, dllName))
             self.enabled = False
     self.settings.deviceSettings.setdefault('continuous', False)
     super(ChaseDA12000, self).__init__(settings)
예제 #19
0
 def setupUi(self, parent):
     super(GateSequenceUi, self).setupUi(parent)
     self.setSettings( self.settings )
     self.GateSequenceEnableCheckBox.stateChanged.connect( self.onEnableChanged )
     self.GateDefinitionButton.clicked.connect( self.onLoadGateDefinition )
     self.GateSequenceButton.clicked.connect( self.onLoadGateSequenceList )
     self.FullListRadioButton.toggled.connect( self.onRadioButtonToggled )
     self.GateEdit.editingFinished.connect( self.onGateEditChanged )
     self.StartAddressBox.currentIndexChanged['QString'].connect( self.onStartAddressParam )
     self.repetitionSpinBox.valueChanged.connect( self.onRepetitionChanged )
     self.GateSequenceBox.currentIndexChanged[str].connect( self.onGateSequenceChanged )
     self.GateDefinitionBox.currentIndexChanged[str].connect( self.onGateDefinitionChanged )
     self.debugCheckBox.stateChanged.connect( self.onDebugChanged )
     self.project = getProject()
     self.defaultGateSequencesDir = self.project.configDir+'/GateSequences'
     if not os.path.exists(self.defaultGateSequencesDir):
         exampleGateSequencesDir = os.path.realpath(os.path.join(os.path.dirname(__file__), '..', 'config/GateSequences')) #/IonControl/config/GateSequences directory
         shutil.copytree(exampleGateSequencesDir, self.defaultGateSequencesDir) #Copy over all example gate sequence files
예제 #20
0
 def __init__(self,
              config,
              globalDict,
              parentname,
              plotnames=None,
              parent=None,
              analysisNames=None,
              counterNames=None):
     logger = logging.getLogger(__name__)
     ControlForm.__init__(self)
     ControlBase.__init__(self, parent)
     self.config = config
     self.configname = 'EvaluationControl.' + parentname
     self.globalDict = globalDict
     self.ppDict = None
     self.counterNames = counterNames
     # History and Dictionary
     try:
         self.settingsDict = self.config.get(self.configname + '.dict',
                                             dict())
     except (TypeError, UnpicklingError):
         logger.info(
             "Unable to read scan control settings dictionary. Setting to empty dictionary."
         )
         self.settingsDict = dict()
     self.evaluationConfigurationChanged.emit(self.settingsDict)
     try:
         self.settings = self.config.get(self.configname, Evaluation())
     except TypeError:
         logger.info(
             "Unable to read scan control settings. Setting to new scan.")
         self.settings = Evaluation()
     self.settingsName = self.config.get(self.configname + '.settingsName',
                                         None)
     self.evalAlgorithmList = list()
     self.plotnames = plotnames
     self.analysisNames = analysisNames
     self.pulseProgramUi = None
     self.parameters = self.config.get(self.configname + '.parameters',
                                       EvaluationControlParameters())
     self.project = getProject()
     self.timestampsEnabled = self.project.isEnabled(
         'software', 'Timestamps')
예제 #21
0
 def path(self, current=None, extradir=''):
     """ Return a string path to data location for the given date.
     @type current: datetime.date
     @type extradir: str  
     """
     if not current:
         current = datetime.date.today()
     basedir = getProject().projectDir
     yeardir = os.path.join(basedir, str(current.year))
     monthdir = os.path.join(yeardir, "{0}_{1:02d}".format(current.year, current.month))
     daydir = os.path.join(monthdir, "{0}_{1:02d}_{2:02d}".format(current.year, current.month, current.day))
     fulldir = os.path.join(daydir, extradir)
     if not os.path.exists(basedir):
         raise DataDirectoryException("Data directory '{0}' does not exist.".format(basedir))
     if not os.path.exists(daydir):
         os.makedirs(daydir)
     if extradir and not os.path.exists(fulldir):
         os.makedirs(fulldir)
     return daydir if not extradir else fulldir
예제 #22
0
 def __init__(self, experimentUi, globalDict):
     super().__init__()
     self.config = experimentUi.config
     self.experimentUi = experimentUi
     self.globalDict = globalDict
     self.configDirFolder = 'UserFunctions'
     self.configname = 'UserFunctionsEditor'
     self.defaultDir = Path(getProject().configDir + '/' +
                            self.configDirFolder)
     self.displayFullPathNames = True
     self.script = UserCode(
         self.displayFullPathNames,
         self.defaultDir)  #carries around code body and filepath info
     if not self.defaultDir.exists():
         defaultScriptsDir = os.path.realpath(
             os.path.join(os.path.dirname(__file__), '..',
                          'config/' + self.configDirFolder)
         )  #/IonControl/config/UserFunctions directory
         shutil.copytree(defaultScriptsDir, str(
             self.defaultDir))  #Copy over all example scripts
예제 #23
0
 def __init__(self, config, dbConnection, pulser, dataAvailableSignal, globalVariablesUi, shutterUi, externalInstrumentObservable, parent=None):
     UiBase.__init__(self,parent)
     UiForm.__init__(self)
     self.globalVariablesUi = globalVariablesUi
     self.shutterUi = shutterUi
     self.pulseProgramUi = PulseProgramUi
     self.config = config
     self.overrideDict = keydefaultdict(lambda key: OverrideRecord(key))
     self.parameters = self.config.get('AutoLoad.Parameters', Parameters() )
     self.settings = self.config.get('AutoLoad.Settings', AutoLoadSettings())
     self.settings.globalDict = self.globalVariablesUi.globalDict
     self.settings.shutterDict = self.shutterUi.shutterTableModel.data
     self.settingsDict = self.config.get('AutoLoad.Settings.dict', dict())
     self.currentSettingsName = self.config.get('AutoLoad.SettingsName', '')
     self.loadingHistory = LoadingHistory(dbConnection)
     self.loadingHistory.open()
     self.loadingHistory.query(now() - timedelta(seconds=self.settings.historyLength.m_as('s')),
                               now() + timedelta(hours=2), self.currentSettingsName)
     self.timer = None
     self.pulser = pulser
     self.dataSignalConnected = False
     self.outOfRangeCount=0
     self.dataSignal = dataAvailableSignal
     self.numFailedAutoload = 0
     self.constructStatemachine()
     self.timerNullTime = now()
     self.trappingTime = None
     self.voltageControl = None
     self.preheatStartTime = now()
     self.externalInstrumentObservable = externalInstrumentObservable
     self.originalResetValue = 0
     self.tempName = None
     self.revertRecord = None
     wavemeterHardwareSetting = next(iter(getProject().hardware.get('HighFinesse Wavemeter', {None: {}}).values()))
     self.wavemeterAddress = wavemeterHardwareSetting.get('uri', None)
     self.wavemeterAvailable = wavemeterHardwareSetting.get('enabled', False) and bool(self.wavemeterAddress)
     logging.getLogger(__name__).info("Wavemeter URI: {0} {1}".format(self.wavemeterAddress, "available" if self.wavemeterAvailable else "not available"))
예제 #24
0
 def __init__(self, config, parameterdict, channelNameData):
     PulseProgramWidget.__init__(self)
     PulseProgramBase.__init__(self)
     self.dependencyGraph = DiGraph()
     self.pulseProgram = PulseProgram.PulseProgram()
     self.sourceCodeEdits = dict()
     self.pppCodeEdits = dict()
     self.config = config
     self.variableTableModel = None
     self.globalVariablesChanged = None
     self.channelNameData = channelNameData
     self.pppCompileException = None
     self.globaldict = parameterdict
     self.project = getProject()
     self.defaultPPPDir = self.project.configDir + '/PulseProgramsPlus'
     if not os.path.exists(self.defaultPPPDir):
         os.makedirs(self.defaultPPPDir)
         examplePPPDir = os.path.realpath(
             os.path.join(os.path.dirname(__file__), '..',
                          'config/PulseProgramsPlus')
         )  #/IonControl/config/PulseProgramsPlus directory
         for basename in os.listdir(examplePPPDir):
             if basename.endswith('.ppp'):
                 pathname = os.path.join(examplePPPDir, basename)
                 if os.path.isfile(pathname):
                     shutil.copy(
                         pathname, self.defaultPPPDir
                     )  #Copy over all example PPP pulse programs
     self.defaultRAMDir = self.project.configDir + '/RAMFiles'
     if not os.path.exists(self.defaultRAMDir):
         exampleRAMDir = os.path.realpath(
             os.path.join(
                 os.path.dirname(__file__), '..',
                 'config/RAMFiles'))  #/IonControl/config/RAMFiles directory
         shutil.copytree(
             exampleRAMDir,
             self.defaultRAMDir)  #Copy over all example RAM files
예제 #25
0
 def __init__(self, settings):
     self.settings = settings
     self.settings.deviceSettings.setdefault('programOnScanStart', False)
     self.settings.deviceSettings.setdefault('useCalibration', False)
     self.waveforms = []
     for channel in range(self.deviceProperties['numChannels']):
         self.waveforms.append(None)
         if channel >= len(self.settings.channelSettingsList): #create new channels if it's necessary
             self.settings.channelSettingsList.append({'segmentDataRoot':AWGSegmentNode(None, ''),
                                                       'segmentTreeState':None,
                                                       'plotEnabled' : True,
                                                       'plotStyle':self.settings.plotStyles.lines})
     self.project = getProject()
     awgConfigDict = list(self.project.hardware[self.displayName].values())[0]
     sampleRateText = awgConfigDict['sampleRate']
     sampleRate = self.expression.evaluateAsMagnitude(sampleRateText)
     self.deviceProperties['sampleRate'] = sampleRate
     sample = 1/self.deviceProperties['sampleRate']
     #new_mag('sample', sample)  # TODO: check whether the added samples = count / second in modules/quantity_units.txt
     #new_mag('samples', sample)  # replaces this
     if not self.project.isEnabled('hardware', self.displayName):
         self.enabled = False
     else:
         self.open()
예제 #26
0
import math
import os.path
import socket
import numpy
from numpy import linspace
from modules import MyException
from modules.SequenceDict import SequenceDict
from modules.doProfile import doprofile
from .AdjustValue import AdjustValue
from ProjectConfig.Project import getProject
from uiModules.ImportErrorPopup import importErrorPopup
from Chassis.itfParser import itfParser
from pulser.DACController import DACControllerException
from inspect import isfunction

project = getProject()
#only one voltage controller is currently allowed, so we can just take the first (and only) value in the software voltages dictionary
voltageHardware = list(project.exptConfig['software']['Voltages'].values())[0]['hardware']
hardwareObjName, hardwareName = project.fromFullName(voltageHardware)
hardwareDict = project.isEnabled('hardware', hardwareObjName).get(hardwareName)

NIObjName = 'NI DAC Chassis'
FPGAObjName = 'Opal Kelly FPGA'

if hardwareDict and hardwareObjName==NIObjName:
    try:
        from Chassis import DAQmxUtility
        from Chassis.WaveformChassis import WaveformChassis
        from Chassis.DAQmxUtility import Mode
        import PyDAQmx.DAQmxFunctions
    except ImportError as e:
예제 #27
0
 def initDB(self):
     dbConnection = getProject().dbConnection
     if DBPersist.store is None:
         DBPersist.store = ValueHistoryStore(dbConnection)
         DBPersist.store.open_session()
     self.initialized = True
예제 #28
0
import math
import os.path
import socket
import numpy
from numpy import linspace
from modules import MyException
from modules.SequenceDict import SequenceDict
from modules.doProfile import doprofile
from .AdjustValue import AdjustValue
from ProjectConfig.Project import getProject
from uiModules.ImportErrorPopup import importErrorPopup
from Chassis.itfParser import itfParser
from pulser.DACController import DACControllerException
from inspect import isfunction

project = getProject()
#only one voltage controller is currently allowed, so we can just take the first (and only) value in the software voltages dictionary
voltageHardware = list(
    project.exptConfig['software']['Voltages'].values())[0]['hardware']
hardwareObjName, hardwareName = project.fromFullName(voltageHardware)
hardwareDict = project.isEnabled('hardware', hardwareObjName).get(hardwareName)

NIObjName = 'NI DAC Chassis'
FPGAObjName = 'Opal Kelly FPGA'

if hardwareDict and hardwareObjName == NIObjName:
    try:
        from Chassis import DAQmxUtility
        from Chassis.WaveformChassis import WaveformChassis
        from Chassis.DAQmxUtility import Mode
        import PyDAQmx.DAQmxFunctions
예제 #29
0
    def setupUi(self, parent):
        super(ExperimentUi,self).setupUi(parent)
        self.dockWidgetConsole.hide()
        self.loggerUi = LoggerLevelsUi(self.config)
        self.loggerUi.setupUi(self.loggerUi)
        self.loggerDock = QtWidgets.QDockWidget("Logging")
        self.loggerDock.setWidget(self.loggerUi)
        self.loggerDock.setObjectName("_LoggerDock")
        self.addDockWidget( QtCore.Qt.RightDockWidgetArea, self.loggerDock)
        self.loggerDock.hide()

        logger = logging.getLogger()
        self.exceptionToolBar.addWidget(ExceptionLogButton())

        self.warningLogButton = LogButton(messageIcon=":/petersIcons/icons/Warning.png", messageName="warnings")
        self.exceptionToolBar.addWidget(self.warningLogButton)
        qtWarningButtonHandler.textWritten.connect(self.warningLogButton.addMessage)

        # Setup Console Dockwidget
        self.levelComboBox.addItems(self.levelNameList)
        self.levelComboBox.currentIndexChanged[int].connect( self.setLoggingLevel )
        self.levelComboBox.setCurrentIndex( self.levelValueList.index(self.loggingLevel) )
        self.consoleClearButton.clicked.connect( self.onClearConsole )
        self.linesSpinBox.valueChanged.connect( self.onConsoleMaximumLinesChanged )
        self.linesSpinBox.setValue( self.consoleMaximumLines )
        self.checkBoxEnableConsole.stateChanged.connect( self.onEnableConsole )
        self.checkBoxEnableConsole.setChecked( self.consoleEnable )

        self.parent = parent
        self.tabDict = SequenceDict()

        if self.project.isEnabled('software', 'Memory Profiler'):
            self.memoryProfiler = MemoryProfiler(self)

        #determine if Voltages software is enabled and import class if it is
        self.voltagesEnabled = self.project.isEnabled('software', 'Voltages')
        if self.voltagesEnabled:
            from voltageControl.VoltageControl import VoltageControl

        #setup external parameters; import specific libraries if they are needed, popup warnings if selected hardware import fail
        import externalParameter.StandardExternalParameter
        import externalParameter.InterProcessParameters
        if self.project.isEnabled('hardware', 'Conex Motion'):
            try:
                import externalParameter.MotionParameter #@UnusedImport
            except ImportError: #popup on failed import
                importErrorPopup('Conex Motion')
        if self.project.isEnabled('hardware', 'APT Motion'):
            try:
                import externalParameter.APTInstruments  # @UnusedImport
                externalParameter.APTInstruments.loadDll(
                    list(self.project.hardware['APT Motion'].values())[0]['dllPath'])
            except Exception as e:  # popup on failed import
                importErrorPopup('APT Motion error {0}'.format(e))
        if self.project.isEnabled('hardware', 'Lab Brick'):
            try:
                import externalParameter.LabBrick  # @UnusedImport
                externalParameter.LabBrick.loadDll(
                    list(self.project.hardware['Lab Brick'].values())[0]['dllPath'])
            except Exception as e:  # popup on failed import
                importErrorPopup('Lab Brick error {0}'.format(e))
        from externalParameter.ExternalParameterBase import InstrumentDict

        # setup FPGAs
        self.setupFPGAs()

        # initialize PulseProgramUi
        pulserConfig = self.pulser.pulserConfiguration()
        self.shutterNameDict.defaultDict = pulserConfig.shutterBits if pulserConfig else dict()
        self.triggerNameDict.defaultDict = pulserConfig.triggerBits if pulserConfig else dict()
        self.counterNameDict = pulserConfig.counterBits if pulserConfig else dict()
        self.channelNameData = (self.shutterNameDict, self.shutterNameSignal, self.triggerNameDict, self.triggerNameSignal, self.counterNameDict )
        self.pulseProgramDialog = PulseProgramUi.PulseProgramSetUi(self.config,  self.channelNameData )
        self.pulseProgramDialog.setupUi(self.pulseProgramDialog)

        # Global Variables
        self.globalVariablesUi = GlobalVariablesUi(self.config)
        self.globalVariablesUi.setupUi(self.globalVariablesUi)
        self.globalVariablesDock = QtWidgets.QDockWidget("Global Variables")
        self.globalVariablesDock.setObjectName("Global Variables")
        self.globalVariablesDock.setWidget( self.globalVariablesUi )
        self.addDockWidget(QtCore.Qt.RightDockWidgetArea , self.globalVariablesDock)

        self.measurementLog = MeasurementLogUi(self.config, self.dbConnection)
        self.measurementLog.setupUi(self.measurementLog)
        #self.measurementLogDock = QtWidgets.QDockWidget("Measurement Log")
        #self.measurementLogDock.setWidget( self.measurementLog )
        #self.measurementLogDock.setObjectName('_MeasurementLog')
        #self.addDockWidget( QtCore.Qt.BottomDockWidgetArea, self.measurementLogDock )

        self.preferencesUi = PreferencesUi(config, self)
        self.preferencesUi.setupUi(self.preferencesUi)
        self.preferencesUiDock = QtGui.QDockWidget("Print Preferences")
        self.preferencesUiDock.setWidget(self.preferencesUi)
        self.preferencesUiDock.setObjectName("_preferencesUi")
        self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.preferencesUiDock)

        for widget, name in [(ScanExperiment.ScanExperiment(self.settings, self.pulser, self.globalVariablesUi,
                                                            "ScanExperiment", toolBar=self.experimentToolBar,
                                                            measurementLog=self.measurementLog,
                                                            callWhenDoneAdjusting=self.callWhenDoneAdjusting,
                                                            preferences=self.preferencesUi.preferences().printPreferences),
                              "Scan")
                             ]:
            widget.setupUi(widget, self.config)
            if hasattr(widget, 'setPulseProgramUi'):
                widget.setPulseProgramUi(self.pulseProgramDialog)
            if hasattr(widget, 'plotsChanged'):
                widget.plotsChanged.connect(self.initMenu)
            self.tabWidget.addTab(widget, name)
            self.tabDict[name] = widget
            widget.ClearStatusMessage.connect(self.statusbar.clearMessage)
            widget.StatusMessage.connect(self.statusbar.showMessage)
            widget.stashChanged.connect(self.onStashChanged)

        self.scanExperiment = self.tabDict["Scan"]

        self.shutterUi, self.shutterDockWidget = self.instantiateShutterUi(self.pulser, 'Shutters', "ShutterUi", self.config, self.globalVariablesUi.globalDict, self.shutterNameDict, self.shutterNameSignal)

        self.triggerUi = ShutterUi.TriggerUi(self.pulser, 'ShutterUi', 'trigger', self.config, (self.triggerNameDict, self.triggerNameSignal) )
        self.triggerUi.offColor =  QtGui.QColor(QtCore.Qt.white)
        self.triggerUi.setupUi(self.triggerUi)
        self.pulser.ppActiveChanged.connect( self.triggerUi.setDisabled )
        self.triggerDockWidget.setWidget( self.triggerUi )

        #AWGs
        enabledAWGDict = {displayName:className for displayName,className in AWGDevices.AWGDeviceDict.items()
                          if self.project.isEnabled('hardware', displayName)}
        self.AWGUiDict = dict()
        if enabledAWGDict:
            AWGIcon = QtGui.QIcon()
            AWGPixmap = QtGui.QPixmap(":/other/icons/AWG.png")
            AWGIcon.addPixmap(AWGPixmap)
            AWGButton = QtWidgets.QToolButton()
            AWGButton.setIcon(AWGIcon)
            self.toolBar.addWidget(AWGButton)
            if len(enabledAWGDict) > 1:
                menu = QtWidgets.QMenu("AWG")
                AWGButton.setMenu(menu)
                AWGButton.setPopupMode(QtWidgets.QToolButton.InstantPopup)
                menu.setIcon(AWGIcon)
                self.menuWindows.addMenu(menu)
            for displayName, className in enabledAWGDict.items():
                awgUi = AWGUi(getattr(AWGDevices, className), self.config, self.globalVariablesUi.globalDict, self.scanExperiment.pulseProgramUi)
                self.AWGUiDict[displayName] = awgUi
                awgUi.setupUi(awgUi)
                awgUi.varDictChanged.connect( partial(self.scanExperiment.updateScanTarget, displayName) )
                self.scanExperiment.updateScanTarget( displayName, awgUi.varAsOutputChannelDict )
                self.globalVariablesUi.valueChanged.connect( awgUi.evaluate )
                action = QtWidgets.QAction(AWGIcon, displayName, self)
                action.triggered.connect(partial(self.onAWG, displayName))
                if len(enabledAWGDict) > 1:
                    menu.addAction(action)
                else:
                    self.menuWindows.addAction(action)
                    AWGButton.clicked.connect(action.trigger)

        ParameterUi, self.pulserParameterUiDock = self.instantiateParametersUi(self.pulser, "Pulser Parameters", "PulserParameterUi", self.config, self.globalVariablesUi.globalDict)
        self.objectListToSaveContext.append(ParameterUi)

        self.DDSUi, self.DDSDockWidget = self.instantiateDDSUi(self.pulser, "DDS", "DDSUi", self.config, self.globalVariablesUi.globalDict)
        self.objectListToSaveContext.append(self.DDSUi)

        self.DACUi, self.DACDockWidget = self.instantiateDACUi(self.pulser, "DAC", "dacUi", self.config, self.globalVariablesUi.globalDict)
        self.objectListToSaveContext.append(self.DACUi)

#         self.DDSUi9910 = DDSUi9910.DDSUi(self.config, self.pulser )
#         self.DDSUi9910.setupUi(self.DDSUi9910)
#         self.DDS9910DockWidget.setWidget( self.DDSUi9910 )
#        self.pulser.ppActiveChanged.connect( self.DDSUi9910.setDisabled )
        #self.tabDict['Scan'].NeedsDDSRewrite.connect( self.DDSUi9910.onWriteAll )
        self.instantiateAuxiliaryPulsers()

        self.valueHistoryUi = ValueHistoryUi(self.config, self.dbConnection)
        self.valueHistoryUi.setupUi( self.valueHistoryUi )
        self.valueHistoryDock = QtWidgets.QDockWidget("Value History")
        self.valueHistoryDock.setWidget( self.valueHistoryUi )
        self.valueHistoryDock.setObjectName("_valueHistory")
        self.addDockWidget( QtCore.Qt.RightDockWidgetArea, self.valueHistoryDock )
        
        # tabify the dock widgets
        self.tabifyDockWidget( self.pulserParameterUiDock, self.preferencesUiDock)
        self.tabifyDockWidget( self.preferencesUiDock, self.triggerDockWidget )
        self.tabifyDockWidget( self.triggerDockWidget, self.shutterDockWidget)
        self.tabifyDockWidget( self.shutterDockWidget, self.DDSDockWidget )
        self.tabifyDockWidget( self.DDSDockWidget, self.DACDockWidget )
#        self.tabifyDockWidget( self.DDSDockWidget, self.DDS9910DockWidget )
#        self.tabifyDockWidget( self.DDS9910DockWidget, self.globalVariablesDock )
        self.tabifyDockWidget( self.DACDockWidget, self.globalVariablesDock )
        self.tabifyDockWidget( self.globalVariablesDock, self.valueHistoryDock )
        self.triggerDockWidget.hide()
        self.preferencesUiDock.hide()

        self.ExternalParametersSelectionUi = ExternalParameterSelection.SelectionUi(self.config, self.globalVariablesUi.globalDict, classdict=InstrumentDict)
        self.ExternalParametersSelectionUi.setupUi( self.ExternalParametersSelectionUi )
        self.ExternalParameterSelectionDock = QtWidgets.QDockWidget("Params Selection")
        self.ExternalParameterSelectionDock.setObjectName("_ExternalParameterSelectionDock")
        self.ExternalParameterSelectionDock.setWidget(self.ExternalParametersSelectionUi)
        self.addDockWidget( QtCore.Qt.RightDockWidgetArea, self.ExternalParameterSelectionDock)

        self.ExternalParametersUi = ExternalParameterUi.ControlUi(self.config, self.globalVariablesUi.globalDict)
        self.ExternalParametersUi.setupUi(self.ExternalParametersSelectionUi.outputChannels())

        self.ExternalParameterDock = QtWidgets.QDockWidget("Params Control")
        self.ExternalParameterDock.setWidget(self.ExternalParametersUi)
        self.ExternalParameterDock.setObjectName("_ExternalParameterDock")
        self.addDockWidget( QtCore.Qt.RightDockWidgetArea, self.ExternalParameterDock)
        self.ExternalParametersSelectionUi.outputChannelsChanged.connect( self.ExternalParametersUi.setupParameters )

        self.instrumentLoggingDisplay = InstrumentLoggingDisplay(self.config)
        self.instrumentLoggingDisplay.setupUi( self.ExternalParametersSelectionUi.inputChannels(), self.instrumentLoggingDisplay )
        self.instrumentLoggingDisplayDock = QtWidgets.QDockWidget("Params Reading")
        self.instrumentLoggingDisplayDock.setObjectName("_ExternalParameterDisplayDock")
        self.instrumentLoggingDisplayDock.setWidget(self.instrumentLoggingDisplay)
        self.addDockWidget( QtCore.Qt.RightDockWidgetArea, self.instrumentLoggingDisplayDock)
        self.ExternalParametersSelectionUi.inputChannelsChanged.connect( self.instrumentLoggingDisplay.setupParameters )
               
        self.ExternalParametersSelectionUi.outputChannelsChanged.connect( partial(self.scanExperiment.updateScanTarget, 'External') )               
        self.scanExperiment.updateScanTarget( 'External', self.ExternalParametersSelectionUi.outputChannels() )
        
        self.todoList = TodoList( self.tabDict, self.config, self.getCurrentTab, self.switchTab, self.globalVariablesUi )
        self.todoList.setupUi()
        self.todoListDock = QtWidgets.QDockWidget("Todo List")
        self.todoListDock.setWidget(self.todoList)
        self.todoListDock.setObjectName("_todoList")
        self.addDockWidget( QtCore.Qt.RightDockWidgetArea, self.todoListDock)
        self.tabifyDockWidget(self.valueHistoryDock, self.todoListDock)

        for name, widget in self.tabDict.items():
            if hasattr( widget, 'scanConfigurationListChanged' ) and widget.scanConfigurationListChanged is not None:
                widget.scanConfigurationListChanged.connect( partial( self.todoList.populateMeasurementsItem, name)  )
            if hasattr( widget, 'evaluationConfigurationChanged' ) and widget.evaluationConfigurationChanged is not None:
                widget.evaluationConfigurationChanged.connect( partial( self.todoList.populateEvaluationItem, name)  )
            if hasattr( widget, 'analysisConfigurationChanged' ) and widget.analysisConfigurationChanged is not None:
                widget.analysisConfigurationChanged.connect( partial( self.todoList.populateAnalysisItem, name)  )
       
        #tabify external parameters controls
        self.tabifyDockWidget(self.ExternalParameterSelectionDock, self.ExternalParameterDock)
        self.tabifyDockWidget(self.ExternalParameterDock, self.instrumentLoggingDisplayDock)
        
        self.tabWidget.currentChanged.connect(self.onCurrentChanged)
        self.actionClear.triggered.connect(self.onClear)
        self.actionPause.triggered.connect(self.onPause)

        #Save and load actions
        self.actionSave_GUI.triggered.connect(self.onSaveGUI)
        self.actionSave_GUI_Yaml.triggered.connect(self.onSaveGUIYaml)

        self.actionStart.triggered.connect(self.onStart)
        self.actionStop.triggered.connect(self.onStop)
        self.actionAbort.triggered.connect(self.onAbort)
        self.actionExit.triggered.connect(self.onClose)
        self.actionContinue.triggered.connect(self.onContinue)
        self.actionPulses.triggered.connect(self.onPulses)
        self.actionReload.triggered.connect(self.onReload)
        self.actionProject.triggered.connect( self.onProjectSelection)
        self.actionDocumentation.triggered.connect(self.onShowDocumentation)
        if self.voltagesEnabled:
            self.actionVoltageControl.triggered.connect(self.onVoltageControl)
        else:
            self.actionVoltageControl.setDisabled(True)
            self.actionVoltageControl.setVisible(False)
        self.actionScripting.triggered.connect(self.onScripting)
        self.actionUserFunctions.triggered.connect(self.onUserFunctionsEditor)
        self.actionMeasurementLog.triggered.connect(self.onMeasurementLog)
        self.actionDedicatedCounters.triggered.connect(self.showDedicatedCounters)
        self.actionLogic.triggered.connect(self.showLogicAnalyzer)
        self.currentTab = self.tabDict.at( min(len(self.tabDict)-1, self.config.get('MainWindow.currentIndex',0) ) )
        self.tabWidget.setCurrentIndex( self.config.get('MainWindow.currentIndex',0) )
        self.currentTab.activate()
        if hasattr( self.currentTab, 'stateChanged' ):
            self.currentTab.stateChanged.connect( self.todoList.onStateChanged )
        if 'MainWindow.State' in self.config:
            self.parent.restoreState(self.config['MainWindow.State'])
        self.initMenu()
        self.actionResume.setEnabled(False)
        if 'MainWindow.pos' in self.config:
            self.move(self.config['MainWindow.pos'])
        if 'MainWindow.size' in self.config:
            self.resize(self.config['MainWindow.size'])
        if 'MainWindow.isMaximized' in self.config:
            if self.config['MainWindow.isMaximized']:
                self.showMaximized()
        else:
            self.showMaximized()
            
        self.dedicatedCountersWindow = DedicatedCounters(self.config, self.dbConnection, self.pulser, self.globalVariablesUi, self.shutterUi,self.ExternalParametersUi.callWhenDoneAdjusting )
        self.dedicatedCountersWindow.setupUi(self.dedicatedCountersWindow)
        
        self.logicAnalyzerWindow = LogicAnalyzer(self.config, self.pulser, self.channelNameData )
        self.logicAnalyzerWindow.setupUi(self.logicAnalyzerWindow)

        if self.voltagesEnabled:
            try:
                self.voltageControlWindow = VoltageControl(self.config, self.globalVariablesUi.globalDict, self.dac)
                self.voltageControlWindow.setupUi(self.voltageControlWindow)
                self.voltageControlWindow.globalAdjustUi.outputChannelsChanged.connect( partial(self.scanExperiment.updateScanTarget, 'Voltage') )
                self.voltageControlWindow.localAdjustUi.outputChannelsChanged.connect( partial(self.scanExperiment.updateScanTarget, 'Voltage Local Adjust') )
                self.scanExperiment.updateScanTarget('Voltage', self.voltageControlWindow.globalAdjustUi.outputChannels())
                self.scanExperiment.updateScanTarget('Voltage Local Adjust', self.voltageControlWindow.localAdjustUi.outputChannels())
            except MyException.MissingFile as e:
                self.voltageControlWindow = None
                self.actionVoltageControl.setDisabled( True )
                logger.warning("Missing file - voltage subsystem disabled: {0}".format(str(e)))
            if self.voltageControlWindow:
                self.tabDict["Scan"].ppStartSignal.connect( self.voltageControlWindow.synchronize )   # upload shuttling data before running pule program
                self.dedicatedCountersWindow.autoLoad.setVoltageControl( self.voltageControlWindow )

        self.setWindowTitle("Experimental Control ({0})".format(self.project) )

        
        QtCore.QTimer.singleShot(60000, self.onCommitConfig )
        traceFilename, _ = DataDirectory.DataDirectory().sequencefile("Trace.log")
        LoggingSetup.setTraceFilename( traceFilename )
        errorFilename, _ = DataDirectory.DataDirectory().sequencefile("Error.log")
        LoggingSetup.setErrorFilename( errorFilename )
        
        # connect signals and slots for todolist and auto resume
        for name, widget in self.tabDict.items():
            if hasattr(widget,'onContinue'):
                self.dedicatedCountersWindow.autoLoad.ionReappeared.connect( widget.onContinue )
                
        # add PushDestinations
        for widget in self.tabDict.values():
            if hasattr(widget, 'addPushDestination'):
                widget.addPushDestination( 'External', self.ExternalParametersUi )
                
        # initialize ScriptingUi
        self.scriptingWindow = ScriptingUi(self)
        self.scriptingWindow.setupUi(self.scriptingWindow)

        # this is redundant in __init__ but this resolves issues with user-defined functions that reference NamedTraces
        localpath = getProject().configDir+'/UserFunctions/'
        for filename in Path(localpath.replace('\\','/')).glob('**/*.py'):
            try:
                importlib.machinery.SourceFileLoader("CustomFunctions", str(filename).replace('\\','/')).load_module()
            except SyntaxError as e:
                SyntaxError('Failed to load {0}'.format(str(filename)))

        # initialize NamedTraceUi
        self.userFunctionsEditor = UserFunctionsEditor(self, self.globalVariablesUi.globalDict)
        self.userFunctionsEditor.setupUi(self.userFunctionsEditor)

        # initialize StashButton
        self.actionStash.triggered.connect(self.onStash)
        self.actionResume.triggered.connect(self.onResume)
        self.stashButton = StashButtonControl(self.actionResume)
        self.stashButton.resume.connect(self.onResume)