|
1 | 1 | #!/usr/bin/env python |
2 | | -# For doing DAQ scans. Logs PV data to a file while doing scan of an arbitrary PV. Uses a supporting IOC (pvScan). |
| 2 | +# For doing DAQ scans. Logs PV data to a file while doing beam scan. Uses a supporting IOC (pvScan). |
3 | 3 | # mdunning 1/7/16 |
4 | 4 |
|
5 | | -from epics import PV |
| 5 | +from epics import caget,caput,PV |
6 | 6 | from time import sleep |
7 | 7 | import datetime,os,sys |
8 | 8 | from threading import Thread |
9 | 9 |
|
| 10 | +args='PV_PREFIX' |
10 | 11 |
|
11 | | -# PV prefix for pvScan IOC; should be passed as an argument to this script. |
| 12 | +def show_usage(): |
| 13 | + "Prints usage" |
| 14 | + print 'Usage: %s %s' %(sys.argv[0], args) |
| 15 | + |
| 16 | +if len(sys.argv) != 2: |
| 17 | + show_usage() |
| 18 | + sys.exit(1) |
| 19 | + |
| 20 | +# PV prefix for pvScan IOC; should be passed as an argument |
12 | 21 | pvPrefix=sys.argv[1] |
13 | 22 | # Set an environment variable for so pvScan module can use it |
14 | 23 | os.environ['PVSCAN_PVPREFIX']=pvPrefix |
15 | 24 |
|
16 | 25 | # Import pvScan module |
17 | 26 | sys.path.append('/afs/slac/g/testfac/extras/scripts/pvScan/R2.0/modules/') |
18 | | -import pvScan2 |
19 | | - |
20 | | -#--- Experiment --------------------------------------- |
21 | | -# Create Experiment object. Sets default filepath and gets experiment name from PV. |
22 | | -# First argument (optional) is an experiment name. |
23 | | -# Second arg (optional) is a filepath. |
24 | | -exp1=pvScan2.Experiment() |
25 | | -sleep(2) |
26 | | - |
27 | | -#--- Scan PVs ------------------------------------------ |
28 | | -# Create ScanPv objects, one for each PV you are scanning. |
29 | | -# First argument is the scan PV, leave blank to get from pvScan IOC. |
30 | | -# Second arg is an index which should be unique. |
31 | | -scanPv1=pvScan2.ScanPv('',1) # (UED Solenoid) |
32 | | - |
33 | | -#--- Shutters ----------------------------------------- |
34 | | -# Create Shutter objects. |
35 | | -# First argument is shutter PV. |
36 | | -# Second arg (optional) is an RBV PV, for example an ADC channel. |
37 | | -shutter1=pvScan2.DummyShutter('ESB:GP01:VAL01','ESB:GP01:VAL01') # (UED Drive laser) |
38 | | -shutter2=pvScan2.DummyShutter('ESB:GP01:VAL02','ESB:GP01:VAL02') # (UED pump laser) |
39 | | -shutter3=pvScan2.DummyShutter('ESB:GP01:VAL03','ESB:GP01:VAL03') # (UED HeNe laser) |
| 27 | +import pvScan |
| 28 | + |
| 29 | +# Scan PVs |
| 30 | +scanPv1=pvScan.ScanPv('ESB:GP01:VAL04',1) # ScanPv class instance (UED Solenoid) |
40 | 31 | # |
41 | | -# Create ShutterGroup object to use common functions on all shutters. |
42 | | -# Argument is a list of shutter objects. |
43 | | -shutterGroup1=pvScan2.ShutterGroup([shutter1,shutter2,shutter3]) |
| 32 | +# Shutters. Make a list for each group, to use shutterFunction() |
| 33 | +shutter1=pvScan.DummyShutter('ESB:GP01:VAL01') # Shutter 1 class instance (UED Drive laser) |
| 34 | +shutter2=pvScan.DummyShutter('ESB:GP01:VAL02') # Shutter 2 class instance (UED pump laser) |
| 35 | +shutter3=pvScan.DummyShutter('ESB:GP01:VAL03') # Shutter 3 class instance (UED HeNe laser) |
| 36 | +shutterList=[shutter1,shutter2,shutter3] |
| 37 | +shutterTTLEnablePVList=[] |
| 38 | +shutterTTLDisablePVList=[] |
| 39 | +shutterOpenPVList=[] |
| 40 | +shutterClosePVList=[] |
| 41 | +shutterSoftPVList=[] |
| 42 | +shutterFastPVList=[] |
| 43 | +for i in xrange(len(shutterList)): |
| 44 | + shutterTTLEnablePVList.append(shutterList[i].ttlInEnable) |
| 45 | + shutterTTLDisablePVList.append(shutterList[i].ttlInDisable) |
| 46 | + shutterOpenPVList.append(shutterList[i].open) |
| 47 | + shutterClosePVList.append(shutterList[i].close) |
| 48 | + shutterSoftPVList.append(shutterList[i].soft) |
| 49 | + shutterFastPVList.append(shutterList[i].fast) |
| 50 | +# Shutter RBVs |
| 51 | +shutter1RBVPv=PV('ESB:GP01:VAL01') |
| 52 | +shutter2RBVPv=PV('ESB:GP01:VAL02') |
| 53 | +shutter3RBVPv=PV('ESB:GP01:VAL03') |
| 54 | +shutterRBVPVList=[shutter1RBVPv,shutter2RBVPv,shutter3RBVPv] |
44 | 55 | # |
45 | | -#--- Other PVs ----------------- |
46 | | -# Define as PV objects. Example PV('MY:RANDOM:PV') |
| 56 | +# ADC values |
47 | 57 | #lsrpwrPv=PV('ESB:A01:ADC1:AI:CH3') |
48 | 58 | #toroid0355Pv=PV('ESB:A01:ADC1:AI:CH4') |
49 | 59 | #toroid2150Pv=PV('ESB:A01:ADC1:AI:CH5') |
50 | 60 | #structureChargePv=PV('ESB:A01:ADC1:CALC:CH1:CONV') |
51 | 61 |
|
52 | | -#---- Data logging -------------------------- |
53 | | -# List of PV() objects to be monitored during scan. |
54 | | -dataLogPvList=shutterGroup1.rbv + [scanPv1] |
55 | | -# |
56 | | -# Create DataLogger object. |
57 | | -# Argument is the list of PVs to monitor. |
58 | | -dataLog1=pvScan2.DataLogger(dataLogPvList) |
| 62 | +pause1=1.0 # sec |
| 63 | + |
| 64 | +#---- For data logging -------------------------- |
| 65 | +pvList=[shutter1RBVPv,shutter2RBVPv,shutter3RBVPv,scanPv1] # list of PVs to be monitored during scan |
| 66 | +expName=PV(pvPrefix + ':IOC.DESC').get() |
| 67 | +if ' ' in expName: expName=expName.replace(' ','_') |
| 68 | +now=datetime.datetime.now().strftime("%Y%m%d_%H%M%S") |
| 69 | +filepath=os.environ['NFSHOME'] + '/pvScan/' + expName + '/' + now + '/' |
| 70 | +if not os.path.exists(filepath): os.makedirs(filepath) |
| 71 | +filepathPv=PV(pvPrefix + ':DATA:FILEPATH') |
| 72 | +filepathPv.put(filepath) # Write filepath to PV for display |
| 73 | +dataFilename=filepath + now + '.dat' |
| 74 | +dataFilenamePv=PV(pvPrefix + ':DATA:FILENAME') |
| 75 | +dataFilenamePv.put(dataFilename) |
| 76 | +logFilename=filepath + now + '.log' |
| 77 | +logFilenamePv=PV(pvPrefix + ':LOG:FILENAME') |
| 78 | +logFilenamePv.put(logFilename) |
| 79 | +dataEnable=PV(pvPrefix + ':DATA:ENABLE').get() # Enable/Disable data logging |
| 80 | +dataInt=PV(pvPrefix + ':DATA:INT').get() # Interval between PV data log points |
| 81 | +nPtsMax=100000 # limits number of data points |
59 | 82 | #------------------------------------------------- |
60 | 83 |
|
61 | | -# --- Image grabbing -------------------------- |
62 | | -# Override saved camera settings here. Leave empty list to use the default; otherwise add PVs with single quotes. |
63 | | -grabImagesSettingsPvList=['13PS10:cam1:Manufacturer_RBV'] |
64 | | -# |
65 | | -# Create ImageGrabber object. |
66 | | -# First arg is the camera PV prefix. |
67 | | -# Second arg (optional) is a list of camera setting PVs to be dumped to a file. |
68 | | -# Third arg (optional) is the image grabbing plugin. |
69 | | -grab1=pvScan2.ImageGrabber('13PS10') |
| 84 | +# --- For grabbing images -------------------------- |
| 85 | +grabImagesFlag=PV(pvPrefix + ':GRABIMAGES:ENABLE').get() |
| 86 | +grabImagesN=PV(pvPrefix + ':GRABIMAGES:N').get() |
| 87 | +grabImagesFilepath=filepath + 'images/' |
| 88 | +grabImagesPlugin='TIFF1' |
| 89 | +grabImagesSource='13PS10' |
| 90 | +# Leave grabImagesSettingsPvList=[] to use the default |
| 91 | +grabImagesSettingsPvList=[] |
70 | 92 | #------------------------------------------------------------- |
71 | 93 |
|
72 | | -### Define scan routine ##################################################### |
| 94 | +#################################################################################################### |
| 95 | + |
| 96 | +def singlePvScan(scanPv,grabImagesFlag=0,grabImagesN=0,grabImagesSource='',grabImagesFilepath='~/pvScan/images/',grabImagesPlugin='TIFF1',grabImagesFilenameExtras='',grabImagesWriteSettingsFlag=1,grabImagesSettingsPvList=[]): |
| 97 | + "Scans pv from start to stop in n steps, optionally grabbing images at each step." |
| 98 | + initialPos=scanPv.get() |
| 99 | + pvScan.printMsg('Starting scan') |
| 100 | + inc=(scanPv.stop-scanPv.start)/(scanPv.nsteps-1) |
| 101 | + for i in range(scanPv.nsteps): |
| 102 | + newPos=scanPv.start + i*inc |
| 103 | + pvScan.printMsg('Setting %s to %f' % (scanPv.pvname,newPos)) |
| 104 | + scanPv.put(newPos) |
| 105 | + pvScan.printSleep(scanPv.settletime,'Settling') |
| 106 | + if grabImagesFlag: |
| 107 | + grabImagesFilenameExtras='_ScanPV-' + '{0:08.4f}'.format(scanPv.get()) |
| 108 | + pvScan.grabImages(grabImagesN,grabImagesSource,grabImagesFilepath,grabImagesPlugin,grabImagesFilenameExtras,grabImagesWriteSettingsFlag,grabImagesSettingsPvList) |
| 109 | + # Move back to initial positions |
| 110 | + pvScan.printMsg('Setting %s back to initial position: %f' %(scanPv.pvname,initialPos)) |
| 111 | + scanPv.put(initialPos) |
73 | 112 |
|
74 | 113 | def scanRoutine(): |
75 | 114 | "This is the scan routine" |
76 | | - pvScan2.printMsg('Starting') |
77 | | - sleep(0.5) # Collect some initial data first |
| 115 | + pvScan.printMsg('Starting') |
| 116 | + sleep(pause1) |
78 | 117 | # Open shutters |
79 | | - pvScan2.printMsg('Opening shutters') |
80 | | - pvScan2.shutterFunction(shutterGroup1.open,1) |
| 118 | + #pvScan.printMsg('Opening shutters') |
| 119 | + #pvScan.shutterFunction(shutterOpenPVList,1) |
81 | 120 | # Scan delay stage and grab images... |
82 | | - pvScan2.ScanPv.pv1DScan(scanPv1,grab1) |
| 121 | + singlePvScan(scanPv1,grabImagesFlag,grabImagesN,grabImagesSource,grabImagesFilepath,grabImagesPlugin,grabImagesFilenameExtras='',grabImagesWriteSettingsFlag=1,grabImagesSettingsPvList=grabImagesSettingsPvList) |
83 | 122 | # Close shutters |
84 | | - pvScan2.printMsg('Closing shutters') |
85 | | - pvScan2.shutterFunction(shutterGroup1.close,0) |
86 | | - pvScan2.printMsg('Done') |
87 | | - |
88 | | -### Main program ##########################################################3 |
| 123 | + #pvScan.printMsg('Closing shutters') |
| 124 | + #pvScan.shutterFunction(shutterClosePVList,0) |
| 125 | + pvScan.printMsg('Done') |
89 | 126 |
|
90 | 127 | if __name__ == "__main__": |
91 | 128 | "Do scan routine; log PV data to file as a separate thread if enabled" |
| 129 | + pvScan.Tee(logFilename, 'w') |
| 130 | + pvScan.dataFlag=1 # Start logging data when thread starts |
| 131 | + if dataEnable==1: |
| 132 | + datalogthread=Thread(target=pvScan.datalog,args=(dataInt,dataFilename,pvList,nPtsMax)) |
| 133 | + datalogthread.start() |
92 | 134 | try: |
93 | | - args='PV_PREFIX' |
94 | | - def show_usage(): |
95 | | - "Prints usage" |
96 | | - print 'Usage: %s %s' %(sys.argv[0], args) |
97 | | - |
98 | | - if len(sys.argv) != 2: |
99 | | - show_usage() |
100 | | - sys.exit(1) |
101 | | - |
102 | | - pid=os.getpid() |
103 | | - pvScan2.pidPV.put(pid) |
104 | | - pvScan2.Tee(dataLog1.logFilename, 'w') |
105 | | - pvScan2.dataFlag=1 # Start logging data when thread starts |
106 | | - if dataLog1.dataEnable==1: |
107 | | - datalogthread=Thread(target=pvScan2.DataLogger.datalog,args=(dataLog1,)) |
108 | | - datalogthread.start() |
109 | 135 | scanRoutine() |
110 | | - sleep(2) # Log data for a little longer |
| 136 | + sleep(pause1) # Log data for a little longer |
111 | 137 | finally: |
112 | | - pvScan2.dataFlag=0 # Stop logging data |
| 138 | + pvScan.dataFlag=0 # Stop logging data |
113 | 139 |
|
114 | 140 |
|
115 | | -### End ########################################################################## |
| 141 | +################################################################################################################## |
116 | 142 |
|
117 | 143 |
|
118 | 144 | exit |
|
0 commit comments