Пример #1
0
    def test_waveform_callback_with_count_arg(self):
        values = []

        # NOTE: do not use get_pv() here, as `count` is incompatible with
        # the cache
        wf = PV(pvnames.char_arr_pv, count=32)

        def onChanges(pvname=None, value=None, char_value=None, **kw):
            write('PV %s %s, %s Changed!\n' %
                  (pvname, repr(value), char_value))
            values.append(value)

        wf.add_callback(onChanges)
        write('Added a callback.  Now wait for changes...\n')

        t0 = time.time()
        while time.time() - t0 < 3:
            time.sleep(1.e-4)
            if len(values) > 0:
                break

        self.failUnless(len(values) > 0)
        self.assertEquals(len(values[0]), 32)

        wf.clear_callbacks()
Пример #2
0
def start_processes(counter_pv, data_pv, logger, *args):
    """
    This is a main thread that starts thread reacting to the callback, starts the consuming process, and sets a
    callback on the frame counter PV change. The function then awaits for the data in the exit queue that indicates
    that all frames have been processed. The functin cancells the callback on exit.

    Parameters
    ----------
    counter_pv : str
        a PV string for the area detector frame counter

    data_pv : str
        a PV string for the area detector frame data

    logger : Logger
        a Logger instance, typically synchronized with the consuming process logger

    *args : list
        a list of arguments specific to the client process

    Returns
    -------
    None
    """
    data_thread = CAThread(target = deliver_data, args=(data_pv, logger,))
    data_thread.start()

    start_process(globals.process_dataq, logger, *args)
    cntr = PV(counter_pv)
    cntr.add_callback(on_change, index = 1)

    globals.exitq.get()
    cntr.clear_callbacks()
Пример #3
0
def run_test_sofb():
    """Test SOFB IOC frequency."""
    def print_time(pvname, value, **kwargs):
        _ = pvname
        nonlocal times, values
        # times.append(time.time())
        times.append(kwargs['timestamp'])
        values.append(value[0])
        print(datetime.datetime.fromtimestamp(times[-1]).isoformat(), value[0])

    times = []
    values = []

    pv = PV('SI-Glob:AP-SOFB:SlowOrbX-Mon')
    pv.wait_for_connection()
    pv.add_callback(print_time)

    total = 30
    time.sleep(total)

    # times = values
    print(f'frequency:    {len(times)/total:.2f} Hz')
    print(f'average time: {np.mean(np.diff(times))*1000:.2f} ms')
    print(f'std time:     {np.std(np.diff(times))*1000:.2f} ms')
    print(f'min time:     {np.min(np.diff(times))*1000:.2f} ms')
    print(f'max time:     {np.max(np.diff(times))*1000:.2f} ms')
    np.savetxt('si_sofb.txt', times)
    pv.clear_callbacks()
Пример #4
0
class PVIntegrator:
    """PVIntegrator"""
    def __init__(self,pv = "IBC1H04CRCUR2",name=None,outpv=None):
        self.output_name = outpv
        if self.output_name != None :
            self.output_pv = PV(self.output_name)
        #else :
        #    self.output_pv  = None
        self.total = 0.0
        self.name = name
        self.total_time = 0.000000001
        if name is None:
            self.name = pv
        self.pv_name = pv
        self.process_var =  PV(self.pv_name)

    def Reset(self):
        self.total = 0.0
        self.total_time = 0.000000001


    def PVChangeCallback(self,pvname=None, value=None, char_value=None, **kws):
        value = float(char_value)
        self.total = self.total + 2.0*value # 2.0 s readout 
        self.total_time = self.total_time + 2.0

    def AddCallback(self):
        self.process_var.add_callback(self.PVChangeCallback)

    def ClearCallback(self):
        self.process_var.clear_callbacks()

    def Dump(self):
        print str("{:^10}   total charge     = {} mC").format(self.pv_name, self.total*0.001)
        print str("{:^10}   average current  = {} uA").format("", self.total/self.total_time)

    def Print(self):
        self.ClearCallback()
        print str("{:^10}   total charge     = {} mC").format(self.pv_name, self.total*0.001)
        print str("{:^10}   average current  = {} uA").format("", self.total/self.total_time)

    def GetJSONObject(self):
        self.ClearCallback()
        trip_dict = {'total': float(self.total)}
        trip_dict.update({'PV': self.pv_name})
        return {self.name: trip_dict }

    def PrintJSON(self):
        print "writing json"
    def run(self, data, store, signal, context, **kwargs):
        """ The main run method of the PvTriggerTask task.

        Args:
            data (MultiTaskData): The data object that has been passed from the
                                  predecessor task.
            store (DataStoreDocument): The persistent data store object that allows the
                                       task to store data for access across the current
                                       workflow run.
            signal (TaskSignal): The signal object for tasks. It wraps the construction
                                 and sending of signals into easy to use methods.
            context (TaskContext): The context in which the tasks runs.
        """
        params = self.params.eval(data, store)

        skipped_initial = False if params.skip_initial_callback else True
        polling_event_number = 0
        queue = deque()

        # set up the internal callback
        pv = PV(params.pv_name,
                callback=partial(self._pv_callback, queue=queue))

        while True:
            if params.event_trigger_time is not None:
                time.sleep(params.event_trigger_time)

            # check every stop_polling_rate events the stop signal
            polling_event_number += 1
            if polling_event_number > params.stop_polling_rate:
                polling_event_number = 0
                if signal.is_stopped:
                    break

            # get all the events from the queue and call the callback function
            while len(queue) > 0:
                event = queue.pop()
                if skipped_initial:
                    if self._callback is not None:
                        self._callback(data, store, signal, context, **event)
                else:
                    skipped_initial = True

        pv.clear_callbacks()
        return Action(data)
Пример #6
0
    def test_get_callback(self):
        write("Callback test:  changing PV must be updated\n")
        global NEWVALS
        mypv = PV(pvnames.updating_pv1)
        NEWVALS = []
        def onChanges(pvname=None, value=None, char_value=None, **kw):
            write( 'PV %s %s, %s Changed!\n' % (pvname, repr(value), char_value))
            NEWVALS.append( repr(value))

        mypv.add_callback(onChanges)
        write('Added a callback.  Now wait for changes...\n')

        t0 = time.time()
        while time.time() - t0 < 3:
            time.sleep(1.e-4)
        write('   saw %i changes.\n' % len(NEWVALS))
        self.failUnless(len(NEWVALS) > 3)
        mypv.clear_callbacks()
Пример #7
0
class PVTracker:
    def __init__(self, pvname = "hcCOINRunAccumulatedCharge",name=None):
        self.pv_name = pvname
        self.name = name
        self.process_var = PV(pvname)
        self.value = self.process_var.get()

    def PVChangeCallback(self,pvname=None, value=None, char_value=None, **kws):
        self.value = value

    def AddCallback(self):
        self.process_var.add_callback(self.PVChangeCallback)

    def ClearCallback(self):
        self.process_var.clear_callbacks()

    def Dump(self):
        print str("{}   value  =  {} ").format(self.name, self.value)
Пример #8
0
    def test_get_callback(self):
        write("Callback test:  changing PV must be updated\n")
        global NEWVALS
        mypv = PV(pvnames.updating_pv1)
        NEWVALS = []
        def onChanges(pvname=None, value=None, char_value=None, **kw):
            write( 'PV %s %s, %s Changed!\n' % (pvname, repr(value), char_value))
            NEWVALS.append( repr(value))

        mypv.add_callback(onChanges)
        write('Added a callback.  Now wait for changes...\n')

        t0 = time.time()
        while time.time() - t0 < 3:
            time.sleep(1.e-4)
        write('   saw %i changes.\n' % len(NEWVALS))
        self.failUnless(len(NEWVALS) > 3)
        mypv.clear_callbacks()
Пример #9
0
    def test_waveform_callback_with_count_arg(self):
        values = []

        wf = PV(pvnames.char_arr_pv, count=32)
        def onChanges(pvname=None, value=None, char_value=None, **kw):
            write( 'PV %s %s, %s Changed!\n' % (pvname, repr(value), char_value))
            values.append( value)

        wf.add_callback(onChanges)
        write('Added a callback.  Now wait for changes...\n')

        t0 = time.time()
        while time.time() - t0 < 3:
            time.sleep(1.e-4)
            if len(values)>0:
                break

        self.failUnless(len(values) > 0)
        self.assertEquals(len(values[0]),32)

        wf.clear_callbacks()
Пример #10
0
def main(argv=None):
    global dbd
    global simulate
    global fp
    global shut_open
    global current
    global T_stop
    dSi111 = SRXenergy.d111
    dbragg = SRXenergy.dBragg

    #parse command line options
    usage = "usage: %prog [options]\nData files are written to /data/<year>/<month>/<day>/"
    parser = OptionParser(usage)
    parser.add_option("--wait",
                      action="store",
                      type="float",
                      dest="stall",
                      help="wait at each step [seconds]")
    parser.add_option("--config",
                      action="store",
                      type="string",
                      dest="fname",
                      help="name of config file")
    parser.add_option("--simulate",
                      action="store_true",
                      dest="sim",
                      default=False,
                      help="simulate motor moves and bursting")
    parser.add_option("--checkbeam",
                      action="store_true",
                      dest="checkbeam",
                      default=False,
                      help="only acquire when beam is on")
    parser.add_option("--acqtime",
                      action="store",
                      type="float",
                      dest="acqt",
                      help="image integration time [sec]")
    parser.add_option("--acqnum",
                      action="store",
                      type="int",
                      dest="acqn",
                      help="images to collect")

    (options, args) = parser.parse_args()

    #open log file
    D0 = time.localtime()[0]
    D1 = time.localtime()[1]
    D2 = time.localtime()[2]
    D3 = time.localtime()[3]
    D4 = time.localtime()[4]
    cd = os.getcwd()
    fstr = '/nfs/xf05id1/data/'
    if sys.argv[0][0] == '.':
        out_filename=fstr+repr(D0)+'/'+repr(D1)+'/'+repr(D2)+'/'+'log_'+repr(D0)+'_'+repr(D1)+'_'+repr(D2)+'_'+repr(D3)+'_'+repr(D4)+'_'+\
         string.split(string.strip(sys.argv[0],'./'),'/')[0]+'.txt'
    else:
        out_filename=fstr+repr(D0)+'/'+repr(D1)+'/'+repr(D2)+'/'+'log_'+repr(D0)+'_'+repr(D1)+'_'+repr(D2)+'_'+repr(D3)+'_'+repr(D4)+'_'+\
         string.split(string.strip(sys.argv[0],'./'),'/')[5]+'.txt'
    try:
        os.chdir(fstr + repr(D0))
    except OSError:
        try:
            os.mkdir(fstr + repr(D0))
        except Exception:
            print 'cannot create directory: ' + fstr + repr(D0)
            sys.exit()

    try:
        os.chdir(fstr + repr(D0) + '/' + repr(D1))
    except OSError:
        try:
            os.mkdir(fstr + repr(D0) + '/' + repr(D1))
        except Exception:
            print 'cannot create directory: ' + fstr + repr(D0) + '/' + repr(
                D1)
            sys.exit()
    try:
        os.chdir(fstr + repr(D0) + '/' + repr(D1) + '/' + repr(D2))
    except OSError:
        try:
            os.mkdir(fstr + repr(D0) + '/' + repr(D1) + '/' + repr(D2))
        except Exception:
            print 'cannot create directory: ' + fstr + repr(D0) + '/' + repr(
                D1) + '/' + repr(D2)
            sys.exit()
    try:
        fp = open(out_filename, 'a')
    except Exception:
        print 'cannot open file: ' + out_filename
        sys.exit()
    try:
        os.chdir(fstr + repr(D0) + '/' + repr(D1) + '/' + repr(D2) + '/' +
                 'HDF5')
    except OSError:
        try:
            os.mkdir(fstr + repr(D0) + '/' + repr(D1) + '/' + repr(D2) + '/' +
                     'HDF5')
        except Exception:
            print 'cannot create directory: ' + fstr + repr(D0) + '/' + repr(
                D1) + '/' + repr(D2) + '/' + 'HDF5'
            sys.exit()
