def __init__(self, pv_files, macros):
        super().__init__(pv_files, macros)

        # On the A3200 we can read the number of encoder counts per rotation from the controller
        # Unfortunately the Ensemble does not support this
        pso_model = self.epics_pvs['PSOControllerModel'].get(as_string=True)
        if (pso_model == 'A3200'):
            pso_axis = self.epics_pvs['PSOAxisName'].get(as_string=True)
            self.epics_pvs['PSOCommand.BOUT'].put("UNITSTOCOUNTS(%s, 360.0)" %
                                                  pso_axis,
                                                  wait=True,
                                                  timeout=10.0)
            reply = self.epics_pvs['PSOCommand.BINP'].get(as_string=True)
            counts_per_rotation = float(reply[1:])
            self.epics_pvs['PSOCountsPerRotation'].put(counts_per_rotation)

        # Setting the pva servers to broadcast dark and flat fields
        if 'PvaStream' in self.pv_prefixes:
            prefix = self.pv_prefixes['PvaStream']

            self.pva_stream_dark = pvaccess.PvObject({
                'value': [pvaccess.pvaccess.ScalarType.FLOAT],
                'sizex':
                pvaccess.pvaccess.ScalarType.INT,
                'sizey':
                pvaccess.pvaccess.ScalarType.INT
            })
            self.pva_server_dark = pvaccess.PvaServer(
                prefix + 'StreamDarkFields', self.pva_stream_dark)
            self.pva_stream_flat = pvaccess.PvObject({
                'value': [pvaccess.pvaccess.ScalarType.FLOAT],
                'sizex':
                pvaccess.pvaccess.ScalarType.INT,
                'sizey':
                pvaccess.pvaccess.ScalarType.INT
            })
            self.pva_server_flat = pvaccess.PvaServer(
                prefix + 'StreamFlatFields', self.pva_stream_flat)

            self.pva_stream_theta = pvaccess.PvObject({
                'value': [pvaccess.pvaccess.ScalarType.DOUBLE],
                'sizex':
                pvaccess.pvaccess.ScalarType.INT
            })
            self.pva_server_theta = pvaccess.PvaServer(prefix + 'StreamTheta',
                                                       self.pva_stream_theta)

        self.stream_init()
Exemple #2
0
def main():
    server = pva.PvaServer()
    server.start()
    N_IMAGES = 100
    NX = 1024
    NY = 1024
    COLOR_MODE = 0
    IMAGE_RATE = 1.0  # Hz
    EXTRA_FIELDS_OBJECT = pva.PvObject(
        {
            'customField1': pva.INT,
            'customField2': pva.STRING
        }, {
            'customField1': 10,
            'customField2': 'GeneratedBy: PvaPy'
        })
    CHANNEL = 'pvapy:image'
    for i in range(0, N_IMAGES):
        print('Image id: {}'.format(i))
        image = createImage(i, NX, NY, COLOR_MODE, EXTRA_FIELDS_OBJECT)
        time.sleep(1 / IMAGE_RATE)
        if i == 0:
            server.addRecord(CHANNEL, image)
        else:
            server.update(CHANNEL, image)
Exemple #3
0
 def _start_pva_server(self):
     if self._pva_server is None:
         self._pva_server = pvaccess.PvaServer()
         # {mri: Endpoint}
         self._endpoints = {}
         for mri in self._published:
             self._add_new_pva_channel(mri)
         self._spawned = self.spawn(self._pva_server.startListener)
Exemple #4
0
    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')
Exemple #5
0
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()}, )
Exemple #6
0
# 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}, )
    time.sleep(1)
Exemple #7
0
    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()
