cleaner app starting, new application settings class

This commit is contained in:
2022-07-20 17:52:55 +02:00
parent 4a6db36805
commit 569ce8a78d
8 changed files with 224 additions and 176 deletions

View File

@@ -8,7 +8,7 @@ from PyQt5.QtWidgets import QMenu, QAction, QSpinBox, QMenu
from pyqtgraph import ROI, Point, RectROI, mkPen
from pyqtgraph import functions as fn
from app_config import settings
from app_config import AppCfg# settings
from math import *

View File

@@ -14,13 +14,13 @@ from pathlib import Path
#import qsingleton #ZAC: orig. code
#from CoordinatesModel import CoordinatesModel #ZAC: orig. code
from app_config import settings, appsconf, option
from app_config import AppCfg #settings, option, appsconf
EMBL_RESULTS_TIMEOUT = "embl/results_timeout"
EMBL_SAVE_FILES = "embl/save_files"
embl = appsconf["embl"]
#embl = appsconf["embl"]
#import imageio
import numpy as np
@@ -72,6 +72,7 @@ class EmblMessage(QObject):
def __init__(self, parent=None, **kwargs):
super(EmblMessage, self).__init__(parent, **kwargs)
return #ZAC: orig. code
if not embl["enabled"]:
return
context = zmq.Context()

View File

@@ -34,7 +34,7 @@ logger = logging.getLogger(__name__)
# from coord_library import conversions
#import conversions #ZAC: orig. code
from app_config import settings
from app_config import AppCfg
#from storage import Folders #ZAC: orig. code
#folders = Folders() #ZAC: orig. code

View File

@@ -1,4 +1,3 @@
#TODO:
# currently 2 settings/configs are used
# QSettings -> cat ~/.config/Paul\ Scherrer\ Institut/SwissMX.conf
@@ -6,54 +5,102 @@
# QSettings are changed by program
# #yaml is fixed and not altened by program
import yaml
from PyQt5.QtCore import QSettings
from pathlib import Path
import logging
logger = logging.getLogger(__name__)
_log = logging.getLogger(__name__)
import os
from PyQt5.QtCore import QSettings
#import yaml
#from pathlib import Path
class AppCfg(QSettings):
SKIP_ESCAPE_TRANSITIONS_IF_SAFE="escape/skip_transitions_if_safe"
BEAM_MARKER_POSITIONS="beam/marker_positions"
BEAM_SIZE="beam/size"
CRYOJET_MOTION_ENABLED="cryojet/motion_enabled"
CRYOJET_NOZZLE_OUT="cryojet/nozzle_out"
CRYOJET_NOZZLE_IN="cryojet/nozzle_in"
DELTATAU_SHOW_PLOTS="deltatau/show_plots"
DELTATAU_OMEGACOS="deltatau/omegacos"
DELTATAU_SORT_POINTS="deltatau/sort_points"
DELTATAU_VELOCITY_SCALE="deltatau/velocity_scale"
CAMERA_TRANSFORMATIONS="camera/transformations"
CAMERA_ZOOM_TO_PPM="camera/zoom_to_ppm"
EXPERIMENT_PGROUP="experiment/pgroup"
EXPERIMENT_UID="experiment/uid"
ACTIVATE_PULSE_PICKER="scanning/activate_pulse_picker"
def __init__(self):
super(AppCfg, self).__init__("PSI", "SwissMX")
keys = self.allKeys()
if AppCfg.ACTIVATE_PULSE_PICKER not in keys:
self.setValue(AppCfg.ACTIVATE_PULSE_PICKER, False)
if AppCfg.SKIP_ESCAPE_TRANSITIONS_IF_SAFE not in keys:
self.setValue(AppCfg.SKIP_ESCAPE_TRANSITIONS_IF_SAFE, False)
if "hits/marker_size" not in keys:
self.setValue("hits/marker_size", 10)
if "graphs/show_auxiliary" not in keys:
self.setValue("graphs/show_auxiliary", False)
if "graphs/auxiliary_graph_index" not in keys:
self.setValue("graphs/auxiliary_graph_index", 0)
if "scan_request/last_location" not in keys:
d10 = os.path.join(os.path.expanduser("~"), "Data10")
self.setValue("scan_request/last_location", d10)
if AppCfg.BEAM_SIZE in keys:
_log.info("setting beamsize from stored settings: {}".format(self.value(AppCfg.BEAM_SIZE)))
else:
_log.warning("beam size may not reflect reality, please check")
self.setValue(AppCfg.BEAM_SIZE, (40, 20))
settings = QSettings("PSI", "SwissMX")
def option(self,key: str) -> bool:
try:
return self.value(key, type=bool)
except:
_log.error(f"option {key} not known")
return False
inst_folder = Path(__file__).absolute().parent
def toggle_option(self,key: str):
v = self.value(key, type=bool)
self.setValue(key, not v)
self.sync()
config_file = inst_folder / "swissmx.yaml"
configs = yaml.load(config_file.read_text(),Loader=yaml.FullLoader)
endstation = configs["configure_for"]
appsconf = configs[endstation]
simulated = appsconf.get("simulate", False)
#inst_folder = Path(__file__).absolute().parent
#config_file = inst_folder / "swissmx.yaml"
#configs = yaml.load(config_file.read_text(),Loader=yaml.FullLoader)
#endstation = configs["configure_for"]
#appsconf = configs[endstation]
#simulated = appsconf.get("simulate", False)
#logger.info(f"configuring for endstation: {endstation.upper()}")
logger.info(f"configuring for endstation: {endstation.upper()}")
if simulated:
logger.warning("SIMULATION is ACTIVE")
css_file = inst_folder / "swissmx.css"
#if simulated:
# logger.warning("SIMULATION is ACTIVE")
#css_file = inst_folder / "swissmx.css"
def font(name: str) -> str:
p = Path(__file__).absolute().parent / "fonts" / name
return str(p)
#def font(name: str) -> str:
# p = Path(__file__).absolute().parent / "fonts" / name
# return str(p)
def logo(size: int = 0) -> str:
p = Path(__file__).absolute().parent / "logos" / "logo.png"
if size:
p = Path(__file__).absolute().parent / "logos" / f"tell_logo_{size}x{size}.png"
return str(p)
#def logo(size: int = 0) -> str:
# p = Path(__file__).absolute().parent / "logos" / "logo.png"
# if size:
# p = Path(__file__).absolute().parent / "logos" / f"tell_logo_{size}x{size}.png"
# return str(p)
def option(key: str) -> bool:
try:
return settings.value(key, type=bool)
except:
logger.error(f"option {key} not known")
return False
def toggle_option(key: str):
v = settings.value(key, type=bool)
settings.setValue(key, not v)
settings.sync()