#    H5path=fstr+repr(D0)+'/'+repr(D1)+'/'+repr(D2)+'/HDF5'
    H5path = '/epics/data/2015-3/300226-2'
    #    H5path='/epics/data/2015-3/in-house'

    os.chdir(cd)
    fp.write('#')
    fp.write(', '.join(sys.argv))
    fp.write('\n')
    #open list of scan points
    try:
        fconfig = open(options.fname)
    except Exception:
        print "cannot open file containing scan points.  Error opening: " + options.fname
        sys.exit()

    fstr = '#a default string'
    pN = 0
    angle = list()
    ivu = list()
    t2gap = list()
    while fstr.rsplit().__len__() > 0:
        if (fstr[0] is not '#'):
            pN = pN + 1
            angle.append(fstr.rsplit()[0])
            ivu.append(fstr.rsplit()[1])
            t2gap.append(fstr.rsplit()[2])
        fstr = fconfig.readline()
    fconfig.close()

    #initialize PVs and callbacks
    detstr = 'XF:05IDA{IM:1}'
    bmot = PV('XF:05IDA-OP:1{Mono:HDCM-Ax:P}Mtr.VAL', connection_timeout=4)
    bmot_cur = PV('XF:05IDA-OP:1{Mono:HDCM-Ax:P}Mtr.RBV', connection_timeout=4)
    bmot_stop = PV('XF:05IDA-OP:1{Mono:HDCM-Ax:P}Mtr.STOP',
                   connection_timeout=4)
    umot = PV('SR:C5-ID:G1{IVU21:1-Mtr:2}Inp:Pos', connection_timeout=4)
    umot_cur = PV('SR:C5-ID:G1{IVU21:1-LEnc}Gap', connection_timeout=4)
    umot_go = PV('SR:C5-ID:G1{IVU21:1-Mtr:2}Sw:Go', connection_timeout=4)
    gmot = PV('XF:05IDA-OP:1{Mono:HDCM-Ax:X2}Mtr.VAL', connection_timeout=4)
    gmot_cur = PV('XF:05IDA-OP:1{Mono:HDCM-Ax:X2}Mtr.RBV',
                  connection_timeout=4)
    gmot_stop = PV('XF:05IDA-OP:1{Mono:HDCM-Ax:X2}Mtr.STOP',
                   connection_timeout=4)
    shut_status = PV('SR:C05-EPS{PLC:1}Shutter:Sum-Sts', connection_timeout=4)
    beam_current = PV('SR:C03-BI{DCCT:1}I:Total-I', connection_timeout=4)
    bragg_temp = PV('XF:05IDA-OP:1{Mono:HDCM-Ax:P}T-I', connection_timeout=4)
    norm0 = PV('XF:05IDD-BI:1{BPM:01}.S20', connection_timeout=4)
    norm1 = PV('XF:05IDD-BI:1{BPM:01}.S21', connection_timeout=4)
    norm2 = PV('XF:05IDD-BI:1{BPM:01}.S22', connection_timeout=4)
    norm3 = PV('XF:05IDD-BI:1{BPM:01}.S23', connection_timeout=4)

    wb = srxslit.nsls2slit(tb='XF:05IDA-OP:1{Slt:1-Ax:T}',
                           bb='XF:05IDA-OP:1{Slt:1-Ax:B}',
                           ib='XF:05IDA-OP:1{Slt:1-Ax:I}',
                           ob='XF:05IDA-OP:1{Slt:1-Ax:O}')
    pb = srxslit.nsls2slit(ib='XF:05IDA-OP:1{Slt:2-Ax:I}',
                           ob='XF:05IDA-OP:1{Slt:2-Ax:O}')
    ssa = srxslit.nsls2slit(tb='XF:05IDB-OP:1{Slt:SSA-Ax:T}',
                            bb='XF:05IDB-OP:1{Slt:SSA-Ax:B}',
                            ob='XF:05IDB-OP:1{Slt:SSA-Ax:O}',
                            ib='XF:05IDB-OP:1{Slt:SSA-Ax:I}')
    x3acq = PV('XSPRESS3-EXAMPLE:Acquire', connection_timeout=4)
    x3erase = PV('XSPRESS3-EXAMPLE:ERASE', connection_timeout=4)
    x3acqtime = PV('XSPRESS3-EXAMPLE:AcquireTime', connection_timeout=4)
    x3acqnum = PV('XSPRESS3-EXAMPLE:NumImages', connection_timeout=4)
    x3tmode = PV('XSPRESS3-EXAMPLE:TriggerMode', connection_timeout=4)
    x3h5path = PV('XSPRESS3-EXAMPLE:HDF5:FilePath', connection_timeout=4)
    x3h5fname = PV('XSPRESS3-EXAMPLE:HDF5:FileName', connection_timeout=4)
    x3h5fnum = PV('XSPRESS3-EXAMPLE:HDF5:FileNumber', connection_timeout=4)
    x3h5vdim = PV('XSPRESS3-EXAMPLE:HDF5:NumExtraDims', connection_timeout=4)
    x3h5size = PV('XSPRESS3-EXAMPLE:HDF5:ExtraDimSizeN', connection_timeout=4)
    x3h5d1 = PV('XSPRESS3-EXAMPLE:HDF5:ExtraDimSizeX', connection_timeout=4)
    x3h5d2 = PV('XSPRESS3-EXAMPLE:HDF5:ExtraDimSizeY', connection_timeout=4)
    x3h5writerbv = PV('XSPRESS3-EXAMPLE:HDF5:WriteFile_RBV',
                      connection_timeout=2)
    #report ROIs for channels and counts at each point
    x3ch1roi0min = PV('XSPRESS3-EXAMPLE:C1_MCA_ROI1_LLM', connection_timeout=4)
    x3ch1roi0max = PV('XSPRESS3-EXAMPLE:C1_MCA_ROI1_HLM', connection_timeout=4)
    x3ch1roi0ct = PV('XSPRESS3-EXAMPLE:C1_ROI1:Value_RBV',
                     connection_timeout=4)
    x3ch1roi1min = PV('XSPRESS3-EXAMPLE:C1_MCA_ROI2_LLM', connection_timeout=4)
    x3ch1roi1max = PV('XSPRESS3-EXAMPLE:C1_MCA_ROI2_HLM', connection_timeout=4)
    x3ch1roi1ct = PV('XSPRESS3-EXAMPLE:C1_ROI2:Value_RBV',
                     connection_timeout=4)
    x3ch1roi2min = PV('XSPRESS3-EXAMPLE:C1_MCA_ROI3_LLM', connection_timeout=4)
    x3ch1roi2max = PV('XSPRESS3-EXAMPLE:C1_MCA_ROI3_HLM', connection_timeout=4)
    x3ch1roi2ct = PV('XSPRESS3-EXAMPLE:C1_ROI3:Value_RBV',
                     connection_timeout=4)
    x3ch2roi0min = PV('XSPRESS3-EXAMPLE:C2_MCA_ROI1_LLM', connection_timeout=4)
    x3ch2roi0max = PV('XSPRESS3-EXAMPLE:C2_MCA_ROI1_HLM', connection_timeout=4)
    x3ch2roi0ct = PV('XSPRESS3-EXAMPLE:C2_ROI1:Value_RBV',
                     connection_timeout=4)
    x3ch2roi1min = PV('XSPRESS3-EXAMPLE:C2_MCA_ROI2_LLM', connection_timeout=4)
    x3ch2roi1max = PV('XSPRESS3-EXAMPLE:C2_MCA_ROI2_HLM', connection_timeout=4)
    x3ch2roi1ct = PV('XSPRESS3-EXAMPLE:C2_ROI2:Value_RBV',
                     connection_timeout=4)
    x3ch2roi2min = PV('XSPRESS3-EXAMPLE:C2_MCA_ROI3_LLM', connection_timeout=4)
    x3ch2roi2max = PV('XSPRESS3-EXAMPLE:C2_MCA_ROI3_HLM', connection_timeout=4)
    x3ch2roi2ct = PV('XSPRESS3-EXAMPLE:C2_ROI3:Value_RBV',
                     connection_timeout=4)
    x3ch3roi0min = PV('XSPRESS3-EXAMPLE:C3_MCA_ROI1_LLM', connection_timeout=4)
    x3ch3roi0max = PV('XSPRESS3-EXAMPLE:C3_MCA_ROI1_HLM', connection_timeout=4)
    x3ch3roi0ct = PV('XSPRESS3-EXAMPLE:C3_ROI1:Value_RBV',
                     connection_timeout=4)
    x3ch3roi1min = PV('XSPRESS3-EXAMPLE:C3_MCA_ROI2_LLM', connection_timeout=4)
    x3ch3roi1max = PV('XSPRESS3-EXAMPLE:C3_MCA_ROI2_HLM', connection_timeout=4)
    x3ch3roi1ct = PV('XSPRESS3-EXAMPLE:C3_ROI2:Value_RBV',
                     connection_timeout=4)
    x3ch3roi2min = PV('XSPRESS3-EXAMPLE:C3_MCA_ROI3_LLM', connection_timeout=4)
    x3ch3roi2max = PV('XSPRESS3-EXAMPLE:C3_MCA_ROI3_HLM', connection_timeout=4)
    x3ch3roi2ct = PV('XSPRESS3-EXAMPLE:C3_ROI3:Value_RBV',
                     connection_timeout=4)
    #claim ROI 4 for our own use.  we will integrate over all 4096 channels.
    x3ch1roi3min = PV('XSPRESS3-EXAMPLE:C1_MCA_ROI4_LLM', connection_timeout=4)
    x3ch1roi3max = PV('XSPRESS3-EXAMPLE:C1_MCA_ROI4_HLM', connection_timeout=4)
    x3ch1roi3ct = PV('XSPRESS3-EXAMPLE:C1_ROI4:Value_RBV',
                     connection_timeout=4)
    x3ch2roi3min = PV('XSPRESS3-EXAMPLE:C2_MCA_ROI4_LLM', connection_timeout=4)
    x3ch2roi3max = PV('XSPRESS3-EXAMPLE:C2_MCA_ROI4_HLM', connection_timeout=4)
    x3ch2roi3ct = PV('XSPRESS3-EXAMPLE:C2_ROI4:Value_RBV',
                     connection_timeout=4)
    x3ch3roi3min = PV('XSPRESS3-EXAMPLE:C3_MCA_ROI4_LLM', connection_timeout=4)
    x3ch3roi3max = PV('XSPRESS3-EXAMPLE:C3_MCA_ROI4_HLM', connection_timeout=4)
    x3ch3roi3ct = PV('XSPRESS3-EXAMPLE:C3_ROI4:Value_RBV',
                     connection_timeout=4)

    dett = PV('XF:05IDD-ES:1{EVR:1-Out:FP3}Src:Scale-SP', connection_timeout=4)
    deti = PV('XF:05IDA{IM:1}Per-SP', connection_timeout=4)
    detinit = PV('XF:05IDA{IM:1}Cmd:Init', connection_timeout=4)
    det0 = PV(detstr + 'Cur:I0-I', connection_timeout=4)
    det1 = PV(detstr + 'Cur:I1-I', connection_timeout=4)
    det2 = PV(detstr + 'Cur:I2-I', connection_timeout=4)
    det3 = PV(detstr + 'Cur:I3-I', connection_timeout=4)

    bmot.info
    bmot_cur.info
    bmot_stop.info
    umot.info
    umot_cur.info
    umot_go.info
    gmot.info
    gmot_cur.info
    gmot_stop.info
    det0.info
    det1.info
    det2.info
    det3.info
    bragg_temp.info

    bmot_cur.add_callback(cbfx)
    bmot_cur.run_callbacks()
    umot_cur.add_callback(cbfy)
    umot_cur.run_callbacks()
    gmot_cur.add_callback(cbfz)
    gmot_cur.run_callbacks()
    shut_status.add_callback(cbf_shut)
    beam_current.add_callback(cbf_curr)
    shut_status.run_callbacks()
    beam_current.run_callbacks()
    bragg_temp.add_callback(cbf_temp)
    bragg_temp.run_callbacks()
    x3h5path.put(H5path)
    x3h5fname.put(
        repr(D0) + '_' + repr(D1) + '_' + repr(D2) + '_' + repr(D3) + '_' +
        repr(D4) + '_')
    x3h5fnum.put(0)
    x3acqtime.put(options.acqt)
    x3acqnum.put(options.acqn)
    x3tmode.put(1)
    x3ch1roi3min.put(0)
    x3ch2roi3min.put(0)
    x3ch3roi3min.put(0)
    x3ch1roi3max.put(4096)
    x3ch2roi3max.put(4096)
    x3ch3roi3max.put(4096)
    #h5 set up
    x3h5vdim.put(1)
    x3h5size.put(options.acqn)
    x3h5d1.put(pN)
    x3h5d2.put(0)
    roits = x3ch3roi3ct.timestamp
    dett.put(3)
    #overhead on triggering F460
    deti.put(float(options.acqn) * options.acqt * .9)
    detinit.put(1)

    #check command line options
    if options.stall == None:
        twait = 0.
    else:
        twait = options.stall

    str = '#NSLS-II SRX' + time.asctime()
    fp.write(str)
    fp.write('\n')

    str = '# Start time is ' + time.asctime()
    print str
    fp.write(str)
    fp.write('\n')
    if options.sim is True:
        str = "      -----simulating motor moves and bursts-----"
        print str
        fp.write(str)
        fp.write('\n')
    else:
        x3h5capture.put(1)
        dett.put(4)
        while x3h5capture.get() == 0:
            time.sleep(0.5)
        time.sleep(2)
        while x3h5writerbv.get() == 0:
            x3h5capture.put(0)
            print "File write is not confirmed.  Waiting for confirmation..."
            time.sleep(30)
            x3h5capture.put(1)
            time.sleep(2)
        dett.put(3)

    str='# bragg: %(br)6.4f ; undulator: %(un)6.4f ; gap: %(cg)f ; ROI1 %(roi1i)d:%(roi1a)d ; ROI2 %(roi2i)d:%(roi2a)d ; ROI3 %(roi3i)d:%(roi3a)d'%\
     {"br":bmot_cur.get(),"un":umot_cur.get(), "cg":gmot_cur.get(),'roi1i':x3ch1roi0min.get(), 'roi1a':x3ch1roi0max.get(), 'roi2i':x3ch1roi1min.get(), 'roi2a':x3ch1roi1max.get(), 'roi3i':x3ch1roi2min.get(), 'roi3a':x3ch1roi2max.get()}
    print str
    fp.write(str)
    fp.write('\n')
    str = "# --------------------"
    print str
    fp.write(str)
    fp.write('\n')
    str = "# bragg u-gap c-gap energy I0-1 I0-2 I0-3 I0-4 time ROI-1 ROI-2 ROI-3 ROI-4 intensity"
    print str
    fp.write(str)
    fp.write('\n')
    LN = 0
    oldsig = det0.get()
    t0 = time.time()
    sig0 = 0.
    sig1 = 0.
    sig2 = 0.
    sig3 = 0.
    nsig0 = 0.
    nsig1 = 0.
    nsig2 = 0.
    nsig3 = 0.
    for x in range(0, pN):
        tar[0][1] = 1
        tar[0][0] = float(angle[x])
        tar[1][1] = 1
        tar[1][0] = float(ivu[x])
        tar[2][1] = 1
        tar[2][0] = float(t2gap[x])
        #if tar[0][0] is the original position, raise "in position" flag
        if indeadband(float(tar[0][0]), float(bmot_cur.get()), dbd) == 1:
            tar[0][1] = 0
        if indeadband(float(tar[1][0]), float(umot_cur.get()), dbd) == 1:
            tar[1][1] = 0
        if indeadband(float(tar[2][0]), float(gmot_cur.get()), dbd) == 1:
            tar[2][1] = 0
        if options.sim is False:
            bmot.put(tar[0][0])
            umot.put(tar[1][0])
            gmot.put(tar[2][0])
            time.sleep(1)
            umot_go.put(0)
        else:
            tar[0][1] = 0
            tar[1][1] = 0
            tar[2][1] = 0
        while (tar[0][1] == 1) or (tar[1][1] == 1) or (tar[2][1] == 1):
            time.sleep(0.05)
            if LN > 400:
                umot_go.put(0)
                LN = 0
            else:
                LN = LN + 1
        if options.sim is False:
            time.sleep(twait)
            while (options.checkbeam and
                   (shut_open == False
                    or beam_current == False)) or T_stop == True:
                print "Stopped.  Waiting for scan conditions to return to normal."
                if shut_open == False:
                    print "\t->shutter is closed"
                elif beam_current == False:
                    print "\t->Ring current is below threshold"
                elif T_stop == True:
                    print "\t->HDCM pitch motor is too hot"
                else:
                    print "\t->why not have a nice cup of tea or hit ctrl-C?"
                time.sleep(60.)
            x3erase.put(1)
            dett.put(4)
            nsig0 = norm0.get()
            nsig1 = norm1.get()
            nsig2 = norm2.get()
            nsig3 = norm3.get()
            #??
            #           sig0=sig1=sig2=sig3=3
            sig0 = sig1 = sig2 = sig3 = 0
            for i in range(0, options.acqn):
                x3acq.put(1)
                while (x3ch3roi3ct.get() == 0.0
                       or x3ch3roi3ct.timestamp == roits):
                    time.sleep(0.02)
                sig0 = sig0 + x3ch1roi0ct.get() + x3ch2roi0ct.get(
                ) + x3ch3roi0ct.get()
                sig1 = sig1 + x3ch1roi1ct.get() + x3ch2roi1ct.get(
                ) + x3ch3roi1ct.get()
                sig2 = sig2 + x3ch1roi2ct.get() + x3ch2roi2ct.get(
                ) + x3ch3roi2ct.get()
                sig3 = sig3 + x3ch1roi3ct.get() + x3ch2roi3ct.get(
                ) + x3ch3roi3ct.get()
                #                sig0=sig0+x3ch2roi0ct.get()+x3ch3roi0ct.get()
                #                sig1=sig1+x3ch2roi1ct.get()+x3ch3roi1ct.get()
                #                sig2=sig2+x3ch2roi2ct.get()+x3ch3roi2ct.get()
                #                sig3=sig3+x3ch2roi3ct.get()+x3ch3roi3ct.get()
                roits = x3ch3roi3ct.timestamp
            signal0 = float(det1.get())
            while (signal0 == 0.0):
                signal0 = float(det1.get())