Exemple #8
0
    def __init__(self, pv_files, macros):
        self.scan_is_running = False
        self.config_pvs = {}
        self.control_pvs = {}
        self.pv_prefixes = {}

        # These variables are set in begin_scan().
        # They are used to prevent reading PVs repeatedly, and so that if the users changes
        # a PV during the scan it won't mess things up.
        self.exposure_time = None
        self.rotation_start = None
        self.rotation_step = None
        self.rotation_stop = None
        self.rotation_resolution = None
        self.max_rotation_speed = None
        self.return_rotation = None
        self.num_angles = None
        self.num_dark_fields = None
        self.dark_field_mode = None
        self.num_flat_fields = None
        self.flat_field_mode = None
        self.total_images = None
        self.file_path_rbv = None
        self.file_name_rbv = None
        self.file_number = None
        self.file_template = None

        if not isinstance(pv_files, list):
            pv_files = [pv_files]
        for pv_file in pv_files:
            self.read_pv_file(pv_file, macros)

        if 'Rotation' not in self.control_pvs:
            log.error('RotationPVName must be present in autoSettingsFile')
            sys.exit()
        if 'Camera' not in self.pv_prefixes:
            log.error('CameraPVPrefix must be present in autoSettingsFile')
            sys.exit()
        if 'FilePlugin' not in self.pv_prefixes:
            log.error('FilePluginPVPrefix must be present in autoSettingsFile')
            sys.exit()

        #Define PVs we will need from the rotation motor, which is on another IOC
        rotation_pv_name = self.control_pvs['Rotation'].pvname
        self.control_pvs['RotationSpeed'] = PV(rotation_pv_name + '.VELO')
        self.control_pvs['RotationMaxSpeed'] = PV(rotation_pv_name + '.VMAX')
        self.control_pvs['RotationResolution'] = PV(rotation_pv_name + '.MRES')
        self.control_pvs['RotationSet'] = PV(rotation_pv_name + '.SET')
        self.control_pvs['RotationStop'] = PV(rotation_pv_name + '.STOP')
        self.control_pvs['RotationDmov'] = PV(rotation_pv_name + '.DMOV')
        self.control_pvs['RotationDirection'] = PV(rotation_pv_name + '.DIR')

        #Define PVs from the camera IOC that we will need
        prefix = self.pv_prefixes['Camera']
        camera_prefix = prefix + 'cam1:'
        self.control_pvs['CamManufacturer'] = PV(camera_prefix +
                                                 'Manufacturer_RBV')
        self.control_pvs['CamModel'] = PV(camera_prefix + 'Model_RBV')
        self.control_pvs['CamAcquire'] = PV(camera_prefix + 'Acquire')
        self.control_pvs['CamAcquireBusy'] = PV(camera_prefix + 'AcquireBusy')
        self.control_pvs['CamImageMode'] = PV(camera_prefix + 'ImageMode')
        self.control_pvs['CamTriggerMode'] = PV(camera_prefix + 'TriggerMode')
        self.control_pvs['CamNumImages'] = PV(camera_prefix + 'NumImages')
        self.control_pvs['CamNumImagesCounter'] = PV(camera_prefix +
                                                     'NumImagesCounter_RBV')
        self.control_pvs['CamAcquireTime'] = PV(camera_prefix + 'AcquireTime')
        self.control_pvs['CamAcquireTimeRBV'] = PV(camera_prefix +
                                                   'AcquireTime_RBV')
        self.control_pvs['CamBinX'] = PV(camera_prefix + 'BinX')
        self.control_pvs['CamBinY'] = PV(camera_prefix + 'BinY')
        self.control_pvs['CamWaitForPlugins'] = PV(camera_prefix +
                                                   'WaitForPlugins')
        self.control_pvs['PortNameRBV'] = PV(camera_prefix + 'PortName_RBV')

        # If this is a Point Grey camera then assume we are running ADSpinnaker
        # and create some PVs specific to that driver
        manufacturer = self.control_pvs['CamManufacturer'].get(as_string=True)
        model = self.control_pvs['CamModel'].get(as_string=True)
        if (manufacturer.find('Point Grey') !=
                -1) or (manufacturer.find('FLIR') != -1):
            self.control_pvs['CamExposureMode'] = PV(camera_prefix +
                                                     'ExposureMode')
            self.control_pvs['CamTriggerOverlap'] = PV(camera_prefix +
                                                       'TriggerOverlap')
            self.control_pvs['CamPixelFormat'] = PV(camera_prefix +
                                                    'PixelFormat')
            self.control_pvs['CamArrayCallbacks'] = PV(camera_prefix +
                                                       'ArrayCallbacks')
            self.control_pvs['CamFrameRateEnable'] = PV(camera_prefix +
                                                        'FrameRateEnable')
            self.control_pvs['CamTriggerSource'] = PV(camera_prefix +
                                                      'TriggerSource')
            if model.find('Grasshopper3') != -1:
                self.control_pvs['CamVideoMode'] = PV(camera_prefix +
                                                      'GC_VideoMode_RBV')

        # Set some initial PV values
        self.control_pvs['CamWaitForPlugins'].put('Yes')
        self.control_pvs['StartScan'].put(0)

        prefix = self.pv_prefixes['FilePlugin']
        self.control_pvs['FPNDArrayPort'] = PV(prefix + 'NDArrayPort')
        self.control_pvs['FPFileWriteMode'] = PV(prefix + 'FileWriteMode')
        self.control_pvs['FPNumCapture'] = PV(prefix + 'NumCapture')
        self.control_pvs['FPNumCaptured'] = PV(prefix + 'NumCaptured_RBV')
        self.control_pvs['FPCapture'] = PV(prefix + 'Capture')
        self.control_pvs['FPCaptureRBV'] = PV(prefix + 'Capture_RBV')
        self.control_pvs['FPFilePath'] = PV(prefix + 'FilePath')
        self.control_pvs['FPFilePathRBV'] = PV(prefix + 'FilePath_RBV')
        self.control_pvs['FPFilePathExists'] = PV(prefix +
                                                  'FilePathExists_RBV')
        self.control_pvs['FPFileName'] = PV(prefix + 'FileName')
        self.control_pvs['FPFileNameRBV'] = PV(prefix + 'FileName_RBV')
        self.control_pvs['FPFileNumber'] = PV(prefix + 'FileNumber')
        self.control_pvs['FPAutoIncrement'] = PV(prefix + 'AutoIncrement')
        self.control_pvs['FPFileTemplate'] = PV(prefix + 'FileTemplate')
        self.control_pvs['FPFullFileName'] = PV(prefix + 'FullFileName_RBV')
        self.control_pvs['FPAutoSave'] = PV(prefix + 'AutoSave')
        self.control_pvs['FPEnableCallbacks'] = PV(prefix + 'EnableCallbacks')

        # Set some initial PV values
        file_path = self.config_pvs['FilePath'].get(as_string=True)
        self.control_pvs['FPFilePath'].put(file_path)
        file_name = self.config_pvs['FileName'].get(as_string=True)
        self.control_pvs['FPFileName'].put(file_name)
        self.control_pvs['FPAutoSave'].put('No')
        self.control_pvs['FPFileWriteMode'].put('Stream')
        self.control_pvs['FPEnableCallbacks'].put('Enable')

        #Define PVs from the MCS or PSO that live on another IOC
        if 'MCS' in self.pv_prefixes:
            prefix = self.pv_prefixes['MCS']
            self.control_pvs['MCSEraseStart'] = PV(prefix + 'EraseStart')
            self.control_pvs['MCSStopAll'] = PV(prefix + 'StopAll')
            self.control_pvs['MCSPrescale'] = PV(prefix + 'Prescale')
            self.control_pvs['MCSDwell'] = PV(prefix + 'Dwell')
            self.control_pvs['MCSLNEOutputWidth'] = PV(prefix +
                                                       'LNEOutputWidth')
            self.control_pvs['MCSChannelAdvance'] = PV(prefix +
                                                       'ChannelAdvance')
            self.control_pvs['MCSMaxChannels'] = PV(prefix + 'MaxChannels')
            self.control_pvs['MCSNuseAll'] = PV(prefix + 'NuseAll')

        if 'PSO' in self.pv_prefixes:
            prefix = self.pv_prefixes['PSO']
            self.control_pvs['PSOscanDelta'] = PV(prefix + 'scanDelta')
            self.control_pvs['PSOstartPos'] = PV(prefix + 'startPos')
            self.control_pvs['PSOendPos'] = PV(prefix + 'endPos')
            self.control_pvs['PSOslewSpeed'] = PV(prefix + 'slewSpeed')
            self.control_pvs['PSOtaxi'] = PV(prefix + 'taxi')
            self.control_pvs['PSOfly'] = PV(prefix + 'fly')
            self.control_pvs['PSOscanControl'] = PV(prefix + 'scanControl')
            self.control_pvs['PSOcalcProjections'] = PV(prefix + 'numTriggers')
            self.control_pvs['ThetaArray'] = PV(prefix + 'motorPos.AVAL')

        if 'PvaPlugin' in self.pv_prefixes:
            prefix = self.pv_prefixes['PvaPlugin']
            self.control_pvs['PVANDArrayPort'] = PV(prefix + 'NDArrayPort')
            self.control_pvs['PVAEnableCallbacks'] = PV(prefix +
                                                        'EnableCallbacks')

        if 'RoiPlugin' in self.pv_prefixes:
            prefix = self.pv_prefixes['RoiPlugin']
            self.control_pvs['ROINDArrayPort'] = PV(prefix + 'NDArrayPort')
            self.control_pvs['ROIScale'] = PV(prefix + 'Scale')
            self.control_pvs['ROIBinX'] = PV(prefix + 'BinX')
            self.control_pvs['ROIBinY'] = PV(prefix + 'BinY')
            self.control_pvs['ROIEnableCallbacks'] = PV(prefix +
                                                        'EnableCallbacks')

        if 'CbPlugin' in self.pv_prefixes:
            prefix = self.pv_prefixes['CbPlugin']
            self.control_pvs['CBPortNameRBV'] = PV(prefix + 'PortName_RBV')
            self.control_pvs['CBNDArrayPort'] = PV(prefix + 'NDArrayPort')
            self.control_pvs['CBPreCount'] = PV(prefix + 'PreCount')
            self.control_pvs['CBPostCount'] = PV(prefix + 'PostCount')
            self.control_pvs['CBCapture'] = PV(prefix + 'Capture')
            self.control_pvs['CBCaptureRBV'] = PV(prefix + 'Capture_RBV')
            self.control_pvs['CBTrigger'] = PV(prefix + 'Trigger')
            self.control_pvs['CBTriggerRBV'] = PV(prefix + 'Trigger_RBV')
            self.control_pvs['CBCurrentQtyRBV'] = PV(prefix + 'CurrentQty_RBV')
            self.control_pvs['CBEnableCallbacks'] = PV(prefix +
                                                       'EnableCallbacks')
            self.control_pvs['CBStatusMessage'] = PV(prefix + 'StatusMessage')

        self.epics_pvs = {**self.config_pvs, **self.control_pvs}
        # Wait 1 second for all PVs to connect
        time.sleep(1)
        self.check_pvs_connected()
        # Setting the pva servers to broadcast dark and flat fields
        if 'PvaStream' in self.pv_prefixes:
            prefix = self.pv_prefixes['PvaStream']
            self.pva_stream_dark = pvaccess.PvObject({
                'value': [pvaccess.pvaccess.ScalarType.FLOAT],
                'sizex':
                pvaccess.pvaccess.ScalarType.INT,
                'sizey':
                pvaccess.pvaccess.ScalarType.INT
            })
            self.pva_server_dark = pvaccess.PvaServer(prefix + 'dark',
                                                      self.pva_stream_dark)

            self.pva_stream_flat = pvaccess.PvObject({
                'value': [pvaccess.pvaccess.ScalarType.FLOAT],
                'sizex':
                pvaccess.pvaccess.ScalarType.INT,
                'sizey':
                pvaccess.pvaccess.ScalarType.INT
            })
            self.pva_server_flat = pvaccess.PvaServer(prefix + 'flat',
                                                      self.pva_stream_flat)

        # Configure callbacks on a few PVs
        for epics_pv in ('MoveSampleIn', 'MoveSampleOut', 'StartScan',
                         'AbortScan', 'ExposureTime', 'FilePath',
                         'FPFilePathExists'):
            self.epics_pvs[epics_pv].add_callback(self.pv_callback)

        # Synchronize the FilePathExists PV
        self.copy_file_path_exists()

        # Set ^C interrupt to abort the scan
        signal.signal(signal.SIGINT, self.signal_handler)

        # Start the watchdog timer thread
        thread = threading.Thread(target=self.reset_watchdog,
                                  args=(),
                                  daemon=True)
        thread.start()
