def _execute_monitor(self, request): # Connect to the channel path = ".".join(request.path[1:]) channel = pvaccess.Channel(request.path[0]) self._monitors[request.generate_key()] = channel # Store the connection within the monitor set def callback(value=None): # TODO: ordering is not maintained here... # TODO: should we strip_tuples here? d = value.toDict(True) if d.get("typeid", "") == Error.typeid: response = Error(request.id, d["message"]) self._monitors.pop(request.generate_key()) channel.unsubscribe("") else: # TODO: support Deltas properly if request.delta: response = Delta(request.id, [[[], d]]) else: response = Update(request.id, d) request.callback(response) # Perform a subscribe, but it returns nothing channel.subscribe("sub", callback) channel.startMonitor(path) a = None return a
def __enter__(self): self.pv_channel = pvaccess.Channel(self.pv_image) x, y = self.pv_channel.get('field()')['dimension'] self.dims = (y['size'], x['size']) labels = [ item["name"] for item in self.pv_channel.get('field()')["attribute"] ] self.theta_key = labels.index("SampleRotary") self.scan_delta_key = labels.index("ScanDelta") self.start_position_key = labels.index("StartPos") self.last_save_dest = labels.index("SaveDest") self.imageId = labels.index("ArrayCounter") self.flat_count = 0 self.dark_count = 0 self.flat_counter = 0 self.dark_counter = 0 self.sequence = 0 print(self.dims) if self.num_sinograms > 0: if (self.beg_sinogram < 0) or ( self.beg_sinogram + self.num_sinograms > self.dims[0]): raise Exception( "Exceeds the sinogram boundary: {} vs. {}".format( self.beg_sinogram + self.num_sinograms, self.dims[0])) self.beg_index = self.beg_sinogram * self.dims[1] self.end_index = self.beg_sinogram * self.dims[ 1] + self.num_sinograms * self.dims[1] self.pv_channel.subscribe('push_image_data', self.push_image_data) return self
def __init__(self,stype): [ntheta,nz,n] = [1024,1024,1024] rate = 5*1024**3#GB/s buffer_size = 100000 # queue self.data_queue = queue.Queue(maxsize=buffer_size) self.epics_pvs = {} # pva type channel that contains projection and metadata image_pv_name = "2bmbSP2:Pva1:" self.epics_pvs['PvaPImage'] = pva.Channel(image_pv_name + 'Image') self.epics_pvs['PvaPDataType_RBV'] = pva.Channel(image_pv_name + 'DataType_RBV') self.pva_plugin_image = self.epics_pvs['PvaPImage'] # create pva type pv for reconstrucion by copying metadata from the data pv, but replacing the sizes # This way the ADViewer (NDViewer) plugin can be also used for visualizing reconstructions. pva_image_data = self.pva_plugin_image.get('') pva_image_dict = pva_image_data.getStructureDict() self.pv_rec = pva.PvObject(pva_image_dict) # run server for reconstruction pv recon_pva_name = "2bmb:Rec" if(stype=='server'): self.server_rec = pva.PvaServer(recon_pva_name, self.pv_rec) pva_image_data = self.pva_plugin_image.get('') width = pva_image_data['dimension'][0]['size'] height = pva_image_data['dimension'][1]['size'] self.pv_rec['dimension'] = [{'size': width, 'fullSize': width, 'binning': 1}, {'size': height, 'fullSize': height, 'binning': 1}] self.epics_pvs['PvaPImage'] = pva.Channel(recon_pva_name) self.pva_rec_image = self.epics_pvs['PvaPImage'] #self.pv_rec['value'] = ({'floatValue': rec.flatten()},) # self.theta = self.epics_pvs['ThetaArray'].get()[:self.epics_pvs['NumAngles'].get()] # start monitoring projection data datatype_list = self.epics_pvs['PvaPDataType_RBV'].get()['value'] self.datatype = datatype_list['choices'][datatype_list['index']].lower() self.datatype='uint16' self.buffer_size=buffer_size self.height=height self.width=width self.cur_id=0 self.tmp=np.zeros([height*width],dtype='uint16')
def execute_put(self, request): # Connect to the channel c = pvaccess.Channel(request["endpoint"][0]) # Create the path request from the endpoints (not including the block name endpoint) path = ".".join(request["endpoint"][1:]) self.log_debug("path: %s", path) # Perform a put, but there is no response available c.put(request["value"], path) # Now create the Return object and populate it with the response return_object = Return(id_=request["id"], value="No return value from put") return return_object
def main(): global app, img, x, y, MAX_FRAMES global args parser = argparse.ArgumentParser(description='AreaDetector video example') parser.add_argument( "ImagePV", help="EPICS PVA image PV name, such as 13PG2:Pva1:Image") parser.add_argument('--benchmark', action='store_true', help='measure framerate') parser.add_argument('--noAGC', action='store_true', help='disable auto gain') parser.add_argument('--frames', action='store_true', help='maximum number of frames (-1: unlimited)') args = parser.parse_args() app = QtGui.QApplication([]) win = QtWidgets.QWidget() win.setWindowTitle('daqScope') layout = QtGui.QGridLayout() layout.setMargin(0) win.setLayout(layout) img = RawImageWidget(win) layout.addWidget(img, 0, 0, 0, 0) win.show() chan = pvaccess.Channel(args.ImagePV) x, y = chan.get('field()')['dimension'] x = x['size'] y = y['size'] win.resize(x, y) chan.subscribe('update', update) chan.startMonitor() if args.benchmark: start = time.time() if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'): QtGui.QApplication.instance().exec_() chan.stopMonitor() chan.unsubscribe('update') if args.benchmark: stop = time.time() print('Frames displayed: %d' % framesDisplayed) print('Elapsed time: %.3f sec' % (stop - start)) print('Frames per second: %.3f FPS' % (framesDisplayed / (stop - start)))
def __enter__(self): self.pv_channel = pvaccess.Channel(self.pv_image) y, x = self.pv_channel.get('field()')['dimension'] self.dims=(y['size'], x['size']) if self.num_sinograms>0: if (self.beg_sinogram<0) or (self.beg_sinogram+self.num_sinograms>self.dims[0]): raise Exception("Exceeds the sinogram boundary: {} vs. {}".format( self.beg_sinogram+self.num_sinograms, self.dims[0])) self.beg_index = self.beg_sinogram*self.dims[1] self.end_index = self.beg_sinogram*self.dims[1] + self.num_sinograms*self.dims[1] self.pv_channel.subscribe('push_image_data', self.push_image_data) return self
def takeflat(chdata): """ take 1 flat field, probably Multiple is needed """ chTriggerMode = pva.Channel('2bmbSP1:cam1:TriggerMode', pva.CA) chImageMode = pva.Channel('2bmbSP1:cam1:ImageMode', pva.CA) chAcquire = pva.Channel('2bmbSP1:cam1:Acquire', pva.CA) #chNumImages= pva.Channel('2bmbSP1:cam1:NumImages', pva.CA) chSamXrbv = pva.Channel('2bma:m49.RBV', pva.CA) chSamX = pva.Channel('2bma:m49', pva.CA) # remember the current position samx cur = chSamXrbv.get('')['value'] # move sample out chSamX.put(-10) time.sleep(10) # change to single mode chTriggerMode.put('Off') time.sleep(0.1) chImageMode.put('Single') time.sleep(0.1) # chNumImages.put(10) # time.sleep(0.1) # Acquire, and take array from pv chAcquire.put(1) flat = chdata.get('')['value'][0]['ubyteValue'] time.sleep(1) # move sample in chSamX.put(cur) time.sleep(10) return flat
def execute_monitor(self, request): # Connect to the channel c = pvaccess.Channel(request["endpoint"][0]) # Store the connection within the monitor set mon = MonitorHandler(request["id"], c, self) self._monitors[request["id"]] = mon # Create the path request from the endpoints (not including the block name endpoint) path = ".".join(request["endpoint"][1:]) self.log_debug("Monitor path: %s", path) # Perform a put, but there is no response available c.subscribe(path, mon.monitor_update) self.log_debug("Created subscription") c.startMonitor(path) self.log_debug("Started monitor") return None
def feed_data(self): self.chan = pvaccess.Channel(self.pva_name) x, y = self.chan.get('field()')['dimension'] self.dims = (y['size'], x['size']) print(self.dims) labels = [ item['name'] for item in self.chan.get('field()')['attribute'] ] self.ack_time = labels.index("AckTime") self.chan.subscribe('update', self.on_change) self.chan.startMonitor("value,attribute,uniqueId") # start the infinit loop so the feed does not stop after this init if True: time.sleep(10)
def subscribe(self, client): """ Subscribes WebSocket client to receive this PV's updates. """ if client not in self._clients: self._clients.append(client) #log.info("Subscribed client: {0}".format(client.getClientId())) if self._ch is None: self._ch = pvaccess.Channel(self._pvname, self._protocol) self._ch.subscribe("webepics", self.updateCb) self._ch.startMonitor("field()") if self._cached: # Monitor is already active and it won't send full PV structure once it connects, # but the protocol requires client receives full update on connect so do it here try: self.sendToClients(self._cached, [client]) except tornado.websocket.WebSocketClosedError: pass
def feed_data(self): self.chan = pvaccess.Channel(self.pva_name) x, y = self.chan.get('field()')['dimension'] self.dims = (y['size'], x['size']) print(self.dims) #send the dimensions to client data = containers.Data(const.DATA_STATUS_DIM) data.dim_x = x data.dim_y = y self.cons.send_to_zmq(data) labels = [item['name'] for item in self.chan.get('field()')['attribute']] self.theta_key = labels.index("SampleRotary") self.scan_delta_key = labels.index("ScanDelta") self.start_position_key = labels.index("StartPos") self.chan.subscribe('update', self.on_change) self.chan.startMonitor("value,attribute,uniqueId")
def execute_get(self, request): # Connect to the channel c = pvaccess.Channel(request["endpoint"][0]) # Create the path request from the endpoints (not including the block name endpoint) path = ".".join(request["endpoint"][1:]) self.log_debug("path: %s", path) # Perform a get and record the response response = c.get(path) self.log_debug("Response: %s", response) # Now create the Return object and populate it with the response value = response.toDict(True) if 'typeid' in value: if value['typeid'] == 'malcolm:core/Error:1.0': return_object = Error(id_=request["id"], message=value['message']) else: return_object = Return(id_=request["id"], value=value) else: return_object = Error(id_=request["id"], message="No valid return typeid") return return_object
def _execute_put(self, request): path = ".".join(request.path[1:]) channel = pvaccess.Channel(request.path[0]) channel.put(request.value, path) response = Return(request.id) return response
def _execute_get(self, request): path = ".".join(request.path[1:]) channel = pvaccess.Channel(request.path[0]) d = channel.get(path).toDict() response = self._response_from_dict(request, d) return response
def start_fly(): """ init and run fly scan """ chfly = pva.Channel('2bma:PSOFly2:fly', pva.CA) chtaxi = pva.Channel('2bma:PSOFly2:taxi', pva.CA) chTriggerMode = pva.Channel('2bmbSP1:cam1:TriggerMode', pva.CA) chTriggerSource = pva.Channel('2bmbSP1:cam1:TriggerSource', pva.CA) chTriggerOverlap = pva.Channel('2bmbSP1:cam1:TriggerOverlap', pva.CA) chExposureMode = pva.Channel('2bmbSP1:cam1:ExposureMode', pva.CA) chImageMode = pva.Channel('2bmbSP1:cam1:ImageMode', pva.CA) chArrayCallbacks = pva.Channel('2bmbSP1:cam1:ArrayCallbacks', pva.CA) chFrameRateEnable = pva.Channel('2bmbSP1:cam1:FrameRateEnable', pva.CA) chTriggerMode = pva.Channel('2bmbSP1:cam1:TriggerMode', pva.CA) chAcquire = pva.Channel('2bmbSP1:cam1:Acquire', pva.CA) chtaxi.put(1) chTriggerMode.put('Off') time.sleep(0.1) chTriggerSource.put('Line2') chTriggerOverlap.put('ReadOut') chExposureMode.put('Timed') chImageMode.put('Continuous') chArrayCallbacks.put('Enable') chFrameRateEnable.put(0) time.sleep(0.1) chTriggerMode.put('On') time.sleep(0.1) chAcquire.put(1) chfly.put(1)
#!/usr/bin/env python import pvaccess as pva s = pva.PvaServer('foo', pva.PvObject({'value': pva.INT})) c = pva.Channel('foo') c.get() s.removeRecord('foo')
def pvput(name, value, use_ca=True): pvaccess.Channel(name, pvaccess.CA if use_ca else pvaccess.PVA).put(value)
def _create_pv(self, pv_name): return pvaccess.Channel(pv_name, pvaccess.PVA if self.usepva else pvaccess.CA)
# Read PV from EPICSV4Sandbox/neutronsDemoServer # (start_neutrondemo) import pvaccess c = pvaccess.Channel('neutrons') # By default, the Channel will request "field(value"), # which is not valid for this custom structure and # would result in "PvaClientGet::connect invalid pvRequest". # Fetch all elements: custom = c.get("field()") # Could also configure the channel to fetch selected # elements of the structure: # custom = c.get("field(proton_charge, pixel)") print("Custom data structure:") print(custom) # Acts as a python dictionary p_charge = custom['proton_charge']['value'] pixels = custom['pixel']['value'] print("Last pulse had a charge of %g Coulomb" % p_charge) print("The detector was hit at these pixels IDs:") print(str(pixels))
def streaming(): """ Main computational function, take data from pvdata ('2bmbSP1:Pva1:Image'), reconstruct orthogonal slices and write the result to pvrec ('AdImage') """ ##### init pvs ###### # init pvs for the streaming GUI # orthoslices chStreamX = pva.Channel('2bmS1:StreamX', pva.CA) chStreamY = pva.Channel('2bmS1:StreamY', pva.CA) chStreamZ = pva.Channel('2bmS1:StreamZ', pva.CA) # frame type chStreamFrameType = pva.Channel('2bma:TomoScan:FrameType', pva.CA) # theta array chStreamThetaArray = pva.Channel('2bma:PSOFly2:motorPos.AVAL', pva.CA) # total number of fly scan angles chStreamNumAngles = pva.Channel('2bma:TomoScan:NumAngles', pva.CA) # total number of dark fields chStreamNumDarkFields = pva.Channel('2bma:TomoScan:NumDarkFields', pva.CA) # total number of flat fields chStreamNumFlatFields = pva.Channel('2bma:TomoScan:NumFlatFields', pva.CA) # dark field mode chStreamDarkFieldMode = pva.Channel('2bma:TomoScan:DarkFieldMode', pva.CA) # flat field mode chStreamFlatFieldMode = pva.Channel('2bma:TomoScan:FlatFieldMode', pva.CA) # NEW: buffer size for for projections #chStreamBS = pva.Channel('2bmS1:StreamBS', pva.CA) # NEW: rotation center #chStreamRC = pva.Channel('2bmS1:StreamRC', pva.CA) ## init pva streaming pv for the detector # NEW: PV channel that contains projection and metadata (angle, flag: regular, flat or dark) chdata = pva.Channel('2bmbSP1:Pva1:Image') pvdata = chdata.get('') # init pva streaming pv for reconstrucion with coping dictionary from pvdata pvdict = pvdata.getStructureDict() pvrec = pva.PvObject(pvdict) # take dimensions n = pvdata['dimension'][0]['size'] nz = pvdata['dimension'][1]['size'] # set dimensions for reconstruction pvrec['dimension'] = [{ 'size': 3 * n, 'fullSize': 3 * n, 'binning': 1 }, { 'size': n, 'fullSize': n, 'binning': 1 }] ##### run server for reconstruction pv ##### # NEW: replace AdImage by a new name for Reconstruction PV, e.g. 2bmS1:StreamREC s = pva.PvaServer('AdImage', pvrec) ##### procedures before running fly ####### # 0) form circular buffer, whenever the angle goes higher than 180 # than corresponding projection is replacing the first one ntheta = 180 #chStreamBS.get('')['value'] nflatinit = chStreamNumFlatFields.get('')['value'] ndarkinit = chStreamNumDarkFields.get('')['value'] databuffer = np.zeros([ntheta, nz * n], dtype='uint8') flatbuffer = np.zeros([nflatinit, nz * n], dtype='uint8') darkbuffer = np.zeros([ndarkinit, nz * n], dtype='uint8') thetabuffer = np.zeros(ntheta, dtype='float32') # Load angles theta = chStreamThetaArray.get( '')['value'][:chStreamNumAngles.get('')['value']] # find first id of the projection data, skipping ids for dadrk and flat fields flatmodeall = chStreamFlatFieldMode.get('')['value'] flatmode = flatmodeall['choices'][flatmodeall['index']] darkmodeall = chStreamDarkFieldMode.get('')['value'] darkmode = darkmodeall['choices'][darkmodeall['index']] ## the following is not needed, since the id is set to zero before acquiring pojections # firstid = chdata.get('')['uniqueId'] # if(flatmode == 'Start' or flatmode=='Both'): # firstid += chStreamNumFlatFields.get('')['value'] # if(darkmode == 'Start' or darkmode=='Both'): # firstid += chStreamNumDarkFields.get('')['value'] # print('first projection id', firstid) nflat = 0 ndark = 0 nproj = 0 # number of streamed images of each type def addData(pv): """ read data from the detector, 3 types: flat, dark, projection""" nonlocal nflat nonlocal ndark nonlocal nproj #with mrwlock.w_locked(): curid = pv['uniqueId'] ftypeall = chStreamFrameType.get('')['value'] ftype = ftypeall['choices'][ftypeall['index']] if (ftype == 'FlatField'): flatbuffer[nflat] = pv['value'][0]['ubyteValue'] nflat += 1 if (ftype == 'DarkField'): darkbuffer[ndark] = pv['value'][0]['ubyteValue'] ndark += 1 if (ftype == 'Projection'): databuffer[np.mod(nproj, ntheta)] = pv['value'][0]['ubyteValue'] thetabuffer[np.mod(nproj, ntheta)] = theta[curid - 1] nproj += 1 print('add:', ftype, 'id:', curid) # start monitoring projection data chdata.monitor(addData, '') # create solver class on GPU slv = OrthoRec(ntheta, n, nz) # allocate memory for result slices recall = np.zeros([n, 3 * n], dtype='float32') # wait until dark and flats are acquired while (nproj == 0): 1 # init data as flat databuffer[:] = flatbuffer[0] print(databuffer.shape) # copy dark and flat to GPU print('copy dark and flat to GPU') slv.set_flat(np.mean(flatbuffer[:nflat], axis=0)) slv.set_dark(np.mean(darkbuffer[:ndark], axis=0)) ##### streaming reconstruction ###### while (True): #with mrwlock.r_locked(): # lock buffer before reading datap = databuffer.copy() thetap = thetabuffer.copy() # take 3 ortho slices ids idx = chStreamX.get('')['value'] idy = chStreamY.get('')['value'] idz = chStreamZ.get('')['value'] # NEW: center center = 1224 #chStreamC.get('')['value'] # print(thetap) # reconstruct on GPU #tic() recx, recy, recz = slv.rec_ortho(datap, thetap * np.pi / 180, center, idx, idy, idz) #print('rec time:',toc(),'norm',np.linalg.norm(recx)) # concatenate (supposing nz<n) recall[:nz, :n] = recx recall[:nz, n:2 * n] = recy recall[:, 2 * n:] = recz # write to pv pvrec['value'] = ({'floatValue': recall.flatten()}, ) # reconstruction rate limit time.sleep(0.1)
def streaming(): """ Main computational function, take data from pvdata ('2bmbSP1:Pva1:Image'), reconstruct orthogonal slices and write the result to pvrec ('AdImage') """ ##### init pvs ###### # init ca pvs chscanDelta = pva.Channel('2bma:PSOFly2:scanDelta', pva.CA) chrotangle = pva.Channel('2bma:m82', pva.CA) chrotangleset = pva.Channel('2bma:m82.SET', pva.CA) chrotanglestop = pva.Channel('2bma:m82.STOP', pva.CA) chStreamX = pva.Channel('2bmS1:StreamX', pva.CA) chStreamY = pva.Channel('2bmS1:StreamY', pva.CA) chStreamZ = pva.Channel('2bmS1:StreamZ', pva.CA) # init pva streaming pv for the detector chdata = pva.Channel('2bmbSP1:Pva1:Image') pvdata = chdata.get('') # init pva streaming pv for reconstrucion with coping dictionary from pvdata pvdict = pvdata.getStructureDict() pvrec = pva.PvObject(pvdict) # take dimensions n = pvdata['dimension'][0]['size'] nz = pvdata['dimension'][1]['size'] # set dimensions for reconstruction pvrec['dimension'] = [{ 'size': 3 * n, 'fullSize': 3 * n, 'binning': 1 }, { 'size': n, 'fullSize': n, 'binning': 1 }] ##### run server for reconstruction pv ##### s = pva.PvaServer('AdImage', pvrec) ##### procedures before running fly ####### # 0) form circular buffer, whenever the angle goes higher than 180 # than corresponding projection is replacing the first one scanDelta = chscanDelta.get('')['value'] ntheta = np.int(180 / scanDelta + 0.5) databuffer = np.zeros([ntheta, nz * n], dtype='uint8') thetabuffer = np.zeros(ntheta, dtype='float32') # 1) stop rotation, replace rotation stage angle to a value in [0,360) chrotanglestop.put(1) time.sleep(3) rotangle = chrotangle.get('')['value'] chrotangleset.put(1) chrotangle.put(rotangle - rotangle // 360 * 360) chrotangleset.put(0) # 2) take flat field flat = takeflat(chdata) firstid = chdata.get('')['uniqueId'] # 3) create solver class on GPU, and copy flat field to gpu slv = OrthoRec(ntheta, n, nz) slv.set_flat(flat) # 4) allocate memory for result slices recall = np.zeros([n, 3 * n], dtype='float32') # 5) start monitoring the detector pv for data collection def addProjection(pv): with mrwlock.w_locked(): curid = pv['uniqueId'] databuffer[np.mod(curid, ntheta)] = pv['value'][0]['ubyteValue'] thetabuffer[np.mod(curid, ntheta)] = (curid - firstid) * scanDelta #print(firstid, curid) chdata.monitor(addProjection, '') ##### start acquisition ####### start_fly() ##### streaming reconstruction ###### while (True): # infinite loop over angular partitions with mrwlock.r_locked(): # lock buffer before reading datap = databuffer.copy() thetap = thetabuffer.copy() # take 3 ortho slices ids idx = chStreamX.get('')['value'] idy = chStreamY.get('')['value'] idz = chStreamZ.get('')['value'] # reconstruct on GPU tic() recx, recy, recz = slv.rec_ortho(datap, thetap * np.pi / 180, n // 2, idx, idy, idz) print('rec time:', toc()) # concatenate (supposing nz<n) recall[:nz, :n] = recx recall[:nz, n:2 * n] = recy recall[:, 2 * n:] = recz # write to pv pvrec['value'] = ({'floatValue': recall.flatten()}, ) # reconstruction rate limit time.sleep(0.1)
def put(self, value): """ Request a put command with a new value. """ ch = pvaccess.Channel(self._pvname, self._protocol) ch.put(value)
# takes Pva from AD and extracts the NTNDArray structure then # creates a new pv that uses the same structure and hosts a random image. # these new pv is them served as 'AdImage'. # run it with: # # python -i test_03.py # # then from a terminal you can get the image with: # pvget AdImage | more import pvaccess as pva import numpy as np import time c = pva.Channel('2bmbSP1:Pva1:Image') pv1 = c.get('') pv1d = pv1.getStructureDict() print(pv1d) exit() # copy dictionaries for value and dimension fields pv2 = pva.PvObject(pv1d) image = (np.random.random([512, 256]) * 256).astype('float32') pv2['value'] = ({'floatValue': image}, ) # set dimensions for data pv2['dimension'] = [{'size':image.shape[0], 'fullSize':image.shape[0], 'binning':1},\ {'size':image.shape[1], 'fullSize':image.shape[0], 'binning':1}] s = pva.PvaServer('AdImage', pv2) while (True): image = (np.random.random([512, 256])).astype('float32').flatten() pv2['value'] = ({'floatValue': image}, )
def main(): global app, img, x, y, MAX_FRAMES global args parser = argparse.ArgumentParser(description='AreaDetector video example') parser.add_argument( "ImagePV", help="EPICS PVA image PV name, such as 13PG2:Pva1:Image") parser.add_argument('--benchmark', action='store_true', help='measure framerate') parser.add_argument('--noAGC', action='store_true', help='disable auto gain') parser.add_argument('--frames', help='maximum number of frames (-1: unlimited)') parser.add_argument('--bindip', default=None, help='ip address to bind tmq)') parser.add_argument('--port', type=int, default=5560, help='Port address to bind tmq') parser.add_argument('--beg_sinogram', type=int, help='Starting sinogram for reconstruction') parser.add_argument('--num_sinograms', type=int, help='Number of sinograms to reconstruct') parser.add_argument('--mock_data', action='store_true', default=False, help='Mock data acquisition from file') parser.add_argument('--mock_file', help='File name for mock data acquisition') args = parser.parse_args() global start_sino, num_sinos, mock_data start_sino = args.beg_sinogram num_sinos = args.num_sinograms mock_data = args.mock_data if mock_data: print("Mock data is set") setup_mock_data(args.mock_file) app = QtGui.QApplication([]) win = QtWidgets.QWidget() win.setWindowTitle('daqScope') layout = QtGui.QGridLayout() layout.setMargin(0) win.setLayout(layout) img = RawImageWidget(win) layout.addWidget(img, 0, 0, 0, 0) win.show() chan = pvaccess.Channel(args.ImagePV) global x, y x, y = chan.get('field()')['dimension'] x = x['size'] y = y['size'] win.resize(x, y) #### Setup TMQ ##### tmq.init_tmq() # Handshake w. remote processes # For set TMQ for 2 sinograms print(type(x)) print(type(num_sinos)) if mock_data: print("Mock data handshake: input data shape={}".format(idata.shape)) tmq.handshake(args.bindip, args.port, int(num_sinos), idata.shape[2]) else: print("Streaming data handshake: input data shape={},{}".format( int(num_sinos), int(x))) tmq.handshake(args.bindip, args.port, int(num_sinos), int(x)) #################### chan.subscribe('update', update) chan.startMonitor() if args.benchmark: start = time.time() # Finalize streaming ? if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'): QtGui.QApplication.instance().exec_() chan.stopMonitor() chan.unsubscribe('update') print("Remove") # Finalize TMQ tmq.done_image() tmq.finalize_tmq() if args.benchmark: stop = time.time() print('Frames displayed: %d' % framesDisplayed) print('Elapsed time: %.3f sec' % (stop - start)) print('Frames per second: %.3f FPS' % (framesDisplayed / (stop - start)))
def pvget(name, as_string=False, use_ca=True): channel = pvaccess.Channel(name, pvaccess.CA if use_ca else pvaccess.PVA) return _pvget(channel, as_string=as_string)
def __init__(self, pv_files, macros): log.setup_custom_logger("./tomostream.log") # init pvs self.config_pvs = {} self.control_pvs = {} self.pv_prefixes = {} if not isinstance(pv_files, list): pv_files = [pv_files] for pv_file in pv_files: self.read_pv_file(pv_file, macros) self.show_pvs() self.epics_pvs = {**self.config_pvs, **self.control_pvs} prefix = self.pv_prefixes['TomoScan'] # tomoscan pvs self.epics_pvs['FrameType'] = PV(prefix + 'FrameType') self.epics_pvs['NumAngles'] = PV(prefix + 'NumAngles') self.epics_pvs['RotationStep'] = PV(prefix + 'RotationStep') # Replace PSOPVPrefix to link to check a TomoScanStream PV so it returns if scan IOC is down # self.epics_pvs['PSOPVPrefix'] = PV(prefix + 'PSOPVPrefix') # if self.epics_pvs['PSOPVPrefix'].get(as_string=True) == None: # log.error("TomoScan is down") # log.error("Type exit() here and start TomoScan first") # return # pva type channel for flat and dark fields pv broadcasted from the detector machine self.epics_pvs['PvaDark'] = pva.Channel(self.epics_pvs['DarkPVAName'].get()) self.pva_dark = self.epics_pvs['PvaDark'] self.epics_pvs['PvaFlat'] = pva.Channel(self.epics_pvs['FlatPVAName'].get()) self.pva_flat = self.epics_pvs['PvaFlat'] self.epics_pvs['PvaTheta'] = pva.Channel(self.epics_pvs['ThetaPVAName'].get()) self.pva_theta = self.epics_pvs['PvaTheta'] # pva type channel that contains projection and metadata image_pv_name = PV(self.epics_pvs['ImagePVAPName'].get()).get() self.epics_pvs['PvaPImage'] = pva.Channel(image_pv_name + 'Image') self.epics_pvs['PvaPDataType_RBV'] = pva.Channel(image_pv_name + 'DataType_RBV') self.pva_plugin_image = self.epics_pvs['PvaPImage'] # create pva type pv for reconstrucion by copying metadata from the data pv, but replacing the sizes # This way the ADViewer (NDViewer) plugin can be also used for visualizing reconstructions. pva_image_data = self.pva_plugin_image.get('') pva_image_dict = pva_image_data.getStructureDict() self.pv_rec = pva.PvObject(pva_image_dict) # run server for reconstruction pv recon_pva_name = self.epics_pvs['ReconPVAName'].get() self.server_rec = pva.PvaServer(recon_pva_name, self.pv_rec) self.epics_pvs['StartRecon'].put('Done') self.epics_pvs['AbortRecon'].put('Yes') self.epics_pvs['StartRecon'].add_callback(self.pv_callback) self.epics_pvs['AbortRecon'].add_callback(self.pv_callback) # Set ^C, ^Z interrupt to abort the stream reconstruction signal.signal(signal.SIGINT, self.signal_handler) signal.signal(signal.SIGTSTP, self.signal_handler) # Start the watchdog timer thread thread = threading.Thread(target=self.reset_watchdog, args=(), daemon=True) thread.start()
#!/usr/bin/env python from __future__ import print_function import time import pvaccess def monitor(pvObject): ntTable = pvaccess.NtTable(pvObject) print("Full NT Table") print(ntTable) print("Column 0:") print(ntTable.getColumn(0)) c = pvaccess.Channel('testTable') c.subscribe('m1', monitor) c.startMonitor('field()') time.sleep(10) c.unsubscribe('m1')
# Read PV from examples/iocBoot/iocExample import pvaccess c = pvaccess.Channel('training:calc1') print(c.get())
def streaming(theta, nthetap): """ Main computational function, take data from pvdata ('2bmbSP1:Pva1:Image'), reconstruct orthogonal slices and write the result to pvrec ('AdImage') """ # init streaming pv for the detector c = pva.Channel('2bmbSP1:Pva1:Image') pvdata = c.get('') # take dimensions n = pvdata['dimension'][0]['size'] nz = pvdata['dimension'][1]['size'] # init streaming pv for reconstrucion with copuing dictionary from pvdata pvdatad = pvdata.getStructureDict() pvrec = pva.PvObject(pvdatad) # set dimensions for data pvrec['dimension'] = [{ 'size': 3 * n, 'fullSize': 3 * n, 'binning': 1 }, { 'size': n, 'fullSize': n, 'binning': 1 }] s = pva.PvaServer('AdImage', pvrec) # init with slices through the middle ix = n // 2 iy = n // 2 iz = nz // 2 # I suggest using buffers that has only certain number of angles, # e.g. nhetap=50, this buffer is continuously update with monitoring # the detector pv (function addProjection), called inside pv monitor databuffer = np.zeros([nthetap, nz, n], dtype='float32') thetabuffer = np.zeros(nthetap, dtype='float32') def addProjection(pv): curid = pv['uniqueId'] databuffer[np.mod(curid, nthetap)] = pv['value'][0]['ubyteValue'].reshape( nz, n).astype('float32') thetabuffer[np.mod(curid, nthetap)] = theta[np.mod( curid, ntheta)] # take some theta with respect to id c.monitor(addProjection, '') # solver class on gpu with OrthoRec(nthetap, n, nz) as slv: # memory for result slices recall = np.zeros([n, 3 * n], dtype='float32') while (True): # infinite loop over angular partitions # new = take ix,iy,iz from gui new = None flgx, flgy, flgz = 0, 0, 0 # recompute slice or not if (new != None): [newx, newy, newz] = new if (newx != ix): ix = newx # change slice id flgx = 1 # recompute flg if (newy != iy): iy = newy flgy = 1 if (newz != iz): iz = newz flgz = 1 # take interlaced projections and corresponding angles # I guess there should be read/write locks here. datap = databuffer.copy() thetap = thetabuffer.copy() print('data partition norm:', np.linalg.norm(datap)) print('partition angles:', thetap) # recover 3 ortho slices recx, recy, recz = slv.rec_ortho(datap, thetap, n // 2, ix, iy, iz, flgx, flgy, flgz) # concatenate (supposing nz<n) recall[:nz, :n] = recx recall[:nz, n:2 * n] = recy recall[:, 2 * n:] = recz # 1s reconstruction rate time.sleep(1) # write to pv pvrec['value'] = ({'floatValue': recall.flatten()}, )
def __init__(self): #Define all channels with CA self.EvgPrescaleSP1 = pvaccess.Channel( "Utgard:MDS:TS-EVG-01:Mxc2-Prescaler-SP", pvaccess.ProviderType.CA) self.EvgPrescaleSP2 = pvaccess.Channel( "Utgard:MDS:TS-EVG-01:Mxc3-Prescaler-SP", pvaccess.ProviderType.CA) self.EvgPrescaleSP3 = pvaccess.Channel( "Utgard:MDS:TS-EVG-01:Mxc4-Prescaler-SP", pvaccess.ProviderType.CA) self.EvgPrescaleSP4 = pvaccess.Channel( "Utgard:MDS:TS-EVG-01:Mxc5-Prescaler-SP", pvaccess.ProviderType.CA) self.EvgEvtCode1 = pvaccess.Channel( "Utgard:MDS:TS-EVG-01:TrigEvt2-EvtCode-SP", pvaccess.ProviderType.CA) self.EvgEvtCode2 = pvaccess.Channel( "Utgard:MDS:TS-EVG-01:TrigEvt3-EvtCode-SP", pvaccess.ProviderType.CA) self.EvgEvtCode3 = pvaccess.Channel( "Utgard:MDS:TS-EVG-01:TrigEvt4-EvtCode-SP", pvaccess.ProviderType.CA) self.EvgEvtCode4 = pvaccess.Channel( "Utgard:MDS:TS-EVG-01:TrigEvt5-EvtCode-SP", pvaccess.ProviderType.CA) self.EvrOutEvtTrig = pvaccess.Channel( "MDTST{evr:1-DlyGen:3}Evt:Trig0-SP", pvaccess.ProviderType.CA) self.EvrInEvt = pvaccess.Channel("MDTST{evr:1-In:0}Code:Ext-SP", pvaccess.ProviderType.CA) self.EvrCptEvtSP1 = pvaccess.Channel("MDTST{evr:1-tsflu:1}CptEvt-SP", pvaccess.ProviderType.CA) self.EvrCptEvtSP2 = pvaccess.Channel("MDTST{evr:1-tsflu:2}CptEvt-SP", pvaccess.ProviderType.CA) self.EvrCptEvtSP3 = pvaccess.Channel("MDTST{evr:1-tsflu:3}CptEvt-SP", pvaccess.ProviderType.CA) self.EvrCptEvtSP4 = pvaccess.Channel("MDTST{evr:1-tsflu:4}CptEvt-SP", pvaccess.ProviderType.CA) self.EvrCptEvtPrevSP1 = pvaccess.Channel( "MDTST{evr:1-tsprev:1}CptEvt-SP", pvaccess.ProviderType.CA) self.EvrFlshEvtSP1 = pvaccess.Channel("MDTST{evr:1-tsflu:1}FlshEvt-SP", pvaccess.ProviderType.CA) self.EvrFlshEvtSP2 = pvaccess.Channel("MDTST{evr:1-tsflu:2}FlshEvt-SP", pvaccess.ProviderType.CA) self.EvrFlshEvtSP3 = pvaccess.Channel("MDTST{evr:1-tsflu:3}FlshEvt-SP", pvaccess.ProviderType.CA) self.EvrFlshEvtSP4 = pvaccess.Channel("MDTST{evr:1-tsflu:4}FlshEvt-SP", pvaccess.ProviderType.CA) self.EvrFlshEvtPrevSP1 = pvaccess.Channel( "MDTST{evr:1-tsprev:1}FlshEvt-SP", pvaccess.ProviderType.CA) self.EvrTSI1 = pvaccess.Channel("MDTST{evr:1-tsflu:1}TS-I", pvaccess.ProviderType.CA) self.EvrTSI2 = pvaccess.Channel("MDTST{evr:1-tsflu:2}TS-I", pvaccess.ProviderType.CA) self.EvrTSI3 = pvaccess.Channel("MDTST{evr:1-tsflu:3}TS-I", pvaccess.ProviderType.CA) self.EvrTSI4 = pvaccess.Channel("MDTST{evr:1-tsflu:4}TS-I", pvaccess.ProviderType.CA) self.EvrTSIPrev1 = pvaccess.Channel("MDTST{evr:1-tsprev:1}TS-I", pvaccess.ProviderType.CA) self.EvrCptEvtFirSP1 = pvaccess.Channel( "MDTST{evr:1-tsfir:1}CptEvt-SP", pvaccess.ProviderType.CA) self.EvrFlshEvtFirSP1 = pvaccess.Channel( "MDTST{evr:1-tsfir:1}FlshEvt-SP", pvaccess.ProviderType.CA) self.EvrCptEvtFirSP2 = pvaccess.Channel( "MDTST{evr:1-tsfir:2}CptEvt-SP", pvaccess.ProviderType.CA) self.EvrFlshEvtFirSP2 = pvaccess.Channel( "MDTST{evr:1-tsfir:2}FlshEvt-SP", pvaccess.ProviderType.CA) self.EvrTSIFir1 = pvaccess.Channel("MDTST{evr:1-tsfir:1}TS-I", pvaccess.ProviderType.CA) self.EvrTSIFir2 = pvaccess.Channel("MDTST{evr:1-tsfir:2}TS-I", pvaccess.ProviderType.CA) self.EvrManFlshFir2 = pvaccess.Channel("MDTST{evr:1-tsfir:2}Flsh-SP", pvaccess.ProviderType.CA) self.EvrDropI1 = pvaccess.Channel("MDTST{evr:1-tsflu:1}Drop-I", pvaccess.ProviderType.CA) self.EvrDropI2 = pvaccess.Channel("MDTST{evr:1-tsflu:2}Drop-I", pvaccess.ProviderType.CA) self.EvgSeq2Unit = pvaccess.Channel( "Utgard:MDS:TS-EVG-01:SoftSeq2-TsResolution-Sel", pvaccess.ProviderType.CA) self.EvgSeq2Evts = pvaccess.Channel( "Utgard:MDS:TS-EVG-01:SoftSeq2-EvtCode-SP", pvaccess.ProviderType.CA) self.EvgSeq2TS = pvaccess.Channel( "Utgard:MDS:TS-EVG-01:SoftSeq2-Timestamp-SP", pvaccess.ProviderType.CA) self.EvgSeq2Commit = pvaccess.Channel( "Utgard:MDS:TS-EVG-01:SoftSeq2-Commit-Cmd", pvaccess.ProviderType.CA) self.EvrRBCptEvtSP1 = pvaccess.Channel("MDTST{evr:1-ts:1}CptEvt-SP", pvaccess.ProviderType.CA) self.EvrRBCptEvtRB1 = pvaccess.Channel("MDTST{evr:1-ts:1}CptEvt-RB", pvaccess.ProviderType.CA) self.EvrTSI1Alrm = pvaccess.Channel("MDTST{evr:1-tsflu:1}TS-I")