#            while(signal0 == oldsig):
#                signal0=det0.get()
#            oldsig=signal0
            dett.put(3)
        else:
            while (options.checkbeam
                   and (shut_open == False or beam_current == False)):
                print "Stopped.  Waiting for beam to return."
                time.sleep(60.)
            signal0 = 0.
            nsig1 = 0
            nsig2 = 0
            nsig3 = 0
        tn = time.time() - t0
        if options.sim is False:
            #            str=' %(B)8.4f %(U)8.4f %(G)8.3f %(E)8.2f %(C0)10.7e %(C1)10.7e %(C2)10.7e %(C3)10.7e %(T)d %(ROI1)d %(ROI2)d %(ROI3)d %(ROI4)d %(T1)10.7e'%{"B":float(bmot_cur.get()), "U":float(umot_cur.get()), "G":float(gmot_cur.get()), "C0":nsig0, "C1":nsig1, "C2":nsig2, "C3":nsig3, "ROI1":sig0,'T':tn,"ROI2":sig1,"ROI3":sig2,"ROI4":sig3,"T1":signal0,"E":12398.4 / (2 * 3.13029665951 * math.sin((bmot_cur.get()+0.323658778534)/180.*np.pi))}
            str = ' %(B)8.4f %(U)8.4f %(G)8.3f %(E)8.2f %(C0)10.7e %(C1)10.7e %(C2)10.7e %(C3)10.7e %(T)d %(ROI1)d %(ROI2)d %(ROI3)d %(ROI4)d %(T1)10.7e' % {
                "B":
                float(bmot_cur.get()),
                "U":
                float(umot_cur.get()),
                "G":
                float(gmot_cur.get()),
                "C0":
                nsig0,
                "C1":
                nsig1,
                "C2":
                nsig2,
                "C3":
                nsig3,
                "ROI1":
                sig0,
                'T':
                tn,
                "ROI2":
                sig1,
                "ROI3":
                sig2,
                "ROI4":
                sig3,
                "T1":
                signal0,
                "E":
                12398.4 / (2 * dSi111 * math.sin(
                    (bmot_cur.get() + dbragg) / 180. * np.pi))
            }

            print str
            fp.write(str)
            fp.write('\n')
        else:
            str = ' B= %(B)8.4f U= %(U)8.4f G= %(G)8.3f : %(C0)10.7e %(C1)10.7e %(C2)10.7e %(C3)10.7e %(ROI)d %(T)d' % {
                "B": tar[0][0],
                "U": tar[1][0],
                "G": tar[2][0],
                "C0": signal0,
                "C1": nsig1,
                "C2": nsig2,
                "C3": nsig3,
                "ROI": x3ch1roi0ct.get(),
                'T': time.time()
            }
            print str
            fp.write(str)
            fp.write('\n')

    str = '#End time is ' + time.asctime()
    print str
    fp.write(str)
    fp.write('\n')
    fp.close()

    bmot_cur.clear_callbacks()
    umot_cur.clear_callbacks()
    gmot_cur.clear_callbacks()
    shut_status.clear_callbacks()
    beam_current.clear_callbacks()
    bragg_temp.clear_callbacks()

    return 0
Пример #11
0
class _RunListener:
    '''Run listener for a single run type.

    Helper class for RunDaemon.
    '''
    def __init__(self, run_type):
        '''Initialize the listener for run_type.'''
        self.run_type = run_type.upper()
        self.name = 'listener for {} runs'.format(self.run_type)
        print('Creating ' + self.name)
        self.reset()
        #print('hc{}RunNumber'.format(self.run_type))
        self.pv_run_number = PV('hc{}RunNumber'.format(self.run_type))
        self.pv_is_running = PV('hc{}RunInProgress'.format(self.run_type))

    def reset(self):
        '''Reset/initialize the listener.'''
        self.tasks = {'run_start': [], 'run_stop': []}
        self.coda_running = False
        self.run_number = -1

    def on_event(self, event, callback):
        '''Append callback task to the listener.'''
        if event in self.tasks:
            self.tasks[event].append(callback)
        else:
            raise EventTypeError(event, [e for e in self.tasks])

    def interrupt(self):
        '''Interrupt the listener by issue a run_stop event if CODA is running.'''
        self.pv_is_running.clear_callbacks()
        if self.coda_running:
            self._run_stop()

    def listen(self):
        '''Start listening for events.'''
        self.pv_is_running.add_callback(self._listener)

    def _listener(self, pvname=None, value=None, char_value=None, **kwargs):
        '''Event listener, dispatches events.'''
        run_in_progress = int(char_value)
        self.run_number = self.pv_run_number.get()
        ## Bail and print warning if we could not get a valid run number
        if self.run_number is None:
            print('WARNING({}): Unable to load run number from EPICS'.format(
                self.name))
            print('WARNING({}): Skipping this callback...'.format(self.name))
            return
        self.run_number = int(self.run_number)
        if run_in_progress and not self.coda_running:
            self._run_start()
        elif not run_in_progress and self.coda_running:
            self._run_stop()

    def _run_start(self):
        '''Handle run_start event.'''
        print('New {} run started: {}'.format(self.run_type, self.run_number))
        self.coda_running = True
        for task in self.tasks['run_start']:
            task(self.run_number)

    def _run_stop(self):
        '''Handle run_stop event.'''
        print('End of {} run: {}'.format(self.run_type, self.run_number))
        self.coda_running = False
        for task in self.tasks['run_stop']:
            task(self.run_number)
Пример #12
0
class XltEpics(Assembly):
    def __init__(self, pvname="SLAAR02-LTIM-PDLY", name="lxt_epics"):
        super().__init__(name=name)
        self.pvname = pvname
        self.settings_collection.append(self, force=True)
        self.status_indicators_collection.append(self, force=True)
        self._append(
            PvEnum,
            self.pvname + ":SHOTDELAY",
            name="oscillator_pulse_offset",
            is_setting=True,
            is_status=True,
        )
        self._append(
            PvEnum,
            self.pvname + ":SHOTMOFFS_ENA",
            name="modulo_offset_mode",
            is_setting=True,
            is_status=True,
        )
        self._append(
            PvRecord,
            self.pvname + ":DELAY_Z_OFFS",
            name="_offset",
            is_setting=True,
            is_status=False,
        )
        self._append(
            AdjustableVirtual,
            [self._offset],
            lambda offset: offset * 1e-12,
            lambda offset: offset / 1e-12,
            name="offset",
            is_setting=False,
            is_status=True,
        )
        self._append(
            PvRecord,
            self.pvname + ":DELAY",
            name="_set_user_delay_value",
            is_setting=False,
            is_status=False,
        )
        self._append(
            PvRecord,
            self.pvname + ":P_RATIO",
            name="rep_len",
            is_setting=True,
            is_status=True,
        )
        self._append(
            PvRecord,
            "SIN-TIMAST-TMA:Evt-22-Freq-SP",
            name="laser_frequency",
            is_setting=True,
            is_status=True,
        )
        self._delay_dial_rb = PV("SLAAR-LGEN:DLY_OFFS2")
        self.alias.append(
            Alias("delay_dial_rb", "SLAAR-LGEN:DLY_OFFS2", channeltype="CA")
        )
        self.waiting_for_change = PV(self.pvname + ":WAITING")

    def get_current_dial_value(self):
        return self._delay_dial_rb.get() * 1e-6

    def get_current_value(self):
        return self.get_current_dial_value() - self.offset.get_current_value()

    def change_user_and_wait(self, value, check_interval=0.03):
        if np.abs(value) > 0.1:
            raise Exception("Very large value! This value is counted in seconds!")
        if not self.waiting_for_change.get():
            raise Exception("lxt is still moving!")
        self.is_moving = False
        self.is_stopped = False

        def set_is_stopped(**kwargs):
            old_status = self.is_moving
            new_status = not bool(kwargs["value"])
            if (not new_status) and old_status:
                self.is_stopped = True
            self.is_moving = new_status

        self.waiting_for_change.add_callback(callback=set_is_stopped)
        self._set_user_delay_value.set_target_value(value / 1e-12)

        while not self.is_stopped:
            time.sleep(check_interval)
        self.waiting_for_change.clear_callbacks()

    def set_target_value(self, value, hold=False):
        return Changer(
            target=value,
            parent=self,
            changer=self.change_user_and_wait,
            hold=hold,
            stopper=None,
        )

    def reset_current_value_to(self, value):
        self.offset.set_target_value((self.get_current_dial_value() - value)).wait()
Пример #13
0
class TripCounter:
    """Trip Counter"""
    def __init__(self,pv = "IBC1H04CRCUR2",th=7.6,name=None):
        self.name = name
        if name is None:
            self.name = pv
        self.trip_count = 0
        self.currently_tripped = False
        self.trip_threshold = th
        self.pv_name = pv
        self.process_var =  PV(self.pv_name)
        self.trips = []
        self.latest_trip = None

    def Reset(self):
        self.trip_count = 0
        self.currently_tripped = False
        self.trips = []
        self.latest_trip = None

    def PVChangeCallback(self,pvname=None, value=None, char_value=None, **kws):
        """Call back for epics PV."""
        #self.trip_count
        #self.trip_threshold
        #self.currently_tripped
        value = float(char_value)
        #print 'PV :', pvname, char_value, time.ctime(), " thresh ", self.trip_threshold
        if (value < self.trip_threshold) and not self.currently_tripped: 
            self.latest_trip = Trip(len(self.trips))
            print 'PV tripped!', pvname, char_value, time.strftime('%X %x %Z')
            self.trip_count = self.trip_count +1
            print self.trip_count
            self.currently_tripped = True
        if self.currently_tripped and (value > self.trip_threshold): 
            print 'PV restored', pvname, char_value, time.strftime('%X %x %Z')
            self.currently_tripped = False
            if not (self.latest_trip == None) :
                self.latest_trip.stop()
                self.trips.append(self.latest_trip)
        #if self.currently_tripped: 
        #    print 'PV still tripped', pvname, char_value, time.ctime()

    def AddCallback(self):
        self.process_var.add_callback(self.PVChangeCallback)

    def ClearCallback(self):
        self.process_var.clear_callbacks()

    def Dump(self):
        print(self.pv_name, "counts ", self.trip_count )

    def Print(self):
        self.ClearCallback()
        print(self.pv_name, "counts ", self.trip_count )

    def GetJSONObject(self):
        self.ClearCallback()
        all_trips = []
        for num,atrip in enumerate(self.trips):
            all_trips.append(atrip.GetJSONObject())
        trip_dict = {'trips': len(self.trips)}
        trip_dict.update({'PV': self.pv_name})
        trip_dict.update({'trip_events': all_trips})
        return {self.name: trip_dict }

    def PrintJSON(self):
        print "printing "
