Skip to content

Commit

Permalink
fix for BBN-Q#69,BBN-Q#71, and BBN-Q#72
Browse files Browse the repository at this point in the history
BBN-Q#69
In the Looper Form of MeasFilterViews.enaml, test that the selected
filter is in the filter dictionary else return -1

BBN-Q#71
In the QtListStrWidget, test if the enable changed when the labels are the same
and the label is in the item list. Also, only signal a name change when the
labels are not the same and the newlabel is not in the item list. In the old
version of code there are some conditions when on_edit is called that result in
the dictionary manager trying to rename an item that does not exist.

BBN-Q#72
Added a new feature to save config in a different directory and load a config
from a different directory.  After loading a config, the GUI will restart itself
for the changes to take effectively
  • Loading branch information
rmcgurrin committed Sep 24, 2015
1 parent 002b830 commit 1ceb396
Show file tree
Hide file tree
Showing 11 changed files with 143 additions and 40 deletions.
4 changes: 2 additions & 2 deletions DictManager.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ def remove_item(self, itemLabel):
self.itemDict.pop(itemLabel)
#TODO: once ContainerDicts land see if we still need this
self.displayList.pop(self.displayList.index(itemLabel))
else:
print("WARNING: %s is not in the list"%itemLabel)
elif itemLabel != '':
self.displayList.pop(self.displayList.index(itemLabel))

def name_changed(self, oldLabel, newLabel):
# Add copy of changing item
Expand Down
50 changes: 46 additions & 4 deletions ExpSettingsGUI.py
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#! /usr/bin/env python
import h5py
from atom.api import Atom, Typed, Str, Bool, List

Expand All @@ -14,6 +15,7 @@
import os
import config
import ExpSettingsVal
import shutil

class ExpSettings(Atom):

Expand Down Expand Up @@ -46,9 +48,10 @@ def load_from_file(self, fileName):
import JSONHelpers
pass

def write_to_file(self):
def write_to_file(self,fileName=None):
import JSONHelpers
with open(self.curFileName,'w') as FID:
curFileName = fileName if fileName != None else self.curFileName
with open(curFileName, 'w') as FID:
json.dump(self, FID, cls=JSONHelpers.ScripterEncoder, indent=2, sort_keys=True, CWMode=self.CWMode)

def write_libraries(self):
Expand All @@ -63,13 +66,52 @@ def write_libraries(self):
return False
elif not self.validate:
print "JSON Files validation disabled"

self.channels.write_to_file()
self.instruments.write_to_file()
self.measurements.write_to_file()
self.sweeps.write_to_file()

return True

def save_config(self,path):

if self.validate:
self.validation_errors = ExpSettingsVal.validate_lib()
if self.validation_errors != []:
print "JSON Files did not validate"
return False
elif not self.validate:
print "JSON Files validation disabled"

try:
self.channels.write_to_file(fileName=path+ os.sep + os.path.basename(self.channels.libFile))
self.measurements.write_to_file(fileName=path+ os.sep + os.path.basename(self.measurements.libFile))
self.instruments.write_to_file(fileName=path+ os.sep + os.path.basename(self.instruments.libFile))
self.sweeps.write_to_file(fileName=path+ os.sep + os.path.basename(self.sweeps.libFile))
self.write_to_file(fileName=path+ os.sep + os.path.basename(self.curFileName))
except:
return False


return True

def load_config(self,path):

print("LOADING FROM:",path)

try:
shutil.copy(path+ os.sep + os.path.basename(self.channels.libFile),self.channels.libFile)
shutil.copy(path+ os.sep + os.path.basename(self.instruments.libFile),self.instruments.libFile)
shutil.copy(path+ os.sep + os.path.basename(self.measurements.libFile),self.measurements.libFile)
shutil.copy(path+ os.sep + os.path.basename(self.sweeps.libFile),self.sweeps.libFile)
shutil.copy(path+ os.sep + os.path.basename(self.curFileName),self.curFileName)
except shutil.Error as e:
print('Error: %s' % e)
except IOError as e:
print('Error: %s' % e.strerror)

