add files and simulated modes
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
__pycache__/
|
||||||
@@ -146,3 +146,8 @@ p.put(a)
|
|||||||
print(p.get())
|
print(p.get())
|
||||||
https://pyepics.github.io/pyepics/arrays.html
|
https://pyepics.github.io/pyepics/arrays.html
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
EPICS_CA_ADDR_LIST='129.129.244.255 sf-saresc-cagw.psi.ch:5062 sf-saresc-cagw.psi.ch:5066'
|
||||||
|
cd /home/zamofing_t/Documents/prj/SwissFEL/epics_ioc_modules/ESB_MX/python/oldRepos/app/src
|
||||||
|
python swissmx.py
|
||||||
|
|||||||
70
backlight.py
Executable file
70
backlight.py
Executable file
@@ -0,0 +1,70 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# *-----------------------------------------------------------------------*
|
||||||
|
# | |
|
||||||
|
# | Copyright (c) 2022 by Paul Scherrer Institute (http://www.psi.ch) |
|
||||||
|
# | Based on Zac great first implementation |
|
||||||
|
# | Author Thierry Zamofing (thierry.zamofing@psi.ch) |
|
||||||
|
# *-----------------------------------------------------------------------*
|
||||||
|
|
||||||
|
import logging
|
||||||
|
_log=logging.getLogger(__name__)
|
||||||
|
import epics
|
||||||
|
|
||||||
|
#from app_config import settings
|
||||||
|
#from app_utils import assert_motor_positions
|
||||||
|
|
||||||
|
class Backlight(object):
|
||||||
|
def __init__(self, prefix: str='SAR-EXPMX:MOT_BLGT'):
|
||||||
|
if prefix is None:
|
||||||
|
self._sim={'pos':'out'}
|
||||||
|
_log.info('simulated mode:{}'.format(self._sim))
|
||||||
|
return #simulated mode
|
||||||
|
self._mot = epics.Motor(prefix)
|
||||||
|
self._pos = {'in':-29000,'out':0}
|
||||||
|
|
||||||
|
def is_pos(self,strPos):
|
||||||
|
try:
|
||||||
|
m=self._mot
|
||||||
|
except AttributeError:
|
||||||
|
_log.info('simulated mode:{}'.format(strPos))
|
||||||
|
return self._sim['pos']==strPos
|
||||||
|
m.refresh()
|
||||||
|
return abs(m.readback - self._pos[strPos]) < 10
|
||||||
|
|
||||||
|
def move(self, strPos, wait=False):
|
||||||
|
try:
|
||||||
|
m=self._mot
|
||||||
|
except AttributeError:
|
||||||
|
_log.info('simulated mode:{}'.format(strPos))
|
||||||
|
self._sim['pos']=strPos
|
||||||
|
return
|
||||||
|
m=self._mot
|
||||||
|
_log.debug("backlight to {}".format(strPos))
|
||||||
|
target=self._pos[strPos]
|
||||||
|
m.move(target, ignore_limits=True, wait=wait)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import time,os
|
||||||
|
import argparse
|
||||||
|
logging.basicConfig(level=logging.DEBUG,format='%(levelname)s:%(module)s:%(lineno)d:%(funcName)s:%(message)s ')
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument('-m', '--mode', help='mode string with characters: "frgbka" for front,red,green,blue,back,all')
|
||||||
|
parser.add_argument("-t", "--test", help="test sequence", action="store_true")
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
os.environ['EPICS_CA_ADDR_LIST'] = '129.129.244.255 sf-saresc-cagw.psi.ch:5062 sf-saresc-cagw.psi.ch:5066'
|
||||||
|
|
||||||
|
_log.debug(args)
|
||||||
|
bl = Backlight()
|
||||||
|
if args.test:
|
||||||
|
bl.move('in')
|
||||||
|
time.sleep(2)
|
||||||
|
bl.move('out')
|
||||||
|
time.sleep(2)
|
||||||
|
bl.move('in')
|
||||||
|
time.sleep(2)
|
||||||
|
bl.move('out')
|
||||||
|
time.sleep(2)
|
||||||
28
camera.py
28
camera.py
@@ -1,4 +1,10 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
# *-----------------------------------------------------------------------*
|
||||||
|
# | |
|
||||||
|
# | Copyright (c) 2022 by Paul Scherrer Institute (http://www.psi.ch) |
|
||||||
|
# | Based on Zac great first implementation |
|
||||||
|
# | Author Thierry Zamofing (thierry.zamofing@psi.ch) |
|
||||||
|
# *-----------------------------------------------------------------------*
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Hi Zac,
|
Hi Zac,
|
||||||
@@ -38,7 +44,11 @@ class CameraStatus(enum.IntEnum):
|
|||||||
|
|
||||||
class epics_cam(object):
|
class epics_cam(object):
|
||||||
|
|
||||||
def __init__(self, prefix="ESB-MX-CAM"):
|
def __init__(self, prefix='SARES30-CAMS156-SMX-OAV'):
|
||||||
|
if prefix is None:
|
||||||
|
self._sim={'exp':3.1315}
|
||||||
|
_log.info('simulated mode:{}'.format(self._sim))
|
||||||
|
return #simulated mode
|
||||||
self._pv=pv=dict()
|
self._pv=pv=dict()
|
||||||
if prefix[-1]!=':': prefix+=':'
|
if prefix[-1]!=':': prefix+=':'
|
||||||
self._prefix=prefix
|
self._prefix=prefix
|
||||||
@@ -132,9 +142,21 @@ class epics_cam(object):
|
|||||||
self._sz=(int(pv_w.value), int(pv_h.value))
|
self._sz=(int(pv_w.value), int(pv_h.value))
|
||||||
|
|
||||||
def set_exposure(self,exp):
|
def set_exposure(self,exp):
|
||||||
pv_exp=self.getPv('EXPOSURE')
|
try:
|
||||||
|
pv_exp=self.getPv('EXPOSURE')
|
||||||
|
except AttributeError:
|
||||||
|
_log.info('simulated mode:{}'.format(exp))
|
||||||
|
self._sim['exp']=exp
|
||||||
|
return
|
||||||
pv_exp.put(exp, wait=True)
|
pv_exp.put(exp, wait=True)
|
||||||
pass
|
|
||||||
|
def get_exposure(self):
|
||||||
|
try:
|
||||||
|
pv_exp=self.getPv('EXPOSURE')
|
||||||
|
except AttributeError:
|
||||||
|
exp=self._sim['exp'];_log.info('simulated mode:{}'.format(exp))
|
||||||
|
return exp
|
||||||
|
return pv_exp.get()
|
||||||
|
|
||||||
def set_roi(self,rxs,rxe,rys,rye):
|
def set_roi(self,rxs,rxe,rys,rye):
|
||||||
pv_rxs=self.getPv('REGIONX_START');pv_rxe=self.getPv('REGIONX_END')
|
pv_rxs=self.getPv('REGIONX_START');pv_rxe=self.getPv('REGIONX_END')
|
||||||
|
|||||||
82
geometry.py
Normal file
82
geometry.py
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# *-----------------------------------------------------------------------*
|
||||||
|
# | |
|
||||||
|
# | Copyright (c) 2022 by Paul Scherrer Institute (http://www.psi.ch) |
|
||||||
|
# | Based on Zac great first implementation |
|
||||||
|
# | Author Thierry Zamofing (thierry.zamofing@psi.ch) |
|
||||||
|
# *-----------------------------------------------------------------------*
|
||||||
|
'''
|
||||||
|
coordinate systems, optical center, xray axis, pixel sizes etc.
|
||||||
|
'''
|
||||||
|
|
||||||
|
class gepmetry:
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
def find_optical_center(p):
|
||||||
|
# p is an array of
|
||||||
|
# at zoom out: (p1x,p1y),(p2x,p2y),(p3x,p3y),...
|
||||||
|
# at zoom in : (p1x,p1y),(p2x,p2y),(p3x,p3y),...
|
||||||
|
#
|
||||||
|
# the pixel positions are given in chip pixel coordinates (0/0= top/right)
|
||||||
|
# and ignore roi and binning
|
||||||
|
# the returned (cx,cy) is the pixel koordinate that does not change with zoom
|
||||||
|
# this coordinate represents also the origin of other coordinates
|
||||||
|
pass
|
||||||
|
|
||||||
|
def zoom2pixsz(zoom):
|
||||||
|
# this returns the pixel size at a given zoom level
|
||||||
|
# the returned value is a 2x2 matrix:
|
||||||
|
# [pxx pxy]
|
||||||
|
# [pyx pyy] which is interpolated out of a lookup table
|
||||||
|
#
|
||||||
|
# [pxx pxy] [nx]
|
||||||
|
# [pyx pyy]*[ny] results in a vector in meter of a vector [nx,ny] pixels in x and y direction
|
||||||
|
pass
|
||||||
|
|
||||||
|
def set_zoom2pixsz():
|
||||||
|
#tx: 2d-vector in m when moving px pixel in x direction
|
||||||
|
#ty: 2d-vector in m when moving py pixel in y direction
|
||||||
|
# the _lut_z2p is dictionaty a lookuptable
|
||||||
|
# zoom {1,200,400,600,800,1000}
|
||||||
|
#[pxx pxy]
|
||||||
|
#[pyx pyy]
|
||||||
|
self._lut_z2p=_lut_z2p={
|
||||||
|
'zoom': np.array((1,200,400,600,800,1000),dtype=np.float32),
|
||||||
|
'pixsz': np.array(
|
||||||
|
#((pxx,pxy),(pyx,pyy)), # zoom n
|
||||||
|
(( 1,0),(0, 1)), # zoom 1
|
||||||
|
(( 2,0),(0, 2)), # zoom 200
|
||||||
|
(( 4,0),(0, 4)), # zoom 400
|
||||||
|
(( 6,0),(0, 6)), # zoom 600
|
||||||
|
(( 8,0),(0, 8)), # zoom 800
|
||||||
|
((10,0),(0,10)), # zoom 1000
|
||||||
|
dtype=np.float32)}
|
||||||
|
|
||||||
|
def autofocus():
|
||||||
|
# cam camera object
|
||||||
|
# mot motor object
|
||||||
|
# rng region (min max relative to current position) to seek
|
||||||
|
# n number of images to take in region
|
||||||
|
# roi region of interrest to calculate sharpness
|
||||||
|
# mode mode to calculate sharpness (sum/max-min/hist? of edge detection in roi)
|
||||||
|
pass
|
||||||
|
|
||||||
|
def pix2pos(p,zoom=None):
|
||||||
|
# returns the position m(x,y) in meter relative to the optical center at a given zoom level of the pixel p(x,y)
|
||||||
|
# if zoom=None, the last zoom value is used
|
||||||
|
pass
|
||||||
|
|
||||||
|
def pos2pix(p,zoom=None):
|
||||||
|
# returns the pixel p(x,y) of the position m(x,y) in meter relative to the optical center at a given zoom level
|
||||||
|
# if zoom=None, the last zoom value is used
|
||||||
|
pass
|
||||||
|
|
||||||
|
def optctr2xray():
|
||||||
|
# returns the vector m(x,y) of the optical center to the xray
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,4 +1,10 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
# *-----------------------------------------------------------------------*
|
||||||
|
# | |
|
||||||
|
# | Copyright (c) 2022 by Paul Scherrer Institute (http://www.psi.ch) |
|
||||||
|
# | Based on Zac great first implementation |
|
||||||
|
# | Author Thierry Zamofing (thierry.zamofing@psi.ch) |
|
||||||
|
# *-----------------------------------------------------------------------*
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
_log=logging.getLogger(__name__)
|
_log=logging.getLogger(__name__)
|
||||||
@@ -39,7 +45,11 @@ all = 0xff
|
|||||||
|
|
||||||
class IlluminationControl(object):
|
class IlluminationControl(object):
|
||||||
|
|
||||||
def __init__(self,hostname: str,port: int):
|
def __init__(self,hostname: str="129.129.221.92",port: int=1003):
|
||||||
|
if hostname is None: #simulated mode
|
||||||
|
self._sim={'stat':0}
|
||||||
|
_log.info('simulated mode:{}'.format(self._sim))
|
||||||
|
return
|
||||||
self._hostname = hostname
|
self._hostname = hostname
|
||||||
self._port = port
|
self._port = port
|
||||||
self.connect()
|
self.connect()
|
||||||
@@ -59,14 +69,15 @@ class IlluminationControl(object):
|
|||||||
|
|
||||||
def is_on(self, led_flags: int) -> bool:
|
def is_on(self, led_flags: int) -> bool:
|
||||||
"""check status for light state, see CONSTANTS STATUS_BITS_*"""
|
"""check status for light state, see CONSTANTS STATUS_BITS_*"""
|
||||||
try:
|
s = self.status()
|
||||||
s = self.status()[0]
|
|
||||||
except:
|
|
||||||
print("error reading status")
|
|
||||||
return False
|
|
||||||
return bool(s & led_flags)
|
return bool(s & led_flags)
|
||||||
|
|
||||||
def send_command(self, cmd: bytes):
|
def send_command(self, cmd: bytes):
|
||||||
|
try:
|
||||||
|
s=self._socket
|
||||||
|
except AttributeError: #simulated mode
|
||||||
|
_log.info('simulated mode:{}'.format(cmd))
|
||||||
|
return
|
||||||
try:
|
try:
|
||||||
self._socket.sendall(cmd)
|
self._socket.sendall(cmd)
|
||||||
except (BrokenPipeError, OSError) as e:
|
except (BrokenPipeError, OSError) as e:
|
||||||
@@ -75,9 +86,14 @@ class IlluminationControl(object):
|
|||||||
try:
|
try:
|
||||||
self._socket.sendall(cmd)
|
self._socket.sendall(cmd)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise IlluminationControlException("unrecoverable socket error: {}".format(e.args))
|
_log.error("unrecoverable socket error: {}".format(e.args))
|
||||||
|
|
||||||
def status(self):
|
def status(self):
|
||||||
|
try:
|
||||||
|
s=self._socket
|
||||||
|
except AttributeError: #simulated mode
|
||||||
|
_log.info('simulated mode')
|
||||||
|
return self._sim['stat']
|
||||||
self.send_command(bytes((stat,all)))
|
self.send_command(bytes((stat,all)))
|
||||||
resp = self._socket.recv(1024)
|
resp = self._socket.recv(1024)
|
||||||
return resp[0]&0x1f
|
return resp[0]&0x1f
|
||||||
|
|||||||
63
zoom.py
63
zoom.py
@@ -1,5 +1,12 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
# *-----------------------------------------------------------------------*
|
||||||
|
# | |
|
||||||
|
# | Copyright (c) 2022 by Paul Scherrer Institute (http://www.psi.ch) |
|
||||||
|
# | Based on Zac great first implementation |
|
||||||
|
# | Author Thierry Zamofing (thierry.zamofing@psi.ch) |
|
||||||
|
# *-----------------------------------------------------------------------*
|
||||||
|
'''
|
||||||
|
'''
|
||||||
|
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
@@ -25,7 +32,7 @@ from PyQt5.QtWidgets import (
|
|||||||
from PyQt5.uic import loadUiType
|
from PyQt5.uic import loadUiType
|
||||||
import epics
|
import epics
|
||||||
|
|
||||||
Ui_Zoom, QWidget = loadUiType("epics_widgets/zoom.ui")
|
Ui_Zoom, QWidget = loadUiType("zoom.ui")
|
||||||
MIN_ZOOM = 1
|
MIN_ZOOM = 1
|
||||||
MAX_ZOOM = 1000
|
MAX_ZOOM = 1000
|
||||||
SPINNER_SINGLE_STEP = 50
|
SPINNER_SINGLE_STEP = 50
|
||||||
@@ -199,7 +206,7 @@ class Zoom(QGroupBox, Ui_Zoom):
|
|||||||
|
|
||||||
def toggle_backlight(self):
|
def toggle_backlight(self):
|
||||||
bl=QApplication.instance()._backlight
|
bl=QApplication.instance()._backlight
|
||||||
if bl.is_in() or bl.is_diode():
|
if bl.is_pos('in'):
|
||||||
self.moveBacklight.emit("out")
|
self.moveBacklight.emit("out")
|
||||||
self.blgt_button.setText("Move Backlight IN")
|
self.blgt_button.setText("Move Backlight IN")
|
||||||
else:
|
else:
|
||||||
@@ -277,6 +284,9 @@ class Zoom(QGroupBox, Ui_Zoom):
|
|||||||
class QopticZoom(object):
|
class QopticZoom(object):
|
||||||
|
|
||||||
def __init__(self, prefix='SAR-EXPMX-FETURA'):
|
def __init__(self, prefix='SAR-EXPMX-FETURA'):
|
||||||
|
if prefix is None:
|
||||||
|
self._val=1
|
||||||
|
return #simulated mode
|
||||||
self._pv=pv=dict()
|
self._pv=pv=dict()
|
||||||
if prefix[-1]!=':': prefix+=':'
|
if prefix[-1]!=':': prefix+=':'
|
||||||
self._prefix=prefix
|
self._prefix=prefix
|
||||||
@@ -291,32 +301,57 @@ class QopticZoom(object):
|
|||||||
return pv
|
return pv
|
||||||
|
|
||||||
def get(self) -> int:
|
def get(self) -> int:
|
||||||
pv=self.getPv('POS_RB')
|
try:
|
||||||
|
pv = self.getPv('POS_RB')
|
||||||
|
except AttributeError:
|
||||||
|
val=self._val; _log.info('simulated mode:{}'.format(val))
|
||||||
|
return val
|
||||||
|
else:
|
||||||
|
pv=self.getPv('POS_RB')
|
||||||
return pv.get()
|
return pv.get()
|
||||||
|
|
||||||
def set(self, val: int):
|
def set(self, val: int):
|
||||||
|
try:
|
||||||
pv=self.getPv('POS_SP')
|
pv=self.getPv('POS_SP')
|
||||||
pv.put(val)
|
except AttributeError:
|
||||||
|
_log.info('simulated mode:{}'.format(val))
|
||||||
|
self._val=val #simulated mode
|
||||||
|
else:
|
||||||
|
pv.put(val)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
import time, os, PIL.Image, platform, subprocess
|
||||||
|
import argparse
|
||||||
|
logging.basicConfig(level=logging.DEBUG,format='%(levelname)s:%(module)s:%(lineno)d:%(funcName)s:%(message)s ')
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument("--sim", "-s", help="simulate all devices", action='store_true')
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import backlight
|
import backlight
|
||||||
import illumination
|
import illumination
|
||||||
import camera
|
import camera
|
||||||
|
|
||||||
|
_log.info('Start')
|
||||||
|
os.environ['EPICS_CA_ADDR_LIST'] = '129.129.244.255 sf-saresc-cagw.psi.ch:5062 sf-saresc-cagw.psi.ch:5066'
|
||||||
|
app = QApplication(sys.argv)
|
||||||
from app_config import settings, appsconf
|
from app_config import settings, appsconf
|
||||||
|
|
||||||
logging.basicConfig(level=logging.DEBUG,format='%(levelname)s:%(module)s:%(lineno)d:%(funcName)s:%(message)s ')
|
if args.sim:
|
||||||
|
app._backlight = backlight.Backlight(None)
|
||||||
|
app._illumination = illumination.IlluminationControl(None)
|
||||||
|
app._zoom = QopticZoom(None)
|
||||||
|
app._camera = camera.epics_cam(None)
|
||||||
|
else:
|
||||||
|
app._backlight = backlight.Backlight()
|
||||||
|
app._illumination = illumination.IlluminationControl()
|
||||||
|
app._zoom = QopticZoom()
|
||||||
|
app._camera = camera.epics_cam()
|
||||||
|
|
||||||
_log.debug('Start')
|
|
||||||
app = QApplication(sys.argv)
|
|
||||||
|
|
||||||
app._backlight = backlight.Backlight()
|
|
||||||
app._illumination = illumination.IlluminationControl("129.129.221.92", 1003)
|
|
||||||
app._zoom = QopticZoom()
|
|
||||||
app._camera = camera.camera_server('SARES30-CAMS156-SMX-OAV')
|
|
||||||
|
|
||||||
simulated = appsconf["microscope"]["zoom"].get("simulate", False)
|
simulated = appsconf["microscope"]["zoom"].get("simulate", False)
|
||||||
|
|
||||||
|
|||||||
50
zoom.ui
Normal file
50
zoom.ui
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>Form</class>
|
||||||
|
<widget class="QWidget" name="Form">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>400</width>
|
||||||
|
<height>300</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Form</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>2</number>
|
||||||
|
</property>
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>2</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>2</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>2</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>2</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="_top_grid">
|
||||||
|
<property name="title">
|
||||||
|
<string>Lighting && Camera</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="_button_box">
|
||||||
|
<property name="title">
|
||||||
|
<string>Zoom</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
||||||
Reference in New Issue
Block a user