Пример #14
0
def main(argv=None):
    global dbd
    global simulate
    global fp
    global xmot_cur
    #deadband in motor units
    dbd = .001

    #parse command line options
    usage = "usage: %prog [options]\nData files are written to /data/<year>/<month>/<day>/"
    parser = OptionParser(usage)
    parser.add_option("--motname",
                      action="store",
                      type="string",
                      dest="motname",
                      help="motor to scan")
    parser.add_option("--detname",
                      action="store",
                      type="string",
                      dest="detname",
                      help="detector to trigger")
    parser.add_option("--xstart",
                      action="store",
                      type="float",
                      dest="xo",
                      help="starting X position")
    parser.add_option("--xnumstep",
                      action="store",
                      type="int",
                      dest="Nx",
                      help="number of steps in X")
    parser.add_option("--xstepsize",
                      action="store",
                      type="float",
                      dest="dx",
                      help="step size in X")
    parser.add_option(
        "--deadband",
        action="store",
        type="float",
        dest="dbd",
        help="software deadband for motion, default is 0.001 motor units")
    parser.add_option("--wait",
                      action="store",
                      type="float",
                      dest="stall",
                      help="wait at each step [seconds]")
    parser.add_option("--simulate",
                      action="store_true",
                      dest="sim",
                      default=False,
                      help="simulate motor moves and bursting")
    parser.add_option("--acqtime",
                      action="store",
                      type="float",
                      dest="acqt",
                      help="SDD acquisition time at each step [seconds]")

    (options, args) = parser.parse_args()

    #open log file
    D0 = time.localtime()[0]
    D1 = time.localtime()[1]
    D2 = time.localtime()[2]
    D3 = time.localtime()[3]
    D4 = time.localtime()[4]
    cd = os.getcwd()
    fstr = '/nfs/xf05id1/data/'
    if sys.argv[0][0] == '.':
        out_filename=fstr+repr(D0)+'/'+repr(D1)+'/'+repr(D2)+'/'+'log_'+repr(D3)+'_'+repr(D4)+'_'+\
         string.split(string.strip(sys.argv[0],'./'),'/')[0]+'.txt'
    else:
        out_filename=fstr+repr(D0)+'/'+repr(D1)+'/'+repr(D2)+'/'+'log_'+repr(D3)+'_'+repr(D4)+'_'+\
         string.split(string.strip(sys.argv[0],'./'),'/')[5]+'.txt'
    try:
        os.chdir(fstr + repr(D0))
    except OSError:
        try:
            os.mkdir(fstr + repr(D0))
        except Exception:
            print 'cannot create directory: ' + fstr + repr(D0)
            sys.exit()

    try:
        os.chdir(fstr + repr(D0) + '/' + repr(D1))
    except OSError:
        try:
            os.mkdir(fstr + repr(D0) + '/' + repr(D1))
        except Exception:
            print 'cannot create directory: ' + fstr + repr(D0) + '/' + repr(
                D1)
            sys.exit()
    try:
        os.chdir(fstr + repr(D0) + '/' + repr(D1) + '/' + repr(D2))
    except OSError:
        try:
            os.mkdir(fstr + repr(D0) + '/' + repr(D1) + '/' + repr(D2))
        except Exception:
            print 'cannot create directory: ' + fstr + repr(D0) + '/' + repr(
                D1) + '/' + repr(D2)
            sys.exit()
    H5path = '/epics/data/201507'
    try:
        fp = open(out_filename, 'a')
    except Exception:
        print 'cannot open file: ' + out_filename
        sys.exit()
    os.chdir(cd)
    fp.write(', '.join(sys.argv))
    fp.write('\n')
    #initialize PVs and callbacks
    if options.motname == None:
        #       xmotstr='XF:03IDA-OP{Mon:1-Ax:P}'
        xmotstr = ''
        print "must provide motor pv base, e.g., 'XF:28IDA-OP:1{Slt:MB1-Ax:T}'"
        sys.exit()
    else:
        xmotstr = options.motname
    if options.detname == None:
        #       detstr='XF:03IDA-BI{FS:1-CAM:1}'
        detstr = ''
        print "must provide detector pv base, e.g., 'XF:28IDA-BI{URL:01}'"
        sys.exit()
    else:
        detstr = options.detname
    if xmotstr.rsplit('{')[1].rsplit('}')[0] == 'IVU21:1-Mtr:2':
        undpv = True
    else:
        undpv = False
    if options.dbd is not None:
        dbd = options.dbd
    #transmission
    if undpv is False:
        xmot = PV(xmotstr + 'Mtr.VAL', connection_timeout=2)
        xmot_cur = PV(xmotstr + 'Mtr.RBV', connection_timeout=2)
        xmot_stop = PV(xmotstr + 'Mtr.STOP', connection_timeout=2)
    else:
        xmot = PV(xmotstr + 'Inp:Pos', connection_timeout=2)
        xmot_cur = PV(xmotstr.rsplit('{')[0] + '{IVU21:1-LEnc}Gap',
                      connection_timeout=2)
        xmot_stop = PV(xmotstr + 'Sw:Go', connection_timeout=2)


#   det_acq = PV(detstr+'Cur:I0-I')
    if 'IM' in detstr:
        det0_acq = PV(detstr, connection_timeout=4)
        det1_acq = PV(detstr.replace('I0-I', 'I1-I'), connection_timeout=4)
    else:
        det0_acq = PV(detstr, connection_timeout=2)
        det1_acq = None
    x3acq = PV('XSPRESS3-EXAMPLE:Acquire', connection_timeout=2)
    x3erase = PV('XSPRESS3-EXAMPLE:ERASE', connection_timeout=2)
    x3acqtime = PV('XSPRESS3-EXAMPLE:AcquireTime', connection_timeout=2)
    x3acqnum = PV('XSPRESS3-EXAMPLE:NumImages', connection_timeout=2)
    x3tmode = PV('XSPRESS3-EXAMPLE:TriggerMode', connection_timeout=2)
    x3h5path = PV('XSPRESS3-EXAMPLE:HDF5:FilePath', connection_timeout=2)
    x3h5fname = PV('XSPRESS3-EXAMPLE:HDF5:FileName', connection_timeout=2)
    x3h5fnum = PV('XSPRESS3-EXAMPLE:HDF5:FileNumber', connection_timeout=2)
    x3h5capture = PV('XSPRESS3-EXAMPLE:HDF5:Capture', connection_timeout=2)
    x3ch1roi0min = PV('XSPRESS3-EXAMPLE:C1_MCA_ROI1_LLM', connection_timeout=2)
    x3ch1roi0max = PV('XSPRESS3-EXAMPLE:C1_MCA_ROI1_HLM', connection_timeout=2)
    x3ch1roi0ct = PV('XSPRESS3-EXAMPLE:C1_ROI1:Value_RBV',
                     connection_timeout=2)

    xmot_cur.get(as_string=True)
    xmot_cur.add_callback(cbfx)
    xmot_cur.run_callbacks()
    det0_acq.info
    if det1_acq is not None:
        det1_acq.info
    #check command line options
    if options.xo == None:
        xo = xmot_cur.get(timeout=3)
    else:
        xo = options.xo
    if options.dx == None:
        dx = 0.00000001
    else:
        dx = options.dx
    if options.Nx == None:
        Nx = 0
    else:
        Nx = options.Nx
    if options.stall == None:
        twait = 0.
    else:
        twait = options.stall
    x3h5path.put(H5path)
    x3h5fname.put(repr(D3) + '_' + repr(D4) + '_')
    x3h5fnum.put(0)
    x3acqtime.put(options.acqt)
    x3acqnum.put(1)
    x3tmode.put(1)

    str = 'Start time is ' + time.asctime()
    print str
    fp.write(str)
    fp.write('\n')
    if options.sim is True:
        str = "      -----simulating motor moves and bursts-----"
        print str
        fp.write(str)
        fp.write('\n')
    str="Current position [mm]: %(XC)7.3f" %\
     {"XC":xmot_cur.get(timeout=3)}
    print str
    fp.write(str)
    fp.write('\n')
    str="Starting scan at: %(XO)7.3f"%\
     {"XO":xo}
    print str
    fp.write(str)
    fp.write('\n')
    time.sleep(2)

    #number of rows and columns completed by scan
    Ncol = 0
    LN = 0

    #scan direction for x
    dir = 1

    #intensity
    ROIint = -1

    count = 0
    #nested loops for scanning z,x,y
    for x in frange(0, Nx * dx, dx):
        tar[0][1] = 1
        tar[0][0] = x + xo
        #if tar[0][0] is the original position, raise "in position" flag
        if indeadband(float(tar[0][0]), float(xmot_cur.get()), dbd) == 1:
            tar[0][1] = 0
        if options.sim is False:
            xmot.put(tar[0][0])
            if undpv == True:
                time.sleep(0.5)
                xmot_stop.put(0)
        else:
            tar[0][1] = 0
        while (tar[0][1] == 1):
            if LN > 1000:
                LN = 0
                xmot.put(tar[0][0])
                LN = LN + 1
                xmot.info
                if xmot.severity == 2:
                    str = "\t scan stopped at " + xmot_cur.get()
                    print str
                    fp.write(str)
                    fp.write('\n')
                    raw_input(
                        "clear motor error and press enter (or ctrl-C to halt)"
                    )
                    xmot.put(tar[0][0])
                    time.sleep(twait)
        if options.sim is False:
            time.sleep(twait)
            x3h5capture.put(1)
            x3erase.put(1)
            x3acq.put(1)
            signal = [0., 0.]
            signal[0] = float(det0_acq.get())
            while (signal[0] == 0.):
                time.sleep(0.01)
                signal[0] = float(det0_acq.get())
            if det1_acq is not None:
                signal[1] = float(det1_acq.get())
                while (signal[1] == 0.):
                    time.sleep(0.01)
                    signal[1] = float(det1_acq.get())
            time.sleep(options.acqt)
        else:
            print "bang"
            signal = 0.
        if options.sim is False:
            sigstr = '%(one)10.7e %(two)10.7e' % {
                'one': signal[0],
                'two': signal[1]
            }
            str = ' [%(X)04d] at (X= %(XC)9.4f ): signal is %(RI)s ' % {
                "X": Ncol,
                "XC": xmot_cur.get(),
                "RI": sigstr
            }
            print str
            fp.write(str)
            fp.write('\n')
        else:
            str = ' [%(X)04d] at (X= %(XC)8.3f )' % {
                "X": Ncol,
                "XC": tar[0][0]
            }
            print str
            fp.write(str)
            fp.write('\n')
        Ncol = Ncol + 1

    #return to starting positions
    if options.sim is False:
        xmot.put(xo)
        time.sleep(0.01)
        if undpv == True:
            time.sleep(0.5)
            xmot_stop.put(0)

    str = 'End time is ' + time.asctime()
    print str
    fp.write(str)
    fp.write('\n')
    fp.close()
    xmot_cur.clear_callbacks()

    return 0
Пример #15
0
class Feed:
    """
    This class reads frames in a real time using pyepics, and delivers to consuming process.
    """

    def __init__(self):
        """
        Constructor

        This constructor creates the following queues:
        process_dataq : a queue used to pass data to the consuming process
        exitq : a queue used to signal awaiting process the end of processing, so the resources can be closed
        thread_dataq : this queue delivers counter number on change from call back thread
        Other fields are initialized.
        """
        self.process_dataq = Queue()
        self.exitq = tqueue.Queue()
        self.thread_dataq = tqueue.Queue()
        self.sizex = 0
        self.sizey = 0
        self.no_frames = 0
        self.sequence = None
        self.sequence_index = 0
        self.callback_pv = None
        self.counter_pv = None
        self.offset = 0
        self.ctr = None
        self.file_name = []

    def deliver_data(self, data_pv, frame_type_pv, logger):
        """
        This function receives data, processes it, and delivers to consuming process.

        This function is invoked at the beginning of the feed as a distinct thread. It reads data from a thread_dataq
        inside a loop that delivers current counter value on change.
        If the counter is not a consecutive number to the previous reading a 'missing' string is enqueued into
        process_dataq in place of the data to mark the missing frames.
        For every received frame data, it reads a data type from PV, and the two elements are delivered to a consuming
        process via process_dataq as Data instance. If a sequence is defined, then the data type for this frame
        determined from sequence is compared with the data type read from PV. If they are different, a warning log is
        recorded.
        On the loop exit an 'all_data' string is enqueud into the inter-process queue, and 'exit' string is enqueued
        into the inter-thread queue, to notify the main thread of the exit event.

        Parameters
        ----------
        data_pv : str
            a PV string for the area detector data

        frame_type_pv : str
            a PV string for the area detector data type

        logger : Logger
            a Logger instance, typically synchronized with the consuming process logger

        Returns
        -------
        None
        """

        def build_type_map():
            types = {}
            types[0] = 'data'
            types[1] = 'data_dark'
            types[2] = 'data_white'
            # types[3] = 'data' # it'd double correlation, but leave data for now
            return types

        def verify_sequence(logger, data_type):
            while frame_index > self.sequence[self.sequence_index][1]:
                self.sequence_index += 1
            planned_data_type = self.sequence[self.sequence_index][0]
            if planned_data_type != data_type:
                logger.warning('The data type for frame number ' + str(
                    frame_index) + ' is ' + data_type + ' but was planned ' + planned_data_type)

        types = build_type_map()
        self.done = False
        frame_index = 0
        while not self.done:
            try:
                callback_item = self.thread_dataq.get(timeout=1)
                if isinstance(callback_item, (int, long, float)):  # came from on_change function
                    current_counter = callback_item
                    if self.callback_pv is None:
                        file_name = None
                    else:
                        if len(self.file_name) > 0:
                            file_name = self.file_name.pop(0)
                        else:
                            print('race conditions')
                else:
                    self.file_name.append(callback_item)
                    continue
            except tqueue.Empty:
                continue
            if self.no_frames < 0 or current_counter < self.no_frames + 1:
                try:
                    data = np.array(caget(data_pv))
                    data_type = types[caget(frame_type_pv)]
                    if data is None:
                        self.finish()
                        done = True
                        logger.error('reading image times out, possibly the detector exposure time is too small')
                    else:
                        delta = current_counter - self.ctr
                        self.ctr = current_counter
                        data.resize(self.sizex, self.sizey)
                        if delta > 1:
                            for i in range(1, delta):
                                self.process_dataq.put(adapter.pack_data(None, "missing"))
                        frame_index += delta
                        packed_data = self.get_packed_data(data, data_type, file_name)
                        self.process_dataq.put(packed_data)
                        if self.sequence is not None:
                            verify_sequence(logger, data_type)
                except:
                    self.finish()
                    self.done = True
                    logger.error('reading image raises exception, possibly the detector exposure time is too small')
            else:
                self.done = True
        self.finish()

    def get_packed_data(self, data, data_type, file_name):
        return adapter.pack_data(data, data_type)

    def acq_done(self, pvname=None, **kws):
        """
        A callback method that activates when a frame counter of area detector changes.

        This method reads the counter value and enqueues it into inter-thread queue that will be dequeued by the
        'deliver_data' function.
        If it is a first read, the function adjusts counter data in the self object.

        Parameters
        ----------
        pvname : str
            a PV string for the area detector frame counter

        Returns
        -------
        None
        """
        # if the callback is not on the counter pv, keep track of counter
        if kws['value'] == 0:
            self.thread_dataq.put(self.ctr + 1)

    def on_change(self, pvname=None, **kws):
        """
        A callback method that activates when a frame counter of area detector changes.

        This method reads the counter value and enqueues it into inter-thread queue that will be dequeued by the
        'deliver_data' function.
        If it is a first read, the function adjusts counter data in the self object.

        Parameters
        ----------
        pvname : str
            a PV string for the area detector frame counter

        Returns
        -------
        None
        """
        file_name = kws['value'][:-1]
        file_name = ''.join(chr(i) for i in file_name)
        self.thread_dataq.put(file_name)

    def on_ctr_change(self, pvname=None, **kws):
        """
        A callback method that activates when a frame counter of area detector changes.

        This method reads the counter value and enqueues it into inter-thread queue that will be dequeued by the
        'deliver_data' function.
        If it is a first read, the function adjusts counter data in the self object.

        Parameters
        ----------
        pvname : str
            a PV string for the area detector frame counter

        Returns
        -------
        None
        """

        current_ctr = kws['value']
        # on first callback adjust the values
        if self.ctr is None:
            self.offset = current_ctr
            self.ctr = 0
        else:
            current_ctr -= self.offset
            if current_ctr > 1:
                self.thread_dataq.put(current_ctr)
            else:
                self.ctr = current_ctr

    def start_processes(self, acquire_pv, counter_pv_name, data_pv, frame_type_pv, logger, reportq, *args, **kwargs):
        """
        This function starts processes and callbacks.

        This is a main thread that starts thread reacting to the callback, starts the consuming process, and sets a
        callback on the frame counter PV change. The function then awaits for the data in the exit queue that indicates
        that all frames have been processed. The functin cancells the callback on exit.

        Parameters
        ----------
        counter_pv : str
            a PV string for the area detector frame counter

        data_pv : str
            a PV string for the area detector frame data

        frame_type_pv : str
            a PV string for the area detector data type

        logger : Logger
            a Logger instance, typically synchronized with the consuming process logger

        *args : list
            a list of arguments specific to the client process

        Returns
        -------
        None
        """
        data_thread = CAThread(target=self.deliver_data, args=(data_pv, frame_type_pv, logger,))
        data_thread.start()
        p = Process(target=handler.handle_data,
                    args=(self.process_dataq, reportq, args, kwargs,))
        p.start()

        self.counter_pv = PV(counter_pv_name)
        self.counter_pv.add_callback(self.on_ctr_change, index=1)

        self.acq_pv = PV(acquire_pv)
        self.acq_pv.add_callback(self.acq_done, index=2)

        try:
            callback_pv_name = kwargs['callback_pv']
            self.callback_pv = PV(callback_pv_name)
            self.callback_pv.add_callback(self.on_change, as_string=True, index=3)
        except KeyError:
            pass

    def get_pvs(self, detector):
        """
        This function takes defined strings from configuration file and constructs PV variables that are accessed during
        processing.

        Parameters
        ----------
        detector : str
            a string defining the first prefix in area detector, it has to match the area detector configuration

        Returns
        -------
        acquire_pv : str
            a PV string representing acquireing state

        counter_ pv : str
            a PV string representing frame counter

        data_pv : str
            a PV string representing acquired data

        sizex_pv : str
            a PV string representing x size of acquired data

        sizey_pv : str
            a PV string representing y size of acquired data

        frame_type_pv : str
            a PV string for the area detector data type

        """

        acquire_pv = detector + ':cam1:Acquire'
        counter_pv = detector + ':cam1:ArrayCounter_RBV'
        data_pv = detector + ':image1:ArrayData'
        sizex_pv = detector + ':image1:ArraySize0_RBV'
        sizey_pv = detector + ':image1:ArraySize1_RBV'
        frame_type_pv = detector + ':cam1:FrameType'
        return acquire_pv, counter_pv, data_pv, sizex_pv, sizey_pv, frame_type_pv

    def feed_data(self, logger, reportq, *args, **kwargs):  # no_frames, detector, logger, sequence=None, *args):
        """
        This function is called by a client to start the process.

        After all initial settings are completed, the method awaits for the area detector to start acquireing by polling
        the PV. When the area detective is active it starts processing.

        Parameters
        ----------
        no_frames : int
            number of frames to feed, indefinately if -1

        detector : str
            detector name

        logger : Logger
            a Logger instance, recommended to use the same logger for feed and consuming process

        sequence : list or int
            if int, the number is used to set number of frames to process,
            if list, take the number of frames from the list, and verify the sequence of data is correct during
            processing

        *args : list
            a list of process specific arguments

        Returns
        -------
        None
        """
        acquire_pv, counter_pv, data_pv, sizex_pv, sizey_pv, frame_type_pv = self.get_pvs(kwargs['detector'])
        self.no_frames = args[2]

        test = True

        while test:
            self.sizex = caget(sizex_pv)
            self.sizey = caget(sizey_pv)
            ack = caget(acquire_pv)
            if ack == 1:
                test = False
                self.start_processes(acquire_pv, counter_pv, data_pv, frame_type_pv, logger, reportq, *args, **kwargs)
            else:
                time.sleep(.005)

        return caget(acquire_pv)

    def finish(self):
        self.process_dataq.put(adapter.pack_data(None, const.DATA_STATUS_END))
        self.done = True
        try:
            self.counter_pv.clear_callbacks()
            self.acq_pv.clear_callbacks()
            if not self.callback_pv is None:
                self.callback_pv.clear_callbacks()
        except:
            pass