Exemple #9
0
 def create_pva_server(self):
     #self.log_debug("Creating PVA server object")
     self._server = pvaccess.PvaServer()
Exemple #10
0
import pvaccess as pva

ARRAY_SIZE = 10 * 1024
N_FLAT_ARRAYS = 100
dataStruct = {
    'ArrayId': pva.UINT,
    'Time': [pva.DOUBLE],
    'Sinusoid': [pva.FLOAT],
    'Triangle': [pva.FLOAT],
}
for i in range(0, N_FLAT_ARRAYS):
    arrayName = 'Flat%03d' % (i + 1)
    dataStruct[arrayName] = [pva.FLOAT]

srv = pva.PvaServer('server1_data', pva.PvObject(dataStruct))
t0 = 0.0
n = 0
dt = 1. / 1000
startTime = unixTime.time()
# Time is double (8 bytes), other arrays are floats (4 bytes each)
dataSize = ARRAY_SIZE * (8 + N_FLAT_ARRAYS * 4)
dataSizeMB = dataSize / (1024 * 1024)

while True:
    time = [t0 + dt * i for i in range(0, ARRAY_SIZE)]
    # Disable sinusoid/triangle for performance measurements
    #sinusoid = [sin(2*pi*1.1*t + pi/2) for t in time]
    sinusoid = []
    #triangle = [(2/pi)*asin(sin(2*pi*1.1*t)) for t in time]
    triangle = []
Exemple #11
0
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)
Exemple #12
0
#!/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 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)