prototype for a camera server client plus CLI control script

This commit is contained in:
2020-06-20 18:47:15 +02:00
parent 41ea3fa084
commit 4c6101a13f
5 changed files with 256 additions and 0 deletions

0
cameras/__init__.py Normal file
View File

138
cameras/cameraclient.py Normal file
View File

@ -0,0 +1,138 @@
from types import SimpleNamespace
from .waiting_epics import PV, caput, caget
from .utils import intify
class CameraClient:
def __init__(self, name):
self.name = name
pv_roi_xmin = PV(name + ":REGIONX_START")
pv_roi_xmax = PV(name + ":REGIONX_END")
pv_roi_ymin = PV(name + ":REGIONY_START")
pv_roi_ymax = PV(name + ":REGIONY_END")
self.pvs = SimpleNamespace(
xmin=pv_roi_xmin,
xmax=pv_roi_xmax,
ymin=pv_roi_ymin,
ymax=pv_roi_ymax
)
self.max_roi = self.get_max_roi()
def __repr__(self):
tn = type(self).__name__
fn = self.name
return f"{tn}(\"{fn}\")"
@property
def status(self):
head = repr(self)
print(head)
print("-" * len(head))
channels = ("WARNCODE", "ERRCODE", "STATUSCODE", "BUSY", "CAMRATE", "FILERATE")
maxlen = max(len(ch) for ch in channels)
for ch in channels:
fch = self.name +":" + ch
val = caget(fch)
line = ch + ": "
line = line.ljust(maxlen + 2)
line += str(val)
print(line)
print("-" * len(head))
roi = self.get_roi()
full = self.get_max_roi()
print(f"roi: {roi}")
print(f"full: {full}")
def restart(self):
self.off()
self.offline()
self.init()
sleep(0.01)
self.running()
def offline(self):
caput(self.name + ":INIT", 0) # OFFLINE
def init(self):
caput(self.name + ":INIT", 1) # INIT
def off(self):
caput(self.name + ":CAMERA", 0) # OFF
def running(self):
caput(self.name + ":CAMERA", 1) # RUNNING
def reset_roi(self):
caput(self.name + ":RESETROI.PROC", 1) # Reset ROI
def set_parameters(self):
caput(self.name + ":SET_PARAM", 1) # Set Parameters
def clear_buffer(self):
caput(self.name + ":CLEARMEM", 1) # Clear Buffer
def get_max_roi(self):
current_roi = self.get_roi()
self.reset_roi()
max_roi = self.get_roi()
self._set_roi(*current_roi)
return max_roi
def get_roi(self):
xmin = self.pvs.xmin.get()
xmax = self.pvs.xmax.get()
ymin = self.pvs.ymin.get()
ymax = self.pvs.ymax.get()
return intify(xmin, xmax, ymin, ymax)
def set_roi(self, xmin, xmax, ymin, ymax, debug=False):
if debug:
asked = (xmin, xmax, ymin, ymax)
xminmin, xmaxmax, yminmin, ymaxmax = self.max_roi
xmin = max(xmin, xminmin)
xmax = min(xmax, xmaxmax)
ymin = max(ymin, yminmin)
ymax = min(ymax, ymaxmax)
ymindelta = ymin - yminmin
ymaxdelta = ymaxmax - ymax
ydelta = min(ymindelta, ymaxdelta)
ymin = yminmin + ydelta
ymax = ymaxmax - ydelta
if debug:
adjusted = (xmin, xmax, ymin, ymax)
print(" ", asked, "\n-> ", adjusted, ":", ydelta, ymindelta, ymaxdelta)
self._set_roi(xmin, xmax, ymin, ymax, debug=debug)
def _set_roi(self, xmin, xmax, ymin, ymax, debug=False):
xmin, xmax, ymin, ymax = intify(xmin, xmax, ymin, ymax)
self.off()
self.pvs.xmin.put(xmin)
self.pvs.xmax.put(xmax)
self.pvs.ymin.put(ymin)
self.pvs.ymax.put(ymax)
self.set_parameters()
self.clear_buffer()
self.running()
if debug:
print("-->", self.get_roi(), "\n")

6
cameras/utils.py Normal file
View File

@ -0,0 +1,6 @@
def intify(*args):
return [int(round(i)) for i in args]

14
cameras/waiting_epics.py Normal file
View File

@ -0,0 +1,14 @@
import epics
from epics import caget
def caput(*args, wait=True, **kwargs):
return epics.caput(*args, wait=wait, **kwargs)
class PV(epics.PV):
def put(self, *args, wait=True, **kwargs):
super().put(*args, wait=wait, **kwargs)

98
clicamesh.py Executable file
View File

@ -0,0 +1,98 @@
#!/usr/bin/env python
import argparse
from time import sleep
from cameras.cameraclient import CameraClient
def main():
commands = ["restart", "roi", "status", "test"]
commands.sort()
printable_commands = ", ".join(commands)
parser = argparse.ArgumentParser(description="CLI Cam (esh)")
parser.add_argument("-c", "--camera", help="camera name", default="SATES24-CAMS161-M1")
parser.add_argument("-v", "--verbose", help="verbose output", action="store_true")
subparsers = parser.add_subparsers(title="commands", dest="command", help=printable_commands)
subparser_restart = subparsers.add_parser("restart", description="Restart camera server")
subparser_roi = subparsers.add_parser("roi", description="Set ROI")
subparser_status = subparsers.add_parser("status", description="Print status")
subparser_test = subparsers.add_parser("test", description="Test setting ROIs")
for sp in subparsers.choices.values():
sp.add_argument("-v", "--verbose", help="verbose output", action="store_true")
subparser_restart.add_argument("-r", "--reset", help="reset ROI", action="store_true")
subparser_roi.add_argument("xmin", type=int, help="x min")
subparser_roi.add_argument("xmax", type=int, help="x max")
subparser_roi.add_argument("ymin", type=int, help="y min")
subparser_roi.add_argument("ymax", type=int, help="y max")
clargs = parser.parse_args()
command = clargs.command
if command is None:
parser.print_help()
raise SystemExit(1)
camera = CameraClient(clargs.camera)
if clargs.verbose:
print(camera)
print(f"command: {command}")
# print(clargs)
if command == "restart":
do_restart(camera, clargs)
elif command == "roi":
do_roi(camera, clargs)
elif command == "test":
do_test(camera, clargs)
elif command == "status":
do_status(camera, clargs)
else:
print(f"nothing assigned to command: {command}")
parser.print_help()
raise SystemExit(2)
def do_restart(camera, clargs):
if not clargs.reset:
roi = camera.get_roi()
camera.restart()
if not clargs.reset:
camera.set_roi(*roi, debug=clargs.verbose) #TODO: workaround! why does the first try always set to: [101, 2400, 100, 2061]?
camera.set_roi(*roi, debug=clargs.verbose)
def do_roi(camera, clargs):
camera.set_roi(clargs.xmin, clargs.xmax, clargs.ymin, clargs.ymax, debug=clargs.verbose)
def do_status(camera, clargs):
camera.status
def do_test(camera, _clargs):
camera.reset_roi() # [1, 2560, 1, 2160]
print(camera.get_roi())
for i in (1, 10, 100, 200, 300, 999, 1000, 1001):
camera.set_roi(i, 1500, i, 1900, debug=True)
if __name__ == "__main__":
main()
#CA client library tcp receive thread terminating due to a non-standard C++ exception
#FATAL: exception not rethrown
#Aborted (core dumped)
# "solved" by
sleep(0.0001)