Пример #16
0
class Feed:
    """
    This class reads frames in a real time using pyepics, and delivers to consuming process.
    """
    def __init__(self):
        """
        Constructor

        This constructor creates the following queues:
        process_dataq : a queue used to pass data to the consuming process
        exitq : a queue used to signal awaiting process the end of processing, so the resources can be closed
        thread_dataq : this queue delivers counter number on change from call back thread
        Other fields are initialized.
        """
        self.process_dataq = Queue()
        self.exitq = tqueue.Queue()
        self.thread_dataq = tqueue.Queue()
        self.sizex = 0
        self.sizey = 0
        self.no_frames = 0
        self.ctr = 0
        self.sequence = None
        self.sequence_index = 0
        self.cntr_pv = None


    def deliver_data(self, data_pv, frame_type_pv, logger):
        """
        This function receives data, processes it, and delivers to consuming process.

        This function is invoked at the beginning of the feed as a distinct thread. It reads data from a thread_dataq
        inside a loop that delivers current counter value on change.
        If the counter is not a consecutive number to the previous reading a 'missing' string is enqueued into
        process_dataq in place of the data to mark the missing frames.
        For every received frame data, it reads a data type from PV, and the two elements are delivered to a consuming
        process via process_dataq as Data instance. If a sequence is defined, then the data type for this frame
        determined from sequence is compared with the data type read from PV. If they are different, a warning log is
        recorded.
        On the loop exit an 'all_data' string is enqueud into the inter-process queue, and 'exit' string is enqueued
        into the inter-thread queue, to notify the main thread of the exit event.
    
        Parameters
        ----------
        data_pv : str
            a PV string for the area detector data

        frame_type_pv : str
            a PV string for the area detector data type
    
        logger : Logger
            a Logger instance, typically synchronized with the consuming process logger
    
        Returns
        -------
        None
        """
        def build_type_map():
            types = {}
            types[0] = 'data'
            types[1] = 'data_dark'
            types[2] = 'data_white'
            types[3] = 'data' # it'd double correlation, but leave data for now
            return types

        def verify_sequence(logger, data_type):
            while frame_index > self.sequence[self.sequence_index][1]:
                self.sequence_index += 1
            planned_data_type = self.sequence[self.sequence_index][0]
            if planned_data_type != data_type:
                logger.warning('The data type for frame number ' + str(frame_index) + ' is ' + data_type + ' but was planned ' + planned_data_type)

        # def finish():
        #     self.process_dataq.put(pack_data(None, "end"))
        #     self.exitq.put('exit')

        types =  build_type_map()
        done = False
        frame_index = 0
        while not done:
            current_counter = self.thread_dataq.get()
            if self.no_frames < 0 or current_counter < self.no_frames:
                try:
                    data = np.array(caget(data_pv))
                    data_type = types[caget(frame_type_pv)]
                    if data is None:
                        self.finish()
                        done = True
                        logger.error('reading image times out, possibly the detector exposure time is too small')
                    else:
                        delta = current_counter - self.ctr
                        self.ctr = current_counter
                        data.resize(self.sizex, self.sizey)
                        if delta > 1:
                            for i in range (1, delta):
                                self.process_dataq.put(adapter.pack_data(None, "missing"))
                        frame_index += delta
                        packed_data = self.get_packed_data(data, data_type)
                        self.process_dataq.put(packed_data)
                        if self.sequence is not None:
                            verify_sequence(logger, data_type)
                except:
                    self.finish()
                    done = True
                    logger.error('reading image raises exception, possibly the detector exposure time is too small')
            else:
                done = True

        self.finish()

    def get_packed_data(self, data, data_type):
        return adapter.pack_data(data, data_type)
    
    def on_change(self, pvname=None, **kws):
        """
        A callback method that activates when a frame counter of area detector changes.

        This method reads the counter value and enqueues it into inter-thread queue that will be dequeued by the
        'deliver_data' function.
        If it is a first read, the function adjusts counter data in the self object.
    
        Parameters
        ----------
        pvname : str
            a PV string for the area detector frame counter
    
        Returns
        -------
        None
        """
    
        current_ctr = kws['value']
        #on first callback adjust the values
        if self.ctr == 0:
            self.ctr = current_ctr
            if self.no_frames >= 0:
                self.no_frames += current_ctr

        self.thread_dataq.put(current_ctr)
    
    
    def start_processes(self, counter_pv, data_pv, frame_type_pv, logger, *args):
        """
        This function starts processes and callbacks.

        This is a main thread that starts thread reacting to the callback, starts the consuming process, and sets a
        callback on the frame counter PV change. The function then awaits for the data in the exit queue that indicates
        that all frames have been processed. The functin cancells the callback on exit.
    
        Parameters
        ----------
        counter_pv : str
            a PV string for the area detector frame counter
    
        data_pv : str
            a PV string for the area detector frame data

        frame_type_pv : str
            a PV string for the area detector data type
    
        logger : Logger
            a Logger instance, typically synchronized with the consuming process logger
    
        *args : list
            a list of arguments specific to the client process
    
        Returns
        -------
        None
        """
        data_thread = CAThread(target = self.deliver_data, args=(data_pv, frame_type_pv, logger,))
        data_thread.start()

        adapter.start_process(self.process_dataq, logger, *args)
        self.cntr_pv = PV(counter_pv)
        self.cntr_pv.add_callback(self.on_change, index = 1)
    
        # self.exitq.get()
        # print 'got Exit in exitq stopping callback'
        # self.cntr.clear_callbacks()
    
    
    def get_pvs(self, detector, detector_basic, detector_image):
        """
        This function takes defined strings from configuration file and constructs PV variables that are accessed during
        processing.
    
        Parameters
        ----------
        detector : str
            a string defining the first prefix in area detector, it has to match the area detector configuration
    
        detector_basic : str
            a string defining the second prefix in area detector, defining the basic parameters, it has to
            match the area detector configuration
    
        detector_image : str
            a string defining the second prefix in area detector, defining the image parameters, it has to
            match the area detector configuration
    
        Returns
        -------
        acquire_pv : str
            a PV string representing acquireing state
    
        counter_ pv : str
            a PV string representing frame counter
    
        data_pv : str
            a PV string representing acquired data
    
        sizex_pv : str
            a PV string representing x size of acquired data
    
        sizey_pv : str
            a PV string representing y size of acquired data

        frame_type_pv : str
            a PV string for the area detector data type

        """
    
        acquire_pv = detector + ':' + detector_basic + ':' + 'Acquire'
        counter_pv = detector + ':' + detector_basic + ':' + 'NumImagesCounter_RBV'
        data_pv = detector + ':' + detector_image + ':' + 'ArrayData'
        sizex_pv = detector + ':' + detector_image + ':' + 'ArraySize0_RBV'
        sizey_pv = detector + ':' + detector_image + ':' + 'ArraySize1_RBV'
        frame_type_pv = detector + ':' + detector_basic + ':' + 'FrameType'
        return acquire_pv, counter_pv, data_pv, sizex_pv, sizey_pv, frame_type_pv
    
    
    def feed_data(self, no_frames, detector, detector_basic, detector_image, logger, sequence=None, *args):
        """
        This function is called by an client to start the process.

        It parses configuration and gets needed process variables. It stores necessary values in the self object.
        After all initial settings are completed, the method awaits for the area detector to start acquireing by polling
        the PV. When the area detective is active it starts processing.
    
        Parameters
        ----------
        config : str
            a configuration file
    
        logger : Logger
            a Logger instance, recommended to use the same logger for feed and consuming process

        sequence : list or int
            if int, the number is used to set number of frames to process,
            if list, take the number of frames from the list, and verify the sequence of data is correct during
            processing
    
        *args : list
            a list of process specific arguments
    
        Returns
        -------
        None
        """
        acquire_pv, counter_pv, data_pv, sizex_pv, sizey_pv, frame_type_pv = self.get_pvs(detector, detector_basic, detector_image)
        self.no_frames = no_frames
        # if sequence is None:
        #     self.no_frames = no_frames
        # elif type(sequence) is int:
        #     self.no_frames = sequence
        # else:
        #     self.sequence = sequence
        #     self.no_frames = sequence[len(sequence)-1][1] + 1

        test = True

        while test:
            self.sizex = caget (sizex_pv)
            self.sizey = caget (sizey_pv)
            ack =  caget(acquire_pv)
            if ack == 1:
                test = False
                self.start_processes(counter_pv, data_pv, frame_type_pv, logger, *args)

        return caget(acquire_pv)


    def finish(self):
        self.process_dataq.put(adapter.pack_data(None, "end"))
        self.cntr_pv.clear_callbacks()