View File

@@ -341,6 +341,15 @@ if __name__ == "__main__":
exit(0)
n += 1
else:
def closeEvent(cam,evt):
print(args)
try:
pv=cam._pv['pic']
pv.clear_auto_monitor() # disconnect PV monitor callback -> program exit faster.
except AttributeError:
_log.warning('disconnect PV callback failed.')
class UIcamera(epics_cam):
def __init__(self, prefix="ESB-MX-CAM"):
@@ -446,7 +455,7 @@ if __name__ == "__main__":
## Display the data and assign each frame a time value from 1.0 to 3.0
cam = UIcamera(prefix=args.prefix)
win.closeEvent=lambda x:closeEvent(cam, x)
#cam.set_binning(4,4)
#cam.run()
@@ -470,3 +479,4 @@ if __name__ == "__main__":
## Start Qt event loop unless running in interactive mode.
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()

View File

@@ -1,7 +1,7 @@
from PyQt5 import QtWidgets, QtGui
from PyQt5.QtWidgets import QWidget, QSizePolicy, QVBoxLayout, QDoubleSpinBox, QMessageBox
from app_config import option, toggle_option
from app_config import AppCfg #option, toggle_option
def toggle_warn(key):

View File

@@ -28,6 +28,16 @@ logging.getLogger('matplotlib').setLevel(logging.INFO)
logging.basicConfig(level=logging.DEBUG, format='%(levelname)s:%(module)s:%(lineno)d:%(funcName)s:%(message)s ')
_log = logging.getLogger("swissmx")
import time
class timestamp():
def __init__(self):
self.t=time.time()
def log(self,txt):
t=time.time()
print(txt+f'{t-self.t:6.3g}')
self.t=t
ts=timestamp()
ts.log('Import part 1/7:')
import sys, os, time
import json, re
import random, signal
@@ -40,27 +50,6 @@ import random, signal
#from helicalscan import HelicalScanGui #ZAC: orig. code
# publisher = pubber.Publisher()
SKIP_ESCAPE_TRANSITIONS_IF_SAFE = "escape/skip_transitions_if_safe"
BEAM_MARKER_POSITIONS = "beam/marker_positions"
BEAM_SIZE = "beam/size"
CRYOJET_MOTION_ENABLED = "cryojet/motion_enabled"
CRYOJET_NOZZLE_OUT = "cryojet/nozzle_out"
CRYOJET_NOZZLE_IN = "cryojet/nozzle_in"
DELTATAU_SHOW_PLOTS = "deltatau/show_plots"
DELTATAU_OMEGACOS = "deltatau/omegacos"
DELTATAU_SORT_POINTS = "deltatau/sort_points"
DELTATAU_VELOCITY_SCALE = "deltatau/velocity_scale"
CAMERA_TRANSFORMATIONS = "camera/transformations"
CAMERA_ZOOM_TO_PPM = "camera/zoom_to_ppm"
EXPERIMENT_PGROUP = "experiment/pgroup"
EXPERIMENT_UID = "experiment/uid"
ACTIVATE_PULSE_PICKER = "scanning/activate_pulse_picker"
TASK_JUNGFRAU_SETTINGS = "jungfrau_settings"
TASK_SETUP_PPM_CALIBRATION = "ppm_calibration"
@@ -74,7 +63,7 @@ TASK_GRID = "grid"
TASK_PRELOCATED = "prelocated"
TASK_HELICAL = "helical"
TASK_EMBL = "embl"
ts.log('Import part 2/7:')
import PrelocatedCoordinatesModel # ZAC: orig. code
from EmblModule import EmblWidget #ZAC: orig. code
from HelicalTable import HelicalTableWidget #ZAC: orig. code
@@ -84,7 +73,7 @@ from HelicalTable import HelicalTableWidget #ZAC: orig. code
#import mx_swissfel #ZAC: orig. code
#swissfel = mx_swissfel.SwissFELMachine() #ZAC: orig. code
#from bernina_pulse_picker import pulsePicker #ZAC: orig. code
ts.log('Import part 3/7:')
import qtawesome
import qutilities
from PyQt5 import QtCore, QtGui
@@ -95,7 +84,7 @@ from PyQt5.QtWidgets import (
QMessageBox, QPlainTextEdit, QProgressBar, QProgressDialog, QPushButton, QShortcut, QSizePolicy, QSpinBox,
QSplashScreen, QTextBrowser, QToolBox, QVBoxLayout, QWidget,)
from PyQt5.uic import loadUiType
ts.log('Import part 4/7:')
import CustomROI as CstROI
#from CustomROI import BeamMark, Grid, CrystalCircle #ZAC: orig. code
#from GenericDialog import GenericDialog #ZAC: orig. code
@@ -104,21 +93,21 @@ import CustomROI as CstROI
from epics_widgets.MotorTweak import MotorTweak
from epics_widgets.SmaractMotorTweak import SmaractMotorTweak
from epics_widgets.SimMotorTweak import SimMotorTweak
ts.log('Import part 5/7:')
from matplotlib import pyplot
import numpy as np
import pyqtgraph as pg
import pyqtgraph.exporters
# use antialias for draw lines, interpret image data as row-major instead of col-major
pg.setConfigOptions(antialias=True,imageAxisOrder='row-major')
ts.log('Import part 6/7:')
import app_utils
from app_config import settings, appsconf, option, toggle_option, simulated
from app_config import AppCfg #settings, option, toggle_option
import epics
from epics.ca import pend_event
import camera,backlight,zoom,illumination,geometry
ts.log('Import part 7/7:')
#_URL = "http://PC12288:8080"
@@ -386,7 +375,9 @@ class Main(QMainWindow, Ui_MainWindow):
tbox.layout().addWidget(htab)
def add_beam_marker(self):
w, h = settings.value(BEAM_SIZE)
app = QApplication.instance()
cfg = app._cfg
w, h = cfg.value(AppCfg.BEAM_SIZE)
self._beammark = CstROI.BeamMark([100, 100], (int(w), int(h)), parent=self)
self.vb.addItem(self._beammark)
@@ -422,6 +413,8 @@ class Main(QMainWindow, Ui_MainWindow):
self.img.setImage(pic)
def init_settings_tracker(self):
app=QApplication.instance()
cfg=app._cfg
_log.info("configuring widget persistence")
fields = {
# 'folder': (self._label_folder, str),
@@ -434,7 +427,7 @@ class Main(QMainWindow, Ui_MainWindow):
}
for key, f_config in fields.items():
widget, conv = f_config
value = settings.value(key)
value = cfg.value(key)
try:
wset, wget = widget.setText, widget.text
_log.debug("tracking text field {}".format(key))
@@ -530,8 +523,10 @@ class Main(QMainWindow, Ui_MainWindow):
_log.warning("failed writing {}".format(fname))
def persist_setting(self, s, v):
app=QApplication.instance()
cfg=app._cfg
_log.debug("persisting {} = {}".format(s, v))
settings.setValue(s, v)
cfg.setValue(s, v)
def method_changed(self, index):
method = self._tabs_daq_methods.currentWidget().accessibleName()
@@ -2477,8 +2472,8 @@ class Main(QMainWindow, Ui_MainWindow):
self._grids = []
tab = self._tab_daq_method_grid
layout = tab.layout() # gridlayout
self._sb_grid_x_step.setValue(30.0)
self._sb_grid_y_step.setValue(30.0)
self._sb_grid_x_step.setValue(30)
self._sb_grid_y_step.setValue(30)
self._bt_add_grid.clicked.connect(self.daq_grid_add_grid)
self._bt_remove_all_grids.clicked.connect(self.daq_grid_remove_all)
self._find_targets_from_microscope_image.clicked.connect(
@@ -2564,6 +2559,8 @@ class Main(QMainWindow, Ui_MainWindow):
cont.layout().addWidget(w)
def init_actions(self):
app = QApplication.instance()
cfg = app._cfg
self.toolBar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
self.shortcut = QShortcut(QKeySequence(Qt.CTRL + Qt.SHIFT + Qt.Key_S), self)
@@ -2611,8 +2608,8 @@ class Main(QMainWindow, Ui_MainWindow):
# icon = qtawesome.icon("material.shutter_speed")
action = QAction("Use Pulse Picker", self)
action.setCheckable(True)
action.setChecked(option(ACTIVATE_PULSE_PICKER))
action.triggered.connect(lambda: toggle_option(ACTIVATE_PULSE_PICKER))
action.setChecked(cfg.option(AppCfg.ACTIVATE_PULSE_PICKER))
action.triggered.connect(lambda: cfg.toggle_option(AppCfg.ACTIVATE_PULSE_PICKER))
self.toolBar.addAction(action)
icon = qtawesome.icon("material.timeline")
@@ -3120,60 +3117,33 @@ class Main(QMainWindow, Ui_MainWindow):
def init_settings(self):
app = QApplication.instance()
# settings = Settings
#global folders
s = settings
keys = s.allKeys()
if ACTIVATE_PULSE_PICKER not in keys:
settings.setValue(ACTIVATE_PULSE_PICKER, False)
if SKIP_ESCAPE_TRANSITIONS_IF_SAFE not in keys:
settings.setValue(SKIP_ESCAPE_TRANSITIONS_IF_SAFE, False)
cfg = app._cfg
keys = cfg.allKeys()
#if EXPERIMENT_PGROUP not in keys:
# self.update_user_and_storage()
if "hits/marker_size" not in keys:
settings.setValue("hits/marker_size", 10)
if "window/geometry" in keys:
self.restoreGeometry(s.value("window/geometry", ""))
self.restoreState(s.value("window/windowState", ""))
self.restoreGeometry(cfg.value("window/geometry", ""))
self.restoreState(cfg.value("window/windowState", ""))
if "window/main_splitter" in keys:
sizes = [int(s) for s in s.value("window/main_splitter")]
sizes = [int(s) for s in cfg.value("window/main_splitter")]
self._main_splitter.setSizes(sizes)
else:
self._main_splitter.setSizes([500, 1200])
if "graphs/show_auxiliary" not in keys:
s.setValue("graphs/show_auxiliary", False)
if "graphs/auxiliary_graph_index" not in keys:
s.setValue("graphs/auxiliary_graph_index", 0)
if "scan_request/last_location" not in keys:
d10 = os.path.join(os.path.expanduser("~"), "Data10")
s.setValue("scan_request/last_location", d10)
if BEAM_MARKER_POSITIONS in keys:
self._beam_markers = s.value(BEAM_MARKER_POSITIONS)
if AppCfg.BEAM_MARKER_POSITIONS in keys:
self._beam_markers = s.value(AppCfg.BEAM_MARKER_POSITIONS)
self.update_beam_marker_fitters()
_log.info("read beam markers {}".format(self._beam_markers))
if BEAM_SIZE in keys:
_log.info("setting beamsize from stored settings: {}".format(s.value(BEAM_SIZE)))
else:
_log.warning("beam size may not reflect reality, please check")
s.setValue(BEAM_SIZE, (40, 20))
if AppCfg.CAMERA_TRANSFORMATIONS in keys:
app._camera.set_transformations(s.value(AppCfg.CAMERA_TRANSFORMATIONS))
if CAMERA_TRANSFORMATIONS in keys:
app._camera.set_transformations(s.value(CAMERA_TRANSFORMATIONS))
if CAMERA_ZOOM_TO_PPM in keys:
self._zoom_to_ppm = s.value(CAMERA_ZOOM_TO_PPM)
_log.info(f"{CAMERA_ZOOM_TO_PPM} updated: {self._zoom_to_ppm}")
if AppCfg.CAMERA_ZOOM_TO_PPM in keys:
self._zoom_to_ppm = s.value(AppCfg.CAMERA_ZOOM_TO_PPM)
_log.info(f"{AppCfg.CAMERA_ZOOM_TO_PPM} updated: {self._zoom_to_ppm}")
self.update_ppm_fitters()
def really_quit(self):
@@ -3184,11 +3154,9 @@ class Main(QMainWindow, Ui_MainWindow):
def closeEvent(self, event):
"""this is called when the user clicks the window's cross icon"""
if (
self._do_quit
or QMessageBox.question( self, "", "Are you sure you want to quit?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No,) == QMessageBox.Yes
):
if (self._do_quit or QMessageBox.question( self, "", "Are you sure you want to quit?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No,) == QMessageBox.Yes):
app=QApplication.instance()
cfg=app._cfg
try:
pv=app._camera._pv['pic']
pv.clear_auto_monitor() # disconnect PV monitor callback -> program exit faster.
@@ -3196,10 +3164,10 @@ class Main(QMainWindow, Ui_MainWindow):
_log.warning('disconnect PV callback failed.')
_log.info('disconnect PV callback')
settings.setValue("window/geometry", self.saveGeometry())
settings.setValue("window/windowState", self.saveState())
settings.setValue("window/main_splitter", self._main_splitter.sizes())
settings.setValue("last_active", time.time())
cfg.setValue("window/geometry", self.saveGeometry())
cfg.setValue("window/windowState", self.saveState())
cfg.setValue("window/main_splitter", self._main_splitter.sizes())
cfg.setValue("last_active", time.time())
_log.info('save settings')
#QMainWindow.closeEvent(self, event)
_log.info('closeEvent done')
@@ -3242,6 +3210,27 @@ def sigint_handler(*args):
app.quit()
class StartupSplash:
def __init__(self):
splash_pix = QPixmap("artwork/logo/256x256.png")
self._wnd=splash = QSplashScreen(splash_pix, Qt.WindowStaysOnTopHint)
splash.setWindowFlags(Qt.WindowStaysOnTopHint | Qt.FramelessWindowHint)
splash.setEnabled(False)
self._prgsBar=prgs=QProgressBar(splash)
prgs.setMaximum(100)
prgs.setGeometry(0, splash_pix.height() - 50, splash_pix.width(), 20)
splash.show()
def set(self,i,msg):
self._prgsBar.setValue(i)
self._wnd.showMessage(f"<font color='red'>{msg}</font></h1>", int(Qt.AlignBottom|Qt.AlignCenter), Qt.black)
app=QApplication.instance()
app.processEvents()
time.sleep(.1)
def main():
import argparse
@@ -3253,38 +3242,11 @@ def main():
args = parser.parse_args()
_log.info('Arguments:{}'.format(args.__dict__))
# needed so pycharm can restart application
signal.signal(signal.SIGINT, sigint_handler)
from PyQt5.QtWidgets import QApplication
# set app icon
app = QApplication(sys.argv)
app._args=args
if args.sim&0x01:
app._backlight = backlight.Backlight(None)
else:
app._backlight = backlight.Backlight()
if args.sim&0x02:
app._illumination = illumination.IlluminationControl(None)
else:
app._illumination = illumination.IlluminationControl()
if args.sim&0x04:
app._zoom = zoom.QopticZoom(None)
else:
app._zoom = zoom.QopticZoom()
if args.sim&0x08:
app._camera = camera.epics_cam(None)
app._camera.sim_gen(mode=1)
else:
app._camera = camera.epics_cam()
#app._camera.run() is called in center_piece_update
app._geometry=geometry.geometry()
app_icon = QtGui.QIcon()
app_icon.addFile("artwork/logo/16x16.png", QtCore.QSize(16, 16))
app_icon.addFile("artwork/logo/24x24.png", QtCore.QSize(24, 24))
@@ -3293,29 +3255,55 @@ def main():
app_icon.addFile("artwork/logo/256x256.png", QtCore.QSize(256, 256))
app.setWindowIcon(app_icon)
splash_pix = QPixmap("artwork/logo/256x256.png")
splash = QSplashScreen(splash_pix, Qt.WindowStaysOnTopHint)
splash.setWindowFlags(Qt.WindowStaysOnTopHint | Qt.FramelessWindowHint)
splash.setEnabled(False)
startupWin=StartupSplash()
progressBar = QProgressBar(splash)
progressBar.setMaximum(10)
progressBar.setGeometry(0, splash_pix.height() - 50, splash_pix.width(), 20)
#for i in range(1, 20):
# startupWin.set(i,f'sample startup text {i}')
# #app.processEvents()
# t = time.time()
# #while time.time() < t + 0.1:
# # app.processEvents()
splash.show()
# splash.showMessage("<h1><font color='red'>Solid support scanning brought to you by</font></h1>", Qt.AlignTop | Qt.AlignCenter, Qt.black)
#app._settings=QSettings("PSI", "SwissMX")
for i in range(1, 11):
progressBar.setValue(i)
t = time.time()
while time.time() < t + 0.1:
app.processEvents()
app._args=args
startupWin.set(5, f'load settings')
app._cfg=AppCfg()
app._geometry=geometry.geometry()
startupWin.set(15, f'connect backlight')
if args.sim&0x01:
app._backlight = backlight.Backlight(None)
else:
app._backlight = backlight.Backlight()
startupWin.set(20, f'connect illumination')
if args.sim&0x02:
app._illumination = illumination.IlluminationControl(None)
else:
app._illumination = illumination.IlluminationControl()
startupWin.set(40, f'connect zoom')
if args.sim&0x04:
app._zoom = zoom.QopticZoom(None)
else:
app._zoom = zoom.QopticZoom()
startupWin.set(60, f'connect camera')
if args.sim&0x08:
app._camera = camera.epics_cam(None)
app._camera.sim_gen(mode=1)
else:
app._camera = camera.epics_cam()
#app._camera.run() is called in center_piece_update
startupWin.set(60, f'start main window')
main = Main()
main.show()
splash.finish(main)
startupWin._wnd.finish(main)
# needed so pycharm can restart application
signal.signal(signal.SIGINT, sigint_handler)
#main.update_user_and_storage() #ZAC: orig. code
sys.exit(app.exec_())

18
zoom.py
View File

@@ -32,7 +32,7 @@ from PyQt5.uic import loadUiType
import backlight, illumination, camera
import epics
from app_config import settings
from app_config import AppCfg #settings
Ui_Zoom, QWidget = loadUiType("zoom.ui")
MIN_ZOOM = 1
@@ -50,19 +50,21 @@ class Zoom(QGroupBox, Ui_Zoom):
self.setTitle("Sample Viewing")
def configure(self):
keys = settings.allKeys()
app=QApplication.instance()
cfg=app._cfg
keys=cfg.allKeys()
if "sample_viewing/zoom_buttons" not in keys:
settings.setValue("sample_viewing/zoom_buttons",
cfg.setValue("sample_viewing/zoom_buttons",
json.dumps([(1, "1"),(200, "200"),(400, "400"),(600, "600"),(800, "800"),(1000, "1000"),]),)
buttons = json.loads(settings.value("sample_viewing/zoom_buttons"))
buttons = json.loads(cfg.value("sample_viewing/zoom_buttons"))
if "backlight/backlight_pv" not in keys:
settings.setValue("backlight/backlight_pv", "SAR-EXPMX:MOT_BLGT")
backlight_pv = settings.value("backlight/backlight_pv")
cfg.setValue("backlight/backlight_pv", "SAR-EXPMX:MOT_BLGT")
backlight_pv = cfg.value("backlight/backlight_pv")
if "sample_viewing/zoom_api" not in keys:
settings.setValue("sample_viewing/zoom_api", "rest://pc12818.psi.ch:9999")
zoom_api = settings.value("sample_viewing/zoom_api")
cfg.setValue("sample_viewing/zoom_api", "rest://pc12818.psi.ch:9999")
zoom_api = cfg.value("sample_viewing/zoom_api")
#self.get_zoom_pv = PV(zoom_api + ":ZOOM-RBV", callback=self.zoom_update_cb)
#self.status_pv = PV(zoom_api + ":ZOOM-STATUS", callback=self.zoom_status_cb)