return True


def apply_quickpick(self, name):
try:
Expand Down Expand Up @@ -109,7 +151,7 @@ def format_errors(self):

if __name__ == '__main__':
import Libraries

from ExpSettingsGUI import ExpSettings
expSettings = ExpSettings(sweeps=Libraries.sweepLib,
instruments=Libraries.instrumentLib,
Expand Down
42 changes: 37 additions & 5 deletions ExpSettingsView.enaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from enaml.widgets.api import MainWindow, Window, Container, Notebook, Page, MenuBar, \
Menu, Action, FileDialog, ComboBox, PushButton, PopupView, Label, \
Menu, Action, FileDialogEx, ComboBox, PushButton, PopupView, Label, \
CheckBox, Form
from enaml.core.api import Looper
from enaml.layout.api import hbox, vbox, spacer, align
Expand All @@ -8,6 +8,7 @@ from QGL.ChannelsViews import ChannelLibraryView
from instruments.InstrumentManagerView import InstrumentManagerView
from SweepsViews import SweepManager
from MeasFiltersViews import MeasFilterManager
import os, sys, time


#See what's in the quick pick file to enumerate it
Expand All @@ -24,6 +25,7 @@ def get_update_script_file_callback(expSettings):
def update_script_file_callback(dlg):
if dlg.result == 'accepted': #if the pressed "open" otherwise we get 'rejected'
expSettings.curFileName = dlg.path
print(expSettings.curFileName)
return update_script_file_callback

chosenQuickPick = bytearray("")
Expand Down Expand Up @@ -92,12 +94,42 @@ enamldef ExpSettingsView(MainWindow): main:
ep.center_on_widget(main)

Action:
text = 'Save As\tCtrl+Shift+S'
text = 'Save Config As\tCtrl+Shift+S'
tool_tip = 'Save to a new setting file'
triggered ::
dlg = FileDialog(root_object(), title='Choose a script file..', mode='save_file',
callback=get_update_script_file_callback(expSettings), filters=['*.json'])
dlg.open()
path = FileDialogEx.get_existing_directory(main,show_dirs_only=False)
if not os.path.isdir(path) and path !='':
print('% s Does not Exist: Creating %s'%(path,path))
os.mkdir(path)

if expSettings.save_config(path):
NotificationPopup(main, window_type='window', displayText="Config Saved").show()
else:
ep = ErrorPopup(displayText=expSettings.format_errors())
ep.show()
ep.center_on_widget(main)

Action:
text = 'Load Config\tCtrl+Shift+O'
tool_tip = 'Load Config Files from Saved Location'
triggered ::
path = FileDialogEx.get_existing_directory(main,show_dirs_only=False)
if not os.path.isdir(path):
print('% s Does not Exist: Creating %s'%(path,path))
ep = ErrorPopup(displayText=expSettings.format_errors())
ep.show()
ep.center_on_widget(main)
os.mkdir(path)

if expSettings.load_config(path):
NotificationPopup(main, window_type='window', displayText="New Config Loaded ... Restarting GUI").show()
os.execl(sys.executable, sys.executable, * sys.argv)

else:
ep = ErrorPopup(displayText=expSettings.format_errors())
ep.show()
ep.center_on_widget(main)

Action:
text = "Stash current settings"
enabled = False
Expand Down
20 changes: 12 additions & 8 deletions MeasFilters.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,11 +120,14 @@ def __init__(self, **kwargs):
def __getitem__(self, filterName):
return self.filterDict[filterName]

def write_to_file(self):
def write_to_file(self,fileName=None):
#Move import here to avoid circular import
import JSONHelpers
if self.libFile:
with open(self.libFile,'w') as FID:

libFileName = fileName if fileName != None else self.libFile

if libFileName:
with open(libFileName, 'w') as FID:
json.dump(self, FID, cls=JSONHelpers.LibraryEncoder, indent=2, sort_keys=True)

def load_from_library(self):
Expand Down Expand Up @@ -162,12 +165,13 @@ def json_encode(self, matlabCompatible=False):
if __name__ == "__main__":

#Work around annoying problem with multiple class definitions
from MeasFilters import DigitalHomodyne, Correlator, MeasFilterLibrary
from MeasFilters import DigitalDemod, Correlator, MeasFilterLibrary

testFilter1 = DigitalHomodyne(label='M1', boxCarStart=100, boxCarStop=500, IFfreq=10e6, samplingRate=250e6, channel=1)
testFilter2 = DigitalHomodyne(label='M2', boxCarStart=150, boxCarStop=600, IFfreq=39.2e6, samplingRate=250e6, channel=2)
testFilter3 = Correlator(label='M12')
filterDict = {'M1':testFilter1, 'M2':testFilter2, 'M12':testFilter3}
testFilter1 = DigitalDemod(label='M1')
testFilter2 = DigitalDemod(label='M2')
testFilter3 = Correlator(label='M3')
testFilter4 = Correlator(label='M4')
filterDict = {'M1':testFilter1, 'M2':testFilter2, 'M3':testFilter3,'M4':testFilter4}

testLib = MeasFilterLibrary(libFile='MeasFilterLibrary.json', filterDict=filterDict)

Expand Down
12 changes: 11 additions & 1 deletion MeasFiltersViews.enaml
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,16 @@ enamldef KernelIntegrationForm(GroupBox):
obj := myFilter
enumName = 'plotMode'

#moved this logic to a separate function to tidy things up a bit
def filterLooperGetIdndex(filterLib,myFilter,loop_index):
if loop_index < len(myFilter.filters) and \
myFilter.filters[loop_index] in filterLib.filterDict.values():
return filterLib.filterDict.values().index(myFilter.filters[loop_index])
else:
return -1



enamldef CorrelatorView(GroupBox):
attr myFilter
attr filterLib
Expand All @@ -199,7 +209,7 @@ enamldef CorrelatorView(GroupBox):
text = 'Filter {}:'.format(loop_index+1)
ComboBox:
items << filterLib.filterDict.keys()
index << filterLib.filterDict.values().index(myFilter.filters[loop_index]) if loop_index < len(myFilter.filters) and myFilter.filters[loop_index] else -1
index << filterLooperGetIdndex(filterLib,myFilter,loop_index)
index ::
myFilter.filters[loop_index] = filterLib.filterDict[selected_item]
Label:
Expand Down
7 changes: 4 additions & 3 deletions QGL/Channels.py
Original file line number Diff line number Diff line change
Expand Up @@ -287,13 +287,14 @@ def build_connectivity_graph(self):
self.connectivityG.add_edge(chan.source, chan.target)
self.connectivityG[chan.source][chan.target]['channel'] = chan

def write_to_file(self):
def write_to_file(self,fileName=None):
import JSONHelpers
if self.libFile:
libFileName = fileName if fileName != None else self.libFile
if libFileName:
#Pause the file watcher to stop cicular updating insanity
if self.fileWatcher:
self.fileWatcher.pause()
with open(self.libFile, 'w') as FID:
with open(libFileName, 'w') as FID:
json.dump(self, FID, cls=JSONHelpers.LibraryEncoder, indent=2, sort_keys=True)
if self.fileWatcher:
self.fileWatcher.resume()
Expand Down
9 changes: 6 additions & 3 deletions Sweeps.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,10 +147,13 @@ def __getitem__(self, sweepName):
def _get_sweepList(self):
return [sweep.label for sweep in self.sweepDict.values() if sweep.enabled]

def write_to_file(self):
def write_to_file(self,fileName=None):
import JSONHelpers
if self.libFile:
with open(self.libFile, 'w') as FID:

libFileName = fileName if fileName != None else self.libFile

if libFileName:
with open(libFileName, 'w') as FID:
json.dump(self, FID, cls=JSONHelpers.LibraryEncoder, indent=2, sort_keys=True)

def load_from_library(self):
Expand Down
13 changes: 7 additions & 6 deletions config.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,13 @@
PyQLabCfg = json.load(f)

#pull out the variables
AWGDir = PyQLabCfg['AWGDir']
channelLibFile = PyQLabCfg['ChannelLibraryFile']
instrumentLibFile = PyQLabCfg['InstrumentLibraryFile']
sweepLibFile = PyQLabCfg['SweepLibraryFile']
measurementLibFile = PyQLabCfg['MeasurementLibraryFile']
quickpickFile = PyQLabCfg['QuickPickFile'] if 'QuickPickFile' in PyQLabCfg else ''
#abspath allows the use of relative file names in the config file
AWGDir = os.path.abspath(PyQLabCfg['AWGDir'])
channelLibFile = os.path.abspath(PyQLabCfg['ChannelLibraryFile'])
instrumentLibFile = os.path.abspath(PyQLabCfg['InstrumentLibraryFile'])
sweepLibFile = os.path.abspath(PyQLabCfg['SweepLibraryFile'])
measurementLibFile = os.path.abspath(PyQLabCfg['MeasurementLibraryFile'])
quickpickFile = os.path.abspath(PyQLabCfg['QuickPickFile']) if 'QuickPickFile' in PyQLabCfg else ''

# plotting options
plotBackground = PyQLabCfg['PlotBackground'] if 'PlotBackground' in PyQLabCfg else '#EAEAF2'
Expand Down
2 changes: 2 additions & 0 deletions instruments/AWGs.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
from importlib import import_module
import os
import inspect
from drivers.APS import APS


AWGList = []

Expand Down
10 changes: 7 additions & 3 deletions instruments/InstrumentManager.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,19 @@ def __init__(self, **kwargs):
def __getitem__(self, instrName):
return self.instrDict[instrName]

def write_to_file(self):
def write_to_file(self,fileName=None):
#Move import here to avoid circular import
import JSONHelpers
libFileName = fileName if fileName != None else self.libFile
if self.libFile:
#Pause the file watcher to stop circular updating insanity
if self.fileWatcher:
self.fileWatcher.pause()
with open(self.libFile,'w') as FID:
json.dump(self, FID, cls=JSONHelpers.LibraryEncoder, indent=2, sort_keys=True)

if libFileName:
with open(libFileName, 'w') as FID:
json.dump(self, FID, cls=JSONHelpers.LibraryEncoder, indent=2, sort_keys=True)

if self.fileWatcher:
self.fileWatcher.resume()

Expand Down
14 changes: 9 additions & 5 deletions widgets/qt_list_str_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,15 +99,19 @@ def on_edit(self, item):
itemRow = widget.indexFromItem(item).row()
oldLabel = self.items[itemRow]
newLabel = item.text()
if oldLabel != newLabel:

#only signal the enable change when the labels are the same and is in
#the item list, also only signal a name change when the labels are not
#the same and the newlabel is not in the item list
if newLabel == oldLabel and newLabel in self.items:
self.checked_states[itemRow] = True if item.checkState() == Qt.Checked else False
self.enable_changed(item.text(), self.checked_states[itemRow])
elif oldLabel != newLabel and newLabel not in self.items:
self.item_changed(oldLabel, newLabel)
self.selected_item = item.text()
self.items[itemRow] = item.text()
self.apply_validator(item, newLabel)
else:
self.checked_states[itemRow] = True if item.checkState() == Qt.Checked else False
self.enable_changed(item.text(), self.checked_states[itemRow])


#--------------------------------------------------------------------------
# ProxyListStrView API
#--------------------------------------------------------------------------
Expand Down

0 comments on commit 1ceb396

Please sign in to comment.