Пример #17
0
class Feed:
    """
    This class reads frames in a real time using pyepics, and delivers to consuming process.
    """
    def __init__(self):
        """
        Constructor

        This constructor creates the following queues:
        process_dataq : a queue used to pass data to the consuming process
        exitq : a queue used to signal awaiting process the end of processing, so the resources can be closed
        thread_dataq : this queue delivers counter number on change from call back thread
        Other fields are initialized.
        """
        self.process_dataq = Queue()
        self.exitq = tqueue.Queue()
        self.thread_dataq = tqueue.Queue()
        self.sizex = 0
        self.sizey = 0
        self.no_frames = 0
        self.ctr = 0
        self.sequence = None
        self.sequence_index = 0
        self.cntr_pv = None

    def deliver_data(self, data_pv, frame_type_pv, logger):
        """
        This function receives data, processes it, and delivers to consuming process.

        This function is invoked at the beginning of the feed as a distinct thread. It reads data from a thread_dataq
        inside a loop that delivers current counter value on change.
        If the counter is not a consecutive number to the previous reading a 'missing' string is enqueued into
        process_dataq in place of the data to mark the missing frames.
        For every received frame data, it reads a data type from PV, and the two elements are delivered to a consuming
        process via process_dataq as Data instance. If a sequence is defined, then the data type for this frame
        determined from sequence is compared with the data type read from PV. If they are different, a warning log is
        recorded.
        On the loop exit an 'all_data' string is enqueud into the inter-process queue, and 'exit' string is enqueued
        into the inter-thread queue, to notify the main thread of the exit event.
    
        Parameters
        ----------
        data_pv : str
            a PV string for the area detector data

        frame_type_pv : str
            a PV string for the area detector data type
    
        logger : Logger
            a Logger instance, typically synchronized with the consuming process logger
    
        Returns
        -------
        None
        """
        def build_type_map():
            types = {}
            types[0] = 'data'
            types[1] = 'data_dark'
            types[2] = 'data_white'
            types[
                3] = 'data'  # it'd double correlation, but leave data for now
            return types

        def verify_sequence(logger, data_type):
            while frame_index > self.sequence[self.sequence_index][1]:
                self.sequence_index += 1
            planned_data_type = self.sequence[self.sequence_index][0]
            if planned_data_type != data_type:
                logger.warning('The data type for frame number ' +
                               str(frame_index) + ' is ' + data_type +
                               ' but was planned ' + planned_data_type)

        # def finish():
        #     self.process_dataq.put(pack_data(None, "end"))
        #     self.exitq.put('exit')

        types = build_type_map()
        done = False
        frame_index = 0
        while not done:
            current_counter = self.thread_dataq.get()
            if self.no_frames < 0 or current_counter < self.no_frames:
                try:
                    data = np.array(caget(data_pv))
                    data_type = types[caget(frame_type_pv)]
                    if data is None:
                        self.finish()
                        done = True
                        logger.error(
                            'reading image times out, possibly the detector exposure time is too small'
                        )
                    else:
                        delta = current_counter - self.ctr
                        self.ctr = current_counter
                        data.resize(self.sizex, self.sizey)
                        if delta > 1:
                            for i in range(1, delta):
                                self.process_dataq.put(
                                    adapter.pack_data(None, "missing"))
                        frame_index += delta
                        packed_data = self.get_packed_data(data, data_type)
                        self.process_dataq.put(packed_data)
                        if self.sequence is not None:
                            verify_sequence(logger, data_type)
                except:
                    self.finish()
                    done = True
                    logger.error(
                        'reading image raises exception, possibly the detector exposure time is too small'
                    )
            else:
                done = True

        self.finish()

    def get_packed_data(self, data, data_type):
        return adapter.pack_data(data, data_type)

    def on_change(self, pvname=None, **kws):
        """
        A callback method that activates when a frame counter of area detector changes.

        This method reads the counter value and enqueues it into inter-thread queue that will be dequeued by the
        'deliver_data' function.
        If it is a first read, the function adjusts counter data in the self object.
    
        Parameters
        ----------
        pvname : str
            a PV string for the area detector frame counter
    
        Returns
        -------
        None
        """

        current_ctr = kws['value']
        #on first callback adjust the values
        if self.ctr == 0:
            self.ctr = current_ctr
            if self.no_frames >= 0:
                self.no_frames += current_ctr

        self.thread_dataq.put(current_ctr)

    def start_processes(self, counter_pv, data_pv, frame_type_pv, logger,
                        *args):
        """
        This function starts processes and callbacks.

        This is a main thread that starts thread reacting to the callback, starts the consuming process, and sets a
        callback on the frame counter PV change. The function then awaits for the data in the exit queue that indicates
        that all frames have been processed. The functin cancells the callback on exit.
    
        Parameters
        ----------
        counter_pv : str
            a PV string for the area detector frame counter
    
        data_pv : str
            a PV string for the area detector frame data

        frame_type_pv : str
            a PV string for the area detector data type
    
        logger : Logger
            a Logger instance, typically synchronized with the consuming process logger
    
        *args : list
            a list of arguments specific to the client process
    
        Returns
        -------
        None
        """
        data_thread = CAThread(target=self.deliver_data,
                               args=(
                                   data_pv,
                                   frame_type_pv,
                                   logger,
                               ))
        data_thread.start()

        adapter.start_process(self.process_dataq, logger, *args)
        self.cntr_pv = PV(counter_pv)
        self.cntr_pv.add_callback(self.on_change, index=1)

        # self.exitq.get()
        # print 'got Exit in exitq stopping callback'
        # self.cntr.clear_callbacks()

    def get_pvs(self, detector, detector_basic, detector_image):
        """
        This function takes defined strings from configuration file and constructs PV variables that are accessed during
        processing.
    
        Parameters
        ----------
        detector : str
            a string defining the first prefix in area detector, it has to match the area detector configuration
    
        detector_basic : str
            a string defining the second prefix in area detector, defining the basic parameters, it has to
            match the area detector configuration
    
        detector_image : str
            a string defining the second prefix in area detector, defining the image parameters, it has to
            match the area detector configuration
    
        Returns
        -------
        acquire_pv : str
            a PV string representing acquireing state
    
        counter_ pv : str
            a PV string representing frame counter
    
        data_pv : str
            a PV string representing acquired data
    
        sizex_pv : str
            a PV string representing x size of acquired data
    
        sizey_pv : str
            a PV string representing y size of acquired data

        frame_type_pv : str
            a PV string for the area detector data type

        """

        acquire_pv = detector + ':' + detector_basic + ':' + 'Acquire'
        counter_pv = detector + ':' + detector_basic + ':' + 'NumImagesCounter_RBV'
        data_pv = detector + ':' + detector_image + ':' + 'ArrayData'
        sizex_pv = detector + ':' + detector_image + ':' + 'ArraySize0_RBV'
        sizey_pv = detector + ':' + detector_image + ':' + 'ArraySize1_RBV'
        frame_type_pv = detector + ':' + detector_basic + ':' + 'FrameType'
        return acquire_pv, counter_pv, data_pv, sizex_pv, sizey_pv, frame_type_pv

    def feed_data(self,
                  no_frames,
                  detector,
                  detector_basic,
                  detector_image,
                  logger,
                  sequence=None,
                  *args):
        """
        This function is called by an client to start the process.

        It parses configuration and gets needed process variables. It stores necessary values in the self object.
        After all initial settings are completed, the method awaits for the area detector to start acquireing by polling
        the PV. When the area detective is active it starts processing.
    
        Parameters
        ----------
        config : str
            a configuration file
    
        logger : Logger
            a Logger instance, recommended to use the same logger for feed and consuming process

        sequence : list or int
            if int, the number is used to set number of frames to process,
            if list, take the number of frames from the list, and verify the sequence of data is correct during
            processing
    
        *args : list
            a list of process specific arguments
    
        Returns
        -------
        None
        """
        acquire_pv, counter_pv, data_pv, sizex_pv, sizey_pv, frame_type_pv = self.get_pvs(
            detector, detector_basic, detector_image)
        self.no_frames = no_frames
        # if sequence is None:
        #     self.no_frames = no_frames
        # elif type(sequence) is int:
        #     self.no_frames = sequence
        # else:
        #     self.sequence = sequence
        #     self.no_frames = sequence[len(sequence)-1][1] + 1

        test = True

        while test:
            self.sizex = caget(sizex_pv)
            self.sizey = caget(sizey_pv)
            ack = caget(acquire_pv)
            if ack == 1:
                test = False
                self.start_processes(counter_pv, data_pv, frame_type_pv,
                                     logger, *args)

        return caget(acquire_pv)

    def finish(self):
        self.process_dataq.put(adapter.pack_data(None, "end"))
        self.cntr_pv.clear_callbacks()
Пример #18
0
def main(argv=None):
    global simulate
    global fp
    global shut_open
    global current
    global x3h5capture
    global xmot_cur
    global ymot_cur
    global shut_status
    global beam_current

    #parse command line options
    usage = "usage: %prog [options]\nData files are written to /data/<year>/<month>/<day>/"
    parser = OptionParser(usage)
    parser.add_option("--detname", action="store", type="string", dest="detname", help="detector PV base")
    parser.add_option("--xstart", action="store", type="float", dest="xo", help="starting X position")
    parser.add_option("--xnumstep", action="store", type="int", dest="Nx", help="number of steps in X")
    parser.add_option("--xstepsize", action="store", type="float", dest="dx", help="step size in X")
    parser.add_option("--ystart", action="store", type="float", dest="yo", help="starting Y position")
    parser.add_option("--ynumstep", action="store", type="int", dest="Ny", help="number of steps in Y")
    parser.add_option("--ystepsize", action="store", type="float", dest="dy", help="step size in Y")
    parser.add_option("--wait", action="store", type="float", dest="stall", help="wait at each step [seconds]")
    parser.add_option("--simulate", action="store_true", dest="sim", default=False, help="simulate motor moves")
    parser.add_option("--checkbeam", action="store_true", dest="checkbeam", default=False, help="only acquire when beam is on")
    parser.add_option("--checkcryo", action="store_true", dest="checkcryo", default=False, help="only acquire when cryo status is ok")
    parser.add_option("--acqtime", action="store", type="float", dest="acqt", default=1, help="image integration time [sec]")
    parser.add_option("--acqnum", action="store", type="int", dest="acqn", default=1, help="frames per scan point")

    (options,args) = parser.parse_args()

    #open log file
    D0=time.localtime()[0]
    D1=time.localtime()[1]
    D2=time.localtime()[2]
    D3=time.localtime()[3]
    D4=time.localtime()[4]
    cd=os.getcwd()
    
    filedir = '/nfs/xf05id1/data/' 
    
    if sys.argv[0][0]=='.':
        out_filename=filedir+repr(D0)+'/'+repr(D1)+'/'+repr(D2)+'/'+'log_'+repr(D1)+'_'+repr(D2)+'_'+repr(D3)+'_'+repr(D4)+'_'+\
         string.split(string.strip(sys.argv[0],'./'),'/')[0]+'.txt'
    else:
        out_filename=filedir+repr(D0)+'/'+repr(D1)+'/'+repr(D2)+'/'+'log_'+repr(D1)+'_'+repr(D2)+'_'+repr(D3)+'_'+repr(D4)+'_'+\
         string.split(string.strip(sys.argv[0],'./'),'/')[5]+'.txt'
    try:
        os.chdir(filedir+repr(D0))
    except OSError:
        try:    
            os.mkdir(filedir+repr(D0))
        except Exception:
            print 'cannot create directory: '+'/data/'+repr(D0)
            sys.exit()

    try:
        os.chdir(filedir+repr(D0)+'/'+repr(D1))
    except OSError:
        try:
            os.mkdir(filedir+repr(D0)+'/'+repr(D1))
        except Exception:
            print 'cannot create directory: '+'/data/'+repr(D0)+'/'+repr(D1)
            sys.exit()
    try:
        os.chdir(filedir+repr(D0)+'/'+repr(D1)+'/'+repr(D2))
    except OSError:
        try:
            os.mkdir(filedir+repr(D0)+'/'+repr(D1)+'/'+repr(D2))
        except Exception:
            print 'cannot create directory: '+filedir+repr(D0)+'/'+repr(D1)+'/'+repr(D2)
            sys.exit()
    try:
        fp=open(out_filename,'a')
    except Exception:
        print 'cannot open file: '+out_filename
        sys.exit()
    os.chdir(cd)
    fp.write('#'+', '.join(sys.argv))
    fp.write('\n')
    H5path='/epics/data/2015-3/in-house'
    #H5path='/epics/data/2015-2/testing'
    #initialize PVs and callbacks
    if options.detname == None:
        detstr=''
        print "must provide detector pv base, e.g., 'XF:28IDA-BI{URL:01}'"
        sys.exit()
    else:
        detstr=options.detname

##### original script for Aerotech stages
#    xmotname='XF:05IDD-ES:1{Stg:Smpl1-Ax:X}'
#    ymotname='XF:05IDD-ES:1{Stg:Smpl1-Ax:Y}'
#    xmot=PV(xmotname+'Mtr.VAL')
#    xmot_cur=PV(xmotname+'Mtr.RBV')
#    ymot=PV(ymotname+'Mtr.VAL')
#    ymot_cur=PV(ymotname+'Mtr.RBV')
######
#####modified for nPoint Stages
#    xmot=PV('NPOINT:CH1:SET_POSITION.A',connection_timeout=2)
#    xmot_cur=PV('NPOINT:CH1:GET_POSITION',connection_timeout=2)
#    ymot=PV('NPOINT:CH2:SET_POSITION.A',connection_timeout=2)
#    ymot_cur=PV('NPOINT:CH2:GET_POSITION',connection_timeout=2)    
#####modified for HR coarse Stages; X=Attocube ECS505 X, Y=Attocube ECS505 Z
    xmot=PV('XF:05IDD-ES:1{Stg:Ecs50}:ACT0:CMD:TARGET',connection_timeout=2)
    xmot_cur=PV('XF:05IDD-ES:1{Stg:Ecs50}:ACT0:POSITION',connection_timeout=2)
    ymot=PV('XF:05IDD-ES:1{Stg:Ecs50}:ACT1:CMD:TARGET',connection_timeout=2)
    ymot_cur=PV('XF:05IDD-ES:1{Stg:Ecs50}:ACT1:POSITION',connection_timeout=2)  

