1 | # |
---|
2 | # usaxs_uascan.mac |
---|
3 | # |
---|
4 | # USAXS-specific macros |
---|
5 | # maintained by Jan Ilavsky |
---|
6 | # last edit: 2012-02-29 |
---|
7 | # |
---|
8 | ########### SVN repository information ################### |
---|
9 | # $Date: 2012-04-02 13:51:57 -0500 (Mon, 02 Apr 2012) $ |
---|
10 | # $Author: jemian $ |
---|
11 | # $Revision: 524 $ |
---|
12 | # $HeadURL: https://subversion.xor.aps.anl.gov/spec/beamline_config/trunk/usaxs/usaxs/usaxs_uascan.mac $ |
---|
13 | # $Id: usaxs_uascan.mac 524 2012-04-02 18:51:57Z jemian $ |
---|
14 | ########### SVN repository information ################### |
---|
15 | # |
---|
16 | # this file contains the USAXSscan, uascan macro (1-D & 2-D collimated USAXS) and supporting subprograms. |
---|
17 | # June 02 - replaced all lax:upd2 with brq:pd01:seq01 to move UPD to e-brick |
---|
18 | # Oct. 6 - X Jiao Oct.6 |
---|
19 | # 2007-09-10,PRJ: replaced all "lax:" with "15iddLAX:" |
---|
20 | # September 27, 2007 replaced all "brq:" with "32idbUSX:" since the PVV names changed. JIL |
---|
21 | # OCT 2008 JIL - changed to epics variables |
---|
22 | # NOV 3 2008 changed Finish to be in Q units, JIL |
---|
23 | # MAY 09, chaned ar controls to new DC driven Aeortech stage, JIL |
---|
24 | # JUNE 10, changed all 32idbLAX/USXto 15iddLAX/USX after moved to 15idd |
---|
25 | # OCOTOBER 10, JIL - Changed to be able to use Femto300 amlifier |
---|
26 | # APRIL 20, 2011, PAB - Added useDynamicTime settings. |
---|
27 | # APRIL 26, 2011, PAB - Added useIntelligentTime setting. |
---|
28 | # February 29, 2012, JIL - added delay in uascan after PD range change to fix some problems. |
---|
29 | # globals: |
---|
30 | # these numbers should be mostly set in USAXS_conf.mac or other configuration file... |
---|
31 | |
---|
32 | global useSBUSAXS # set to 1 if running SBUSAXS geometry, else 0 |
---|
33 | global SAMPLE_DETECTOR_DISTANCE_MM # need to set configuration in USAXS.conf |
---|
34 | global SAMPLE_ANALYZER_DISTANCE_MM # need to set configuration in USAXS.conf |
---|
35 | global ARenc_CENTER # AR center in encoder value... Probably not needed anymore |
---|
36 | global SPEC_STD_TITLE # scan title |
---|
37 | global USAXS_SAMPLE_THICKNESS # sample thickness |
---|
38 | global ASRP_DEGREES_PER_VDC # calibration constant for asrp |
---|
39 | global Use_DLPCA300 # if 1, using Femto300 amplifier, if 0 usign Femto200 |
---|
40 | global PDstring |
---|
41 | global useDynamicTime # if 1, use dynamic count time (change count time 3 times during a scan at fixed point numbers). if 0, use static. |
---|
42 | global useIntelligentTime # if 1, use intelligent count time (nondeterministic method, chooses count time based on upd range). if 0, use static. |
---|
43 | global old_UPDRange # UPDRange for the last point |
---|
44 | global UPD_Change_delay # delay in usaxs scan after range change |
---|
45 | |
---|
46 | global CT_RANGE_1 |
---|
47 | global CT_RANGE_2 |
---|
48 | global CT_RANGE_3 |
---|
49 | global CT_RANGE_4 |
---|
50 | global CT_RANGE_5 |
---|
51 | |
---|
52 | # these are now epics variables |
---|
53 | #global ASRP0 # start value of Asrp |
---|
54 | #global USAXS_TIME # time to measure each point in USAX sscan |
---|
55 | #global AR_VAL_CENTER # center value for AR stage |
---|
56 | #global NUMPTS # number of points |
---|
57 | #global DY0 # start position of detector stage |
---|
58 | #global SDD # sample to detector disatnce |
---|
59 | #global AY0 # start analyzer height |
---|
60 | #global SAD # sample to analyzer distacne |
---|
61 | #global UATERM # weighing value... Changes spread of the log stepping |
---|
62 | #global SAMPLE_Y_STEP # sample Y movement, mm, to make after each step in the scan |
---|
63 | #global START_OFFSET # angle offset to start above AR_VAL_CENTER |
---|
64 | #global FINISH # end angle for USAXS scans |
---|
65 | #global USAXS_MINSTEP # min step of uascan |
---|
66 | |
---|
67 | # |
---|
68 | # |
---|
69 | # ASRP calibration. 8/2/2006 Found two different numbers... |
---|
70 | # ASRP_DEGREES_PER_VDC = 0.0039065 # (4.5 um/V) / (66mm arm) * (180/pi) |
---|
71 | ## ASRP_DEGREES_PER_VDC = 0.00586 # reported by PI, note sais, that it is confirmed by measurement |
---|
72 | ASRP_DEGREES_PER_VDC = 0.0059721 # measured by JI October 9, 2006 during setup at 32ID. Std Dev 4e-5 |
---|
73 | ####### |
---|
74 | ############################################################################# |
---|
75 | ############################################################################# |
---|
76 | ############################################################################# |
---|
77 | ################################################################################### |
---|
78 | ################################################################################### |
---|
79 | #### |
---|
80 | #### general scan macro for USAXS for both 1D & 2D collimations |
---|
81 | #### |
---|
82 | def USAXSscan '{ |
---|
83 | local pos_X pos_Y scan_title Finish_in_Angle _USAXS_Lambda |
---|
84 | |
---|
85 | global ARenc_CENTER |
---|
86 | global SPEC_STD_TITLE |
---|
87 | global USAXS_SAMPLE_THICKNESS |
---|
88 | global useSBUSAXS |
---|
89 | global USAXS_MEASURE_DARK_CURENTS |
---|
90 | if( $# != 4) { |
---|
91 | printf ("USAXSscan pos_X pos_Y thickness_mm scan_title\n"); |
---|
92 | exit; |
---|
93 | } |
---|
94 | pos_X = $1 |
---|
95 | pos_Y = $2 |
---|
96 | USAXS_SAMPLE_THICKNESS = $3 |
---|
97 | scan_title = \'$4\' |
---|
98 | |
---|
99 | # need to check pos_X and pos_Y against soft limits before proceeding |
---|
100 | _bad_lim = 0 |
---|
101 | _chk_lim sx pos_X |
---|
102 | _chk_lim sy pos_Y |
---|
103 | if (_bad_lim) { |
---|
104 | printf("sample position (%.3f,%.3f) exceeds soft limits\n", pos_X, pos_Y) |
---|
105 | exit; |
---|
106 | } |
---|
107 | |
---|
108 | SPEC_STD_TITLE = TITLE |
---|
109 | TITLE = scan_title |
---|
110 | |
---|
111 | epics_put ("15iddLAX:USAXS:sampleTitle", scan_title) |
---|
112 | epics_put ("15iddLAX:USAXS:state", sprintf("USAXS count time: %g seconds", USAXS_TIME)) |
---|
113 | epics_put ("15iddLAX:USAXS:userName", USER) |
---|
114 | epics_put ("15iddLAX:USAXS:userDir", CWD) |
---|
115 | epics_put ("15iddLAX:USAXS:specFile", DATAFILE) |
---|
116 | epics_put ("15iddLAX:USAXS:specScan", SCAN_N+1) |
---|
117 | if (useSBUSAXS) { |
---|
118 | epics_put ("15iddLAX:USAXS:scanMacro", "sbuascan") |
---|
119 | } else { |
---|
120 | epics_put ("15iddLAX:USAXS:scanMacro", "uascan") |
---|
121 | } |
---|
122 | epics_put ("15iddLAX:USAXS:timeStamp", date()) |
---|
123 | |
---|
124 | comment "Moving AR motor to %g degrees (beam center)" AR_VAL_CENTER |
---|
125 | mv ar AR_VAL_CENTER |
---|
126 | waitmove; get_angles; |
---|
127 | sleep (0.5) |
---|
128 | ARenc_CENTER = A[ar] |
---|
129 | comment "for next scan: encoder ARenc_CENTER = %7.4f" ARenc_CENTER |
---|
130 | |
---|
131 | # Set the center for the Q calculation for plotting here |
---|
132 | epics_put("15iddLAX:USAXS:Q.B", ARenc_CENTER-0.00005) |
---|
133 | |
---|
134 | START = AR_VAL_CENTER + START_OFFSET |
---|
135 | MINSTEP = USAXS_MINSTEP # JI 10 26 2006 change to allow user specified min step |
---|
136 | TIME = USAXS_TIME |
---|
137 | |
---|
138 | epics_put ("15iddLAX:USAXS:state", "moving sample into beam") |
---|
139 | moveSample pos_X pos_Y |
---|
140 | |
---|
141 | #Calculate Finish in angle, since now it is in Q units |
---|
142 | #use en as energy in keV, |
---|
143 | _USAXS_Lambda = 12.4 / A[en] |
---|
144 | Finish_in_Angle = AR_VAL_CENTER - (360/PI)*asin( FINISH * _USAXS_Lambda / (4*PI)) |
---|
145 | |
---|
146 | # cleanup macro for ^C usage |
---|
147 | rdef _cleanup3 \'resetUSAXS\' |
---|
148 | |
---|
149 | epics_put ("15iddLAX:USAXS:state", "starting USAXS scan") |
---|
150 | |
---|
151 | comment "uascan started" |
---|
152 | |
---|
153 | uascan ar START AR_VAL_CENTER Finish_in_Angle MINSTEP DY0 SDD AY0 SAD UATERM NUMPNTS TIME |
---|
154 | |
---|
155 | comment "uascan finished" |
---|
156 | |
---|
157 | |
---|
158 | if (USAXS_MEASURE_DARK_CURENTS) { |
---|
159 | epics_put ("15iddLAX:USAXS:state", "measuring dark currents") |
---|
160 | measure_USAXS_PD_dark_currents |
---|
161 | } |
---|
162 | |
---|
163 | comment "Moving AR motor back to %g degrees (beam center)" AR_VAL_CENTER |
---|
164 | mv ar AR_VAL_CENTER |
---|
165 | waitmove; get_angles |
---|
166 | |
---|
167 | # normal cleanup macro for ^C usage |
---|
168 | rdef _cleanup3 \'\' |
---|
169 | comment %s scan_title |
---|
170 | TITLE = SPEC_STD_TITLE |
---|
171 | epics_put ("15iddLAX:USAXS:state", "scan finished") |
---|
172 | }' |
---|
173 | #################################################### |
---|
174 | ##### resetUSAXS macro |
---|
175 | #################################################### |
---|
176 | |
---|
177 | def resetUSAXS '{ |
---|
178 | global SPEC_STD_TITLE |
---|
179 | global useSBUSAXS |
---|
180 | global NOTIFY_ON_RESET |
---|
181 | comment "Resetting USAXS" |
---|
182 | epics_put ("15iddLAX:USAXS:state", "resetting motors") |
---|
183 | setplot 131 |
---|
184 | closeTiFilterShutter |
---|
185 | # speed the motor up for the return |
---|
186 | # epics_put("15iddLAX:xps:c0:m2.S", "2.0") |
---|
187 | # clear the user bit to indicate USAXS scan is not running |
---|
188 | epics_put ("15iddLAX:USAXS:scanning", 0) |
---|
189 | waitmove; get_angles |
---|
190 | A[dy] = DY0 |
---|
191 | A[ay] = AY0 |
---|
192 | A[ar] = AR_VAL_CENTER |
---|
193 | if(useSBUSAXS){ |
---|
194 | A[asrp] = ASRP0 |
---|
195 | } |
---|
196 | move_em; waitmove |
---|
197 | TITLE = SPEC_STD_TITLE |
---|
198 | epics_put (sprintf("15iddUSX:%s:mode",PDstring), 2) |
---|
199 | epics_put (sprintf("%s.CONT",_SCALER_PV), 1) #from jfk:vsc:c0 -xjiao |
---|
200 | # set a moderate motor speed for general use |
---|
201 | # epics_put("15iddLAX:xps:c0:m2.S", "1.0") |
---|
202 | epics_put ("15iddLAX:USAXS:state", "USAXS reset complete") |
---|
203 | if(NOTIFY_ON_RESET) { sendNotifications("USAXS has reset","spec has encountered a problem and reset the USAXS.");} |
---|
204 | chk_beam_off |
---|
205 | rdef _cleanup3 \'\' |
---|
206 | }' |
---|
207 | |
---|
208 | ############################################################################# |
---|
209 | ############################################################################# |
---|
210 | ############################################################################# |
---|
211 | # |
---|
212 | # uascan scans the one motor (AR assumed). |
---|
213 | # (uascan stands for USAXS ascan, incorporating a step |
---|
214 | # size that varies with distance from a center point.) |
---|
215 | ######################################################################### |
---|
216 | # |
---|
217 | # `uascan' is a single-motor scan with adjustable step size |
---|
218 | # |
---|
219 | def uascan ' |
---|
220 | if ($# != 12) { |
---|
221 | printf("Usage: uascan %s %s %s\n", \ |
---|
222 | "motor start center finish minStep", \ |
---|
223 | "dy0 SDD_mm ay0 SAD_mm", \ |
---|
224 | "exponent intervals time") |
---|
225 | exit |
---|
226 | } |
---|
227 | local _s |
---|
228 | local _f |
---|
229 | local _d |
---|
230 | local _center |
---|
231 | local _asrp0 |
---|
232 | |
---|
233 | # read header into internal (local) parameters. |
---|
234 | # Do they have to be declared local or global or just left as is? |
---|
235 | _s = $2; _center = $3; _f = $4; _ms = $5 |
---|
236 | _dy0 = $6; |
---|
237 | SAMPLE_DETECTOR_DISTANCE_MM = $7; |
---|
238 | _ay0 = $8; |
---|
239 | SAMPLE_ANALYZER_DISTANCE_MM = $9; |
---|
240 | _exp = $10 |
---|
241 | _n1 = int($11) |
---|
242 | _ctime = $12 |
---|
243 | _ctime_base = _ctime |
---|
244 | |
---|
245 | if(useDynamicTime) |
---|
246 | { |
---|
247 | _ctime = _ctime_base / 3 |
---|
248 | } |
---|
249 | if(useIntelligentTime) |
---|
250 | { |
---|
251 | _ctime = CT_RANGE_1 |
---|
252 | } |
---|
253 | # end of reading the header |
---|
254 | |
---|
255 | # declare variables to store current values... |
---|
256 | local old_dy # position of photodiode before scan |
---|
257 | local old_ay # position of AY before scan |
---|
258 | local old_sy # position of SY before scan |
---|
259 | local old_ar # position of AR motor before scan |
---|
260 | local old_ASRP # position of ASRP motor before scan |
---|
261 | |
---|
262 | # check some basic conditions |
---|
263 | if (_n1 <= 0) { |
---|
264 | print "Intervals <= 0" |
---|
265 | exit |
---|
266 | } |
---|
267 | _bad_lim = 0 |
---|
268 | _chk_lim ar _s |
---|
269 | _chk_lim ar _f |
---|
270 | if (_bad_lim) exit; |
---|
271 | |
---|
272 | # set heading for scans to show if we are running USAXS or SBUSAXS |
---|
273 | HEADING = (useSBUSAXS) ? "sbuascan " : "uascan " |
---|
274 | HEADING=sprintf("%s%s",HEADING,sprintf(" %s %g %g %g %g ",\ |
---|
275 | "ar",_s,_center,_f,_ms)) |
---|
276 | HEADING=sprintf("%s %g %g",HEADING,_dy0,SAMPLE_DETECTOR_DISTANCE_MM) |
---|
277 | HEADING=sprintf("%s %g %g",HEADING,_ay0,SAMPLE_ANALYZER_DISTANCE_MM) |
---|
278 | HEADING=sprintf("%s %g %g %g",HEADING,_exp,_n1,_ctime) |
---|
279 | |
---|
280 | |
---|
281 | # find appropriate factor for weighing the points |
---|
282 | _d = uascanFindFactor(_s, _center, _f, _n1, _exp, _ms) |
---|
283 | _dir = (_s < _f) ? 1 : -1 |
---|
284 | _n1++ |
---|
285 | _cols=1 |
---|
286 | X_L = motor_name(ar) |
---|
287 | Y_L = cnt_name(DET) |
---|
288 | _sx = _s; _fx = _f |
---|
289 | _stype = 1 |
---|
290 | FPRNT=PPRNT=VPRNT="" |
---|
291 | FPRNT=sprintf("%s%s ",FPRNT,motor_name(ar)) |
---|
292 | PPRNT=sprintf("%s%8.8s ",PPRNT,motor_name(ar)) |
---|
293 | VPRNT=sprintf("%s%9.9s ",VPRNT,motor_name(ar)) |
---|
294 | scan_head |
---|
295 | PFMT=sprintf("%%s%%8.%df ",UP) |
---|
296 | VFMT=sprintf("%%s%%9.%df ",UP) |
---|
297 | # UP is user precision, defined in standard.mac as 4 |
---|
298 | # it can be redefined to show more decimal places if needed |
---|
299 | |
---|
300 | # count the actual number of data points in this scan |
---|
301 | def _scan_on \' |
---|
302 | local scan_over |
---|
303 | scan_over = 0 |
---|
304 | # _s is next point calculate during last point, or start angle from call to macro |
---|
305 | _pos = _s |
---|
306 | for (; NPTS < _n1; NPTS++) { |
---|
307 | local target_sy target_ay target_dy |
---|
308 | ### set Ar angle to target |
---|
309 | A[ar] = _pos |
---|
310 | |
---|
311 | ### re-position DY on the scattered beam |
---|
312 | target_dy = _dy0 + _usaxs_triangulate (A[ar], AR_VAL_CENTER, SAMPLE_DETECTOR_DISTANCE_MM) |
---|
313 | A[dy] = target_dy |
---|
314 | |
---|
315 | ### re-position AY on the scattered beam |
---|
316 | target_ay = _ay0 + _usaxs_triangulate (A[ar], AR_VAL_CENTER, SAMPLE_ANALYZER_DISTANCE_MM) |
---|
317 | A[ay] = target_ay |
---|
318 | |
---|
319 | target_sy = A[sy] |
---|
320 | if (NPTS > 0) { |
---|
321 | ### (maybe) re-position the sample before each step after the first |
---|
322 | target_sy = A[sy] + SAMPLE_Y_STEP |
---|
323 | A[sy] = target_sy |
---|
324 | } |
---|
325 | ### ASRP stuff, more complicated... |
---|
326 | if(useSBUSAXS){ |
---|
327 | ### adjust the ASRP piezo on the AS side-bounce stage |
---|
328 | tanBragg = tan(_center*PI/180) |
---|
329 | cosScatAngle = cos((_center-A[ar])*PI/180) |
---|
330 | diff = atan(tanBragg/cosScatAngle)*180/PI - _center |
---|
331 | # on 11 19 2003 the original (Pete) formula with sin replaced |
---|
332 | # by Jan and Andrew with formulas using tan... Should be correct... |
---|
333 | # this is original Petes formula .... diff = asin(sinBragg/cosScatAngle)*180/PI - _center |
---|
334 | # |
---|
335 | # Note on asrp adjustment: NOTE: seems wrong, but may need to be revisited??? |
---|
336 | # use "-" when reflecting inboard towards storage ring (single bounce setup) |
---|
337 | # use "+" when reflecting outboard towards experimenters (channel-cut setup) |
---|
338 | ### on 2/06/2002 Andrew realized, that we are moving in wrong direction |
---|
339 | ## the sign change to - moves ASRP towards larger Bragg angles... |
---|
340 | ## verified experimentally - higher voltage on piezo = lower Bragg angle... |
---|
341 | ## and we need to INCREASE the Bragg Angle with increasing Q, to correct for tilt down... |
---|
342 | #######p "updating the piezo with" asrp_vdc |
---|
343 | ###old-style###epics_put (asrp_control_PV, asrp_vdc) |
---|
344 | asrp_vdc = _asrp0 - diff/ASRP_DEGREES_PER_VDC |
---|
345 | A[asrp] = asrp_vdc |
---|
346 | #######p "ASRP has been updated" |
---|
347 | } |
---|
348 | |
---|
349 | ### write comment for GUI |
---|
350 | epics_put ("15iddLAX:USAXS:state", sprintf("%s %d/%d", "moving motors", NPTS+1, _n1-1)) |
---|
351 | ### move to point |
---|
352 | scan_move |
---|
353 | ### spec stuff |
---|
354 | FPRNT=PPRNT=VPRNT="" |
---|
355 | FPRNT=sprintf("%s%.8g ",FPRNT,A[ar]) |
---|
356 | PPRNT=sprintf(PFMT,PPRNT,A[ar]) |
---|
357 | VPRNT=sprintf(VFMT,VPRNT,A[ar]) |
---|
358 | ### write comment for GUI |
---|
359 | epics_put ("15iddLAX:USAXS:state", sprintf("%s %d/%d", "counting", NPTS+1, _n1-1)) |
---|
360 | ### spec stuff... |
---|
361 | |
---|
362 | ## wait if range changed |
---|
363 | if(fabs(old_UPDRange-UPDRange)>0){ |
---|
364 | #print "Sleeping due to range change" |
---|
365 | sleep (UPD_Change_delay) |
---|
366 | } |
---|
367 | old_UPDRange = UPDRange |
---|
368 | scan_loop |
---|
369 | scan_data(NPTS,A[ar]) |
---|
370 | scan_plot |
---|
371 | ### calculate position for next step here |
---|
372 | _pos += _dir * uascanStepFunc(_pos, _d, _center, _exp, _ms) |
---|
373 | |
---|
374 | if(useDynamicTime){ |
---|
375 | if(NPTS < (_n1/3)) { _ctime = _ctime_base / 2 } |
---|
376 | if(NPTS > (_n1/3) && NPTS < ((2/3)*_n1)) { _ctime = _ctime_base } |
---|
377 | if(NPTS > ((2/3)*_n1)) { _ctime = 2*_ctime_base} |
---|
378 | } |
---|
379 | |
---|
380 | if(useIntelligentTime) { |
---|
381 | updRange = epics_get("15iddUSX:pd01:seq02:reqrange","short") |
---|
382 | if(updRange==0) |
---|
383 | { |
---|
384 | _ctime = CT_RANGE_1 |
---|
385 | } |
---|
386 | else if(updRange == 1) |
---|
387 | { |
---|
388 | _ctime = CT_RANGE_2 |
---|
389 | } |
---|
390 | else if(updRange == 2) |
---|
391 | { |
---|
392 | _ctime = CT_RANGE_3 |
---|
393 | } |
---|
394 | else if(updRange == 3) |
---|
395 | { |
---|
396 | _ctime = CT_RANGE_4 |
---|
397 | } |
---|
398 | else |
---|
399 | { |
---|
400 | _ctime = CT_RANGE_5 |
---|
401 | } |
---|
402 | } |
---|
403 | |
---|
404 | ### check if done. |
---|
405 | if (_dir > 0) { |
---|
406 | if (_pos > _f) scan_over = 1 |
---|
407 | } else { |
---|
408 | if (_pos < _f) scan_over = 1 |
---|
409 | } |
---|
410 | if (scan_over == 1) break |
---|
411 | } |
---|
412 | scan_tail |
---|
413 | \' |
---|
414 | ### remember pre-scan motor positions: AY, SY, DY, and AR |
---|
415 | old_ay = A[ay] |
---|
416 | old_sy = A[sy] |
---|
417 | old_dy = A[dy] |
---|
418 | old_ar = A[ar] |
---|
419 | if(useSBUSAXS){ |
---|
420 | old_ASRP = A[asrp] |
---|
421 | _asrp0 = A[asrp] |
---|
422 | } |
---|
423 | # make the scaler wait before counting |
---|
424 | epics_put(sprintf("%s.DLY",_SCALER_PV), MOTOR_PRESCALER_WAIT) |
---|
425 | # turn off the AutoCount mode on the scaler |
---|
426 | epics_put(sprintf("%s.CONT",_SCALER_PV), "0") |
---|
427 | # turn on the photodiode automatic range changer, automatic mode |
---|
428 | epics_put(sprintf("15iddUSX:%s:mode",PDstring), "1") |
---|
429 | # slow the AR motor down for the scan |
---|
430 | # epics_put("15iddLAX:xps:c0:m2.S", 0.5) old motor |
---|
431 | # When using the USAXS_chk_beam macro, |
---|
432 | # test for the "beam dumped" condition by |
---|
433 | # setting a threshold on the I0 monitor counts. |
---|
434 | # Specify here using a minimum I0 count rate. |
---|
435 | chk_thresh = _ctime * 2000 |
---|
436 | # close the shutter just in case it is important |
---|
437 | closeTiFilterShutter |
---|
438 | # rotate AR (or MR) to the starting position |
---|
439 | epics_put ("15iddLAX:USAXS:state", "rotate to first angle") |
---|
440 | waitmove; get_angles |
---|
441 | A[ar] = _s |
---|
442 | move_em; waitmove |
---|
443 | # open the shutters just before each scan to preserve the detector |
---|
444 | openTiFilterShutter |
---|
445 | openMonoShutter |
---|
446 | # set the photodiode on mid-range |
---|
447 | epics_put(sprintf("15iddUSX:%s:reqrange.VAL",PDstring), 2); |
---|
448 | # set a bit to indicate USAXS scan is running |
---|
449 | if (useSBUSAXS) { |
---|
450 | epics_put ("15iddLAX:USAXS:scanMacro", "sbuascan") |
---|
451 | } else { |
---|
452 | epics_put ("15iddLAX:USAXS:scanMacro", "uascan") |
---|
453 | } |
---|
454 | epics_put ("15iddLAX:USAXS:scanning", 1) |
---|
455 | |
---|
456 | ###------------------------ |
---|
457 | # def chk_beam \'USAXS_chk_beam\' |
---|
458 | #setplot 163 ;# 163 turns on log(Yaxis) |
---|
459 | #setplot 131 ;# 131 turns off log(Yaxis) |
---|
460 | setplot 131 ;# 0 turns off plot during scan |
---|
461 | |
---|
462 | _scan_on |
---|
463 | |
---|
464 | # def chk_beam \'standard_chk_beam\' |
---|
465 | ###------------------------ |
---|
466 | # clear the user bit to indicate USAXS scan is not running |
---|
467 | epics_put ("15iddLAX:USAXS:scanning.VAL", 0) |
---|
468 | # close the shutter after each scan to preserve the detector |
---|
469 | closeTiFilterShutter |
---|
470 | # turn on the AutoCount mode on the scaler |
---|
471 | epics_put(sprintf("%s.CONT",_SCALER_PV), "1") #from jfk |
---|
472 | # turn on the photodiode automatic range changer, auto+bkg mode |
---|
473 | epics_put(sprintf("15iddUSX:%s:mode",PDstring), "2") |
---|
474 | # speed the motor up for the return |
---|
475 | # epics_put("15iddLAX:xps:c0:m2.S", "2.0") old motor |
---|
476 | # reset motors to pre-scan positions: AY, SY, DY, and "the first motor" (AR) |
---|
477 | epics_put ("15iddLAX:USAXS:state", "returning AR, AY, SY, and DY") |
---|
478 | get_angles |
---|
479 | A[ay] = old_ay |
---|
480 | A[sy] = old_sy |
---|
481 | A[dy] = old_dy |
---|
482 | A[ar] = old_ar |
---|
483 | if(useSBUSAXS){ |
---|
484 | A[asrp] = old_ASRP |
---|
485 | } |
---|
486 | move_em; waitmove |
---|
487 | # set a moderate motor speed for general use |
---|
488 | # epics_put("15iddLAX:xps:c0:m2.S", "0.5") old motor |
---|
489 | ' |
---|
490 | |
---|
491 | ############################################################################# |
---|
492 | ############################################################################# |
---|
493 | ############################################################################# |
---|
494 | ############################################################################# |
---|
495 | ############################################################################# |
---|
496 | ############################################################################# |
---|
497 | # |
---|
498 | # subprograms.... |
---|
499 | # |
---|
500 | # uascanStepFunc |
---|
501 | # |
---|
502 | # Calculate the next step size with the given parameters |
---|
503 | # |
---|
504 | uascanStepDebug = 0 |
---|
505 | def uascanStepFunc(x, factor, center, exponent, minStep) '{ |
---|
506 | local step |
---|
507 | step = factor * pow( fabs(x - center), exponent ) + minStep |
---|
508 | if (uascanStepDebug >= 2) |
---|
509 | printf ("step = %g\n", step) |
---|
510 | return step |
---|
511 | }' |
---|
512 | |
---|
513 | # uascanTestSeries |
---|
514 | # |
---|
515 | # Make a series with the specified parameters |
---|
516 | # If factor is too large, return the number of points required to reach finish. |
---|
517 | # Otherwise, return the closeness of the final point to the finish. |
---|
518 | # |
---|
519 | def uascanTestSeries(start, center, finish, numPts, factor, exponent, minStep) '{ |
---|
520 | local x step i dir |
---|
521 | |
---|
522 | x = start |
---|
523 | dir = (start < finish) ? 1 : -1 |
---|
524 | for (i=1; i < numPts; i++) { |
---|
525 | step = uascanStepFunc(x, factor, center, exponent, minStep) |
---|
526 | x += dir*step |
---|
527 | if ( ((dir>0) && (x > finish)) || ((dir<0) && (x < finish)) ) { |
---|
528 | return i |
---|
529 | } |
---|
530 | } |
---|
531 | return (-1 * fabs(x - finish)) |
---|
532 | }' |
---|
533 | |
---|
534 | # uascanFindFactor |
---|
535 | # |
---|
536 | # Determine the factor that will make a series with the specified parameters. |
---|
537 | # Choose the factor that will minimize | x[n] - finish | subject to: |
---|
538 | # x[1] = start |
---|
539 | # x[n] <= finish |
---|
540 | # This routine CAN FAIL if (finish - start)/minStep >= numPts |
---|
541 | # |
---|
542 | def uascanFindFactor(start center finish numPts exponent minStep) '{ |
---|
543 | local factor fStep result f2 r2 i |
---|
544 | |
---|
545 | factor = 0 |
---|
546 | result = uascanTestSeries(start, finish, numPts, factor, center, exponent, minStep) |
---|
547 | if (result > 0) { |
---|
548 | printf ("With factor=%g, could not get correct result (%g)\n", factor, result) |
---|
549 | # |
---|
550 | # fail gracefully with factor |
---|
551 | # let calling routine decide what to do |
---|
552 | # (usually just step with factor = 0 until x[i] > finish) |
---|
553 | # |
---|
554 | return (factor) |
---|
555 | } |
---|
556 | # |
---|
557 | # Initially, choose factor = abs(finish - start) / (numPts - 1) |
---|
558 | # call uascanTestSeries with factor |
---|
559 | # if result<0, then factor *= 10 and repeat |
---|
560 | # then continue as below |
---|
561 | # |
---|
562 | # r2 = -1 |
---|
563 | # fStep = abs(finish-start) / (numPts -1) |
---|
564 | # while (r2 < 0) { |
---|
565 | # f2 = factor + fStep |
---|
566 | # r2 = uascanTestSeries(start, center, finish, numPts, f2, exponent, minStep) |
---|
567 | # if (uascanStepDebug >= 1) |
---|
568 | # printf("factor = %g result = %g\n", f2, r2) |
---|
569 | # if (r2 < 0) fStep *= 10 |
---|
570 | # } |
---|
571 | fStep = 10 |
---|
572 | # |
---|
573 | # 40 times means better than 12-digit precision |
---|
574 | # |
---|
575 | for (i = 1; i < 40; i++) { |
---|
576 | f2 = factor + fStep |
---|
577 | r2 = uascanTestSeries(start, center, finish, numPts, f2, exponent, minStep) |
---|
578 | if ( (r2 <= 0) && ( fabs(r2) < fabs(result) ) ) { |
---|
579 | factor = f2 |
---|
580 | result = r2 |
---|
581 | } else { |
---|
582 | fStep *= 0.5 |
---|
583 | } |
---|
584 | if (uascanStepDebug >= 1) |
---|
585 | printf ("%d: f=%0.15g result=%0.15g\n", i, factor, result) |
---|
586 | if ( fabs(result) < 0.5*fabs(minStep) ) break |
---|
587 | } |
---|
588 | return (factor) |
---|
589 | }' |
---|
590 | |
---|
591 | def _usaxs_triangulate (rot,center,dist) '{ |
---|
592 | local offset |
---|
593 | offset = dist * tan((rot-center)*PI/180) |
---|
594 | return(offset) |
---|
595 | }' |
---|
596 | |
---|
597 | |
---|
598 | |
---|
599 | |
---|
600 | #global _n1 # number of intervals |
---|
601 | #global _nm # number of motors |
---|
602 | #global _m[] # motor number |
---|
603 | #global _s[] # start position |
---|
604 | #global _f[] # finish position |
---|
605 | #global _d[] # scale factor |
---|
606 | #global _c[] # center position |
---|
607 | #global _ms[] # minimum step size |
---|
608 | #global _dy0 # photodiode Y position at center angle of scan |
---|
609 | #global _ay0 # analyzer stage Y position at center angle of scan |
---|
610 | #global _exp # exponent for step function |
---|
611 | #global _dir[] # direction for motor to move |
---|
612 | #global _pos[] # present function (while step scanning) |
---|