204 lines
6.3 KiB
Python
Executable File
204 lines
6.3 KiB
Python
Executable File
#!/usr/bin/env python
|
|
"""
|
|
Hi Zac,
|
|
|
|
at the moment there is no channel for the min or max values. The reason for this is the binning. With this you change these numbers.
|
|
At the end you need 3*2 numbers :
|
|
Physical resolution
|
|
Max resolution for ROI
|
|
Resolution of your image
|
|
And the logic how you can change the numbers ;-)
|
|
|
|
The simples trick for getting the max resolution is to set binning to 1 and write big numbers in the ROI (REGIONX_END / REGIONY_END) channels . They will be corrected to the max resolution.
|
|
|
|
Sorry for this. When you want all numbers, I can think about the export of the whole "mess". Inside the IOC there is the central checking routine. Sometimes it could be helpful to have this in EPICS.
|
|
|
|
Best regards
|
|
Helge
|
|
"""
|
|
|
|
import enum
|
|
import logging
|
|
|
|
import epics
|
|
import numpy as np
|
|
|
|
logger = logging.getLogger(__name__)
|
|
global imv
|
|
|
|
|
|
class camera_server(object):
|
|
|
|
def __init__(self, basename="ESB-MX-CAM"):
|
|
self._pv=pv=dict()
|
|
os.environ['EPICS_CA_ADDR_LIST'] = 'localhost'
|
|
if basename[-1]!=':': basename+=':'
|
|
self._transformations = []
|
|
pv['pic']=epics.PV(basename+"FPICTURE", auto_monitor=True, callback=self.new_frame_callback)
|
|
for k,v in (('w','WIDTH'),('h','HEIGHT'),):
|
|
pv[k]=epics.PV(basename+v)
|
|
return
|
|
|
|
def new_frame_callback(self, **kwargs):
|
|
"""kargs contains:
|
|
pvname: the name of the pv
|
|
value: the latest value
|
|
char_value: string representation of value
|
|
count: the number of data elements
|
|
ftype: the numerical CA type indicating the data type
|
|
type: the python type for the data
|
|
status: the status of the PV (1 for OK)
|
|
precision: number of decimal places of precision for floating point values
|
|
units: string for PV units
|
|
severity: PV severity
|
|
timestamp: timestamp from CA server.
|
|
read_access: read access (True/False)
|
|
write_access: write access (True/False)
|
|
access: string description of read- and write-access
|
|
host: host machine and CA port serving PV
|
|
enum_strs: the list of enumeration strings
|
|
upper_disp_limit: upper display limit
|
|
lower_disp_limit: lower display limit
|
|
upper_alarm_limit: upper alarm limit
|
|
lower_alarm_limit: lower alarm limit
|
|
upper_warning_limit: upper warning limit
|
|
lower_warning_limit: lower warning limit
|
|
upper_ctrl_limit: upper control limit
|
|
lower_ctrl_limit: lower control limit
|
|
chid: integer channel ID
|
|
cb_info: (index, self) tuple containing callback ID
|
|
and the PV object"""
|
|
print('new_frame_callback')
|
|
try:
|
|
pv=self._pv
|
|
w, h = int(pv['w'].value), int(pv['h'].value)
|
|
pic = pv['pic'].get(count=w * h, as_numpy=True).reshape((h, w))
|
|
if pic.dtype==np.int16:
|
|
pic.dtype=np.uint16
|
|
self.pic=pic
|
|
print(pic[-1][-1])
|
|
imv.setImage(pic)
|
|
except:
|
|
logger.warning("failed to fetch image")
|
|
|
|
def get_image(self):
|
|
pv=self._pv
|
|
try:
|
|
pic = self.pic
|
|
except:
|
|
self.new_frame_callback()
|
|
pic = self.pic
|
|
for t in self._transformations:
|
|
if Transforms.ROTATE_90 == t:
|
|
pic = np.rot90(pic, 1)
|
|
elif Transforms.ROTATE_180 == t:
|
|
pic = np.rot90(pic, 2)
|
|
elif Transforms.ROTATE_270 == t:
|
|
pic = np.rot90(pic, 3)
|
|
elif Transforms.FLIP_LR == t:
|
|
pic = np.fliplr(pic)
|
|
elif Transforms.FLIP_UD == t:
|
|
pic = np.flipud(pic)
|
|
elif Transforms.TRANSPOSE == t:
|
|
pic = pic.transpose()
|
|
return pic
|
|
|
|
|
|
if __name__ == "__main__":
|
|
import time, os, PIL
|
|
|
|
logging.basicConfig(format="%(asctime)s $(levelname)s %(message)s", level=logging.DEBUG)
|
|
|
|
import argparse
|
|
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument("--ui", "-u", help="qt test", action="store_true")
|
|
parser.add_argument("--base-pv","-b",help="PV prefix for images; default=ESB-MX-CAM",type=str,default="ESB-MX-CAM",)
|
|
args = parser.parse_args()
|
|
|
|
print('STARTING')
|
|
os.environ['EPICS_CA_ADDR_LIST']='localhost'
|
|
cam = camera_server(basename=args.base_pv)
|
|
#pv = cam._pv
|
|
#w, h = int(pv['w'].value), int(pv['h'].value)
|
|
#a = np.arange(w*h, dtype=np.uint16)
|
|
#pv['pic'].put(a)
|
|
#print(pv['pic'].get())
|
|
|
|
if not args.ui:
|
|
n = 1
|
|
base = time.strftime("/tmp/image_%Y%m%d_%H%M%S_{:05d}.png")
|
|
while True:
|
|
fname = base.format(n)
|
|
img=cam.get_image()
|
|
print(type(img))
|
|
type(img)
|
|
print(img,img.dtype)
|
|
PIL.Image.fromarray(img).save(fname)
|
|
logging.info("acquired {}".format(fname))
|
|
try:
|
|
input("<enter> for next image, ctrl-c to abort")
|
|
except KeyboardInterrupt:
|
|
exit(0)
|
|
n += 1
|
|
else:
|
|
import sys
|
|
from pyqtgraph.Qt import QtCore, QtGui
|
|
import pyqtgraph as pg
|
|
print(pg.__version__)
|
|
|
|
# Interpret image data as row-major instead of col-major
|
|
pg.setConfigOptions(imageAxisOrder='row-major')
|
|
|
|
app = QtGui.QApplication([])
|
|
|
|
## Create window with ImageView widget
|
|
win = QtGui.QMainWindow()
|
|
win.resize(800,800)
|
|
imv = pg.ImageView()
|
|
win.setCentralWidget(imv)
|
|
win.show()
|
|
win.setWindowTitle('pyqtgraph example: ImageView')
|
|
|
|
## Create random 3D data set with noisy signals
|
|
img = pg.gaussianFilter(np.random.normal(size=(200, 200)), (5, 5)) * 20 + 100
|
|
img = img[np.newaxis,:,:]
|
|
decay = np.exp(-np.linspace(0,0.3,100))[:,np.newaxis,np.newaxis]
|
|
data = np.random.normal(size=(100, 200, 200))
|
|
data += img * decay
|
|
data += 2
|
|
|
|
## Add time-varying signal
|
|
sig = np.zeros(data.shape[0])
|
|
sig[30:] += np.exp(-np.linspace(1,10, 70))
|
|
sig[40:] += np.exp(-np.linspace(1,10, 60))
|
|
sig[70:] += np.exp(-np.linspace(1,10, 30))
|
|
|
|
sig = sig[:,np.newaxis,np.newaxis] * 3
|
|
data[:,50:60,30:40] += sig
|
|
|
|
|
|
## Display the data and assign each frame a time value from 1.0 to 3.0
|
|
imv.setImage(data, xvals=np.linspace(1., 3., data.shape[0]))
|
|
imv.setImage(cam.get_image())
|
|
|
|
## Set a custom color map
|
|
colors = [
|
|
(0, 0, 0),
|
|
(45, 5, 61),
|
|
(84, 42, 55),
|
|
(150, 87, 60),
|
|
(208, 171, 141),
|
|
(255, 255, 255)
|
|
]
|
|
cmap = pg.ColorMap(pos=np.linspace(0.0, 1.0, 6), color=colors)
|
|
imv.setColorMap(cmap)
|
|
|
|
## Start Qt event loop unless running in interactive mode.
|
|
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
|
|
QtGui.QApplication.instance().exec_()
|
|
|
|
|
|
|
|
|