#####
    shut_status=PV('SR:C05-EPS{PLC:1}Shutter:Sum-Sts',connection_timeout=2)
    beam_current=PV('SR:C03-BI{DCCT:1}I:Total-I',connection_timeout=2)
    bmot_cur=PV('XF:05IDA-OP:1{Mono:HDCM-Ax:P}Mtr.RBV',connection_timeout=2)
    #transmission
    #check command line options
    if options.yo == None:
        print "must provide a starting point in the vertical"
        sys.exit()
    else:   
        yo = options.yo
    if options.xo == None:
        print "must provide a starting point in the horizontal"
        sys.exit()
    else:   
        xo = options.xo
    if options.dx == None:
        dx = 0.00000001
    else:
        dx = options.dx
    if options.dy == None:
        dy = 0.00000001
    else:
        dy = options.dy
    if options.Nx == None:
        Nx = 0
    else:
        Nx = options.Nx
    if options.Ny == None:
        Ny = 0
    else:
        Ny = options.Ny
    if options.stall == None:
        twait = 0.
    else:
        twait = options.stall
    diode0=PV(detstr+'Cur:I0-I',connection_timeout=4)
    diode1=PV(detstr+'Cur:I1-I',connection_timeout=4)
    diode2=PV(detstr+'Cur:I2-I',connection_timeout=4)
    diode3=PV(detstr+'Cur:I3-I',connection_timeout=4)
    diode0.connect()
    diode1.connect()
    diode2.connect()
    diode3.connect()
    dett=PV('XF:05IDD-ES:1{EVR:1-Out:FP3}Src:Scale-SP',connection_timeout=2)
    deti=PV('XF:05IDA{IM:1}Per-SP',connection_timeout=4)
    detinit=PV('XF:05IDA{IM:1}Cmd:Init',connection_timeout=4)
                
    wb=srxslit.nsls2slit(tb='XF:05IDA-OP:1{Slt:1-Ax:T}',bb='XF:05IDA-OP:1{Slt:1-Ax:B}',ib='XF:05IDA-OP:1{Slt:1-Ax:I}',ob='XF:05IDA-OP:1{Slt:1-Ax:O}')
    pb=srxslit.nsls2slit(ib='XF:05IDA-OP:1{Slt:2-Ax:I}',ob='XF:05IDA-OP:1{Slt:2-Ax:O}')
    ssa=srxslit.nsls2slit(tb='XF:05IDB-OP:1{Slt:SSA-Ax:T}', bb='XF:05IDB-OP:1{Slt:SSA-Ax:B}', ob='XF:05IDB-OP:1{Slt:SSA-Ax:O}',ib='XF:05IDB-OP:1{Slt:SSA-Ax:I}')

    x3acq=PV('XSPRESS3-EXAMPLE:Acquire',connection_timeout=2)
    x3erase=PV('XSPRESS3-EXAMPLE:ERASE',connection_timeout=2)
    x3acqtime=PV('XSPRESS3-EXAMPLE:AcquireTime',connection_timeout=2)
    x3acqnum=PV('XSPRESS3-EXAMPLE:NumImages',connection_timeout=2)
    x3tmode=PV('XSPRESS3-EXAMPLE:TriggerMode',connection_timeout=2)
    x3h5path=PV('XSPRESS3-EXAMPLE:HDF5:FilePath',connection_timeout=2)
    x3h5fname=PV('XSPRESS3-EXAMPLE:HDF5:FileName',connection_timeout=2)
    x3h5fnum=PV('XSPRESS3-EXAMPLE:HDF5:FileNumber',connection_timeout=2)
    x3h5vdim=PV('XSPRESS3-EXAMPLE:HDF5:NumExtraDims',connection_timeout=2)
    x3h5size=PV('XSPRESS3-EXAMPLE:HDF5:ExtraDimSizeN',connection_timeout=2)
    x3h5d1=PV('XSPRESS3-EXAMPLE:HDF5:ExtraDimSizeX',connection_timeout=2)
    x3h5d2=PV('XSPRESS3-EXAMPLE:HDF5:ExtraDimSizeY',connection_timeout=2)
    #report ROIs for channels and counts at each point
    x3ch1roi0min=PV('XSPRESS3-EXAMPLE:C1_MCA_ROI1_LLM',connection_timeout=2)
    x3ch1roi0max=PV('XSPRESS3-EXAMPLE:C1_MCA_ROI1_HLM',connection_timeout=2)
    x3ch1roi0ct=PV('XSPRESS3-EXAMPLE:C1_ROI1:Value_RBV',connection_timeout=2)
    x3ch1roi1min=PV('XSPRESS3-EXAMPLE:C1_MCA_ROI2_LLM',connection_timeout=2)
    x3ch1roi1max=PV('XSPRESS3-EXAMPLE:C1_MCA_ROI2_HLM',connection_timeout=2)
    x3ch1roi1ct=PV('XSPRESS3-EXAMPLE:C1_ROI2:Value_RBV',connection_timeout=2)
    x3ch1roi2min=PV('XSPRESS3-EXAMPLE:C1_MCA_ROI3_LLM',connection_timeout=2)
    x3ch1roi2max=PV('XSPRESS3-EXAMPLE:C1_MCA_ROI3_HLM',connection_timeout=2)
    x3ch1roi2ct=PV('XSPRESS3-EXAMPLE:C1_ROI3:Value_RBV',connection_timeout=2)
    x3ch2roi0min=PV('XSPRESS3-EXAMPLE:C2_MCA_ROI1_LLM',connection_timeout=2)
    x3ch2roi0max=PV('XSPRESS3-EXAMPLE:C2_MCA_ROI1_HLM',connection_timeout=2)
    x3ch2roi0ct=PV('XSPRESS3-EXAMPLE:C2_ROI1:Value_RBV',connection_timeout=2)
    x3ch2roi1min=PV('XSPRESS3-EXAMPLE:C2_MCA_ROI2_LLM',connection_timeout=2)
    x3ch2roi1max=PV('XSPRESS3-EXAMPLE:C2_MCA_ROI2_HLM',connection_timeout=2)
    x3ch2roi1ct=PV('XSPRESS3-EXAMPLE:C2_ROI2:Value_RBV',connection_timeout=2)
    x3ch2roi2min=PV('XSPRESS3-EXAMPLE:C2_MCA_ROI3_LLM',connection_timeout=2)
    x3ch2roi2max=PV('XSPRESS3-EXAMPLE:C2_MCA_ROI3_HLM',connection_timeout=2)
    x3ch2roi2ct=PV('XSPRESS3-EXAMPLE:C2_ROI3:Value_RBV',connection_timeout=2)
    x3ch3roi0min=PV('XSPRESS3-EXAMPLE:C3_MCA_ROI1_LLM',connection_timeout=2)
    x3ch3roi0max=PV('XSPRESS3-EXAMPLE:C3_MCA_ROI1_HLM',connection_timeout=2)
    x3ch3roi0ct=PV('XSPRESS3-EXAMPLE:C3_ROI1:Value_RBV',connection_timeout=2)
    x3ch3roi1min=PV('XSPRESS3-EXAMPLE:C3_MCA_ROI2_LLM',connection_timeout=2)
    x3ch3roi1max=PV('XSPRESS3-EXAMPLE:C3_MCA_ROI2_HLM',connection_timeout=2)
    x3ch3roi1ct=PV('XSPRESS3-EXAMPLE:C3_ROI2:Value_RBV',connection_timeout=2)
    x3ch3roi2min=PV('XSPRESS3-EXAMPLE:C3_MCA_ROI3_LLM',connection_timeout=2)
    x3ch3roi2max=PV('XSPRESS3-EXAMPLE:C3_MCA_ROI3_HLM',connection_timeout=2)
    x3ch3roi2ct=PV('XSPRESS3-EXAMPLE:C3_ROI3:Value_RBV',connection_timeout=2)


    #claim ROI 4 for our own use.  we will integrate over all 4096 channels.
    x3ch1roi3min=PV('XSPRESS3-EXAMPLE:C1_MCA_ROI4_LLM',connection_timeout=2)
    x3ch1roi3max=PV('XSPRESS3-EXAMPLE:C1_MCA_ROI4_HLM',connection_timeout=2)
    x3ch1roi3ct=PV('XSPRESS3-EXAMPLE:C1_ROI4:Value_RBV',connection_timeout=2)
    x3ch2roi3min=PV('XSPRESS3-EXAMPLE:C2_MCA_ROI4_LLM',connection_timeout=2)
    x3ch2roi3max=PV('XSPRESS3-EXAMPLE:C2_MCA_ROI4_HLM',connection_timeout=2)
    x3ch2roi3ct=PV('XSPRESS3-EXAMPLE:C2_ROI4:Value_RBV',connection_timeout=2)
    x3ch3roi3min=PV('XSPRESS3-EXAMPLE:C3_MCA_ROI4_LLM',connection_timeout=2)
    x3ch3roi3max=PV('XSPRESS3-EXAMPLE:C3_MCA_ROI4_HLM',connection_timeout=2)
    x3ch3roi3ct=PV('XSPRESS3-EXAMPLE:C3_ROI4:Value_RBV',connection_timeout=2)

#    xmot_cur.get()
    xmot_cur.connect()
#    ymot_cur.get()
    ymot_cur.connect()

    norm0=PV('XF:05IDD-BI:1{BPM:01}.S20',connection_timeout=2)
    norm1=PV('XF:05IDD-BI:1{BPM:01}.S21',connection_timeout=2)
    norm2=PV('XF:05IDD-BI:1{BPM:01}.S22',connection_timeout=2)
    norm3=PV('XF:05IDD-BI:1{BPM:01}.S23',connection_timeout=2)

    xmot_cur.add_callback(cbfx)
    ymot_cur.add_callback(cbfy)
    shut_status.add_callback(cbf_shut)
    beam_current.add_callback(cbf_curr)
    xmot_cur.run_callbacks()
    ymot_cur.run_callbacks()
    shut_status.run_callbacks()
    beam_current.run_callbacks()

    x3h5path.put(H5path)
    x3h5fname.put(repr(D0)+'_'+repr(D1)+'_'+repr(D2)+'_'+repr(D3)+'_'+repr(D4)+'_')
    x3h5fnum.put(0)
    x3acqtime.put(options.acqt)
    x3acqnum.put(options.acqn)
    x3tmode.put(1)

    x3ch1roi3min.put(0)
    x3ch2roi3min.put(0)
    x3ch3roi3min.put(0)
    x3ch1roi3max.put(4096)
    x3ch2roi3max.put(4096)
    x3ch3roi3max.put(4096)
    #h5 set up
    x3h5vdim.put(2)
    x3h5size.put(options.acqn)
    x3h5d1.put(options.Nx+1)
    x3h5d2.put(options.Ny+1)
    dett.put(3)
    #overhead on triggering F460
    deti.put(float(options.acqn)*options.acqt*1.)
    detinit.put(1)
    #ring buffer and PV for tracking ion chamber value
    ic_hist=collections.deque(maxlen=50)
    ic_hist.append(0.)
    v19st=PV('XF:05IDA-UT{Cryo:1-IV:19}Pos-I',connection_timeout=4)
    v19st.connect()

    str='#NSLS-II SRX'+time.asctime()
    fp.write(str)
    fp.write('\n')
    str='#Start time is '+time.asctime()
    print str
    fp.write(str)
    fp.write('\n')
    str='# x: %(hs)6.4f ; y: %(vs)6.4f ; ROI1 %(roi1i)d:%(roi1a)d ; ROI2 %(roi2i)d:%(roi2a)d ; ROI3 %(roi3i)d:%(roi3a)d'%\
     {"hs":xmot_cur.get(),"vs":ymot_cur.get(), 'roi1i':x3ch1roi0min.get(), 'roi1a':x3ch1roi0max.get(), 'roi2i':x3ch1roi1min.get(), 'roi2a':x3ch1roi1max.get(), 'roi3i':x3ch1roi2min.get(), 'roi3a':x3ch1roi2max.get()}
    print str
    fp.write(str)
    fp.write('\n')
    roits=x3ch3roi3ct.timestamp
    str='# SSA HCEN: %(WBHC)f ; SSA HSIZE: %(WBHS)f ; SSA VCEN: %(WBVC)f ; SSA VSIZE: %(WBVS)f'%\
     {"WBHC":ssa.hcen(), "WBHS":ssa.hsize(), "WBVC":ssa.vcen(), "WBVS":ssa.vsize()}
    print str
    fp.write(str)
    fp.write('\n')
    str='# Bragg: %(B)6.4f ; Energy: %(E)6.4f ; WB HCEN: %(WBHC)f ; WB HSIZE: %(WBHS)f ; WB VCEN: %(WBVC)f ; WB VSIZE: %(WBVS)f'%\
     {"B":bmot_cur.get(), "E": 12398. / (2 * 3.12964794061 * math.sin((bmot_cur.get()+0.323341791985)/180.*3.1416)), "WBHC":wb.hcen(), "WBHS":wb.hsize(), "WBVC":wb.vcen(), "WBVS":wb.vsize()}
    print str
    fp.write(str)
    fp.write('\n')
    str="# --------------------------------------------------------------------    "
    print str
    fp.write(str)
    fp.write('\n')
    str='#[point #]\tX pos\t\tY pos\tch 1\t\tch 2\t\tch 3\t\tch 4\tdBPM1\t\tdBPM2\t\tdBPM3\t\tdBPM4\t\troi0\t\troi1\t\troi2\t\troi3\t\ttime'
    print str
    fp.write(str)
    fp.write('\n')
    if options.sim is True:
        str="      -----simulating motor moves and bursts-----"
        print str
        fp.write(str)
        fp.write('\n')
    else:
        x3h5capture.put(1)
        dett.put(4)
        time.sleep(2)
        thisisstupid=0
        while x3h5capture.get() == 0:
            time.sleep(0.5)
            thisisstupid+=1
            if (thisisstupid%20==0):
                print "waiting for xspress3"
        dett.put(3)
        ic_hist.append(diode1.get())
        

    #number of rows and columns completed by scan
    Ncol=Nrow=0
    LN=0

    #diode readback is now limiting factor for scan speed
    oldsig=0.
    #when the cryocooler kicks in, the beam is unusable for ~3200sec
#    cryo=PV('XF:05IDA-OP:1{Mono:HDCM}T:LN2Out-I')
#    ct=cryo.get()
#    while( ct is None):
#        time.sleep(0.1)
#        ct=cryo.get()
#        print "waiting for cryocooler to respond"
    t0=time.time()
    cryocounter=0
    shut_toggle=False

    #nested loops for scanning z,x,y
    for y in np.linspace(yo,yo+((Ny)*dy),Ny+1):
        tar[1][0]=y
        tar[1][1]=1
        if options.sim is False:
            ymot.put(tar[1][0])
        if indeadband(float(tar[1][0]),float(ymot_cur.get()),dbd)==1:
            tar[1][1] = 0
        if Nrow%2==0:
            xs=0.+xo
            xe=((Nx+1)*dx)+xo-dx
            xi=dx
        else:
            xs=((Nx)*dx)+xo
            xe=0.+xo
            xi=-dx
        for x in np.linspace(xs,xe,Nx+1):
            tar[0][0]=x
            tar[0][1]=1
            if indeadband(float(tar[0][0]),float(xmot_cur.get()),dbd)==1:
                tar[0][1]=0
            if options.sim is False:
                xmot.put(tar[0][0])
                while ((tar[0][1] == 1) or (tar[1][1] == 1)):
                    time.sleep(0.01)
            signal0=signal1=signal2=signal3=0.
            nsig0=nsig1=nsig2=nsig3=0.
            sig0=sig1=sig2=sig3=0.
#            while ( options.checkbeam and (cryo.get() < (ct - 0.1)) ):
#                    print "Stopped.  Detected possible cryocooler activation."
#                    time.sleep(1)
#                    cryocounter=cryocounter+1
            #if the above is true for five cycles, the cryocooler was on, wait another 10min
#            if ( options.checkbeam and cryocounter > 300 ):
#                print "Detected cryocooler activation, waiting 10min"
#                time.sleep(600)
#                cryocounter=0
            #this is my averge IC current
            tavg=np.asarray(ic_hist).mean()
            #check the filling valve status and set flag high if it is open
            while ( options.checkcryo and (v19st.get() > 0.)):
                print "Stopped.  Crycooler valve V19 is open."
                cryocounter=1
                time.sleep(1)
            #while the ion chamber is reading less than 80% of previous history, sleep
            while (cryocounter==1):
                #trigger the 460 and store the ion chamber value
                dett.put(4)
                time.sleep(5+options.acqt)
                oldsig=diode1.get()
                dett.put(3)
                #if the reading is less than 80% of historical value or the valve is open, sleep
                #remember that the reading is negative-going
                if (oldsig > (-1.*0.8*tavg)) and (v19st.get > 0.):
                    print "Beam current has not returned"
                    time.sleep(30)
                else:
                    cryocounter=0
            while ( options.checkbeam and (shut_open == False or beam_current == False)):
                print "Stopped.  Waiting for scan conditions to return to normal."
                if shut_open==False:
                    shut_toggle=True
                time.sleep(10.)
            if shut_toggle==True:
                print "Entering optics conditioning period.  Waiting 5min"
                time.sleep(300)
                shut_toggle=False
            if options.sim is False:
                x3erase.put(1)
                dett.put(4)
                while nsig0==0.:
                    nsig0=float(norm0.get())
                while nsig1==0.:
                    nsig1=float(norm1.get())
                while nsig2==0.:
                    nsig2=float(norm2.get())
                while nsig3==0.:
                    nsig3=float(norm3.get())
                sig0=0
                sig1=0
                sig2=0
                sig3=0
                for i in range(0,options.acqn):
                    x3acq.put(1)
                    while ( x3ch3roi3ct.get()==0.0 or x3ch3roi3ct.timestamp==roits):
                        time.sleep(0.02)
                    sig0=sig0+x3ch1roi0ct.get()+x3ch2roi0ct.get()+x3ch3roi0ct.get()
                    sig1=sig1+x3ch1roi1ct.get()+x3ch2roi1ct.get()+x3ch3roi1ct.get()
                    sig2=sig2+x3ch1roi2ct.get()+x3ch2roi2ct.get()+x3ch3roi2ct.get()
                    sig3=sig3+x3ch1roi3ct.get()+x3ch2roi3ct.get()+x3ch3roi3ct.get()
                    roits=x3ch3roi3ct.timestamp
                signal0=diode0.get()            
                if signal0==oldsig:
                    time.sleep(0.02)
                    signal0=diode0.get()            
                oldsig=signal0
                signal1=diode1.get()
                signal2=diode2.get()            
                signal3=diode3.get()            
                dett.put(3)
                #populate a ring buffer with every 100th ion chamber reading
                #we will use the average of this buffer to determine recovery
                #from a cryocooler activation
                if(Nx%100 ==0):
                    ic_hist.append(signal1)
            time.sleep(twait)
            tn=time.time()-t0
            if options.sim is False:
                str='%(X)06d %(XC)9.4f %(YC)9.4f %(d1)10.7e %(d2)10.7e %(d3)10.7e %(d4)10.7e %(n0)10.7e %(n1)10.7e %(n2)10.7e %(n3)10.7e %(s0)10.7e %(s1)10.7e %(s2)10.7e %(s3)10.7e %(time)9.2f'%{ 'X':Ncol, 'XC':xmot_cur.get(),"YC":ymot_cur.get(), "d1":float(signal0), "d2":float(signal1), "d3":float(signal2),"d4":float(signal3), 'n0':nsig0, 'n1':nsig1, 'n2':nsig2, 'n3':nsig3, "s0":sig0,"s1":sig1,"s2":sig2,"s3":sig3, "time":tn}
                print str
                fp.write(str)
                fp.write('\n')
            else:
                str='%(X)06d %(XC)8.4f  %(YC)8.4f %(d1)10.7e %(d2)10.7e %(d3)10.7e %(d4)10.7e'%{"X":int(Ncol),"XC":tar[0][0], "YC":tar[1][0], "d1":float(signal0), "d2":float(signal1), "d3":float(signal2),"d4":float(signal3)}     
                print str
                fp.write(str)
                fp.write('\n')
    
            Ncol=Ncol+1
        Nrow=Nrow+1

    str='#End time is '+time.asctime()
    print str
    fp.write(str)
    fp.write('\n')
    fp.close()
    xmot_cur.clear_callbacks()
    ymot_cur.clear_callbacks()
    shut_status.clear_callbacks()
    beam_current.clear_callbacks()

    return 0
Пример #19
0
class XAFSviewerFrame(wx.Frame):
    def __init__(self, parent=None, *args, **kwds):

        kwds["style"] = wx.DEFAULT_FRAME_STYLE | wx.RESIZE_BORDER | wx.TAB_TRAVERSAL

        wx.Frame.__init__(self, parent, wx.NewId(), '', wx.DefaultPosition, wx.Size(-1, -1), **kwds)
        self.SetTitle(" WXMPlot Plotting Demo")

        self.SetFont(wx.Font(12, wx.SWISS, wx.NORMAL, wx.BOLD, False))
        menu = wx.Menu()
        ID_EXIT = wx.NewId()
        ID_TIMER = wx.NewId()

        menu.Append(ID_EXIT, "E&xit", "Terminate the program")

        menuBar = wx.MenuBar()
        menuBar.Append(menu, "&File")
        self.SetMenuBar(menuBar)

        wx.EVT_MENU(self, ID_EXIT, self.OnExit)

        self.Bind(wx.EVT_CLOSE, self.OnExit)
        
        self.plotframe = None

        framesizer = wx.BoxSizer(wx.VERTICAL)

        panel = wx.Panel(self, -1, size=(-1, -1))
        panelsizer = wx.BoxSizer(wx.VERTICAL)

        panelsizer.Add(wx.StaticText(panel, -1, 'XAFS Spectra viewer '),
                       0, wx.ALIGN_LEFT | wx.ALIGN_CENTER | wx.LEFT | wx.EXPAND, 10)

        b40 = wx.Button(panel, -1, 'Start Timed Plot',    size=(-1, -1))
        #b40.Bind(wx.EVT_BUTTON,self.onStartTimer)
        panelsizer.Add(b40, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER | wx.LEFT, 5)

        panel.SetSizer(panelsizer)
        panelsizer.Fit(panel)

        framesizer.Add(panel, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER | wx.EXPAND, 2)
        self.SetSizer(framesizer)
        framesizer.Fit(self)

        #----------- added by LWW -----------------------------
        self.ShowPlotFrame(do_raise=False, clear=False)
        self.plotYdata = []
        self.plotXdata = []

        # ----------epics PVs-----------------------
        self.i0 = PV('BL10C:scaler1_calc2.VAL')
        self.it = PV('BL10C:scaler1_calc3.VAL')
        self.iF = PV('BL10C:scaler1_calc4.VAL')
        self.trans = PV('BL10C:scaler1_calc8.VAL')
        self.motorPos = PV('mobiis:m2.RBV')
        
        self.scanStart = PV('BL10C:scan2.EXSC.VAL', callback=self.scanStartCALLBACK)
        
        while self.motorPos.get() is None:
            print self.motorPos.get()
        
        self.countDonePV = PV('BL10C:scaler1.CNT', callback=self.countDoneCALLBACK)
        
        self.time0 = time.time()
        self.datrange = None
        #----------- end of add by LWW -----------------------
        
        #wx.EVT_TIMER(self, ID_TIMER, self.onTimer)
        #self.timer = wx.Timer(self, ID_TIMER)
        self.Refresh()

    # --------------epics callback method---------------------
    def scanStartCALLBACK(self, **kwargs):
        if kwargs['value'] is 1:  # 0:Done, 1: scanning
            self.ShowPlotFrame(do_raise=True, clear=True)
            
            print 'New Scan Started!!!'
        
        else:
            print 'scan stopped!!!'
        
        return
    
    def countDoneCALLBACK(self, **kwargs):
        if kwargs['value'] is 1:  # 0:Done, 1:Counting
            return

        ## self._flag = True
        self.plotYdata.append(self.trans.get())
        self.plotXdata.append(self.motorPos.get())
        ## self._flag = False
        
        print 'X:%s,  Y:%s' % (len(self.plotXdata), len(self.plotYdata))
        
        # Todo: we need new scan start sequence.
        #       new list, graph clear, data save...,
        # print 'timer ', self.count, time.time()
        ## self.count += 1
        #self.ShowPlotFrame(do_raise=False, clear=False)
        ## n = self.count
        if len(self.plotXdata) < 2:
            return
        # Todo: implementation of scan finish sequence.
        '''
        if n >= self.npts:
            self.timer.Stop()
            self.timer_results()
        elif n <= 3:
        '''
        if len(self.plotXdata) <= 3:
            self.plotframe.plot(self.plotXdata, self.plotYdata,
                                linewidth=0.5, marker='o',
                                markersize=6, xlabel='energy[eV]',
                                ylabel='[count]')
                                # , grid=False)

        else:
            xx = np.array(self.plotXdata)
            yy = np.array(self.plotYdata)
            
            self.plotframe.update_line(0, xx, yy, update_limits=len(xx) < 10, draw=True)
            
            etime = time.time() - self.time0
            s = " %i / %i points in %8.4f s" % (len(self.plotXdata), len(self.plotYdata), etime)
            self.plotframe.write_message(s)

        if self.datrange is None:
            self.datrange = [min(self.plotXdata), max(self.plotXdata), min(self.plotYdata), max(self.plotYdata)]

        dr = [min(self.plotXdata), max(self.plotXdata),
              min(self.plotYdata), max(self.plotYdata)]
        
        lims = self.plotframe.panel.get_viewlimits()
        if dr[0] < lims[0] or dr[1] > lims[1] or dr[2] < lims[2] or dr[3] > lims[3]:
            self.datrange = dr
            ## if len(self.plotXdata) < len(self.x):
            ##     nmax = min(int(n*1.6), len(self.x)-1)
            ##     self.datrange[1] = self.x[nmax]
            self.plotframe.panel.set_xylims(self.datrange)
            
    def ShowPlotFrame(self, do_raise=True, clear=True):
        """make sure plot frame is enabled, and visible"""
        if self.plotframe is None:
            self.plotframe = PlotFrame(self, axissize=[0.08, 0.06, 0.91, 0.92])
            # self.has_plot = False
        try:
            self.plotframe.Show()
        except wx.PyDeadObjectError:
            self.plotframe = PlotFrame(self, axissize=[0.08, 0.06, 0.91, 0.92])
            self.plotframe.Show()

        if do_raise:
            self.plotframe.Raise()
        if clear:
            self.plotframe.panel.clear()
            self.plotframe.reset_config()
            
            self.plotYdata = []
            self.plotXdata = []
            
    '''    
    def onStartTimer(self,event=None):
        self.count    = 0
        self.up_count = 0
        self.n_update = 1
        self.datrange = None
        self.time0    = time.time()
        ### LWW self.start_mem= self.report_memory()
        self.timer.Start(10)
        # self.timer.Start(500)
    
    def timer_results(self):
        if (self.count < 2): return
        etime = time.time() - self.time0
        tpp   = etime/max(1,self.count)
        s = "drew %i points in %8.3f s: time/point= %8.4f s" % (self.count,etime,tpp)
        self.plotframe.write_message(s)
        self.time0 = 0
        self.count = 0
        self.datrange = None
    '''
    '''
    def onTimer(self, event):
        # print 'timer ', self.count, time.time()
        self.count += 1
        self.ShowPlotFrame(do_raise=False, clear=False)
        n = self.count
        if n < 2:
            return
        if n >= self.npts:
            self.timer.Stop()
            self.timer_results()
        elif n <= 3:
            self.plotframe.plot(self.x[:n], self.y1[:n])# , grid=False)

        else:
            self.plotframe.update_line(0, self.x[:n], self.y1[:n], update_limits=n<10, draw=True)

            etime = time.time() - self.time0
            s = " %i / %i points in %8.4f s" % (n,self.npts,etime)
            self.plotframe.write_message(s)

        if self.datrange is None:
            self.datrange = [min(self.x[:n]), max(self.x[:n]),
                             min(self.y1[:n]),max(self.y1[:n])]

        dr = [min(self.x[:n]),  max(self.x[:n]),
              min(self.y1[:n]), max(self.y1[:n])]
        
        lims = self.plotframe.panel.get_viewlimits()
        if dr[0] < lims[0] or dr[1] > lims[1] or dr[2] < lims[2] or dr[3] > lims[3]:
            self.datrange = dr
            if n < len(self.x):
                nmax = min(int(n*1.6), len(self.x)-1)
                self.datrange[1] = self.x[nmax]
            self.plotframe.panel.set_xylims(self.datrange)
    '''
    def OnAbout(self, event):
        dlg = wx.MessageDialog(self, "This program shows MCA Spectra\n"
                                     "message dialog.",
                                     "About MPlot test", wx.OK | wx.ICON_INFORMATION)
        dlg.ShowModal()
        dlg.Destroy()

    def OnExit(self, event):
        # 1st. disconnect PV(s)
        self.countDonePV.clear_callbacks()
        self.i0.disconnect()
        self.it.disconnect()
        self.iF.disconnect()
        self.trans.disconnect()
        self.motorPos.disconnect()
        
        try:
            if self.plotframe is not None:
                self.plotframe.onExit()
        except:
            pass
        self.Destroy()