source: beamline_config/trunk/8id/spec/macros/sites/spec8IDI/site_f.mac @ 1463

Last change on this file since 1463 was 1463, checked in by jkirchman, 4 years ago

Check-in

File size: 146.7 KB
Line 
1#file site_f.mac: Generated Mon 2017/11/06 15:20
2#file WARNING.mac
3###################################################################
4# WARNING: this file is automatically generated and so should not #
5# be edited. Find the place which generates it - currently:       #
6# /home/users/S8SPEC/macros/sites/[machinename|specname]macs      #
7###################################################################
8# SPECD/site_f.mac
9
10def showmots '{
11
12        selmots 1 sa1vgap sa1vcen sa1hgap sa1hcen $1
13        selmots 1 ta1_x ta1_z ta2_x ta2_z ta2fine $1
14        print " ";
15        print epicsMotInfo("8ida", "m", 1, 8, "m");
16        print epicsMotInfo("8ida", "m", 1, 8, "u");
17        print epicsMotInfo("8ida", "m", 1, 8, "d");
18
19        print " ";
20        print epicsMotInfo("8ida", "m", 9, 16, "m");
21        print epicsMotInfo("8ida", "m", 9, 16, "u");
22        print epicsMotInfo("8ida", "m", 9, 16, "d");
23        print " ";
24        print epicsMotInfo("8idimono", "m", 1, 5, "m");
25        print epicsMotInfo("8idimono", "m", 1, 5, "u");
26        print epicsMotInfo("8idimono", "m", 1, 5, "d");
27
28        selmots 1 diamx diamz $1
29       
30        selmots 1 ti1_x ti1_z monoth monoE ti2_x ti2_z ti3_x ti3_z $1
31        selmots 1 ti4_x ti4_z tth $1
32        selmots 1 si1vgap si1vcen si1hgap si1hcen $1
33        selmots 1 si2vgap si2vcen si2hgap si2hcen $1
34        selmots 1 si3vgap si3vcen si3hgap si3hcen $1
35        selmots 1 si4vgap si4vcen si4hgap si4hcen $1
36
37        print " ";
38        print epicsMotInfo("8idi", "m", 1, 8, "m");
39        print epicsMotInfo("8idi", "m", 1, 8, "u");
40        print epicsMotInfo("8idi", "m", 1, 8, "d");
41        print " ";
42        print epicsMotInfo("8idi", "m", 9, 16, "m");
43        print epicsMotInfo("8idi", "m", 9, 16, "u");
44        print epicsMotInfo("8idi", "m", 9, 16, "d");
45        print " ";
46        print epicsMotInfo("8idi", "m", 17, 24, "m");
47        print epicsMotInfo("8idi", "m", 17, 24, "u");
48        print epicsMotInfo("8idi", "m", 17, 24, "d");
49        print " ";
50        print epicsMotInfo("8idi", "m", 25, 32, "m");
51        print epicsMotInfo("8idi", "m", 25, 32, "u");
52        print epicsMotInfo("8idi", "m", 25, 32, "d");
53        print " ";
54        print epicsMotInfo("8idi", "m", 49, 56, "m");
55        print epicsMotInfo("8idi", "m", 49, 56, "u");
56        print epicsMotInfo("8idi", "m", 49, 56, "d");
57        print " ";
58        print epicsMotInfo("8idi", "m", 61, 68, "m");
59        print epicsMotInfo("8idi", "m", 61, 68, "u");
60        print epicsMotInfo("8idi", "m", 61, 68, "d");
61        print " ";
62        print epicsMotInfo("8idi", "m", 77, 84, "m");
63        print epicsMotInfo("8idi", "m", 77, 84, "u");
64        print epicsMotInfo("8idi", "m", 77, 84, "d");
65        print " ";
66        print epicsMotInfo("8idi", "m", 85, 88, "m");
67        print epicsMotInfo("8idi", "m", 85, 88, "u");
68        print epicsMotInfo("8idi", "m", 85, 88, "d");
69        print " ";
70        print epicsMotInfo("8idi", "m", 45, 48, "m");
71        print epicsMotInfo("8idi", "m", 45, 48, "u");
72        print epicsMotInfo("8idi", "m", 45, 48, "d");
73        print " ";
74        print epicsMotInfo("8idi", "m", 33, 36, "m");
75        print epicsMotInfo("8idi", "m", 33, 36, "u");
76        print epicsMotInfo("8idi", "m", 33, 36, "d");
77        print " ";
78        print epicsMotInfo("8idi", "m", 57, 60, "m");
79        print epicsMotInfo("8idi", "m", 57, 60, "u");
80        print epicsMotInfo("8idi", "m", 57, 60, "d");
81        print " ";
82        print epicsMotInfo("8idi", "m", 41, 44, "m");
83        print epicsMotInfo("8idi", "m", 41, 44, "u");
84        print epicsMotInfo("8idi", "m", 41, 44, "d");
85
86        if( 77 != MOTORS)
87                p "\nWARNING: number of motors changed since this routine was last modified"
88}'
89#Initialize settings on pin diodes connected to SRS Current PreAmps
90
91def pind1_mono_init '{
92        printf("\nPIND1 preamp is being initialized\n");
93        epics_put("8idi:A1init.DESC","PIND1");
94                sleep(0.1);
95        epics_put("8idi:A1sens_num.VAL","200");
96                sleep(0.1);
97        epics_put("8idi:A1sens_unit.VAL","uA/V");
98                sleep(0.1);
99        epics_put("8idi:A1offset_num.VAL","2");
100                sleep(0.1);
101        epics_put("8idi:A1offset_unit.VAL","uA");
102                sleep(0.1);
103        epics_put("8idi:A1offset_on.VAL","ON");
104                sleep(0.1);
105        epics_put("8idi:A1offset_sign.VAL","+");
106                sleep(0.1);
107        epics_put("8idi:A1off_u_put.VAL",0);
108                sleep(0.1);
109        epics_put("8idi:A1offset_cal.VAL","CAL");
110                sleep(0.1);
111        epics_put("8idi:A1bias_on.VAL","OFF");
112                sleep(0.1);
113        epics_put("8idi:A1filter_type.VAL",0);
114                sleep(0.1);
115        epics_put("8idi:A1gain_mode.VAL","LOW NOISE");
116                sleep(0.1);
117        epics_put("8idi:A1invert_on.VAL","OFF");
118                sleep(0.1);
119        epics_put("8idi:A1blank_on.VAL","OFF");
120                sleep(0.1);
121        epics_put("8idi:A1offset_sign.VAL","+");
122                sleep(0.1);
123}'
124
125def pind2_mono_init '{
126        printf("\nPIND2 preamp is being initialized\n");
127        epics_put("8idi:A2init.DESC","PIND2");
128                sleep(0.1);
129        epics_put("8idi:A2sens_num.VAL","2");
130                sleep(0.1);
131        epics_put("8idi:A2sens_unit.VAL","uA/V");
132                sleep(0.1);
133        epics_put("8idi:A2offset_num.VAL","10");
134                sleep(0.1);
135        epics_put("8idi:A2offset_unit.VAL","nA");
136                sleep(0.1);
137        epics_put("8idi:A2offset_on.VAL","ON");
138                sleep(0.1);
139        epics_put("8idi:A2offset_sign.VAL","+");
140                sleep(0.1);
141        epics_put("8idi:A2off_u_put.VAL",0);
142                sleep(0.1);
143        epics_put("8idi:A2offset_cal.VAL","CAL");
144                sleep(0.1);
145        epics_put("8idi:A2bias_on.VAL","OFF");
146                sleep(0.1);
147        epics_put("8idi:A2filter_type.VAL",0);
148                sleep(0.1);
149        epics_put("8idi:A2gain_mode.VAL","LOW NOISE");
150                sleep(0.1);
151        epics_put("8idi:A2invert_on.VAL","OFF");
152                sleep(0.1);
153        epics_put("8idi:A2blank_on.VAL","OFF");
154                sleep(0.1);
155        epics_put("8idi:A2offset_sign.VAL","+");
156                sleep(0.1);
157}'
158
159
160
161def pind3_mono_init '{
162        printf("\nPIND3 preamp is being initialized\n");
163        epics_put("8idi:A3init.DESC","PIND3");
164                sleep(0.1);
165        epics_put("8idi:A3sens_num.VAL","2");
166                sleep(0.1);
167        epics_put("8idi:A3sens_unit.VAL","uA/V");
168                sleep(0.1);
169        epics_put("8idi:A3offset_num.VAL","10");
170                sleep(0.1);
171        epics_put("8idi:A3offset_unit.VAL","nA");
172                sleep(0.1);
173        epics_put("8idi:A3offset_on.VAL","ON");
174                sleep(0.1);
175        epics_put("8idi:A3offset_sign.VAL","+");
176                sleep(0.1);
177        epics_put("8idi:A3off_u_put.VAL",0);
178                sleep(0.1);
179        epics_put("8idi:A3offset_cal.VAL","CAL");
180                sleep(0.1);
181        epics_put("8idi:A3bias_on.VAL","OFF");
182                sleep(0.1);
183        epics_put("8idi:A3filter_type.VAL",0);
184                sleep(0.1);
185        epics_put("8idi:A3gain_mode.VAL","LOW NOISE");
186                sleep(0.1);
187        epics_put("8idi:A3invert_on.VAL","OFF");
188                sleep(0.1);
189        epics_put("8idi:A3blank_on.VAL","OFF");
190                sleep(0.1);
191        epics_put("8idi:A3offset_sign.VAL","+");
192                sleep(0.1);
193}'
194
195
196def pind4_mono_init '{
197        printf("\nPIND4 preamp is being initialized\n");
198        epics_put("8idi:A4init.DESC","PIND4");
199                sleep(0.1);
200        epics_put("8idi:A4sens_num.VAL","1");
201                sleep(0.1);
202        epics_put("8idi:A4sens_unit.VAL","uA/V");
203                sleep(0.1);
204        epics_put("8idi:A4offset_num.VAL","10");
205                sleep(0.1);
206        epics_put("8idi:A4offset_unit.VAL","nA");
207                sleep(0.1);
208        epics_put("8idi:A4offset_on.VAL","ON");
209                sleep(0.1);
210        epics_put("8idi:A4offset_sign.VAL","+");
211                sleep(0.1);
212        epics_put("8idi:A4off_u_put.VAL",0);
213                sleep(0.1);
214        epics_put("8idi:A4offset_cal.VAL","CAL");
215                sleep(0.1);
216        epics_put("8idi:A4bias_on.VAL","OFF");
217                sleep(0.1);
218        epics_put("8idi:A4filter_type.VAL",0);
219                sleep(0.1);
220        epics_put("8idi:A4gain_mode.VAL","LOW NOISE");
221                sleep(0.1);
222        epics_put("8idi:A4invert_on.VAL","OFF");
223                sleep(0.1);
224        epics_put("8idi:A4blank_on.VAL","OFF");
225                sleep(0.1);
226        epics_put("8idi:A4offset_sign.VAL","+");
227                sleep(0.1);
228}'
229
230def pdbs_mono_init '{
231        printf("\nPDBS preamp is being initialized\n");
232        epics_put("8idi:A5init.DESC","PDBS");
233                sleep(0.1);
234        epics_put("8idi:A5sens_num.VAL","1");
235                sleep(0.1);
236        epics_put("8idi:A5sens_unit.VAL","uA/V");
237                sleep(0.1);
238        epics_put("8idi:A5offset_num.VAL","10");
239                sleep(0.1);
240        epics_put("8idi:A5offset_unit.VAL","nA");
241                sleep(0.1);
242        epics_put("8idi:A5offset_on.VAL","ON");
243                sleep(0.1);
244        epics_put("8idi:A5offset_sign.VAL","-");
245                sleep(0.1);
246        epics_put("8idi:A5off_u_put.VAL",0);
247                sleep(0.1);
248        epics_put("8idi:A5offset_cal.VAL","CAL");
249                sleep(0.1);
250        epics_put("8idi:A5bias_on.VAL","OFF");
251                sleep(0.1);
252        epics_put("8idi:A5filter_type.VAL",0);
253                sleep(0.1);
254        epics_put("8idi:A5gain_mode.VAL","LOW NOISE");
255                sleep(0.1);
256        epics_put("8idi:A5invert_on.VAL","ON");
257                sleep(0.1);
258        epics_put("8idi:A5blank_on.VAL","OFF");
259                sleep(0.1);
260        epics_put("8idi:A5offset_sign.VAL","-");
261                sleep(0.1);
262}'
263
264
265#Initialize "preamps" to their default values
266pind1_mono_init
267sleep(0.1)
268pind1_mono_init
269sleep(0.1)
270pind2_mono_init
271sleep(0.1)
272pind3_mono_init
273sleep(0.1)
274pind4_mono_init
275sleep(0.1)
276pdbs_mono_init
277
278
279#file flux_epics.mac for pin diodes connected to SRS Current PreAmps
280
281global Amps_per_Volt
282
283def preamp_setread '{
284        local amp_scale;
285        local strPVUnit, strPVNum, strID;
286
287        for (i = 1; i <= 5; i++) {
288                strPVUnit = "8idi:A" i "sens_unit.VAL";
289                strPVNum = "8idi:A" i "sens_num.VAL";
290                _unit = epics_get(strPVUnit);
291                sleep(0.1);
292                _num = epics_get(strPVNum);
293                sleep(0.1);
294                if (_unit =="mA/V") amp_scale=1e-3;
295                if (_unit =="uA/V") amp_scale=1e-6;
296                if (_unit =="nA/V") amp_scale=1e-9;
297                if (_unit =="pA/V") amp_scale=1e-12;
298                if (i == 1)
299                        strID = "pind1";
300                else if (i == 2)
301                        strID = "pind2";
302                else if (i == 3)
303                        strID = "pind3";
304                else if (i == 4)
305                        strID = "pind4";
306                else
307                        strID = "pdbs";
308                Amps_per_Volt[strID] = (_num)*amp_scale;
309
310                if (Amps_per_Volt[strID]==0.0) {
311                        printf("\nLooks like SPEC is not getting the sensitivity of  %s (Amps/Volt) from EPICS\n",strID);
312                        exit
313                }
314        }
315
316}'
317
318def flux '{
319        if ($# !=2) {
320        eprint "Usage: flux pin_diode cps"
321        exit
322        }
323        preamp_setread;
324    params = flux_params("$1")
325    print_flux_params params "$1"
326    #printf("\n %g cps is a current of %g Amps \n",$2,\
327     #      ($2/params["CtpV"])*params["Amps_per_Volt"])
328    printf("\n %g cps is a current of %g Amps \n",$2,\
329           ($2/params["CtpV"])*Amps_per_Volt["$1"])
330    printf("\n %8.3g photons per second \n",calc_flux($2,params,"$1"))
331  }'
332
333
334def flux_pind1 '{
335        if ($# !=1) {
336        eprint "Usage: flux_pind1 cps"
337        exit
338        }
339        flux "pind1" $1;
340}'
341
342def flux_pind2 '{
343        if ($# !=1) {
344        eprint "Usage: flux_pind2 cps"
345        exit
346        }
347        flux "pind2" $1;
348}'
349
350def flux_pind3 '{
351        if ($# !=1) {
352        eprint "Usage: flux_pind3 cps"
353        exit
354        }
355        flux "pind3" $1;
356}'
357
358def flux_pind4 '{
359        if ($# !=1) {
360        eprint "Usage: flux_pind4 cps"
361        exit
362        }
363        flux "pind4" $1;
364}'
365
366def flux_pdbs '{
367        if ($# !=1) {
368        eprint "Usage: flux_pdbs cps"
369        exit
370        }
371        flux "pdbs" $1;
372}'
373
374
375def getflux '{
376  local bg cps ctime curnt flx hostname params xtime
377        {
378    preamp_setread;
379    params = flux_params(cnt_mne(DET))
380    print_flux_params params cnt_mne(DET)
381    xtime = ($#) ? $1 : 10
382    printf("\nMeasuring background:\n")
383    att 15; waitmove
384    uct xtime
385    ctime = (S[sec]) ? S[sec] : xtime
386    bg = S[DET]/ctime
387    printf("\nRing Current = %6.2f mA\n",curnt=epics_get("S:SRcurrentAI"));
388    printf("Measuring intensity:\n")
389    att 0; waitmove
390    uct xtime
391    att 15; waitmove
392    ctime = (S[sec]) ? S[sec] : xtime
393    cps = S[DET]/ctime - bg
394
395    if (cps > 650000) {
396                         for (i=1;i<11;i++) {
397                              beep;sleep(1);
398     printf("\nWarning: Counts is close to saturation of the pin diode,Check the sensitivity:\n");
399                                            }
400                      }
401
402    #printf("\n %d cps is a current of %g Amps \n",cps,\
403     #      (cps/params["CtpV"])*params["Amps_per_Volt"])
404    printf("\n %d cps is a current of %g Amps \n",cps,\
405           (cps/params["CtpV"])*Amps_per_Volt[cnt_mne(DET)])
406    flx = calc_flux(cps,params,cnt_mne(DET))
407    printf("\n %8.3g photons per second on %s\n",flx,cnt_mne(DET))
408    if (curnt) printf("\n %8.3g photons per second per 100 mA \n",\
409                      calc_flux(cps*100/curnt,params,cnt_mne(DET)))
410    }
411  }'
412
413def calc_flux(cps,params,pin_diode) '{
414  local Amps photons
415        preamp_setread;
416 # Amps = (cps/params["CtpV"])*params["Amps_per_Volt"]
417  Amps = (cps/params["CtpV"])*Amps_per_Volt[pin_diode]
418  photons = Amps/(1.60218e-19*params["N_elec"]*params["Abs_frac"])
419  return(photons)
420  }'
421
422def print_flux_params '{
423global Resis CtpV Length Element Ephot
424  preamp_setread;
425  printf("\n\n")
426  printf("Detector  = %s \n",$2)
427  #printf("Amps_per_Volt = %g A/V \n",$1["Amps_per_Volt"])
428  printf("Amps_per_Volt(%s)  = %g A/V \n","$2",Amps_per_Volt["$2"])
429  printf("CtpV  = %g  \n",$1["CtpV"])
430  printf("Length = %8.4f cm \n",$1["fluxLength"])
431  printf("Element = %s\n",$1["Element"])
432  printf("Ephot = %5.0f eV\n",$1["Ephot"]);
433  printf("%s Elength = %7.2g cm \n",$1["Element"],$1["Elength"]);
434  }'
435
436def flux_params(_counter) '{
437  local Elength result Mabs N_elec
438
439  result["Amps_per_Volt"] = Amps_per_Volt[_counter];
440
441        CtpV=1e5
442  result["CtpV"] = CtpV
443
444        Length=0.04
445  result["fluxLength"] = Length
446
447        Element="Si"
448   result["Element"] = Element
449
450  #Ephot=epics_get("ID08us:Energy.VAL")*1000-100
451  Ephot=epics_get("8idimono:sm2.RBV")*1000
452  result["Ephot"] = Ephot
453  Ekev = Ephot/1000;
454
455  if (Element == "Ar") {
456        N_elec = Ephot/26.4;
457        Elength =  exp(-2.78262);
458        Elength *= exp(.782515*Ekev);
459        Elength *= exp(-.0379763*Ekev*Ekev);
460        Elength *= exp(1.04293e-3*Ekev*Ekev*Ekev);
461        Elength *= exp(-1.14407e-5*Ekev*Ekev*Ekev*Ekev);
462        }
463  else if ( Element == "N2") {
464        N_elec = Ephot/34.8;
465        Mabs =  exp(6.17639);
466        Mabs *= exp(-6.90647e-1*Ekev);
467        Mabs *= exp(2.44039e-2*Ekev*Ekev);
468        Mabs *= exp(-.453977e-3*Ekev*Ekev*Ekev);
469        Mabs *= exp(0.033084e-4*Ekev*Ekev*Ekev*Ekev);
470        Elength = 1.0/(Mabs*1.165e-3);
471        }
472  else if ( Element == "He") {
473        N_elec = Ephot/41.3;
474        Elength =  exp(15.4707);
475        Elength *= exp(0.972059*Ekev);
476        Elength *= exp(-0.0487191*Ekev*Ekev);
477        Elength *= exp(0.00134312*Ekev*Ekev*Ekev);
478        Elength *= exp(-1.46011e-05*Ekev*Ekev*Ekev*Ekev);
479        Elength /=1e4;
480        }
481  else if (Element == "Si") {
482        N_elec = Ephot/3.62;
483        Elength = 61e-4*pow((7.65/Ekev),-3);
484        Length = 400e-4;
485        }
486  else {
487        printf("This program does not yet calculate %s \n",Element);
488        exit
489        }
490  result["N_elec"] = N_elec
491  result["Elength"] = Elength
492  result["Abs_frac"] = (1-exp(-Length/Elength));
493  return(result)
494  }'
495
496def qct '{
497  # quiet ct, less output
498  local ctime
499  _cols = 0
500  waitmove
501  count_em $*
502  rdef cleanup \'
503    undef cleanup
504    print "If there is an Out of sync: error, please run get_counts once from the SPEC> prompt."
505    batch_cleanup
506    get_counts
507  \'
508  waitcount
509  get_counts
510  printf("   %s\n", date())
511  if (S[sec]) ctime = S[sec]
512  else if ($#) ctime = $1
513  else ctime = 1
514  printf("   pind1 = %d (%g/s)\n",S[pind1],S[pind1]/ctime)
515  printf("   pind2 = %d (%g/s)\n",S[pind2],S[pind2]/ctime)
516  printf("    pdbs = %d (%g/s)\n",S[pdbs],S[pdbs]/ctime)
517#  user_handlecounts
518  undef cleanup
519  }'
520def takeflux '{
521  ##A new pneumatic feedthrough with a 20 mm PIN diode has been mounted at the
522  ##longitudinal location of the beam stop and at 90 degrees. This feedthrough
523  ##will esp. make flux measurement in reflection geometry very quick (3 min
524  ##reduced to 3 sec).(Suresh, Feb.11,2008)
525
526  # Usage: takeflux [vacuum] [time]
527  local i bg cfield cps ctime curnt dt flx ifield nflx params xtime Monitor_flux
528  local sz sx sth
529  {
530    rdef batch_cleanup \'{
531      emptydef batch_cleanup
532      blockbeam; shutteron; waitmove
533      }\'
534    preamp_setread;
535    params = flux_params("pind4")
536    if ("$1" == "vacuum") {
537      printf("\nTakeflux: Moving samx to %g, samz to %g\n",\
538             samxvac, samzvac)
539      umv samx samxvac; umv samz samzvac;
540     ##The function move_pind4z_in and out are defined in pind_positions_8idi.mac
541     move_pind4z_in
542     waitmove;
543      }
544    else {
545     ##The function move_pind4z_in and out are defined in pind_positions_8idi.mac
546      move_pind4z_in
547       waitmove;sleep(0.1)
548      # leave sample wherever it is already
549      }
550    if ($# > 1) xtime = $2
551    else if ($# && "$1" != "vacuum") xtime = $1
552    else xtime = 5
553    printf("Measuring background:\n")
554    p date();
555    blockbeam; waitmove;sleep(0.1)
556    uct xtime
557    ctime = (S[sec]) ? S[sec] : xtime
558#    bg = S[DET]/ctime
559#hard coded the detector to "pind4" since not defining the counter before
560#running the ccd_batch always causes the wrong detector to be used for
561#flux (Suresh, June 2004, onset of Epics in 8-ID-I)
562    bg = S[pind4]/ctime
563    curnt = epics_get("S:SRcurrentAI")
564    printf("Ring Current = %6.2f mA\n",curnt)
565    printf("Measuring intensity:\n")
566    p date();
567    shutteroff_default; showbeam; waitmove;sleep(0.1)
568    uct xtime
569    blockbeam; shutteron;
570     ##The function move_pind4z_in and out are defined in pind_positions_8idi.mac
571    move_pind4z_out
572    waitmove;sleep(.1)
573    ctime = (S[sec]) ? S[sec] : xtime
574#    cps = S[DET]/ctime - bg
575    cps = S[pind4]/ctime - bg
576    Monitor_flux = epics_get("8idi:scaler1_calc1.H")/ctime
577
578    if (cps > 650000) {
579                       for (i=1;i<11;i++) {
580                           beep;sleep(1);
581                           printf("\nWarning: Counts is very close to saturation of pind4, Check the Sensitivity:\n");
582                       }
583    }
584
585    printf("%g cps is a current of %g Amps \n",cps,\
586          (cps/params["CtpV"])*params["Amps_per_Volt"])
587
588    flx = calc_flux(cps,params,"pind4")
589    if (curnt) nflx = calc_flux(cps*100/curnt,params,"pind4")
590    printf("%8.3g photons per second \n",flx)
591    if (nflx) printf("%8.3g photons per second per 100 mA \n",nflx)
592    # make sure the parameters will be in the .batchinfo file
593    if (!exists("batch_pars","Amps_per_Volt")) {
594      for (field in params) batch_pars[field] = params[field]
595      batch_pars["Element"] = inquotes(params["Element"])
596      }
597    if ("$1" == "vacuum") {
598      add_batch_par ring_i_vacuum curnt
599      add_batch_par beam_i_vacuum flx
600      if (curnt) batch_pars["norm_vac_flux"] = flx/curnt
601      fprintf(SHORTFILE,"\nAt samx = %g, samz = %g, samth = %g",A[samx],A[samz],A[samth])
602      fprintf(SHORTFILE," (through vacuum):\n")
603      fprintf(SHORTFILE,"\t%4.3g photons/sec at %5.2f mA",\
604              flx,curnt)
605      if (nflx) fprintf(SHORTFILE," (%4.3g per 100 mA)",nflx)
606      }
607    else { # sample
608      sth = A[samth]; sz = A[samz]; sx = A[samx]; dt=inquotes(date())
609      add_batch_par samth_flux sth
610      add_batch_par samz_flux sz
611      add_batch_par samx_flux sx
612      add_batch_par ring_i_sample curnt
613      add_batch_par beam_i flx
614      add_batch_par beam_i_vacuum max(Monitor_flux,1.0)
615      add_batch_par beam_i_time dt
616      fprintf(SHORTFILE,"\t%4.3g photons/sec at %5.2f mA",flx,curnt)
617      if (curnt && batch_pars["ring_i_vacuum"] && flx)
618        fprintf(SHORTFILE," (a factor of %.3g absorbed)",\
619                batch_pars["norm_vac_flux"]*curnt/flx)
620      else if (nflx) fprintf(SHORTFILE," (%4.3g per 100 mA)",nflx)
621      }
622    fprintf(SHORTFILE,"\n")
623    }
624  emptydef batch_cleanup
625  }'
626def lpstuff '
627        close("/var/tmp/foo1")
628        unix("rm -f /var/tmp/foo1")
629        on("/var/tmp/foo1")
630        offt;
631        $*
632        off("/var/tmp/foo1")
633        ont;
634        u enscript -d garnet -2r -f Courier-Bold7 -h /var/tmp/foo1
635        u rm /var/tmp/foo1
636'
637global pvDELAY_CTL
638pvDELAY_CTL = "8idi:Unidig1Bo13.VAL";
639
640SHUTTER_OPEN_TIME=0.0025
641SHUTTER_CLOSE_TIME=0.002
642
643def write_sample_pars'{
644    fprintf(SHORTFILE,"\nAt samx = %g, samz = %g, samth = %g, ccdx = %g, ccdz = %g, Ctl_Chan = %s, T_A = %g, T_B = %g:\n",\
645    A[samx], A[samz], A[samth], A[ccdx], A[ccdz],\
646    epics_get("8idi:LS331:TC1:CtlInput.SVAL"),\
647    epics_get("8idi:LS331:TC1:SampleA"),\
648    epics_get("8idi:LS331:TC1:SampleB"));
649  }'
650# The following macros may be site dependent.  Need proper modification
651
652global atten_set attvalue
653
654##for XIA S1
655global pvATT_SET
656global pvATT_GET
657
658##for XIA S2
659global pvATT2_SET
660global pvATT2_GET
661
662global pvFILTER5_RDBK
663global pvFILTER5_CTL
664
665pvATT_SET = "8idi:BioEncode1.A";
666pvATT_GET = "8idi:BioDecode1.A";
667
668pvATT2_SET = "8idi:BioEncode2.A";
669pvATT2_GET = "8idi:BioDecode2.A";
670
671pvFILTER5_RDBK = "8idi:BioDecode2.B"
672pvFILTER5_CTL = "8idi:BioEnc2B0.VAL"
673
674# Site-specific information for att in 8-ID-I.
675
676#def attcalc '
677#      local state
678#      totatt = 1.0
679#      state = $1
680#      if(state&0x1) totatt *= 0.252
681#      if(state&0x2) totatt *= 0.0135
682#      if(state&0x4) totatt *= 2.44e-06
683#      if(state&0x8) totatt *= 0.0
684#'
685
686def attcalc '
687        global attvalue
688        attvalue = epics_get("8idi:userTran1.P")
689       
690        printf("\nAttenuation of the Beam (excl. Foils 2,3,4 in XIA S2) = %f\n",attvalue)
691        '
692
693def attshow '
694      printf(" \nUsage: att 0--15|Each bit is one foil\n")
695      printf("This command works on 4 Filters on XIA S1 for 7.35 keV and 4 Filters  on XIA S2 for 11 keV\n")
696     
697      printf(" 0 = no attenuators on XIA S1, 15 = all attenuators on XIA S1 when E=7.35 keV\n")
698      printf(" 0 = no attenuators on XIA S2, 15 = all attenuators on XIA S2 when E=11.0 keV\n")
699
700      printf("  Foil 1 (XIA S1) = 0.5 mil Cu = 1/2     @ 7.50 keV\n")
701      printf("  Foil 2 (XIA S1) = 1.0 mil Cu = 1/4     @ 7.50 keV\n")
702      printf("  Foil 4 (XIA S1) = 2.0 mil Cu = 1/16    @ 7.50 keV\n")
703      printf("  Foil 8 (XIA S1) = 4.0 mil Cu = 1/256   @ 7.50 keV\n\n")
704     
705      printf("  Foil 1 (XIA S2) = 5 mil Al =  1/2      @ 11.0 keV\n")
706      printf("  Foil 2 (XIA S2) = 10 mil Al = 1/4     @ 11.0 keV\n")
707      printf("  Foil 4 (XIA S2) = 20 mil Al = 1/16    @ 11.0 keV\n")
708      printf("  Foil 8 (XIA S2) = 40 mil Al = 1/256   @ 11.0 keV\n\n")
709'
710global pvGATE_SET
711global GATE_ON_VAL
712global GATE_OFF_VAL
713pvGATE_SET = "8idi:Unidig1Bo11.VAL";
714GATE_ON_VAL = 0
715GATE_OFF_VAL = 1
716# [lake331epics.mac]
717# May 25, 2004, temperature control macro for the Lakeshore 331 controller
718#
719#       All Temperatures of the controller are in Celsius !!!
720#
721
722#added a global variable "USE_PELTIER" so that "te" will auto set the right peltier values
723# USE_PELTIER=0 corr. to peltier NOT being used
724# USE_PELTIER=1 corr. to peltier being used
725#this variable is defined in conf.mac
726
727global USE_PELTIER
728
729
730def  measuretemp '             
731        local  temperature_string
732        temperature_string=epics_get("8idi:LS331:TC1:Control")
733        sscanf(temperature_string,"%f",TEMP_CS);
734        DEGC=TEMP_CS;
735        temperature_string=epics_get("8idi:LS331:TC1:wr_SP")
736        sscanf(temperature_string,"%f",TEMP_SP);
737'
738
739def _settemp '
740        if (USE_PELTIER) {
741                if ( (DEGC_SP >= -35) && (DEGC_SP <= 20) ) {cool_high}
742                else if ( (DEGC_SP > 20) && (DEGC_SP <= 60) ) {cool_medium}
743                else if ( (DEGC_SP > 60) && (DEGC_SP <= 110) ) {peltier_reset}
744                else if ( (DEGC_SP > 110) && (DEGC_SP <= 140) ) {heat_low}
745                else if ( (DEGC_SP > 140) && (DEGC_SP <= 175) ) {heat_medium}
746                else if ( (DEGC_SP > 175) && (DEGC_SP <= 220) ) {heat_high}
747                else {peltier_reset}
748        }
749#       check_lakeshore
750        epics_put("8idi:LS331:TC1:wr_SP",DEGC_SP)
751        while (epics_get("8idi:LS331:TC1:SP")!=DEGC_SP) {
752        epics_put("8idi:LS331:TC1:wr_SP",DEGC_SP)
753        sleep(0.2)
754        }
755'
756
757def settemp '
758               
759        if($# != 1) {
760                print "Usage: settemp set_point [C]"
761                exit
762        } else {
763                local _1
764                _1=$1;
765       
766                DEGC_SP=_1;
767                _settemp
768        }
769'
770
771
772def controltemp '{
773        if($# !=1) {
774              printf("Current control channel is %s",epics_get("8idi:LS331:TC1:Input_sel"))
775              print "\nUsage: controltemp A  to change\n"
776              exit
777        }
778        if( "$1"=="A"){
779        epics_put("8idi:LS331:TC1:Input_sel",0)
780        printf("\nTemperature control channel is set to A\n")
781        }
782        if("$1"=="B"){
783        epics_put("8idi:LS331:TC1:Input_sel",1)
784        printf("\nTemperature control channel is set to B\n")
785        } else print "Wrong channel!"
786 }'
787
788
789
790def teramp_on '
791        if($# != 1) {
792                print "Usage: teramp_on ramp_rate(K/min)"
793                exit
794        }
795        epics_put("8idi:LS331:TC1:Ramp_on","ON")
796        sleep(0.1)
797        epics_put("8idi:LS331:TC1:RampR_set",$1)
798        sleep(0.1)
799        epics_put("8idi:LS331:TC1:Ramp_on","ON")
800        sleep(0.1)
801        epics_put("8idi:LS331:TC1:RampR_set",$1)
802        printf("\nTemperature Ramp on the Controller is Turned ON\n")
803'
804
805def teramp_off '
806        epics_put("8idi:LS331:TC1:Ramp_on","OFF")
807        sleep(0.2)
808        epics_put("8idi:LS331:TC1:Ramp_on","OFF")
809        printf("\nTemperature Ramp on the Controller is Turned OFF\n")
810'
811       
812       
813def check_lakeshore '
814#       epics_put("8idi:LS331:TC1:serial.AOUT","HTRST?")
815#       sleep(0.1)
816#       epics_put("8idi:LS331:TC1:serial.SCAN","1 second")
817#       sleep(1.1)
818#       
819#        while (epics_get("8idi:LS331:TC1:serial.AINP")!=0) {
820#       printf("\nHeater is Open, Trying to Turn it ON ... \n")
821#       epics_put("8idi:LS331:TC1:HeatRg", "1 A")
822#       sleep(1.0)
823#       }
824#       epics_put("8idi:LS331:TC1:serial.SCAN","2 second")
825'
826
827def Pheader '
828        printf("\n US Gap=%6.2f mm, Tpr=%6.3f, DS Gap=%6.2f mm, Tpr=%6.3f, I=%6.2f mA\n", \
829        epics_get("ID08us:Gap"), \
830        epics_get("ID08us:TaperGap"), \
831        epics_get("ID08ds:Gap"), \
832        epics_get("ID08ds:TaperGap"), \
833        epics_get("S:SRcurrentAI"))
834        printf(" Setpoint =%g (%g C)\n", TEMP_SP, DEGC_SP)'
835
836def Fheader '
837        #_cols++;
838        printf("#C US Gap=%6.2f mm, Tpr=%6.3f, DS Gap=%6.2f mm, Tpr=%6.3f, I=%6.2f mA\n", \
839        epics_get("ID08us:Gap"), \
840        epics_get("ID08us:TaperGap"), \
841        epics_get("ID08ds:Gap"), \
842        epics_get("ID08ds:TaperGap"), \
843        epics_get("S:SRcurrentAI"))'
844
845def Ftail '
846        printf("#C US Gap=%6.2f mm, Tpr=%6.3f, DS Gap=%6.2f mm, Tpr=%6.3f, I=%6.2f mA\n", \
847        epics_get("ID08us:Gap"), \
848        epics_get("ID08us:TaperGap"), \
849        epics_get("ID08ds:Gap"), \
850        epics_get("ID08ds:TaperGap"), \
851        epics_get("S:SRcurrentAI"))'
852
853#def Plabel ''
854def Plabel '""'
855#def Plabel 'sprintf(" %6.7s %6.7s", "T-set", "T-degc")'
856
857#def Pout ''
858def Pout '""'
859#def Pout 'sprintf(" %6.5g %6.5g", DEGC_SP, DEGC)'
860
861#def Flabel ''
862def Flabel '""'
863#def Flabel '"  DegC "'
864
865#def Fout ''
866def Fout '""'
867#def Fout 'sprintf(" %g ", DEGC)'
868def write_sample_pars'{
869    fprintf(SHORTFILE,"\nAt samx = %g, samz = %g, samth = %g, ccdx = %g, ccdz = %g, Ctl_Chan = %s, T_A = %g, T_B = %g:\n",\
870    A[samx], A[samz], A[samth], A[ccdx], A[ccdz],\
871    epics_get("8idi:LS331:TC1:CtlInput.SVAL"),\
872    epics_get("8idi:LS331:TC1:SampleA"),\
873    epics_get("8idi:LS331:TC1:SampleB"));
874  }'
875# Move tth and samth
876def an '_an $*; move_poll'
877def uan '_an $*; _update("tth samth")'  # update version of above
878def _an '
879        if ($# != 2) {
880                eprint "Usage:  an tth samth"
881                exit
882        } ;
883        waitmove; get_angles; A[tth]=$1; A[samth]=$2
884        ifp { fprintf(PRINTER,"\nmv tth %g\nmv samth %g\n", $1, $2) }
885        move_em
886        uwm tth samth
887'
888# Scan tth and samth
889def th2th '
890        if ($# != 4) {
891            eprint "Usage:  th2th samth_start_abs samth_finish_abs intervals time"
892            exit
893        }
894        an ($1)*2 $1;
895        a2scan samth $1 $2 tth ($1)*2 ($2)*2 $3 $4
896'
897#Macro to list all the slit motor (real & pseudo) positions
898
899def show_si1 '
900        wm si1hgap si1hcen si1vgap si1vcen
901'
902
903def show_si2 '
904        wm si2hgap si2hcen si2vgap si2vcen
905'
906
907def show_si3 '
908        wm si3hgap si3hcen si3vgap si3vcen
909'
910
911def show_si4 '
912        wm si4hgap si4hcen si4vgap si4vcen
913'
914
915def show_si5 '
916        wm si5hgap si5hcen si5vgap si5vcen
917'
918
919def show_si6 '
920        ##wm si6hgap si6hcen si6vgap si6vcen
921        wm si6t si6b si6T si6B
922'
923
924def show_ccd '
925        wm ccdx ccdz bstop
926'
927
928def show_sam '
929        wm samx samz samth tth bstop
930'
931
932def show_ti1 '
933        wm ti1_x ti1_z
934'
935
936def show_ti2 '
937        wm ti2_x ti2_z
938'
939
940def show_ti3 '
941        wm ti3_x ti3_z
942'
943
944def show_ti4 '
945        wm ti4_x ti4_z ti4xu ti4xd ti4zu ti4zdo ti4zdi
946'
947
948def show_slits '
949        show_si1
950        show_si2
951        show_si3
952        show_si4
953        show_si5
954        show_si6
955'
956
957def show_tables '
958        show_ti1
959        show_ti2
960        show_ti3
961        show_ti4
962'
963
964# Revised version of macros after change in spec data groups
965# Larry Lurio, June 14, 2003
966# Revised by Alec Sandy, May 25, 2004 to incorporate I station switch to
967# EPICS
968
969global attAlign, ctAlign,tth_offset,th_low,th_high,sampos_low,sampos_high
970attAlign   = 6
971ctAlign    = 0.1
972tth_offset = 0.035
973th_low = -0.2
974th_high = 0.2
975sampos_low = -0.05
976sampos_high = 0.05
977
978
979def get_halfpoint '
980        global halfpoint;
981        global datamax,datamin,datamid,ymid,I_low,ihigh;
982        array y[NPTS];
983        array x[NPTS];
984        for (i=0;i<NPTS;i++) {
985                y[i]=SCAN_D[i][DET+1];
986                x[i]=SCAN_D[i][0];
987        }
988        datamax=array_op("max",y);
989        datamin=array_op("min",y);
990        datamid=(datamax+datamin)/2.0;
991        ymid=datamin;
992        I_Low=0;
993        for (ii=0;ii<NPTS;ii++) {
994                if ((y[ii]>ymid) & (y[ii]<datamid)) {
995                        ymid=y[ii];
996                        I_low=ii;
997                }
998        }
999        printf("I_low=%d\n",I_low);
1000        if (y[I_low+1]>y[I_low]) ihigh=I_low+1;
1001        else ihigh=I_low-1;
1002        x1=x[I_low];
1003        x2=x[ihigh];
1004        y1=y[I_low];
1005        y2=y[ihigh];
1006        halfpoint = x1+(datamid-y1)*(x2-x1)/(y2-y1)
1007        printf("thcenter = %6.4f xcenter(halfpoint) = %6.4f\n",thcenter,halfpoint);
1008'
1009
1010def thcen '
1011        global thcenter;
1012        shutteroff
1013        showbeam
1014        umv tth tth_offset
1015        att attAlign
1016        lup samth th_high th_low 40 ctAlign
1017        ct;blockbeam;
1018        umv samth CEN
1019        thcenter=CEN
1020        printf("thcenter  %6.4f xcenter = %6.4f\n",thcenter,halfpoint);
1021'
1022
1023def thcen_coarse '
1024        global thcenter;
1025        shutteroff
1026        showbeam
1027        umv tth tth_offset
1028        att attAlign
1029        lup samth th_high*5.0 th_low*5.0 40 ctAlign
1030        ct;blockbeam;
1031        umv samth CEN
1032        thcenter=CEN
1033        printf("thcenter  %6.4f xcenter = %6.4f\n",thcenter,halfpoint);
1034'
1035
1036
1037def thfine '
1038        shutteroff
1039        showbeam
1040        att attAlign
1041        umv tth tth_offset
1042        lup samth th_high*0.5 th_low*0.5 20 ctAlign
1043        ct;blockbeam;
1044        umv samth CEN
1045'
1046
1047def sampitcen '
1048        global thcenter;
1049        shutteroff
1050        showbeam
1051        umv tth tth_offset
1052        att attAlign
1053        lup sampit th_low th_high 40 ctAlign
1054        ct;blockbeam;
1055        umv sampit CEN
1056        thcenter=CEN
1057        printf("thcenter  %6.4f xcenter = %6.4f\n",thcenter,halfpoint);
1058'
1059
1060def sampitcen_coarse '
1061        global thcenter;
1062        shutteroff
1063        showbeam
1064        umv tth tth_offset
1065        att attAlign
1066        lup sampit th_low*5.0 th_high*5.0 40 ctAlign
1067        ct;blockbeam;
1068        umv sampit CEN
1069        thcenter=CEN
1070        printf("thcenter  %6.4f xcenter = %6.4f\n",thcenter,halfpoint);
1071'
1072
1073
1074def sampitfine '
1075        shutteroff
1076        showbeam
1077        att attAlign
1078        umv tth tth_offset
1079        lup sampit th_low*0.5 th_high*0.5 20 ctAlign
1080        ct;blockbeam;
1081        umv sampit CEN
1082'
1083
1084def xcen '
1085        shutteroff
1086        showbeam
1087        att attAlign
1088        umv tth tth_offset
1089        lup samx sampos_low sampos_high 40 ctAlign
1090        ct;blockbeam;
1091        get_halfpoint
1092        umv samx halfpoint
1093'
1094
1095def xcen_coarse '
1096        shutteroff
1097        showbeam
1098        att attAlign
1099        umv tth tth_offset
1100        lup samx sampos_low*5.0 sampos_high*5.0 50 ctAlign
1101        ct;blockbeam;
1102        get_halfpoint
1103        umv samx halfpoint
1104'
1105
1106def zcen '
1107        shutteroff
1108        showbeam
1109        att attAlign
1110        umv tth tth_offset
1111        lup samz sampos_low sampos_high 40 ctAlign
1112        ct;blockbeam;
1113        get_halfpoint
1114        umv samz halfpoint
1115'
1116
1117def zcen_coarse '
1118        shutteroff
1119        showbeam
1120        att attAlign
1121        umv tth tth_offset
1122        lup samz sampos_low*5.0 sampos_high*5.0 50 ctAlign
1123        ct;blockbeam;
1124        get_halfpoint
1125        umv samz halfpoint
1126'
1127
1128def user_filehead '
1129        # motors not in spec - mostly primitives
1130        print "#VA0 " epicsMotInfo("8ida", "m", 1, 8, "m");
1131        print "#VA1 " epicsMotInfo("8ida", "m", 9, 16, "m");
1132        print "#VD0 " epicsMotInfo("8idd", "m", 1, 2, "m");
1133        print "#VI0 " epicsMotInfo("8idi", "m", 5, 8, "m");
1134        print "#VI1 " epicsMotInfo("8idi", "m", 9, 14, "m");
1135        print "#VI2 " epicsMotInfo("8idi", "m", 20, 24, "m");
1136        print "#VI2 " epicsMotInfo("8idi", "m", 28, 32, "m");
1137        print "#VI2 " epicsMotInfo("8idi", "m", 33, 36, "m");
1138        print "#VI2 " epicsMotInfo("8idi", "m", 41, 44, "m");
1139        print "#VI2 " epicsMotInfo("8idi", "m", 45, 48, "m");
1140        print "#VI2 " epicsMotInfo("8idi", "m", 57, 60, "m");
1141'
1142
1143def user_Fheader '
1144        # motors not in spec - mostly primitives
1145        print "#WA0 " epicsMotInfo("8ida", "m", 1, 8, "u");
1146        print "#WA1 " epicsMotInfo("8ida", "m", 9, 16, "u");
1147        print "#WD0 " epicsMotInfo("8idd", "m", 1, 2, "u");
1148        print "#WI0 " epicsMotInfo("8idi", "m", 5, 8, "u");
1149        print "#WI1 " epicsMotInfo("8idi", "m", 9, 14, "u");
1150        print "#WI1 " epicsMotInfo("8idi", "m", 20, 24, "u");
1151        print "#WI1 " epicsMotInfo("8idi", "m", 28, 32, "u");
1152        print "#WI2 " epicsMotInfo("8idi", "m", 33, 36, "u");
1153        print "#WI2 " epicsMotInfo("8idi", "m", 41, 44, "u");
1154        print "#WI2 " epicsMotInfo("8idi", "m", 45, 48, "u");
1155        print "#WI2 " epicsMotInfo("8idi", "m", 57, 60, "u");
1156       
1157        print "#WISRS1 " epics_get("8idi:A1sens_num.VAL") epics_get("8idi:A1sens_unit.VAL")
1158        print "#WISRS2 " epics_get("8idi:A2sens_num.VAL") epics_get("8idi:A2sens_unit.VAL")
1159        print "#WISRS3 " epics_get("8idi:A3sens_num.VAL") epics_get("8idi:A3sens_unit.VAL")
1160        print "#WISRS4 " epics_get("8idi:A4sens_num.VAL") epics_get("8idi:A4sens_unit.VAL")
1161        print "#WISRS5 " epics_get("8idi:A5sens_num.VAL") epics_get("8idi:A5sens_unit.VAL")
1162'
1163global pvFLUX_PIND pvPIND2_ACTUATOR pvPIND1_ACTUATOR
1164pvFLUX_PIND = "8idi:9440:1:bo_0.VAL"
1165pvPIND2_ACTUATOR = "8idi:9440:1:bo_1.VAL"
1166pvPIND1_ACTUATOR = "8idi:9440:1:bo_2.VAL"
1167
1168def move_pind1z_in '
1169        #umv pind1z 14.0;
1170        epics_put(pvPIND1_ACTUATOR,1);
1171        printf("\nMoved PIND-1 Diode IN...\n")
1172'
1173
1174def move_pind1z_out '
1175        #umv pind1z 4.0;
1176        epics_put(pvPIND1_ACTUATOR,0);
1177        printf("\nMoved PIND-1 Diode OUT...\n")
1178'
1179
1180def move_pind2z_in '
1181        ##umv pind2z 21.0;
1182        epics_put(pvPIND2_ACTUATOR,1);
1183        printf("\nMoved PIND-2 Diode IN...\n")
1184'
1185
1186def move_pind2z_out '
1187        ##umv pind2z 7.0;
1188        epics_put(pvPIND2_ACTUATOR,0);
1189        printf("\nMoved PIND-2 Diode OUT...\n")
1190'
1191
1192def move_pind4z_in '
1193        epics_put(pvFLUX_PIND,1);
1194        printf("\nMoved Flux Measuring PIN Diode IN...\n")
1195'
1196
1197def move_pind4z_out '
1198        epics_put(pvFLUX_PIND,0);
1199        printf("\nMoved Flux Measuring PIN Diode OUT...\n")
1200'
1201
1202def move_tth_in '
1203        umv tth 0.0;
1204'
1205
1206def move_tth_out '
1207        umv tth 1.5;
1208'
1209
1210def block_directbeam_common '
1211        epics_put("8idi:BioEncode1.A",15);
1212        epics_put("8idi:BioEncode2.A",15);
1213'
1214
1215def showbeam_common '
1216        epics_put("8idi:Unidig1Bo13","Open");
1217'
1218
1219def blockbeam_common '
1220        epics_put("8idi:Unidig1Bo13","Closed");
1221'
1222
1223
1224def use_blockbeam_common '
1225      def blockbeam \'blockbeam_common\'
1226      def block_directbeam \' block_directbeam_common \'
1227      def showbeam  \'showbeam_common \'
1228'
1229
1230use_blockbeam_common
1231global SHUTTER_TYPE SLOW_pvSHUTT_CTL FAST_pvSHUTT_CTL pvSHUTT_CTL
1232global pvCCD_SHUTTER_SELECT
1233
1234pvSHUTT_CTL = "8idi:Unidig1Bo9.VAL"
1235
1236#SLOW_pvSHUTT_CTL = "8idi:Unidig1Bo23.VAL"
1237FAST_pvSHUTT_CTL = "8idi:Unidig1Bo9.VAL"
1238#SLOW_pvSHUTT_STATE = "8idi:BioEnc2B3.VAL"
1239FAST_pvSHUTT_STATE = "8idi:Unidig1Bo13.VAL"
1240pvCCD_SHUTTER_SELECT = "8idi:Unidig1Bo22.VAL"
1241
1242def ccdtype_shutter_control_select '
1243        # value of 1 sends the output of PI CCD to the fast shutter
1244        # value of 0 sends the output of a second CCD (Detector Pool Fast CCD) to the fast shutter
1245        #This multiplexing is enabled by the 2nd logic box from Steve Ross (March 15, 2010)
1246        #
1247        if($# !=1) {
1248           p "Usage: ccdtype_shutter_control_select [1|0] (1 = PI CCD, 0 - Detector Pool Fast CCD)"
1249           exit
1250        }
1251       
1252        if ($1 ==0) {
1253            epics_put(pvCCD_SHUTTER_SELECT, 0);
1254            print "\nDetector Pool Fast CCD is controlling the shutter ...\n";
1255          } else {
1256                ###default mode: select PI CCD
1257            epics_put(pvCCD_SHUTTER_SELECT, 1);
1258            print "\nDefault CCD is controlling the shutter ...\n";
1259          }
1260'
1261
1262####select PI CCD Controlling the shutter as the default
1263#ccdtype_shutter_control_select 1
1264#############################################
1265##default notion started in July 2017 (Suresh)
1266def shutteron_default '
1267        epics_put(pvSHUTT_CTL, 0);
1268        print "\nCCD is controlling shutter ...\n";
1269'
1270
1271def shutteroff_default '
1272        epics_put(pvSHUTT_CTL, 1);
1273        print "\nCCD control of shutter has been surrendered ...\n";
1274'
1275
1276def shutteron 'shutteron_default'
1277def shutteroff 'shutteroff_default'
1278#############################################
1279def shuttertype '
1280        if($# != 0 && $# !=1) {
1281           p "Usage: shuttertype [0|1] (0 = slow shutter and 1 = fast shutter)"
1282           exit
1283        }
1284        if ($# == 0) {
1285          SHUTTER_TYPE = yesno("Do you want the FAST SHUTTER for controlling the CCD?",SHUTTER_TYPE)
1286        }
1287        if ($# == 1) {
1288          if ($1 ==0 || $1 == 1) {
1289            SHUTTER_TYPE = $1
1290          } else {
1291                ###default mode: Select Fast Shutter and Disable Slow Shutter
1292            SHUTTER_TYPE = 1
1293          }
1294        }
1295        if (SHUTTER_TYPE) {
1296                # Fast
1297                epics_put(SLOW_pvSHUTT_CTL,1)
1298                pvSHUTT_CTL = FAST_pvSHUTT_CTL
1299                p "Fast shutter being used: " pvSHUTT_CTL
1300                shutteron
1301                epics_put(SLOW_pvSHUTT_STATE,"Open")
1302        } else {
1303                # Slow
1304                epics_put(FAST_pvSHUTT_CTL,1)
1305                pvSHUTT_CTL = SLOW_pvSHUTT_CTL
1306                p "Slow shutter being used: " pvSHUTT_CTL
1307                shutteron
1308                epics_put(FAST_pvSHUTT_STATE,0)
1309        }
1310'
1311
1312##shuttertype 1
1313
1314#file aps_gaps.mac
1315# macros associated with undulator gaps.
1316#MS added Sept/98
1317# setup for ID08 IMMCAT
1318# modified minimum gap to 11mm, and updated variables  PF June/02
1319
1320#       gap - print out information on gap and ring currents.
1321#       set_gap - request epics to change gap.
1322#       set_usgap - request epics to change upstream gap only.
1323#       gap1 - like gap but gives up and downstream gaps.
1324#       prepics - print out selected information from epics.
1325
1326#print a summary of info from epic variables
1327
1328def gap '
1329   printf("  Current = %6.2f mA, ", epics_get("S:SRcurrentAI"));
1330   printf("  Lifetime = %6.2f hrs\n", epics_get("S:SRlifeTimeHrsCC"));
1331   printf("  Average Gap = %6.2f mm, ", epics_get("ID08:Gap"));
1332   printf("  Fundamental energy = %6.2f keV\n",epics_get("ID08:Energy"));
1333'
1334
1335def gap1 '
1336   printf("  Current = %6.2f mA, ", epics_get("S:SRcurrentAI"));
1337   printf("  Lifetime = %6.2f hrs\n", epics_get("S:SRlifeTimeHrsCC"));
1338   printf("  Average Gap = %6.2f mm, ", epics_get("ID08:Gap"));
1339   printf("  Fundamental energy = %6.2f keV\n",epics_get("ID08:Energy"));
1340   printf("  Gap taper = %6.2f mm, ", epics_get("ID08:TaperGap"));
1341   printf("  Energy taper  = %6.2f keV\n", epics_get("ID08:TaperEnergy"));
1342'
1343# use "short" in epics get to force a number return value instead of string
1344def set_gap '
1345        if( $# != 1) {
1346                printf("Usage: set_gap gap\n");
1347                exit;
1348        }
1349        gapvalue = $1;
1350        perm = epics_get("ID08:AccessSecurity","short")
1351        if (perm == 0) {
1352                if ((gapvalue >= 11) && (gapvalue <= 200) ) {
1353                        printf("setting undulator gap to: ");
1354                        epics_put("ID08:GapSet",gapvalue);
1355                        p epics_get("ID08:GapSet");
1356                        epics_put("ID08:Start",1);
1357                        gap;
1358                }
1359            else printf("gap parameter value of %f out of range\n",gapvalue);
1360        }
1361        else {
1362                printf("Access denied; Undulator Control in ");
1363                if (perm == 1) printf("\"Operator Mode\".\n");
1364                else if (perm == 2) printf("\"Floor Coordinator Mode\".\n");
1365                else if (perm == 3) printf("\"Machine Physics Mode\".\n");
1366                else if (perm == 4) printf("\"System Manager Mode\".\n");
1367        }
1368
1369'
1370def set_taper '
1371        if( $# != 2) {
1372                printf("Usage: set_taper gap taper \n");
1373                exit;
1374                }
1375        gap = $1;
1376        taper = $2;
1377        perm = epics_get("ID08:AccessSecurity","short")
1378        if (perm == 0) {
1379            if ((gap >= 11) && ( gap<= 200) && (fabs(taper) <= 5) ) {
1380                        printf("Setting  Undulator gap to: ");
1381                        epics_put("ID08:GapSet",gap);
1382                        p epics_get("ID08:GapSet");
1383                        printf("Setting Undulator gap taper to: ");
1384                        epics_put("ID08:TaperGapSet",taper);
1385                        p epics_get("ID08:TaperGapSet");
1386                        epics_put("ID08:Start",1);
1387                        gap1;
1388                        }
1389            else printf("Gap Parameter Value of %f  %f out of range\n",gap,taper);
1390        }
1391        else {
1392                printf("Access denied; Undulator Control in ");
1393                if (perm == 1) printf("\"Operator Mode\".\n");
1394                else if (perm == 2) printf("\"Floor Coordinator Mode\".\n");
1395                else if (perm == 3) printf("\"Machine Physics Mode\".\n");
1396                else if (perm == 4) printf("\"System Manager Mode\".\n");
1397        }
1398
1399'
1400#file newlup.mac
1401
1402# redefine lup to make heading of pplot be labelled by lup instead of ascan.
1403# M. Sutton Dec/98. Before redefined dscan but this broke down as new versios
1404# of dscan where implemented. Now give new name.
1405# Mark Sutton Feb 97
1406
1407# redefine lup to make heading of pplot be labelled by lup instead of ascan.
1408# Changes HEADING variable to lup arguments instead of ascan args.
1409# Also add n2lup for two motors.
1410# redefine dscan to make heading of pplot be labelled by dscan instead of ascan.
1411# only does dscan and d2scan currently
1412
1413def nlup '
1414        if ($# != 5) {
1415                print "Usage:  nlup motor start finish intervals time"
1416                exit
1417        }
1418# Added by Mark Sutton, (dec 98)  should only affect pplot etc
1419        local str;
1420        str = sprintf("nlup %s %g %g %d %d",motor_mne($1),$2,$3,$4,$5);
1421#
1422        dscan $*
1423# Added by Mark Sutton, (dec 98)  should only affect pplot etc
1424        HEADING=sprintf("%s",str);
1425'
1426
1427# Added by Mark Sutton, (dec 98)  should only affect pplot etc
1428def n2lup '
1429        if ($# != 8) {
1430                print \
1431"Usage:  n2lup  motor1 start1 finish1  motor2 start2 finish2  intervals time"
1432                exit
1433        }
1434# Added by Mark Sutton, (dec 98)  should only affect pplot etc
1435        local str;
1436        str = sprintf("n2lup %s %g %g %d %d",motor_mne($1),$2,$3,$4,$5,$6,$7,$8);
1437#
1438        d2scan $*
1439# Added by Mark Sutton, (dec 98)  should only affect pplot etc
1440        HEADING=sprintf("%s",str);
1441'
1442#file nicewa.mac
1443#defined for setup on mica-trxs, Sep 12, 1998 MS
1444#split off showmots into separate files and made this be generic 2001 MS
1445
1446#NOTE: Spectrometer specific versions of showmots are defined in showmots_<site>.mac.
1447
1448#define equivalent to wa
1449def nwa '{
1450        showallmots 1
1451}'
1452#define equivalent to wu
1453def nwu '{
1454        showallmots 0
1455}'
1456
1457#Print a full set of info on all motors
1458def lpmots '{
1459        close("/var/tmp/foo1")
1460        unix("rm -f /var/tmp/foo1")
1461        on("/var/tmp/foo1")
1462        offt;
1463        showallmots 2
1464        off("/var/tmp/foo1")
1465        ont;
1466        u enscript -f Courier-Bold7 -h  /var/tmp/foo1
1467        u rm /var/tmp/foo1
1468}'
1469def prmots '{
1470        local i, n, t, flag1
1471
1472        if ($# == 0) {
1473                printf("Usage:  prmots motorname-array array-length dial-flag")
1474                exit
1475                }
1476        m = $1
1477        n = $2
1478        flag1 = $3
1479        if ( flag1!= 2 ) {
1480                printf("\n")
1481                for (i = 0; i < n; i++) printf("%8.7s ", motor_mne(m[i]))
1482                printf("\n")
1483                for (i = 0; i < n; i++) printf("%8.4f ", A[m[i]])
1484                printf("\n")
1485                if(flag1==1) {
1486                        for (i = 0; i < n; i++) printf("%8.4f ", dial(m[i],A[m[i]]))
1487                        printf("\n")
1488                        }
1489                }
1490        else {
1491                printf("\n          ")
1492                for (i = 0; i < n; i++) printf("   %-7s ", motor_name(m[i]))
1493                printf("\n          ")
1494                for (i = 0; i < n; i++) printf("   %-7s ", motor_mne(m[i]))
1495                printf("\nUser ")
1496                printf("\n%10s", " High")
1497                for (i = 0; i < n; i++)
1498                        printf("%10.4f ", user(m[i], get_lim(m[i], 1)))
1499                printf("\n%10s", " Current")
1500                for (i = 0; i < n; i++)
1501                        printf("%10.4f ", A[m[i]])
1502                printf("\n%10s", " Low")
1503                for (i = 0; i < n; i++)
1504                        printf("%10.4f ", user(m[i], get_lim(m[i], -1)))
1505                printf("\nDial\n%10s", " High")
1506                for (i = 0; i < n; i++)
1507                        printf("%10.4f ", get_lim(m[i], 1))
1508                printf("\n%10s", " Current")
1509                for (i = 0; i < n; i++)
1510                        printf("%10.4f ", dial(m[i], A[m[i]]))
1511                printf("\n%10s", " Low")
1512                for (i = 0; i < n; i++)
1513                        printf("%10.4f ", get_lim(m[i], -1))
1514                printf("\n")
1515                }       
1516}'
1517def showallmots '{
1518        local flag, m[]
1519        array fl[MOTORS]
1520        array m[8]
1521
1522        if ($# == 0) {
1523                print "Usage:  showallmots dial-flag"
1524                exit
1525                }
1526
1527        # show all pre-selected motors 
1528        showmots $1
1529
1530        # show rest of motors   
1531        no=0
1532        for(i=0; i<MOTORS;i++) {
1533                if( !fl[i]) {
1534                        m[no]=i
1535                        no++
1536                        }
1537                if(no==8) {
1538                        prmots m no $1
1539                        no = 0
1540                        }
1541                }
1542        if(no) prmots m no $1
1543}'
1544
1545def selmots '{
1546        local m[],b[],i,no,flag,prflag
1547        array m[8]
1548
1549        if ($# == 0) {
1550                print "Usage:  selmots print-flag motorname-list dial-flag"
1551                exit
1552                }
1553        b[0]=0
1554        n=split("$*",b)
1555        flag=b[n-1]
1556        prflag=$1
1557        no=$#-2
1558        i=0
1559        while(i<no) {
1560                m[i] = motor_num(b[i+1])
1561                fl[motor_num(b[i+1])] = 1
1562                i++
1563                }
1564        if(prflag) prmots m no flag
1565}'
1566
1567def epicsMotInfo(strCrate, strMotPrefix, intMotStart, intMotEnd, strInfoReq) '{
1568# returns a space separated string of EPICS motor or soft motor
1569# information intended to be used for spec commands/macros
1570# that list motor and motor values in spec files or for things like
1571# wa or nwa
1572#
1573# strCrate is a VME crate name like "8idi"
1574# strMotorPrefix is a motor prefix: m = motor and sm = soft motor
1575# intMotStart is the starting motor number - for spec files this should
1576#       be a multiple of 8 (plus 1 - i.e., 1, 9, 17, ...)
1577# intMot End is the ending motor number - for spec files this is
1578#       typically the starting motor + 7 - i.e., per above, 8, 16, 24, ...
1579# strInfoReq is the info requested:
1580#       u = user value
1581#       d = dial value
1582#       m = mnemonic or EPICS description
1583#       uh = high user unit
1584#       ul = low user unit
1585#       dh = high user dial
1586#       ul = low user dial
1587
1588        local i, j;
1589        local strEpicsPV, s, strPVSuffix, strTemp;
1590        if (strInfoReq == "u") {
1591                strPVSuffix = "RBV";
1592        }
1593        else if (strInfoReq == "d") {
1594                strPVSuffix = "DRBV";
1595        }
1596        else if (strInfoReq == "uh") {
1597                strPVSuffix = "HLM";
1598        }
1599        else if (strInfoReq == "ul") {
1600                strPVSuffix = "LLM";
1601        }
1602        else if (strInfoReq == "dh") {
1603                strPVSuffix = "DHLM";
1604        }
1605        else if (strInfoReq == "dl") {
1606                strPVSuffix = "DLLM";
1607        }
1608        else if (strInfoReq == "m") {
1609                strPVSuffix = "DESC";
1610        }
1611        else {
1612                return "";
1613        }
1614        s = "";
1615        for (i = intMotStart; i <= intMotEnd; i++) {
1616                strEpicsPV = sprintf("%s:%s%d.%s", strCrate, strMotPrefix, i, strPVSuffix);
1617                strTemp = epics_get(strEpicsPV);
1618                if (strInfoReq == "m") {
1619                        s = s sprintf("%s", strTemp)
1620                }
1621                else {
1622                        s = s sprintf("%.8g", strTemp)
1623                }
1624
1625                if (i == intMotEnd) {
1626                        s = s "\n";
1627                } else {
1628                        s = s " ";
1629                }
1630        }
1631        return(s);
1632}'
1633
1634def gateYN() '{
1635        _gate = epics_get(pvGATE_SET);
1636        if (_gate == "High")
1637                return "N";
1638        else
1639                return "Y";
1640}'
1641
1642def gatestatus '
1643        if (gateYN() == "Y")
1644                p "\nNote: Counters are being gated by the CCD shutter signal ...\n";
1645        else
1646                p "\nNote: Counters are not being gated by the CCD shutter signal ...\n";
1647'
1648
1649def gateon '
1650        epics_put(pvGATE_SET, GATE_ON_VAL);
1651        if (PRINT_DEBUG_MSG == 1) print "\nNote: Counters are being gated by CCD shutter signal ...\n";
1652'
1653
1654def gateoff '
1655        epics_put(pvGATE_SET, GATE_OFF_VAL);
1656        if (PRINT_DEBUG_MSG == 1) print "\nNote: Counters are _not_ being gated by CCD shutter signal ...\n";
1657'
1658
1659def gate '
1660        if ($# == 0 ) {
1661                gatestatus;
1662                exit;
1663        }
1664        if ($# != 1 || ("$1" != "on"  && "$1" != "off")) {
1665                print "Usage:  gate on|off";
1666                exit;
1667        }
1668        if ("$1" == "on") {
1669                gateon;
1670        }
1671        else
1672        {
1673                gateoff;
1674        }
1675'
1676PLOT_CNTRS_MAX=25;
1677##_plotconfig(); #removed in SPEC V6
1678counters -1 4;
1679plotselect pind4;
1680printf("\npind4 has been set as the default counter\n")
1681gateoff;
1682#DATAFILE="~/spec_data/no_file_name_scans"
1683
1684#file pplot.mac
1685
1686global CP_FILTER        # The cplot filter
1687
1688if ((whatis("CP_FILTER")>>16)&0x0800)
1689        CP_FILTER="psfilter"            # assign a default
1690
1691if (!plot_with_arrays)
1692        rdef plot_defaults() \'{}\'
1693
1694def pplot '{
1695        close("cplot.tmp")
1696        unix("rm -f cplot.tmp")
1697        unix("date +%r%t%D >,cplot_date")
1698        on("cplot.tmp"); offt
1699        printf("zi %s\n", CP_FILTER)
1700        printf("re\n")
1701        printf("ft 2\n")
1702        printf("sy L\n")
1703        printf("tu 1\n")
1704#       printf("wi 3 9 7 5\n")
1705        printf("wi -.5 -1.5 7 5\n")
1706        printf("cs t 2\n")
1707        printf("cs l 2\n")
1708        printf("cs n 2\n")
1709        printf("cs s 2\n")
1710        printf("cs k 2\n")
1711        printf("cs d 2\n")
1712        printf("ty 0 0 0\n")
1713        printf("tx\n")
1714         printf("File %s, %s\n",DATAFILE,T_L)
1715         printf("%s\n",X_L)
1716         printf("\n")
1717         printf("%s\n",Y_L)
1718         printf("\n")
1719
1720        printf("zeqw\n")
1721        printf("gd 1\n")
1722        pts $*
1723        printf("^D\n")
1724
1725#       printf("zapltd\n")
1726        printf("zaplt\n")
1727        printf("sy 0\n")
1728        printf("zp\n")
1729
1730#       printf("wi 9\n")
1731#       printf("zn 2 2\n")
1732        printf("zn 0 -0.6\n")
1733        printf("\\s%s\\l\n", HEADING);
1734        printf("^D\n")
1735
1736        printf("zn 0 6.5\n")
1737       
1738        if (plot_with_arrays) {
1739          plot_defaults($#,"$1","$2","$3","$4")
1740          printf("\\C%s\n", sdata_res_s1(@pl_a,pl_x,pl_y,pl_n,pl_type));
1741          printf("\\C\\d%s\n", sdata_res_s2(@pl_a,pl_x,pl_y,pl_n,pl_type));
1742        } else {
1743          _pl_arg $*
1744          printf("\\C%s\n", splot_res1);
1745          printf("\\C\\d%s\n", splot_res2);
1746        }
1747        printf("^D\n")
1748
1749        printf("zn 4.25 -1.2 ,cplot_date\n")
1750
1751        printf("zs\n")
1752        printf("ex\n")
1753        ont; close("cplot.tmp")
1754#       unix("(cplot cplot.tmp; rm -f cplot.tmp) >/dev/null 2>&1 &")
1755#       unix("(/usr/local/cplot/bin/cplot cplot.tmp) > /dev/null &");
1756        unix("(cplot cplot.tmp; rm -f cplot.tmp) >/dev/null 2>&1 &")
1757}'
1758
1759
1760#file prepics.mac
1761# updated with new variables 12/13/01 PF
1762def prepics '
1763   if( $# > 2) {
1764        print "Usage: prepics \"title\" { filename } "
1765        exit
1766        }
1767   if( $# == 2 ) on("$2")
1768   if( $# > 0 ) printf("%s\n","$1");
1769   
1770   printf("  Fill Number = %6.0f\n",epics_get("S:FillNumber"));
1771   
1772   printf("  Shutter closed? %s\n",substr("yes no",1+4*epics_get("FE:08:ID:FEshutter"),3));
1773   printf("  Operator Messages:\n");
1774   printf("  Operator:              %s\n",epics_get("OPS:message1"));
1775   printf("  Floor coordinator      %s\n",epics_get("OPS:message2"));
1776   printf("  Fill Pattern:          %s\n",epics_get("OPS:message3"));
1777   printf("  Problem info:          %s\n",epics_get("OPS:message4"));
1778   printf("  Last dump/trip reason: %s\n",epics_get("OPS:message5"));
1779   printf("  Next Fill:             %s\n \n",epics_get("OPS:message6"));
1780
1781
1782   printf("  UPstream Undulator Details:\n");
1783   printf("  Serial number and period of ID device is %s\n", epics_get("ID08us:Device"));
1784   printf("  Commission limit = %6.2f mm\n",epics_get("ID08us:DeviceLimit"));
1785   printf("  Gap Taper       = %6.2f mm, ",   epics_get("ID08us:TaperGap"));
1786   printf("  Energy Taper= %6.2f keV\n",epics_get("ID08us:TaperEnergy"));
1787   printf("  Total Power = %6.0f W\n\n",epics_get("ID08us:TotalPower"));
1788   printf("  Gap = %6.2f mm, ", epics_get("ID08us:Gap"));
1789   printf("  Fundamental energy = %6.2f keV  \n\n",epics_get("ID08us:Energy"));
1790   
1791   printf("  DOWNstream Undulator Details:\n");
1792   printf("  Serial number and period of ID device is %s\n", epics_get("ID08ds:Device"));
1793   printf("  Commission limit = %6.2f mm\n",epics_get("ID08ds:DeviceLimit"));
1794   printf("  Gap Taper       = %6.2f mm, ",   epics_get("ID08ds:TaperGap"));
1795   printf("  Energy Taper= %6.2f keV\n",epics_get("ID08ds:TaperEnergy"));
1796   printf("  Total Power = %6.0f W\n\n",epics_get("ID08ds:TotalPower"));
1797   printf("  Gap = %6.2f mm, ", epics_get("ID08ds:Gap"));
1798   printf("  Fundamental energy = %6.2f keV  \n\n",epics_get("ID08ds:Energy"));
1799   
1800   printf("  Current = %6.2f mA, ", epics_get("S:SRcurrentAI"));
1801   printf("  Lifetime = %6.2f hrs\n", epics_get("S:SRlifeTimeHrsCC"));
1802   
1803   printf("  Feedback Global: %s  Vertical: %s  Horizontal: %s \n",epics_get("SRFB:GBL:LoopStatusBI"),epics_get("SRFB:GBL:VLoopStatusBI"),epics_get("SRFB:GBL:HLoopStatusBI"));
1804   printf("  Orbit correction? %s\n",substr("no yes",1+3*epics_get("S:OrbitCorrection:CC"),3));
1805    printf("  Beam positions (using RF BPMs)\n");
1806    printf("    HPOSITION = %10.5f mm",epics_get("FE:08:ID:HPOSITION:CC"));
1807    printf("    VPOSITION = %10.5f mm\n",epics_get("FE:08:ID:VPOSITION:CC"));
1808    printf("    HANGLE    = %10.5f urad",epics_get("FE:08:ID:HANGLE:CC"));
1809    printf("    VANGLE    = %10.5f urad\n",epics_get("FE:08:ID:VANGLE:CC"));
1810   
1811    printf("  RMS beam motion horizontal = %7.3f micron  vertical = %7.3f micron\n",epics_get("SRFB:dsp2:xRMSmotion30HzPkM.VAL"),epics_get("SRFB:dsp2:yRMSmotion30HzPkM.VAL"));
1812
1813    printf("  Emittance horizontal = %7.3f nm rad  vertical = %7.5f nm rad\n",epics_get("S:VID1:filteredXemittance"),epics_get("S:VID1:filteredYemittance"));
1814# I just used the standard beta functions from Steve Davey for topup mode..
1815# If you have specific data to our sector, please enter those PF
1816    printf("  Source size horizontal = %5.1f um vertical = %5.1f um\n\n",sqrt(14.4e3*epics_get("S:VID1:filteredXemittance")),sqrt(4.0e3*epics_get("S:VID1:filteredYemittance")));
1817
1818d
1819 if( $# == 2 )  off("$2")
1820'
1821def shutterStatus(_shutter) '{
1822      ##changes made to account for the PSS changes in Jan 2013 (SN)
1823        local _strShutter _station_name;
1824        if (_shutter == "I") {
1825                _shutter = "F";
1826        }
1827        _station_name = sprintf("S%1sS",_shutter);
1828
1829        if (_shutter == "A") {
1830                _station_name="FES"
1831        }
1832
1833        _strShutter = sprintf("PA:08ID:STA_%1s_%s_OPEN_PL",_shutter,_station_name);
1834        return(epics_get(_strShutter));
1835}'
1836
1837def openShutter(_shutter) '{
1838        return(chgShutterState(_shutter, "ON"));
1839}'
1840
1841def closeShutter(_shutter) '{
1842        return(chgShutterState(_shutter, "OFF"));
1843}'
1844
1845def chgShutterState(_shutter, _shutterState) '{
1846        local _strShutter;
1847        local _shutterNum;
1848        local _shutterStateVal;
1849        local _strShutterMsg;
1850        local MAX_SHUTTER_TRIES;
1851
1852        MAX_SHUTTER_TRIES = 5;
1853
1854        _shutterStateVal = 0;
1855        if (_shutterState == "ON")
1856                _shutterStateVal = 1;
1857
1858        # Check whether there is anything to do
1859        if (shutterStatus(_shutter) == _shutterState) {
1860                print _shutter " Shutter already " _shutterState;
1861                return("True");
1862        }
1863        else {
1864
1865                for (_i = 0; _i < MAX_SHUTTER_TRIES; _i++) {
1866                        if (_shutter=="A" && _shutterState=="ON") {
1867                                epics_put("8ida:rshtrA:Open",1)
1868                                _strShutterMsg = "Open";
1869                        }
1870                        if (_shutter=="A" && _shutterState=="OFF") {
1871                                epics_put("8ida:rshtrA:Close",1)
1872                                _strShutterMsg = "Close";
1873                        }
1874                        if (_shutter=="D" && _shutterState=="ON") {
1875                                epics_put("8ida:rshtrD:Open",1)
1876                                _strShutterMsg = "Open";
1877                        }
1878                        if (_shutter=="D" && _shutterState=="OFF") {
1879                                epics_put("8ida:rshtrD:Close",1)
1880                                _strShutterMsg = "Close";
1881                        }
1882                        if (_shutter=="E" && _shutterState=="ON") {
1883                                epics_put("8ida:rshtrE:Open",1)
1884                                _strShutterMsg = "Open";
1885                        }
1886                        if (_shutter=="E" && _shutterState=="OFF") {
1887                                epics_put("8ida:rshtrE:Close",1)
1888                                _strShutterMsg = "Close";
1889                        }
1890                        if (_shutter=="I" && _shutterState=="ON") {
1891                                epics_put("8ida:rshtrI:Open",1)
1892                                _strShutterMsg = "Open";
1893                        }
1894                        if (_shutter=="I" && _shutterState=="OFF") {
1895                                epics_put("8ida:rshtrI:Close",1)
1896                                _strShutterMsg = "Close";
1897                        }
1898                        print _shutter " Shutter signalled to " _strShutterMsg ": " date();
1899                        sleep(8);
1900                        if (shutterStatus(_shutter) == _shutterState) {
1901                                print _shutter " shutter " shutterStatus(_shutter) ": " date();
1902                                return("True");
1903                        }
1904                }
1905                print _shutter " shutter failed to "  _strShutterMsg ": " date();
1906                return("False");
1907        }
1908}'
1909
1910def isBeamUp() '{
1911        local _strIsBeamUp,_temp;
1912        _strIsBeamUp = "False";
1913        _temp=epics_get("8idi:Unidig1Bi8.VAL");
1914        if (_temp == "High")
1915                _strIsBeamUp = "True";
1916        return(_strIsBeamUp);
1917}'
1918
1919def monitorBeamToI '{
1920        if (isBeamUp() == "False") {
1921                printf("  Beam dump detected: %s\n", date());
1922                fprintf(DATAFILE,"\n#C Beam dump detected: %s\n",date());
1923                waitForBeam;
1924                beamToI;
1925                waitForWarmup;
1926        }
1927}'
1928
1929def monitorBeamToE '{
1930        if (isBeamUp() == "False") {
1931                printf("  Beam dump detected: %s\n", date());
1932                fprintf(DATAFILE,"\n#C Beam dump detected: %s\n",date());
1933                waitForBeam;
1934                beamToE;
1935                waitForWarmup;
1936        }
1937}'
1938
1939def waitForBeam '{
1940        for (;;) {
1941                if (isBeamUp() == "True") {
1942                        print " ";
1943                        print " ";
1944                        break;
1945                }
1946                printf("\rChecking for beam: %s", date());
1947                tty_cntl("ce");
1948                printf("\r");
1949                sleep(60);
1950                tty_cntl("ce");
1951                printf("\r");
1952        }
1953}'
1954
1955def waitForWarmup '{
1956        print "Warmup started: " date();
1957        do_sleep(10*60.);
1958        print "Warmup ended: " date();
1959        fprintf(DATAFILE,"\n#C Beam is Restored, Data Collection to Commence: %s\n",date());
1960}'
1961
1962def beamToI '
1963
1964        foo = openShutter("A");
1965
1966        foo = openShutter("D");
1967
1968        foo = openShutter("I");
1969
1970'
1971
1972def beamToE '
1973
1974        foo = openShutter("A");
1975
1976        foo = openShutter("D");
1977
1978        foo = openShutter("E");
1979
1980'
1981
1982# The following macros may be site dependent.  Need proper modification
1983
1984global atten_set
1985global pvFILTER5_CTL,pvFILTER5_RDBK
1986def showfilter_original '{
1987        local _prevValue;
1988        local filter5_value;
1989        if (epics_get(pvFILTER5_RDBK) == 0) {
1990            filter5_value = 16
1991        }
1992        else {
1993            filter5_value = 0
1994        }
1995        _prevValue = epics_get(pvATT_GET);
1996        _prevValue = _prevValue + filter5_value;
1997        printf("\nCurrent attenuation state = %2d \n",_prevValue);
1998}'
1999
2000def att_original '{
2001        if ($# == 0) {
2002                showfilter_original
2003                attcalc
2004                attshow
2005                exit
2006        } 
2007        if ($# != 1 || $1 > 31 || $1 <0) {
2008                print "Usage:  att filter_position_integer(limits: 0-31)"
2009                exit
2010        } 
2011        local filter5_value, filter5_initial_value, _prevValue;
2012       
2013        ###First check the status of filter5 (XIA S2 - Filter 1)
2014        if (epics_get(pvFILTER5_RDBK) == 0) {
2015                filter5_initial_value=16
2016                } else {filter5_initial_value=0}
2017        _prevValue = epics_get(pvATT_GET) + filter5_initial_value;
2018        sleep(0.1)
2019       
2020        if ($1 > 15) {
2021             epics_put(pvFILTER5_CTL,"Down")
2022             sleep(0.1)
2023             filter5_value = 16
2024             epics_put(pvATT_SET, $1 - 16)
2025        } else {
2026            epics_put(pvATT_SET, $1)
2027            sleep(0.1)
2028        }
2029       
2030        if ($1 <= 15) {
2031             epics_put(pvFILTER5_CTL,"Up")
2032             sleep(0.1)
2033             filter5_value = 0
2034        }       
2035       
2036        atten_set=epics_get(pvATT_SET) + filter5_value
2037        sleep(0.1)
2038        printf("\nAttenuation changed to %2d from %2d \n", atten_set,_prevValue)
2039        sleep(0.1)
2040        attcalc
2041}'
2042
2043def att '{
2044        ####There is more than one att macro due to 8idi energy changes
2045        ####this defines the default for 8ide and 8idg
2046        ####8idi is defined in the conf.mac
2047        att_original $*
2048}'
2049
2050
2051def ccdshutter '
2052        if ($# != 1 || ("$1" != "on"  && "$1" != "off")) {
2053                print "Usage:  ccdshutter on|off";
2054                exit;
2055        } 
2056        if ("$1" == "on") {
2057                shutteron;
2058        }
2059        else {
2060                shutteroff;
2061        }
2062'
2063
2064def shutteron '
2065        epics_put(pvSHUTT_CTL, 0);
2066        print "\nCCD is controlling shutter ...\n";
2067'
2068
2069def shutteroff '
2070        epics_put(pvSHUTT_CTL, 1);
2071        print "\nCCD control of shutter has been surrendered ...\n"; '
2072# default positions so that att global atten_set variable is set
2073# properly
2074#att 15;
2075#shutteron
2076def Set_att_macro_hooks_7keV '
2077        def att \'att_7keV\'
2078        def attcalc \'attcalc_7keV\'
2079        def showfilter \'showfilter_7keV\'
2080        Set_att_params_7keV
2081        printf("Setting all the macro hooks for att at 7 keV\n")
2082'
2083
2084def Set_att_macro_hooks_11keV '
2085        def att \'att_11keV\'
2086        def attcalc \'attcalc_11keV\'
2087        def showfilter \'showfilter_11keV\'
2088        Set_att_params_11keV
2089        printf("Setting all the macro hooks for att at 11 keV\n")
2090'
2091
2092def Set_att_params_7keV '
2093        epics_put("8idi:userTran1.CLCO","EXP(-I/J)");
2094        epics_put("8idi:userTran3.CLCO","EXP(-I/J)");
2095       
2096'
2097
2098def Set_att_params_11keV '
2099        epics_put("8idi:userTran1.CLCO","EXP(-I/K)");
2100        epics_put("8idi:userTran3.CLCO","EXP(-I/K)");
2101'       
2102
2103def att_7keV '{
2104        if ($# == 0) {
2105                showfilter_7keV
2106                attcalc_7keV
2107                attshow
2108                exit
2109        } 
2110        if ($# != 1 || $1 > 15 || $1 <0) {
2111                print "Usage:  att filter_position_integer(limits: 0-15)"
2112                exit
2113        } 
2114        local filter5_value, filter5_initial_value, _prevValue;
2115       
2116        _prevValue = epics_get(pvATT_GET);
2117        sleep(0.1)
2118       
2119        epics_put(pvATT_SET, $1)
2120        sleep(0.1)
2121       
2122        atten_set=epics_get(pvATT_SET)
2123        sleep(0.1)
2124        printf("\nAttenuation changed to %2d from %2d \n", atten_set,_prevValue)
2125        sleep(0.1)
2126        attcalc_7keV
2127}'
2128
2129
2130def att_11keV '{
2131        if ($# == 0) {
2132                showfilter_11keV
2133                attcalc_11keV
2134                attshow
2135                exit
2136        } 
2137        if ($# != 1 || $1 > 15 || $1 <0) {
2138                print "Usage:  att filter_position_integer(limits: 0-15)"
2139                exit
2140        } 
2141        local filter5_value, filter5_initial_value, _prevValue;
2142       
2143        _prevValue = epics_get(pvATT2_GET) ;
2144        sleep(0.1)
2145       
2146        epics_put(pvATT2_SET, $1)
2147        sleep(0.1)
2148       
2149        atten_set=epics_get(pvATT2_SET)
2150        sleep(0.1)
2151        printf("\nAttenuation changed to %2d from %2d \n", atten_set,_prevValue)
2152        sleep(0.1)
2153        attcalc_11keV
2154}'
2155
2156
2157
2158def attcalc_7keV '
2159        global attvalue
2160        attvalue = epics_get("8idi:userTran1.P")
2161       
2162        printf("\nAttenuation of the Beam (excl. Foils 2,3,4 in XIA S2) = %f\n",attvalue)
2163'
2164
2165def attcalc_11keV '
2166        global attvalue
2167        attvalue = epics_get("8idi:userTran3.P")
2168       
2169        printf("\nAttenuation of the Beam (excl. Foils 2,3,4 in XIA S2) = %f\n",attvalue)
2170'
2171
2172def showbeam_common '
2173        epics_put("8idi:Unidig1Bo13","Open");
2174'
2175
2176def showbeam_fccd2 '
2177        epics_put("8idi:Unidig1Bo13","Open");
2178'
2179
2180
2181
2182def blockbeam_common '
2183        epics_put("8idi:Unidig1Bo13","Closed");
2184'
2185
2186def blockbeam_fccd2 '
2187        epics_put("8idi:Unidig1Bo13","Closed");
2188'
2189
2190
2191def Set_Filter_Thickness_Copper '
2192
2193        epics_put("8idi:userTran1.E",12.966)
2194        epics_put("8idi:userTran1.F",26.0511)
2195        epics_put("8idi:userTran1.G",49.4788)
2196        epics_put("8idi:userTran1.H",101.006)
2197'
2198
2199
2200def Set_Filter_Thickness_Aluminum '
2201
2202        epics_put("8idi:userTran3.E",127*1)
2203        epics_put("8idi:userTran3.F",127*2)
2204        epics_put("8idi:userTran3.G",127*4)
2205        epics_put("8idi:userTran3.H",127*8)
2206'
2207
2208
2209
2210
2211def showfilter_7keV '{
2212        local _prevValue;
2213        _prevValue = epics_get(pvATT_GET);
2214        printf("\nCurrent attenuation state = %2d \n",_prevValue);
2215}'
2216
2217def showfilter_11keV '{
2218        local _prevValue;
2219        _prevValue = epics_get(pvATT2_GET);
2220        printf("\nCurrent attenuation state = %2d \n",_prevValue);
2221}'
2222#file temperature_scans.mac
2223
2224# MEASURETEMP and _SETTEMP are called by general SPEC routines
2225T_LO_SP=-273.1
2226T_HI_SP=1400
2227
2228def temp_wait '{
2229
2230        if ($# != 1) {
2231                print "Usage:  temp_wait delta_t"
2232                exit
2233        }
2234        measuretemp
2235        _dt_low = $1
2236        _dt_high = $1
2237        print "Waiting for " TEMP_SP-_dt_low " < T(degC) < " TEMP_SP+_dt_high
2238        while ( (TEMP_SP-_dt_low >= DEGC) || (DEGC >= TEMP_SP+_dt_high) ) {
2239                sscanf(date(),"%s %s %s %s %s",day,month,mday,hour,year);
2240                measuretemp
2241                printf("Measured = %g (%gC) at %s  \n",TEMP_CS,DEGC,hour)
2242        #this line is to check if lakeshore heater is ON (Suresh,July06)
2243        #and is defined in lake331epics.mac in S8SPEC
2244        check_lakeshore
2245        sleep(30)
2246                }
2247        print "Reached window."
2248}'
2249# The following line is to prevent d-mono encoder motor to move during
2250# other motor scans
2251cdef("user_scan_plot","get_angles","get_angles_hack")
2252
2253#to remove
2254#cdef("","","get_angles_hack","delete")
2255
2256
2257
2258#-------------------------------------------------------------------------------
2259# file aalength.mac
2260# Written by X. Jiao 06/05/2005 Version 1.0
2261#
2262# Generic SPEC macros
2263#
2264#
2265# _aa_length -> <generic> return numberof elements in an associative array
2266# strjoin   -> <generic> eliminate the some characters in the string
2267#-------------------------------------------------------------------------------
2268#$Log: aalength.mac,v $
2269#Revision 1.6  2006/05/11 19:35:44  jiaox
2270#Fixed a bug in strjoin that when string is NULL,it returns 0 instead of NULL
2271#
2272#Revision 1.5  2006/05/11 17:46:31  jiaox
2273#Added CVS Log entry.
2274#
2275#
2276#------------------------------------------------------------------------------
2277def _aa_length(aname) '{
2278  local field n
2279  if( !( (whatis("aname")>>16)&0x100 ) ) {
2280    print "Not an associative array."
2281    exit
2282  }
2283  for(field in aname) n++
2284  return n
2285}'
2286
2287def strjoin(s,delimiter) '{
2288   local tmp[] i new n
2289   new=""
2290   split(s,tmp,delimiter)
2291   n=_aa_length(tmp)
2292   for( i=0;i<n;i++) new=sprintf("%s%s",new,tmp[i])
2293   return new
2294} '
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310#===============================================================================
2311# file ucolumn.mac
2312# Written by X. Jiao 07/12/2005 Version 1.0
2313#
2314# Generic SPEC macros
2315#
2316# Decription: to add user defined columns to spec file, based on P. Jamian's
2317#             macros:uni_specdatacolumn.mac
2318#
2319# User Macros:
2320#    u_column_show: display user defined data columns
2321#    u_column_add:  add one new entry of user defined column
2322#    u_column_remove: delete one or( a set related to one key identifier)
2323#                     column/columns
2324#    u_column_clear: clear all user defined columns
2325# Internal Macros:
2326#    u_column_rebuild
2327#
2328# Modification History:
2329# 7/20/2005 X. Jiao -> created based on uni_specdatacolumn.mac, modified so that
2330#                     user columns grouped as key identifier, one can delete
2331#                     as pieces while keep others.
2332#
2333#===============================================================================
2334#
2335#$Log: uspec_column.mac,v $
2336#Revision 1.2  2006/05/11 17:46:31  jiaox
2337#Added CVS Log entry.
2338#
2339#
2340###############################################################################
2341
2342
2343#===============================================================================
2344# global variables
2345#===============================================================================
2346global _ADDCOL_ID[]   ;# associative array with definition key identifier
2347
2348
2349#===============================================================================
2350# User macros defined here
2351#===============================================================================
2352def u_column_show '{
2353    local A_name B_name
2354    for( i in _ADDCOL_ID) {
2355       A_name = _ADDCOL_ID[i]
2356       B_name = sprintf("_ADDCOL_%s_FMT",i)
2357       printf("\nColumns defined as pieces of identifier:%s\n",i)
2358       for( j in @A_name) {
2359          printf("%s :  %s  :  %s \n", j,@A_name[j],@B_name[j])
2360       }   
2361    }     
2362 
2363}'
2364
2365def u_column_add(tag,fmt,cmd,key)'{
2366    local A_name B_name
2367    A_name = sprintf("_ADDCOL_%s_CMD",key)
2368    B_name = sprintf("_ADDCOL_%s_FMT",key)
2369    if(!_ADDCOL_ID[key]) {
2370        _ADDCOL_ID[key] = A_name
2371        global @A_name[] @B_name[]
2372    }
2373   
2374    @A_name[tag] = cmd
2375    @B_name[tag] = fmt
2376    u_column_rebuild
2377 
2378}'
2379
2380def u_column_remove(tag,key) '{
2381    local A_name B_name
2382    if(_ADDCOL_ID[key]) {
2383          A_name = _ADDCOL_ID[key]
2384          B_name = sprintf("_ADDCOL_%s_FMT",key)
2385          delete @A_name[tag]
2386          delete @B_name[tag]
2387    }
2388    u_column_rebuild
2389}'
2390
2391def u_column_clear(key) '{
2392    local A_name B_name i
2393    if(_ADDCOL_ID[key]) {
2394       A_name = _ADDCOL_ID[key]
2395       B_name = sprintf("_ADDCOL_%s_FMT",key)
2396       unglobal @A_name
2397       unglobal @B_name
2398       delete _ADDCOL_ID[key]
2399    }
2400    else {
2401       if (key =="all") {
2402         for(i in _ADDCOL_ID) {
2403           A_name=_ADDCOL_ID[i]
2404           B_name=sprintf("_ADDCOL_%s_FMT",i)
2405           unglobal @A_name
2406           unglobal @B_name
2407           delete _ADDCOL_ID[i]
2408         }
2409       }
2410       
2411    }
2412    u_column_rebuild
2413           
2414}'
2415
2416
2417#===============================================================================
2418# Internal macros defined here
2419#===============================================================================
2420def u_column_rebuild '{
2421    local fout_cmd fout_fmt flabel fheader ncols i j
2422    local A_name B_name
2423    ncols=0
2424    flabel=fout_cmd=fout_fmt=""   
2425    for( i in _ADDCOL_ID) {
2426       A_name = _ADDCOL_ID[i]
2427       B_name = sprintf("_ADDCOL_%s_FMT",i)
2428       for(j in @A_name) {
2429          ncols++
2430          flabel = sprintf("%s  %s",j,flabel)
2431          fout_fmt = sprintf("%s %s",@B_name[j],fout_fmt)
2432          if(ncols==1) fout_cmd=sprintf("%s%s",@A_name[j],fout_cmd)
2433          else fout_cmd=sprintf("%s,%s",@A_name[j],fout_cmd)
2434       }
2435    }
2436    if(ncols) {
2437        flabel  = sprintf("\"%s\"", flabel)
2438        fheader = sprintf("\n _cols+=%d", ncols)
2439        fout    = sprintf("sprintf(\"%s\",%s)", fout_fmt, fout_cmd)
2440        cdef("Fheader", fheader,  "UCOL", 0x20)
2441        cdef("Flabel",  flabel,   "UCOL", 0x20)
2442        cdef("Fout",    fout,     "UCOL", 0x20)
2443    }
2444    else {
2445        cdef("Fheader", "",  "UCOL", "delete")
2446        cdef("Flabel",  "",  "UCOL", "delete")
2447        cdef("Fout",    "",  "UCOL", "delete")
2448        rdef Flabel \'""\'
2449        rdef Fout   \'""\'
2450   }
2451}'   
2452   
2453
2454
2455# ~S8SPEC/macros/common/myfile.mac
2456# functionized version of newfile that supports passing string as new file name - handy for
2457# auto-defined file name upon fresh start - and creation of an accompanying .log file
2458def myfile (fn,sn)'{
2459        local   dfile, scan_num, prev
2460
2461        prev = DATAFILE
2462        dfile = fn
2463
2464        if (dfile == "")
2465                exit
2466
2467        if (dfile == "null")
2468                dfile = "/dev/null"
2469
2470        if (!index(dfile, "/") && file_info(DATA_DIR, "-d"))
2471                dfile = sprintf("%s/%s",DATA_DIR,dfile)
2472
2473        if (!file_info(dfile, "-r")) {
2474                if (dfile == DATAFILE) {
2475                        printf(\
2476        "Warning:  Same name as before, but file isn\'t in %s directory.\n",\
2477                                             index(dfile, "/")? "same":"current")
2478                        printf("A new version of the file will be created.\n")
2479                }
2480                DATAFILE="/dev/null"
2481        } else if (dfile != "/dev/null") {
2482                local s
2483                if (file_info(s = SPECD "/chk_file", "-x"))
2484                        if (unix(sprintf("%s %s",s,dfile)))
2485                                print "Note:  file already exists."
2486        }
2487        #
2488        if (open(dfile)) {
2489                DATAFILE="/dev/null"
2490                exit
2491        }
2492        if (dfile != "tty" && dfile != "/dev/tty")
2493                close(dfile)
2494
2495        scan_num = sn
2496        if (dfile == DATAFILE) {
2497                if (open(dfile)) {
2498                        DATAFILE="/dev/null"
2499                        exit
2500                }
2501                SCAN_N = scan_num
2502        } else {
2503
2504                if (prev != "" && prev != "0" && prev != "tty" && prev != "/dev/tty")
2505                        close(prev)
2506
2507                if (open(dfile)) {
2508                        DATAFILE="/dev/null"
2509                        exit
2510                }
2511
2512                DATAFILE = dfile
2513                SCAN_N = scan_num
2514
2515                if (SCAN_N == 0 || !file_info(DATAFILE, "-s")) {
2516                        constant EPOCH time()
2517                        fprintf(dfile, "#F %s\n", DATAFILE)
2518                }
2519                fprintf(dfile, "#E %d\n",EPOCH)
2520                fprintf(dfile, "#D %s\n",date())
2521                fprintf(dfile, "#C %s  User = %s\n",TITLE,USER)
2522
2523                ond; offt
2524                user_filehead
2525                ont; offd
2526
2527                local i,j,s
2528                for (i=0; i<MOTORS; i+=8) {
2529                        s = sprintf("#O%d ", i/8)
2530                        for (j=i; j<i+8 && j<MOTORS;) {
2531                                if (motor_name(mA[j]) != "unused")
2532                                        s = s sprintf("%8s", motor_name(mA[j]))
2533                                if (j%8 == 7)
2534                                        break
2535                                s = s "  "
2536                                j++
2537                        }
2538                        fprintf(dfile, "%s\n", s)
2539                }
2540        }
2541        printf("Using \"%s\".  Next scan is number %d.\n",DATAFILE,SCAN_N+1)
2542
2543        if(DATAFILE !="" && DATAFILE !="0" && DATAFILE !="tty" && DATAFILE !="/dev/tty" && DATAFILE !="/dev/null") {
2544          logf=DATAFILE ".log"
2545          printf("Logging everything in %s\n",logf)
2546          on(logf)
2547        }
2548}'
2549#===============================================================
2550# file plcounter.mac
2551# by X. Jiao 17/04/2005
2552# Generic SPEC macros
2553#
2554# set a counter as detector and to be plotted.(combines the
2555# functionalities of counters and plotselect)
2556# i.e.: plcounter ccdc or plcounter 3
2557#       plcounter (interactive mode)
2558#
2559# History:
2560# 2014/10/13  JAK Modified to replace _plotconfig/_show_cntr
2561#                 which are no longer available in SPEC >= 6.02
2562#==============================================================
2563def plcounter '{
2564    if ($# >1) {
2565       p "Usage: plcounter or plcounter counter_mne"
2566       exit
2567    }
2568    local s v
2569
2570    s = DET;
2571    if($#==1) {
2572       DET = cnt_num($1);
2573       if (DET < 0 || DET >= COUNTERS) {
2574           printf("Channel %s is invalid for detector.\n", $1)
2575           DET = s
2576           exit
2577       }
2578    }
2579    if( $# ==0) {
2580       plotselect;
2581       exit
2582    }   
2583
2584    plotlist(cnt_mne(DET));
2585
2586    if (DET!=cnt_num($1))
2587        printf("\nFAILED: counter \"%s\" could not be selected as detector.\n", cnt_mne(DET))
2588    else if (PL_Y!=$1)
2589        printf("\nFAILED: counter \"%s\" would not set to be plotted.\n", cnt_mne(DET))
2590    else
2591        printf("\ncounter \"%s\" is selected as detector and will be plotted.\n", cnt_mne(DET))
2592} '
2593
2594
2595
2596### Modified standard newfile macro to create log file automatically based on the new datafile name
2597
2598
2599def newfile '{
2600        local   dfile, scan_num, prev, prevlog, logf
2601
2602        prev = DATAFILE
2603        if ($# == 0)
2604                dfile = getsval("\nData file", DATAFILE)
2605        else
2606                dfile = "$1"
2607
2608        if (dfile == "")
2609                exit
2610
2611        if (dfile == "null")
2612                dfile = "/dev/null"
2613
2614        if (!index(dfile, "/") && file_info(DATA_DIR, "-d"))
2615                dfile = sprintf("%s/%s",DATA_DIR,dfile)
2616
2617        if (!file_info(dfile, "-r")) {
2618                if (dfile == DATAFILE) {
2619                        printf(\
2620        "Warning:  Same name as before, but file isn\'t in %s directory.\n",\
2621                                             index(dfile, "/")? "same":"current")
2622                        printf("A new version of the file will be created.\n")
2623                }
2624                DATAFILE="/dev/null"
2625        } else if (dfile != "/dev/null") {
2626                local s
2627                if (file_info(s = SPECD "/chk_file", "-x"))
2628                        if (unix(sprintf("%s %s",s,dfile)))
2629                                print "Note:  file already exists."
2630        }
2631        #
2632        if (open(dfile)) {
2633                DATAFILE="/dev/null"
2634                exit
2635        }
2636        if (dfile != "tty" && dfile != "/dev/tty")
2637                close(dfile)
2638
2639        scan_num = $2
2640        if (dfile == DATAFILE) {
2641                if (open(dfile)) {
2642                        DATAFILE="/dev/null"
2643                        exit
2644                }
2645                if ($# == 2)
2646                        SCAN_N = scan_num
2647        } else {
2648                if ($# == 0)
2649                        scan_num = getval("Last scan number",scan_num)
2650
2651                if (prev != "" && prev != "0" && prev != "tty" && prev != "/dev/tty")
2652                        close(prev)
2653
2654                if (open(dfile)) {
2655                        DATAFILE="/dev/null"
2656                        exit
2657                }
2658
2659                DATAFILE = dfile
2660                SCAN_N = scan_num
2661               
2662                if (prev != "" && prev != "0" && prev != "tty" && prev != "/dev/tty" && prev != "/dev/null") {
2663                     prevlog=prev ".log"
2664                     close(prevlog)
2665                } 
2666                if (SCAN_N == 0 || !file_info(DATAFILE, "-s")) {
2667                        constant EPOCH time()
2668                        fprintf(dfile, "#F %s\n", DATAFILE)
2669                }
2670                fprintf(dfile, "#E %d\n",EPOCH)
2671                fprintf(dfile, "#D %s\n",date())
2672                fprintf(dfile, "#C %s  User = %s\n",TITLE,USER)
2673
2674                ond; offt
2675                user_filehead
2676                ont; offd
2677
2678                local i,j,s
2679                for (i=0; i<MOTORS; i+=8) {
2680                        s = sprintf("#O%d ", i/8)
2681                        for (j=i; j<i+8 && j<MOTORS;) {
2682                                if (motor_name(mA[j]) != "unused")
2683                                        s = s sprintf("%8s", motor_name(mA[j]))
2684                                if (j%8 == 7)
2685                                        break
2686                                s = s "  "
2687                                j++
2688                        }
2689                        fprintf(dfile, "%s\n", s)
2690                }
2691        }
2692        printf("Using \"%s\".  Next scan is number %d.\n",DATAFILE,SCAN_N+1)
2693       
2694       
2695        if(DATAFILE != ""  && DATAFILE !="0" && DATAFILE != "tty" && DATAFILE != "/dev/tty" && DATAFILE !="/dev/null") {
2696                  logf=DATAFILE ".log"
2697                  printf("Logging everything in %s\n",logf)
2698                 
2699                  on(logf)
2700                   
2701        }
2702}'
2703###########################################################################
2704#   Macros for scaning undulators.  When undulator tracking is on, gap of the
2705# undulator will be adjusted to match the energy of the monochromator.
2706#
2707#
2708# Written by J. Lang April 1999
2709#
2710# Modified by X. Jiao May 27 2005
2711#
2712# Version 1.7
2713#
2714#
2715# Macros
2716#         
2717#         moveundE - Moves undulator to specified energy.
2718#                   
2719#         und_tracking_on - Turns on undulator tracking during Escans
2720#
2721#         und_tracking_off- Turns off undulator tracking
2722#
2723#         undscan - scans the undulator energy.
2724#
2725#         undscangap - scans undulator gap.
2726#
2727# Modification History:
2728#
2729#         2/05/01  J. Lang -> Added Undulator setup command.
2730#
2731#         8/21/01  J. Lang -> Added comments to und_tracking?on:off
2732#
2733#         1/31/02  J. Lang -> Redid und_tracking?on:off to use moveundE.
2734#                             Changed moveundE to not take backlash when
2735#                             new energy is only a few eV above old.  This
2736#                             prevents accidental backlash moves due to
2737#                             readback flicker.
2738#
2739#        10/08/02  J. Lang -> Redid scan_data, scan_plot, to be compatable
2740#                             with plotarrays.
2741#
2742#        10/08/02  J. Lang -> Added undscangap macro.
2743#
2744#        12/14/03  J. Lang -> Only reload und varables if not defined already.
2745#                             Also took out quad term in Eund = f(Emono)
2746#
2747#         2/22/05  J. Lang -> Added fixed taper option (maintains fixed gap
2748#                             (mm not energy) taper for all moves).
2749#
2750#         5/27/05  X. Jiao -> (1) Finished the fixed taper option. When the
2751#                             global variable Und_FixTaper=1, the undulator
2752#                             will keep a fixed taper on each undulator
2753#                             scan/move.
2754#                             (2) _und_tracking_on and _und_tracking_off
2755#                             is modified so we do not redefine user_waitmove
2756#                             to wait even no undulator motion involved.
2757#                             During Escans, the wait for undulator is done 
2758#                             by the 'waitund' inside _moveundE!
2759#                             (3) Added show_und macro to display the
2760#                             undulator status.
2761#         6/5/05   X. Jiao -> (1) fixed  _cols to 3 in undscan and undscangap
2762#                             (2) took out Und_fixed_Taper if coniditons in
2763#                              undscangp,assuming always non_taper mode for gap scan.
2764#         7/27/06  X.Jiao -> (1) Added feature that automatically change the undulator
2765#                             harmonic based on the energy value.
2766#         11/20/07 X.Jiao ->  Added undgaplup                     
2767#
2768######################################################################################
2769#
2770
2771#---------------------------------------------------------------------------
2772#Global variables - Configure for each beamline (usually in the conf.mac)
2773#---------------------------------------------------------------------------
2774
2775global UND_PV[] UND_TAPER[] FIXED_TAPER[]
2776
2777
2778
2779
2780
2781global Und_Delay
2782     
2783
2784Und_Delay = 0.2             #Delay before query of Und. done moving flag.
2785   
2786
2787#---------------------------------------------------------------------------
2788#Macros
2789#--------------------------------------------------------------------------
2790
2791def addund '
2792    if($#!=2) {
2793       p "Usage: addund name pv_prefix"
2794       exit
2795    }
2796    UND_PV["$1"]="$2"
2797    UND_TAPER["$1"]=0
2798    FIXED_TAPER["$1"]=1
2799
2800'
2801def rmund '
2802  if ( $# != 1 ) {
2803    print "Usage: rmund name "
2804    exit
2805  }
2806  delete UND_PV["$1"]
2807  delete UND_TAPER["$1"]
2808  delete FIXED_TAPER["$1"]
2809
2810
2811
2812
2813#und_setup - Sets up undulator tracking parameters
2814def und_setup'  {
2815   local und
2816   for( und in UND_PV)   {
2817      printf("\nSetup for undulator: %s\n\n",und)
2818
2819      if (yesno("  Keep undulator taper (mm) fixed?",FIXED_TAPER[und])) {
2820        FIXED_TAPER[und] = 1
2821        UND_TAPER[und] = getval("  Undulator taper (0-5.0mm):",epics_get(sprintf("%sTaperGapSet",UND_PV[und])))
2822       
2823        while(UND_TAPER[und]>5.0) {
2824           printf("\nTaper Gap has to be less than 5.0mm.\n")
2825           UND_TAPER[und] = getval("  Undulator taper (0-5.0mm):",UND_TAPER[und])
2826        }
2827      } else { FIXED_TAPER[und]= 0 }   
2828     
2829  }
2830}'
2831
2832#show_und  - display the undulator status
2833def show_und '{
2834    local und
2835    printf("\n%40.40s","Curent Undulator Status")
2836    for( und in UND_PV)   {
2837      printf("\n\nName: %s ",und)
2838      printf("\n%30.30s %9.4f","Gap(mm):",epics_get(sprintf("%sGap",UND_PV[und])))
2839      printf("\n%30.30s %9.4f","Energy(keV):",epics_get(sprintf("%sEnergy",UND_PV[und])))
2840      printf("\n%30.30s %9.4s","Taper Mode:", epics_get(sprintf("%sTaper",UND_PV[und])))
2841      printf("\n%30.30s %9.4f","Taper Gap(mm)", epics_get(sprintf("%sTaperGap",UND_PV[und])))
2842      printf("\n%30.30s %9.4s","Using Fixed Taper?:", FIXED_TAPER[und]?"Yes":"NO")
2843   }
2844}'     
2845
2846
2847
2848#waitund - waits for undulator to stop moving
2849def waitund(und)'{
2850
2851     sleep(Und_Delay)
2852     while( epics_get(sprintf("%sBusy",UND_PV[und]),"short") == 1 ){ sleep(0.1) }
2853       
2854}'
2855
2856
2857def mvgap '{
2858    local undpv und
2859    und="$1"
2860    if ( !(undpv = UND_PV[und])) {
2861            p "Invalid undulator name"
2862            exit
2863    }
2864
2865    if ($# !=2) {
2866       p "Usage: mvgap name gap(mm)"
2867       exit
2868    }
2869       
2870    if (FIXED_TAPER["$1"]) {
2871           epics_put(sprintf("%sGapSet",undpv),$2)
2872           epics_put(sprintf("%sTaperGapSet",undpv), UND_TAPER["$1"])
2873           epics_put(sprintf("%sStart",undpv), 1)
2874    }   else {
2875           epics_put(sprintf("%sScanGap",undpv),$2)
2876    }
2877    waitund(und)
2878         
2879}'
2880
2881
2882def mvrgap '{
2883    local undpv und currentV
2884    und="$1"
2885    if ( !(undpv = UND_PV[und])) {
2886            p "Invalid undulator name"
2887            exit
2888    }
2889
2890    if ($# !=2) {
2891       p "Usage: mvrgap name gap(mm)"
2892       exit
2893    }
2894    waitund(und)
2895    currentV = epics_get(sprintf("%sGap",undpv))
2896    mvgap $1 (currentV+($2))
2897}'
2898
2899 
2900def undgaplup '{
2901        if ($# != 5 ) {
2902                print "Usage: undgaplup name start finish intervals time "
2903                print "       (Units are mm)"
2904                exit
2905        }
2906        local undpv currentV
2907
2908        if ( !(undpv = UND_PV["$1"])) {
2909            p "Invalid undulator name"
2910            exit
2911        }
2912        waitund("$1")
2913        currentV = epics_get(sprintf("%sGap",undpv))
2914        undgapscan $1 ($2+currentV) ($3+currentV) $4 $5
2915        mvgap $1  currentV
2916        printf("Returning %s Gap to %f","$1",currentV)
2917
2918}'
2919
2920
2921
2922# undgapscan - scans the undulator gap
2923def undgapscan '{
2924       
2925        if ($# != 5 ) {
2926                print "Usage: undgapscan name start finish intervals time "
2927                print "       (Units are mm)"
2928                exit
2929        }
2930        local undpv
2931       
2932        if ( !(undpv = UND_PV["$1"])) {
2933            p "Invalid undulator name"
2934            exit
2935        }
2936
2937        { _s1 = $2; _f1 = $3; _n1 = int($4); _ctime = $5; }
2938
2939        if (_n1 <= 0) {
2940                print "Number of Intervals <= 0"
2941                exit
2942        }
2943        if (_s1 <= 0 || _f1 <= 0) {
2944                print "Can only deal with positive gaps."
2945                exit
2946        }
2947
2948        #if (_s1 < _f1 ) {
2949        #       print "Must scan from high to low gaps"
2950        #       print "Reversing direction"
2951        #       local tempv
2952        #       tempv=_s1;_s1=_f1;_f1=tempv
2953        #}
2954
2955        HEADING = sprintf("undgapscan %s %g %g %g %g","$1",$2,$3,$4,$5)
2956        _d1 = (_f1 - _s1) / _n1++
2957        X_L = sprintf("%s_gap(mm)","$1")
2958        Y_L = cnt_name(DET)
2959        _sx = _s1; _fx = _f1
2960
2961        FPRNT=sprintf("Gap  Energy  TaperGap  ")
2962        PPRNT=sprintf("%9.9s %9.9s %9.9s ", "Gap","Energy","TaperGap")
2963        VPRNT=PPRNT
2964        _stype = 1|(1<<8)
2965        _cols=3
2966
2967        scan_head
2968        def _scan_on \'
2969         {
2970           for (; NPTS < _n1; NPTS++) {
2971                local E gap  tgap
2972                gap = _s1 + NPTS * _d1
2973                mvgap $1 gap
2974                E = epics_get(undpv "Energy")
2975                gap = epics_get(undpv "Gap")
2976                tgap= epics_get(undpv "TaperGap")
2977                FPRNT=sprintf("%g %.8g %.8g ",gap,E,tgap)
2978                PPRNT=sprintf("%9.4f %9.4f %9.4f ",gap,E,tgap)
2979                VPRNT=PPRNT
2980                scan_loop
2981                scan_data(NPTS, gap)
2982                scan_plot
2983           }
2984         }
2985         scan_tail
2986        \'
2987        _scan_on
2988}'
2989
2990addund dsund ID08ds:
2991addund usund ID08us:
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018"""
3019#Jeff K. modified this empty def that is part of standard set macro
3020#to make the standard set command work with Mooney soft slit database
3021#I think you may need some background to fully understand this. As you already know spec uses the macro "set" to set a
3022#motor's location by modifying it's OFF field. Below is the standard "set" macro:
3023#The important thing here is Gerry provided a user configurable macro call to "user_setpos". This is normally nothing
3024more than a stub in spec so we used this to perform the tasks that Suresh detailed below to use SET instead. We had
3025to verify in our "user_setpos" that this was a slit motor (which we did by checking for either "cen" or "gap" in the
3026name). The main problem we experienced was it was necessary to return the OFF field back to zero because spec
3027automatically does this before the call to user_setpos.
3028
3029The beauty of this is that Suresh is now able to use "set" for all of his motors, whether they are hard ones or soft
3030slit ones. A user doesn't need to know to use a different macro for these slit motors.
3031
3032"""
3033##above are commented using block comment method
3034#January 2017
3035
3036def user_setpos '{
3037# $1=motor, e.g. si2hgap,si2hcen,si2vgap,si2vcen
3038# $2=val
3039
3040  local _motor, _val;
3041  local _str, _crate, _slitPV;
3042
3043  _motor = motor_mne($1)
3044  _val = $2
3045
3046  # If motor does not have a valid misc_par_1 then it is not a slit so we shall exit
3047  # Better long term solution is to check the motor record version string
3048  if (motor_par(_motor,"misc_par_1") == 0) {
3049     exit;
3050  }
3051
3052  _crate = motor_par(_motor,"device_id")
3053  _slitPV = _crate motor_par(_motor,"misc_par_1")
3054
3055  # Final verification that this is a slit motor when IGSET is present and asserted
3056  _str = _slitPV ".IGSET"
3057  if  ( ! epics_pv_is_valid(_str) || ! epics_get(_str) ) {
3058    exit
3059  }
3060
3061  # This is kluge to change offset back to 0 which set changes.
3062  _str = _slitPV ".OFF"
3063  epics_put(_str,0)
3064
3065  _str = _slitPV ".SET"
3066  epics_put(_str, 1)
3067  sleep(0.1)
3068  _str = _slitPV ".VAL"
3069  epics_put(_str, _val)
3070  sleep(0.1)
3071  _str = _slitPV ".SET"
3072  epics_put(_str, 0)
3073  sleep(0.1)
3074
3075}'
3076def check_beam_status() '{
3077        local is_Beam_Up is_A_shutter_closed is_D_shutter_closed is_F_shutter_closed
3078
3079        is_Beam_Up = epics_get("8idi:Unidig1Bi8.VAL","short");
3080
3081        is_A_shutter_closed = epics_get("PA:08ID:STA_A_FES_OPEN_PL","short");
3082        is_D_shutter_closed = epics_get("PA:08ID:STA_D_SDS_OPEN_PL","short");
3083        is_F_shutter_closed = epics_get("PA:08ID:STA_F_SFS_OPEN_PL","short");
3084        return(is_Beam_Up & (is_A_shutter_closed) & (is_D_shutter_closed) & (is_F_shutter_closed) );
3085}'
3086
3087def waitForFaultClear '{
3088        for (;;) {
3089                if (check_beam_status() == 1) {
3090                        print " ";
3091                        print " ";
3092                        break;
3093                }
3094                printf("\rWaiting for EPS Fault to be Cleared OR Station Shutters are NOT ALL OPEN: %s", date());
3095                tty_cntl("ce");
3096                printf("\r");
3097                sleep(10);
3098                tty_cntl("ce");
3099                printf("\r");
3100        }
3101                if (PRINT_DEBUG_MSG == 1) printf("Station Shutters A, D, and I are OPEN now : %s\n",date());
3102}'
3103
3104global SIS_PV  SIS_MCA SIS_TS SIS_name
3105
3106SIS_PV="8idi:3820"
3107SIS_MCA[0]="8idi:3820:mca1"
3108SIS_MCA[1]="8idi:3820:mca2"
3109SIS_MCA[2]="8idi:3820:mca4"
3110
3111
3112
3113
3114def sis_init '{
3115    epics_put(sprintf("%s:scaler1.CONT",SIS_PV),"OneShot")
3116    epics_put(sprintf("%s:PresetReal",SIS_PV),0)
3117    epics_put(sprintf("%s:ChannelAdvance",SIS_PV),"Internal")
3118    epics_put(sprintf("%s:ReadAll.SCAN",SIS_PV),"Passive")
3119    spec_par("epics_timeout",10)
3120}'
3121
3122sis_init
3123
3124def sis_dwelltime '{
3125    if($1>0) {
3126        epics_put(sprintf("%s:Dwell",SIS_PV),$1)
3127    comment "SIS3820 dwell time changed to %f" $1
3128    }
3129}'
3130
3131def sis_numchannels '{
3132    if($1>0) {
3133        epics_put(sprintf("%s:NuseAll",SIS_PV),$1)
3134    comment "SIS3820 Num. of channels changed to %i" $1
3135    }
3136}'
3137
3138def sis_stop '{
3139  epics_put(sprintf("%s:StopAll",SIS_PV),1);
3140  _user_sis_abort
3141}'
3142
3143#def _user_sis_abort 'blockbeam'
3144def _user_sis_abort ''
3145
3146def sis_trig '{
3147    #force stop
3148    epics_put(sprintf("%s:StopAll",SIS_PV),1)
3149#    SIS_TS=epics_get(sprintf("%s.STIM",SIS_MCA[1]))
3150    epics_put(sprintf("%s:EraseStart",SIS_PV),1)
3151    #epics_put(sprintf("%s:EraseAll",SIS_PV),1)
3152    #epics_put(sprintf("%s:StartAll",SIS_PV),1)
3153    sleep(0.6)
3154}'
3155
3156def sis_wait '{
3157    cdef("cleanup_once","sis_stop;sis_read;","sis","0x10")
3158    while((epics_get(sprintf("%s:Acquiring",SIS_PV))=="Acquiring")) sleep(.1)
3159    sis_stop
3160}'
3161
3162def sis_read '{
3163    local n m i
3164    n=epics_get(sprintf("%s:NuseAll",SIS_PV))
3165    m = _aa_length(SIS_MCA)
3166    global array SIS_DATA[n*m]
3167    #for(i in SIS_MCA) {
3168       ##SIS_DATA[i]=epics_get(sprintf("%s",SIS_MCA[i]),"long",n)
3169    #}
3170    #SIS_DATA[0:(n*m/2)-1]=epics_get(sprintf("%s",SIS_MCA[0]),"long",n)
3171    #SIS_DATA[(n*m/2):(n*m)-1]=epics_get(sprintf("%s",SIS_MCA[1]),"long",n)
3172
3173    SIS_DATA[0:(n*m/3)-1]=epics_get(sprintf("%s",SIS_MCA[0]),"long",n)
3174    SIS_DATA[(n*m/3):(n*m*2/3)-1]=epics_get(sprintf("%s",SIS_MCA[1]),"long",n)
3175    SIS_DATA[(n*m*2/3):(n*m)-1]=epics_get(sprintf("%s",SIS_MCA[2]),"long",n)
3176}'
3177
3178def sis_acquire '{
3179    sis_trig;sis_wait
3180    sis_read;
3181}'
3182
3183def sis_save '{
3184      global SIS_name
3185    #for(i in SIS_MCA) {
3186        local fname 
3187       fname=SIS_name   ".sis"
3188       on(fname);offt
3189       array_dump(SIS_DATA,"%d")
3190       ont;close(fname)
3191    #} 
3192   
3193}'
3194
3195
3196if (DATAFILE=="/dev/null") { # makes sure after fresh start that have data file assigned
3197        strDataFile = sprintf("%s%s", "spec8IDIdata_", date(\"%m-%d-%Y-%Hp%Mp%S\"));
3198        myfile(strDataFile, 0);
3199}
3200"""
3201Macros for manipulating EPICS channel access
3202
3203DESCRIPTION
3204===========
3205This file contains EPICS-related macros which control, refresh, or verify
3206EPICS channel access PVs. Macros which detail EPICS motors are also provided.
3207
3208The following are the user macros provided:
3209
3210    * :spec:def:`epics_pv_is_valid` -> Verify validity of a PV name.   
3211    * :spec:def:`checkPV'           -> Wrapper/alias for epics_pv_is_valid.
3212    * :spec:def:`epics_pv_refresh`  -> Refresh an EPICS PV channel.
3213    * :spec:def:`epics_sleep`       -> Sleep when polling an EPICS channel
3214    * :spec:def:`epics_motor_details'  -> Show EPICS settings for a motor.
3215    * :spec:def:`emd'               -> Wrapper/alias for epics_motor_details.
3216    * :spec:def:`epics_list_motor'  -> Show EPICS PVs for motor(s).
3217    * :spec:def:`lsm'               -> Wrapper/alias for epics_list_motor.
3218
3219
3220LIMITATIONS
3221===========
3222None
3223
3224Installation
3225============
3226
3227Setup
3228-----
3229No special configuration is needed to run these macros. Simply load the macro
3230file::
3231
3232  > qdo epics_misc.mac
3233
3234Dependencies
3235------------
3236This macro depends on the following macro files and macros:
3237
3238N/A
3239
3240
3241Impact
3242------
3243
3244
3245
3246File information
3247================
3248
3249AUTHORS:
3250
3251  * J Kirchman (JAK, jkirchman),
3252    Argonne National Laboratory
3253
3254CREATION DATE:
3255
3256  2013-03-19
3257
3258COPYRIGHT:
3259
3260  .. automatically retrieve the current year:
3261  .. |current_year| date:: %Y
3262
3263  Copyright (c) 2013-|current_year|, UChicago Argonne, LLC
3264
3265  All Rights Reserved
3266
3267  APS SPEC macros
3268
3269  APS SPEC development team,
3270  X-ray Science Division and APS Engineering Support Division,
3271  Argonne National Laboratory
3272
3273LICENSE::
3274
3275  OPEN SOURCE LICENSE
3276
3277  Redistribution and use in source and binary forms, with or without
3278  modification, are permitted provided that the following conditions are met:
3279
3280  1. Redistributions of source code must retain the above copyright notice,
3281     this list of conditions and the following disclaimer.  Software changes,
3282     modifications, or derivative works, should be noted with comments and
3283     the author and organization's name.
3284
3285  2. Redistributions in binary form must reproduce the above copyright notice,
3286     this list of conditions and the following disclaimer in the documentation
3287     and/or other materials provided with the distribution.
3288
3289  3. Neither the names of UChicago Argonne, LLC or the Department of Energy
3290     nor the names of its contributors may be used to endorse or promote
3291     products derived from this software without specific prior written
3292     permission.
3293
3294  4. The software and the end-user documentation included with the
3295     redistribution, if any, must include the following acknowledgment:
3296
3297     "This product includes software produced by UChicago Argonne, LLC
3298     under Contract No. DE-AC02-06CH11357 with the Department of Energy."
3299
3300  *****************************************************************************
3301  *****************************************************************************
3302
3303  DISCLAIMER
3304
3305  THE SOFTWARE IS SUPPLIED "AS IS" WITHOUT WARRANTY OF ANY KIND.
3306
3307  Neither the United States GOVERNMENT, nor the United States Department
3308  of Energy, NOR uchicago argonne, LLC, nor any of their employees, makes
3309  any warranty, express or implied, or assumes any legal liability or
3310  responsibility for the accuracy, completeness, or usefulness of any
3311  information, data, apparatus, product, or process disclosed, or
3312  represents that its use would not infringe privately owned rights.
3313
3314  *****************************************************************************
3315
3316VERSION::
3317
3318  $Revision: 634 $
3319  $Date: 2013-02-22 14:18:00 -0600 (Fri, 22 Feb 2013) $
3320  $Author: jkirchman $
3321  $URL: https://subversion.xray.aps.anl.gov/spec/common/bcda/epics_misc.mac $
3322
3323CHANGE LOG:
3324
3325  2013-03-19 (JAK):
3326  - Original
3327 
3328  2013-05-22 (JAK):
3329  - Bug fix: return values for 'epics_pv_is_valid'
3330  - Added checkPV wrapper
3331
3332  2015-02-17 (JAK):
3333  - Renamed '_epics_print_motor_pv' to more appropriate '_epics_get_motor_pv'
3334    since it does not print out the PV name but return it
3335
3336"""
3337
3338
3339def checkPV 'epics_pv_is_valid ("$1")'
3340
3341def epics_pv_is_valid(pv_name) '{
3342  """
3343  Verify validity of a PV name. Print error message and return 0 if does not exist.
3344  Print nothing and return 1 if valid.
3345
3346  USAGE::
3347
3348    > val = epics_pv_is_valid(<PV_name>)
3349
3350  ARGUMENTS:
3351    :pv_name: The EPICS PV to be checked.
3352
3353  RETURNS:
3354    :val: TRUE(1) if the PV channel exists, 0 otherwise
3355   
3356
3357  """
3358
3359  if(epics_par(pv_name,"type") == ""){
3360    local _str
3361    _str = sprintf("The EPICS PV channel %s does not exist.\n",\
3362             pv_name)
3363    eprint _str
3364    return(0)
3365  }
3366  return(1)
3367}'
3368
3369
3370
3371def epics_pv_refresh(pv_name) '{
3372  """
3373  Refresh an EPICS PV channel.
3374
3375  USAGE::
3376
3377    > epics_pv_refresh(<PV_name>)
3378
3379  ARGUMENTS:
3380    :PV_name: The EPICS PV to be checked.
3381
3382  """
3383  local _ver[]
3384
3385  split(VERSION,_ver,".")
3386  if ( (_ver[0]<6) || ((_ver[0]==6)&&(_ver[1]==0)&&(_ver[2]<2)) )
3387  {
3388      print "Cannot perform refresh! SPEC version is prior to 6.0.2\n"
3389      exit
3390  }
3391  if (is_valid_pv(pv_name)) {
3392      epics_par(pv_name,"refresh")
3393  }
3394 }'
3395
3396
3397def epics_sleep(n) '{
3398  """
3399  Perform a sleep when polling an EPICS PV. A normal sleep() call will prevent
3400  an EPICS polling.  Gerry Swislow recommends avoiding it and using this instead
3401  of 'sleep()' if you need a long delay.
3402
3403  USAGE::
3404
3405    > epics_sleep(<time>)
3406
3407  ARGUMENTS:
3408    :time:  Sleep duration [s]
3409
3410  EXAMPLE::
3411
3412    >
3413    > epics_sleep(5)
3414
3415   
3416
3417  """
3418  local done
3419  done = time() + n
3420  for (;;) {
3421    if (time() >= done)
3422      break
3423    wait(0x20)
3424    sleep(.1)
3425}'
3426
3427
3428def emd 'epics_motor_details $1'
3429
3430
3431def epics_motor_details '{
3432  """
3433  Show EPICS settings for a motor.
3434
3435  USAGE::
3436
3437    > epics_motor_show <mne>
3438
3439  ARGUMENTS:
3440    :mne:  Motor mnemonic [str]
3441
3442  EXAMPLE::
3443
3444    > epics_motor_show tth
3445
3446  """
3447  local mpv,mne,maxarr,mps,i,msubs
3448        maxarr=26 # number of elements in the array
3449  string array mps[maxarr][25] # mot_par string arguments [index][max_string_length]
3450  string array mpvsubs[maxarr][25]
3451
3452  mps[0]="device_id"
3453  mps[1]="controller"
3454  mps[2]="unit"     
3455  mps[3]="channel"   
3456  mps[4]="backlash"
3457  mps[5]="step_size"
3458  mps[6]="acceleration"
3459  mps[7]="base_rate"
3460  mps[8]="velocity"
3461  mps[9]="responsive"
3462  mps[10]="active"
3463  mps[11]="disable"
3464  mps[12]="home_base_rate"
3465  mps[13]="home_acceleration"
3466  mps[14]="dc_settle_time"
3467  mps[15]="dc_sampling_interval"
3468  mps[16]="encoder_step_size"
3469  mps[17]="step_mode"
3470  mps[18]="deceleration"
3471  mps[19]="torque"
3472  mps[20]="misc_par_1"
3473  mps[21]="misc_par_2"
3474  mps[22]="misc_par_3"
3475  mps[23]="misc_par_4"
3476  mps[24]="misc_par_5"
3477  mps[25]="misc_par_6"
3478
3479  mpvsubs[0] ="DESC"
3480  mpvsubs[1] ="DTYP"
3481  mpvsubs[2] ="DIR"
3482  mpvsubs[3] ="S"
3483  mpvsubs[4] ="SBAS"
3484  mpvsubs[5] ="SMAX"
3485  mpvsubs[6] ="SBAK"
3486  mpvsubs[7] ="SREV"
3487  mpvsubs[8] =""
3488  mpvsubs[9] ="EGU"
3489  mpvsubs[10]="MRES"
3490  mpvsubs[11]="ERES"
3491  mpvsubs[12]="VELO"
3492  mpvsubs[13]="VBAS"
3493  mpvsubs[14]="VMAX"
3494  mpvsubs[15]="BVEL"
3495  mpvsubs[16]="BDST"
3496  mpvsubs[17]="UREV"
3497  mpvsubs[18]=""
3498  mpvsubs[19]="ACCL"
3499  mpvsubs[20]="BACC"
3500  mpvsubs[21]="DMOV"
3501  mpvsubs[22]="PREC"
3502  mpvsubs[23]="VAL"
3503  mpvsubs[24]="DHLM"
3504  mpvsubs[25]="DLLM"
3505
3506  mne = sprintf("%s", $1)
3507
3508  if(motor_par(mne,"misc_par_1")) {
3509     mpv = motor_par(mne,"device_id") motor_par(mne,"misc_par_1")
3510  } else {
3511     mpv = motor_par(mne,"device_id") "m" motor_par(mne,"channel")+1
3512  }
3513    printf("%25s:  %s\n", "motor name", motor_mne(mne))
3514    printf("%25s:  %d\n", "motor number", mne)
3515    printf("%25s:  %s\n", "motor description", motor_name(mne))
3516
3517
3518#    printf("%35.27s\t\t%35.28s\n","SPEC motor settings","EPICS PV motor settings")
3519     printf("%66.42s\n","SPEC    <<<: motor settings :>>>    EPICS ")
3520    for (i=0 ; i < maxarr; i=i+1) {
3521        printf("%25s:  %-10s", mps[i], motor_par(mne, mps[i]))
3522        if (mpvsubs[i] == "")
3523            printf("\n")
3524        else
3525            printf("\t\t%25s:  %s\n", sprintf("%s.%s",mpv,mpvsubs[i]),\
3526                   epics_get(sprintf("%s.%s",mpv,mpvsubs[i])))
3527
3528    }
3529
3530    printf("%25s:  %s\n", "upper limit", get_lim (mne, "1"))
3531    printf("%25s:  %s\n", "lower limit", get_lim (mne, "-1"))
3532
3533    for (i=0 ; i < 19 ; i++){
3534    }
3535
3536}'
3537
3538
3539def lsm 'epics_list_motors $*'
3540
3541
3542def epics_list_motors '{
3543  """
3544  Show EPICS PVs for motor(s).
3545
3546  USAGE::
3547
3548    > epics_list_motors [<mne> [<mne> ...]]
3549
3550  ARGUMENTS:
3551    :mne:  Motor mnemonic [str]
3552
3553  EXAMPLE::
3554
3555    > epics_list_motors tth
3556
3557  """
3558  local mne,i,mnum
3559
3560  printf(" -m#- ")
3561  printf(" -motor_name- ")
3562  printf("---motor_desc--- ")
3563  printf("-----EPICS PV-----\n")
3564  if ($# == 0) {
3565    for (mnum=0;mnum<MOTORS;mnum++) {
3566      mne=motor_mne(mnum)
3567      printf("%4d  ", mnum)
3568      printf("%12s  ", mne)
3569      printf("%15s  ", motor_name(mnum))
3570      printf(" %-40s\n", _epics_get_motor_pv(mne))
3571    }
3572  }
3573  else {
3574   
3575    for ( i=0 ; i < $# ; i++ ) {
3576      if (i==0) mnum = motor_num(sprintf("%s", $1))
3577      if (i==1) mnum = motor_num(sprintf("%s", $2))
3578      if (i==2) mnum = motor_num(sprintf("%s", $3))
3579      if (i==3) mnum = motor_num(sprintf("%s", $4))
3580      if (i==4) mnum = motor_num(sprintf("%s", $5))
3581      mne=motor_mne(mnum)
3582      printf("%4d  ", mnum)
3583      printf("%12s  ", mne)
3584      printf("%15s  ", motor_name(mnum))
3585      printf(" %-40s\n", _epics_get_motor_pv(mne))
3586    }
3587  }
3588
3589}'
3590
3591
3592
3593def _epics_get_motor_pv(mne) '{
3594  """
3595  Print EPICS PVs for motor specified.
3596
3597  USAGE::
3598
3599    > _epics_get_motor_pv(<mne>)
3600
3601  ARGUMENTS:
3602    :mne:  Motor mnemonic [str]
3603
3604  EXAMPLE::
3605
3606    > epics_print_motor_pv(tth)
3607
3608  """
3609  local mpv
3610 
3611  if(motor_par(motor_num(mne),"controller")=="NONE") {
3612     mpv = "NO CONTROLLER"
3613  } else if(motor_par(motor_num(mne),"controller")=="EPICS_M2") {
3614     if(motor_par(mne,"misc_par_1")) {
3615        mpv = motor_par(mne,"device_id") motor_par(mne,"misc_par_1")
3616     } else {
3617        mpv = motor_par(mne,"device_id") "m" motor_par(mne,"channel")+1
3618     }
3619  } else {
3620     mpv = "Not an EPICS motor"
3621  }
3622
3623  return(mpv)
3624}'
3625
3626"""
3627Library of additional mathematical functions.
3628
3629
3630Description
3631===========
3632
3633These macro definitions provide additional and auxilary mathematical functions
3634not available in standard SPEC.
3635
3636Installation
3637============
3638
3639To use these macro definitions, simply load the ``math.mac`` macro file::
3640
3641  > qdo math.mac
3642
3643
3644File Information
3645================
3646
3647AUTHOR:
3648
3649  * C.M. Schlepuetz (CS, cschlep),
3650    Argonne National Laboratory, cschlep@aps.anl.gov
3651
3652CREATION DATE:
3653
3654  2010-03-23 @ University of Michigan
3655
3656COPYRIGHT:
3657
3658  .. automatically retrieve the current year:
3659  .. |current_year| date:: %Y
3660
3661  Copyright 2010-|current_year| by the above authors (see AUTHOR).
3662
3663  This program is free software: you can redistribute it and/or modify
3664  it under the terms of the GNU General Public License as published by
3665  the Free Software Foundation, either version 3 of the License, or
3666  (at your option) any later version.
3667
3668  This program is distributed in the hope that it will be useful,
3669  but WITHOUT ANY WARRANTY; without even the implied warranty of
3670  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
3671  GNU General Public License for more details.
3672
3673  You should have received a copy of the GNU General Public License
3674  along with this program.  If not, see http://www.gnu.org/licenses/.
3675
3676VERSION::
3677
3678  $Revision: 1153 $
3679  $Date: 2015-05-21 18:00:05 -0500 (Thu, 21 May 2015) $
3680  $Author: cschlep $
3681  $URL: https://subversion.xray.aps.anl.gov/spec/common/aps/math.mac $
3682
3683CHANGE LOG:
3684
3685  2010-07-23 (CS):
3686
3687  - Added SVN keywords
3688
3689  2012-09-18 (CS):
3690
3691  - Modified documentation for Sphinx specdomain markup.
3692
3693  2012-11-09 (CS):
3694
3695  - Fixed bugs in :spec:def:`ceil`, :spec:def:`floor`, :spec:def:`frac`
3696  - Added :spec:def:`min`, :spec:def:`max`
3697 
3698  2015-05-21 (CS):
3699 
3700  - Fixed bugs in :spec:def:`floor`
3701
3702"""
3703
3704
3705#==============================================================================
3706# Global variable definitions
3707#==============================================================================
3708
3709    #: Save the name and path of the math.mac macro file.
3710    global MATH_MAC
3711           MATH_MAC = DOFILE
3712
3713#==============================================================================
3714# Macro command definitions
3715#==============================================================================
3716
3717#------------------------------------------------------------------------------
3718def math_help '{
3719  """
3720  Displays the help text.
3721
3722  USAGE::
3723
3724     > math_help
3725
3726  NOTE:
3727    The help text is generated by simply displaying the text file
3728    ``math_mac.txt``, which should reside in the same directory as
3729    ``math.mac``. If the file does not exist, a generic help text defined in
3730    ``math_help`` is shown.
3731
3732  """
3733
3734  unix (sprintf ("dirname %s", MATH_MAC), _1)
3735  ll = length (_1)
3736  if (substr (_1, ll, 1) == "\n") _1 = substr (_1, 1, (ll - 1))
3737  file = sprintf ("%s/math_mac.txt", _1)
3738  if (file_info (file, "-e")) {
3739    unix (sprintf ("cat %s", file))
3740  } else {
3741    printf("\nMacros available in file math.mac:\n")
3742    printf(  "                         ========\n")
3743    printf("\n")
3744    printf("  math_help     - creates this help text\n")
3745    printf("  round()       - round number to nearest integer\n")
3746    printf("  floor()       - return next lower integer number\n")
3747    printf("  ceil()        - return next higher integer number\n")
3748    printf("  sign()        - return the sign of a number\n")
3749    printf("  frac()        - return the fractional part of a number\n")
3750    printf("  min()         - return the smaller of two numbers\n")
3751    printf("  max()         - return the larger of two numbers\n")
3752    printf("\n")
3753  }
3754}'
3755
3756
3757#------------------------------------------------------------------------------
3758def round(x) '{
3759  """
3760  Round a number to the next nearest integer (symmetric around zero).
3761
3762  USAGE::
3763
3764    > rounded = round(<number>)
3765
3766  """
3767
3768  return int(x > 0.0 ? x + 0.5 : x - 0.5);
3769
3770}'
3771
3772
3773#------------------------------------------------------------------------------
3774def floor(x) '{
3775  """
3776  Return the next lower integer.
3777
3778  USAGE::
3779
3780    > lower_integer = floor(<number>)
3781
3782  """
3783
3784  return int((frac(x) >= 0.0 | (x == 0)) ? x : x - 1);
3785
3786}'
3787
3788
3789#------------------------------------------------------------------------------
3790def ceil(x) '{
3791  """
3792  Return the next higher integer.
3793
3794  USAGE::
3795
3796    > higher_integer = ceil(<number>)
3797
3798  """
3799
3800    return int(frac(x) > 0.0 ? x+1 : x);
3801
3802}'
3803
3804
3805#------------------------------------------------------------------------------
3806def sign(x) '{
3807  """
3808  Return the sign of a number.
3809
3810  USAGE::
3811
3812    > <val> = sign(<number>)
3813
3814  RETURNS:
3815
3816    The return value <val> is
3817
3818      ======= ===============================
3819      ``val`` Description
3820      ======= ===============================
3821      ``1``   if <number> is greater than 0.
3822      ``-1``  if <number> is smaller than 0.
3823      ``0``   if <number> is equal to 0.
3824      ======= ===============================
3825
3826  """
3827
3828  if (x < 0) {
3829     return(-1)
3830  } else if (x > 0) {
3831     return(1)
3832  } else {
3833    return(0)
3834  }
3835
3836}'
3837
3838
3839#------------------------------------------------------------------------------
3840def frac(x) '{
3841  """
3842  Return the fractional part of a real number.
3843
3844  NOTE:
3845
3846    The fractional part of a real number is defined here such that
3847    :math:`x = int(x) + frac(x)`,
3848    where :math:`int(x)` is the integer part of :math:`x`, using a definition
3849    that is symmetric around zero.
3850
3851  USAGE::
3852
3853    > <val> = frac(<number>)
3854
3855  """
3856
3857      return(x - int(x))
3858
3859}'
3860
3861
3862#------------------------------------------------------------------------------
3863def max(a, b) '{
3864  """
3865  Return the larger of the two arguments.
3866
3867  USAGE::
3868
3869    > <val> = max(<a>, <b>)
3870
3871  RETURNS:
3872
3873    The return value <val> is
3874
3875      ========= =========================================
3876      ``val``   Description
3877      ========= =========================================
3878      ``= <a>`` if <a> is greater than or equal to <b>.
3879      `'= <b>`` if <b> is greater than <a>.
3880      ========= =========================================
3881
3882  """
3883
3884  if (a < b) {
3885     return(b)
3886  } else {
3887    return(a)
3888  }
3889}'
3890
3891
3892#------------------------------------------------------------------------------
3893def min(a, b) '{
3894  """
3895  Return the smaller of the two arguments.
3896
3897  USAGE::
3898
3899    > <val> = min(<a>, <b>)
3900
3901  RETURNS:
3902
3903    The return value <val> is
3904
3905      ========= =========================================
3906      ``val``   Description
3907      ========= =========================================
3908      ``= <a>`` if <a> is smaller than or equal to <b>.
3909      `'= <b>`` if <b> is smaller than <a>.
3910      ========= =========================================
3911
3912  """
3913
3914  if (a > b) {
3915     return(b)
3916  } else {
3917    return(a)
3918  }
3919}'
3920
3921
3922#==============================================================================
3923# End of $Id: math.mac 1153 2015-05-21 23:00:05Z cschlep $
3924#==============================================================================
3925"""
3926Macro for sending email messages (or text messages to a mobile phone)
3927from SPEC. This includes the possibility to be notified immediately of
3928any errors that SPEC encounters.
3929
3930Description
3931===========
3932
3933
3934
3935
3936Legal Disclaimer
3937================
3938
3939This macro makes use of the ``mail`` or ``sendmail`` program in Linux to send
3940out emails. These messages could potentially use arbitrary email addresses as
3941the sender, which may not necessarily exist. This method could therefore be
3942abused to send spam messages from an anonymous email address, and hence
3943is not legally tolerated or may be even actively blocked by many institutions.
3944Check with your IT security department and review the corresponding cyber
3945security regulations before attempting to use this macro.
3946
3947Notes
3948=====
3949
3950#.  Messages should not contain any unix control characters (such as
3951    ``/;<>"'@$*~|`` ). They can cause an error when sending the message.
3952
3953#.  The sending of error messages is triggered by any SPEC error. This
3954    is achieved by adding the call to :spec:def:`msg_send_error` to
3955    :spec:def:`cleanup_always`. To avoid sending a flood of messages,
3956    :spec:def:`msg_send_error` is immediately removed from
3957    :spec:def:`cleanup_always` after sending the first error message.
3958    Therefore, one needs to call :spec:def:`msg_on` again after each reported
3959    error to re-enable the error reporting.
3960
3961#.  `msg.mac` can also be used to send text messages to mobile phones,
3962    provided the corresponding mobile carrier provides a so-called email to SMS
3963    gateway. A list of the most common US-based carriers includes
3964    (as of 2010/09/16):
3965
3966      ============  =======================================================
3967      Provider      Email address format
3968      ============  =======================================================
3969      Alltel        ``<n>@message.alltel.com``
3970      ATT Wireless  ``<n>@txt.att.net``
3971      CellularOne   ``<n>@mobile.celloneusa.com``
3972      Cingular      ``1<n>@mobile.mycingular.com``
3973      Sprint PCS    ``<n>@messaging.sprintpcs.com``
3974      T-Mobile      ``<n>@tmomail.net``
3975      O2            ``<n>@mobile.celloneusa.com``
3976      Orange        ``<n>@mobile.celloneusa.com``
3977      Verizon       ``<n>@vtext.com``
3978      ============  =======================================================
3979
3980    where <n> is the 10-digit mobile telephone number.For more information,
3981    refer to a relatively comprehensive international list at
3982
3983      http://www.mutube.com/projects/open-email-to-sms/gateway-list/
3984
3985    .. warning:: Depending on your subscription service with your provider,
3986                 receiving text messages on your phone **MAY NOT BE FREE**!
3987                 Contact your carrier for details.
3988
3989
3990Installation
3991============
3992
3993Dependencies
3994------------
3995
3996`msg.mac` uses the standards `mail` or `sendmail` commands in UNIX to send the
3997messages. At least one of these commands therefore needs to be available and
3998the system has to be configured to allow for the sending of messages through
3999these commands (beware of firewall settings, etc.).
4000
4001Configuration and setup
4002-----------------------
4003
4004First, load the macro file::
4005
4006  > qdo msg.mac
4007
4008The following global variables for `msg.mac` may need to be modified to match
4009any particular UNIX setup (see the global variables section in the source code
4010for more information). This should preferably be done in a site-specific
4011configuration file after loading `msg.mac`.
4012Default values for each variable are given in brackets:
4013
4014  :spec:global:`MSG_METHOD`:
4015    The name of the mail program used to send messages.
4016    Can be ``mail`` or ``sendmail``.
4017    [:spec:global:`MSG_METHOD` = ``"sendmail"``]
4018
4019  :spec:global:`MSG_BIN`:
4020    The path to the mail program binary file.
4021    [:spec:global:`MSG_BIN` = ``"/usr/sbin/sendmail"``]
4022
4023  :spec:global:`MSG_BIN_OPT`:
4024    Additional command line options to be passed to the mail program.
4025    [:spec:global:`MSG_BIN_OPT` = ``""``]
4026
4027  :spec:global:`MSG_MESSAGE_FILE`:
4028    Path and file name for the temporary message file which gets passed to the
4029    mail program.
4030    [:spec:global:`MSG_MESSAGE_FILE` = ``"/tmp/spec_msg_message_file.txt"``]
4031
4032A few more global variables may be pre-defined during the configuration to
4033contain reasonable initial values for your setup, although these can be changed
4034by the user during the :spec:def:`mgs_setup` command:
4035
4036  :spec:global:`MSG_FROM`:
4037    The "from:" address for the message being sent.
4038    [:spec:global:`MSG_FROM` = ``<user>@<hostname>``, where <user> is the
4039    current user name and <hostname> is the hostname of the localhost system]
4040
4041  :spec:global:`MSG_REPLY_TO`:
4042    The "reply-to:" address for the message being sent.
4043    [:spec:global:`MSG_REPLY_TO` = ``""``]
4044
4045  :spec:global:`MSG_SUBJ`:
4046    The default subject line for the message being sent.
4047    [:spec:global:`MSG_SUBJ` = ``"Message from SPEC"``]
4048
4049Impact
4050------
4051
4052Chained macro definitions affected by this macro:
4053
4054  - :spec:def:`cleanup_always`
4055
4056
4057File information
4058================
4059
4060AUTHOR:
4061
4062  * Christian M. Schlepuetz (CS, cschlep),
4063    Argonne National Laboratory, cschlep@aps.anl.gov
4064
4065CREATION DATE:
4066
4067  2010-09-16
4068
4069COPYRIGHT:
4070
4071  .. automatically retrieve the current year:
4072  .. |current_year| date:: %Y
4073
4074  Copyright (c) 2010-|current_year|, UChicago Argonne, LLC
4075
4076  All Rights Reserved
4077
4078  APS SPEC macros
4079
4080  APS SPEC development team,
4081  X-ray Science Division and APS Engineering Support Division,
4082  Argonne National Laboratory
4083
4084LICENSE:
4085
4086  UChicago Argonne, LLC, OPEN SOURCE LICENSE.
4087  See LICENSE file included with this distribution.
4088
4089VERSION::
4090
4091  $Date: 2015-05-05 13:38:00 -0500 (Tue, 05 May 2015) $
4092  $Author: cschlep $
4093  $URL: https://subversion.xray.aps.anl.gov/spec/common/aps/msg.mac $
4094  $Revision: 1125 $
4095
4096CHANGE LOG:
4097
4098  2010-09-16 (CS):
4099
4100  - created first version of this macro based on the older `sms.mac`
4101
4102  2010-11-03 (CS):
4103
4104  - added legal notice in header
4105  - added :spec:def:`msg_reset`.
4106
4107  2011-04-05 (CS):
4108
4109  - changed all macro names to lower case and underscore naming convention.
4110
4111  2012-08-22 (CS):
4112
4113  - modified and updated macro documentation to work with the Sphinx specdomain
4114    documentation tool.
4115
4116"""
4117
4118#==============================================================================
4119# Global variable definitions
4120#==============================================================================
4121
4122    # Save the name of this macro file.
4123    global MSG_MAC
4124           MSG_MAC = DOFILE
4125
4126    # the type of mail program used to send messages. Currently, two programs
4127    # are supported:
4128    # "mail"
4129    # "sendmail"
4130    # Check which programs are available on your system and set the
4131    # corresponding method and path to the binary below
4132    global MSG_METHOD
4133           #MSG_METHOD = "mail"
4134           MSG_METHOD = "sendmail"
4135
4136    # path to the command line mail program binary
4137    global MSG_BIN
4138           #MSG_BIN = "/bin/mail"
4139           MSG_BIN = "/usr/sbin/sendmail"
4140
4141    # optional command line arguments to be passed to the mail program
4142    # (refer to the corresponding mail program documentation for valid options)
4143    global MSG_BIN_OPT
4144           MSG_BIN_OPT = ""
4145
4146    global MSG_SETUP_FILE
4147           MSG_SETUP_FILE = "/tmp/spec_msg_setup_file.txt"
4148    global MSG_MESSAGE_FILE
4149           MSG_MESSAGE_FILE = "/tmp/spec_msg_message_file.txt"
4150
4151    global MSG_ON
4152           MSG_ON = 0
4153    global MSG_ERR
4154           MSG_ERR = 0
4155
4156    global MSG_TO
4157           MSG_TO = ""
4158    global MSG_FROM
4159           MSG_FROM = ""
4160    global MSG_REPLY_TO
4161           MSG_REPLY_TO = ""
4162    global MSG_SUBJ
4163           MSG_SUBJ = "Message from SPEC"
4164
4165    global MSG_TO_LIST
4166           MSG_TO_LIST = ""
4167
4168    global MSG_IS_SETUP
4169           MSG_IS_SETUP = 0
4170
4171
4172    # set default for from address to current user at local hostname
4173    {
4174      local _user, _host, _ll
4175      unix("whoami",_user)
4176      _ll = length(_user)
4177      if ((_ll > 0) && (substr (_user, _ll, 1) == "\n")) {
4178        _user = substr (_user, 1, _ll-1)
4179      }
4180      unix("hostname",_host)
4181      _ll = length(_host)
4182      if ((_ll > 0) && (substr (_host, _ll, 1) == "\n")) {
4183        _host = substr (_host, 1, _ll-1)
4184      }
4185      MSG_FROM = sprintf("%s@%s",_user,_host)
4186    }
4187
4188#==============================================================================
4189# Public macro definitions
4190#==============================================================================
4191
4192#------------------------------------------------------------------------------
4193def msg_help '{
4194  """
4195  Displays the messge help text.
4196
4197  USAGE::
4198
4199    > msg_help
4200
4201  NOTE:
4202    The help text is generated by simply displaying the text file
4203    msg_mac.txt, which should reside in the same directory as
4204    msg.mac. If the file does not exist, a generic help text defined in
4205    msg_help is shown.
4206
4207  """
4208
4209  local  file, ll
4210
4211  unix (sprintf ("dirname %s", MSG_MAC), _1)
4212  ll = length (_1)
4213  if (substr (_1, ll, 1) == "\n") _1 = substr (_1, 1, (ll - 1))
4214  file = sprintf ("%s/msg_mac.txt", _1)
4215  if (file_info (file, "-e")) {
4216    unix (sprintf ("cat %s", file))
4217  } else {
4218    printf ("\n  Macros available in file msg.mac ($$Revision: 1125 $$):\n")
4219    print     "                           ======="
4220    print ""
4221    print "     msg_help                - creates this help text"
4222    print "     msg_on                  - asks to turn on the msg notification"
4223    print "     msg_off                 - turn off the msg notification"
4224    print "     msg_setup               - set up notification parameters"
4225    print "     msg_reset               - reset all notification settings"
4226    print "     msg_send_scan_success   - send a Success Report"
4227    print "     msg_send_error          - send an Error Report"
4228    print "     msg_send_message(<mgs>) - send <msg> (must be a string)"
4229  }
4230}'
4231
4232
4233
4234#------------------------------------------------------------------------------
4235def msg_on '{
4236  """
4237  Enables the message notification service.
4238
4239  DESCRIPTION:
4240    The user is prompted whether SPEC errors should also be reported.
4241    If the optional <err_flag> argument is passed the user prompt is
4242    circumvented and errors are reported if the flag is set to 1, or ignored if
4243    the flag is 0. This requires that msg_setup has been executed before.
4244
4245  USAGE::
4246
4247    > msg_on
4248
4249    > msg_on [<err_flag>]
4250
4251  ARGUMENTS:
4252    :err_flag (optional): Enable or disable reporting of errors:
4253
4254                            =====  ========================
4255                            ``1``  All errors are reported
4256                            ``0``  No errors are reported
4257                            =====  ========================
4258
4259    If the optional arguments ``err_flag`` is not provided, the user will be
4260    prompted for input.
4261
4262  EXAMPLE::
4263
4264    > msg_on 1
4265        # enables message notifications with error reporting enabled
4266
4267  """
4268
4269  if($# == 1){
4270    if(!MSG_IS_SETUP){
4271      printf("\n\n-------------------------------------------------------\n\n")
4272      printf("Warning: Message sending may not have been set up correctly!\n")
4273      printf("Call \'msg_setup\' to set up correctly.\n")
4274      printf("Trying to continue anyway, but failure of messaging routines\n")
4275      printf("is very likely...\n")
4276    }
4277    if($1){
4278      MSG_ERR = 1
4279    } else {
4280      MSG_ERR = 0
4281    }
4282
4283  } else {
4284    MSG_ERR = yesno("Also enable automatic messages in case of errors", 1)
4285
4286    # call the setup routine
4287    if(!(MSG_IS_SETUP)){
4288      msg_setup
4289    }
4290  }
4291
4292  MSG_ON = 1
4293  if(MSG_ERR==1){
4294    cdef("cleanup_always", "\n{msg_send_error}; ", "msg_key", 0x10)
4295  } else {
4296    cdef("cleanup_always", "", "msg_key", "delete")
4297  }
4298  printf("msg messaging has been turned ON.\n")
4299
4300}'
4301
4302
4303#------------------------------------------------------------------------------
4304def msg_off '{
4305  """
4306  Turn off the message notification service.
4307
4308  USAGE::
4309
4310    > msg_off
4311
4312  """
4313
4314  MSG_ON = 0
4315  cdef("cleanup_always", "", "msg_key", "delete")
4316
4317}'
4318
4319
4320#------------------------------------------------------------------------------
4321def msg_setup '{
4322  """
4323  Set up the message header information like sender, recipients, etc.
4324
4325  USAGE::
4326
4327    > msg_setup
4328        # then answer the questions in the dialogue
4329
4330  """
4331
4332  local _recipients, _nrecipients, _from, _repl, _listlen
4333
4334  MSG_IS_SETUP = 0
4335  MSG_TO = ""
4336
4337  MSG_SUBJ = getsval("Message subject", MSG_SUBJ)
4338  MSG_FROM = getsval("Sender e-mail address (from:)", MSG_FROM)
4339  MSG_REPLY_TO = getsval("Reply-to e-mail address (reply-to:)", MSG_REPLY_TO)
4340
4341  # select from already entered recipients
4342  _nrecip_list = split(MSG_TO_LIST, _recipients_list, ", ")
4343  for(_ii=0; _ii<_nrecip_list; _ii++){
4344    if(yesno(sprintf("Add \"%s\" to recipients",_recipients_list[_ii]),1)){
4345      MSG_TO = sprintf("%s%s, ", MSG_TO, _recipients_list[_ii])
4346    }
4347  }
4348
4349  if(MSG_TO_LIST != ""){
4350    MSG_TO_LIST = sprintf("%s, ",MSG_TO_LIST)
4351  }
4352
4353  if (_nrecip_list > 0){
4354    _question = "Add other recipients"
4355    _ans = 0
4356  } else {
4357    _question = "Add email recipients"
4358    _ans = 1
4359  }
4360
4361  # add new recipients
4362  while(yesno(_question,_ans)){
4363    _question = "Add other recipients"
4364    _ans = 0
4365
4366    printf("You can enter any number of email addresses\n")
4367    printf("as a comma-separated list\n")
4368    _addr = getsval("Enter email address(es) here: ","")
4369
4370    # split input at each comma
4371    _n1 = split(_addr, _split1, ",")
4372
4373    for(_ii=0; _ii<_n1; _ii++){
4374      # split result at each space, in case list was not comma separated
4375      # this also removes unnecessary spaces if commas were present
4376      _n2 = split(_split1[_ii], _split2)
4377
4378      for(_jj=0; _jj<_n2; _jj++){
4379        # test if this has valid email address format
4380        if(index(_split2[_jj], "@") == 0){
4381          printf("input \"%s\" does not seem to have valid format.\n",\
4382                 _split2[_jj])
4383          printf("Skipping...\n")
4384        } else {
4385          MSG_TO = sprintf("%s%s, ", MSG_TO, _split2[_jj])
4386          MSG_TO_LIST = sprintf("%s%s, ", MSG_TO_LIST, _split2[_jj])
4387        }
4388      }
4389    }
4390  }
4391
4392  # remove trailing ", " from MSG_TO and MSG_TO_LIST
4393  _ll = length(MSG_TO)
4394  while ((_ll > 0) && (substr (MSG_TO, _ll-1, 2) == ", ")) {
4395    MSG_TO = substr (MSG_TO, 1, _ll-2)
4396  }
4397  _ll = length(MSG_TO_LIST)
4398  while ((_ll > 0) && (substr (MSG_TO_LIST, _ll-1, 2) == ", ")) {
4399    MSG_TO_LIST = substr (MSG_TO_LIST, 1, _ll-2)
4400  }
4401
4402  # cancel if no valid email addresses were found
4403  if(split(MSG_TO,_split1,", ") < 1){
4404    printf("Error: You have not specified any valid recipients for the\n")
4405    printf("       email messages. Please run \'msg_setup\' again.\n")
4406    exit
4407  }
4408
4409  # put together the header information file
4410  unix(sprintf("rm -f %s",MSG_SETUP_FILE))
4411  open(MSG_SETUP_FILE)
4412  fprintf(MSG_SETUP_FILE,"From:%s\n",MSG_FROM)
4413  fprintf(MSG_SETUP_FILE,"Reply-To:%s\n",MSG_REPLY_TO)
4414  _nrecip = split(MSG_TO, _recipients, ", ")
4415  for (_ii=0; _ii<_nrecip; _ii++){
4416    fprintf(MSG_SETUP_FILE,"To:%s\n",_recipients[_ii])
4417  }
4418  fprintf(MSG_SETUP_FILE,"Subject:%s\n",MSG_SUBJ)
4419  fprintf(MSG_SETUP_FILE,"\n")
4420  close(MSG_SETUP_FILE)
4421
4422  MSG_IS_SETUP = 1
4423
4424}'
4425
4426
4427#------------------------------------------------------------------------------
4428def msg_reset '{
4429  """
4430  Reset the msg notification service.
4431
4432  DESCRIPTION:
4433    This turns off the service and restores all default parameters. This will
4434    also erase all previously stored email addresses.
4435
4436  USAGE::
4437
4438    > msg_reset
4439
4440  """
4441
4442  MSG_TO = ""
4443  MSG_FROM = ""
4444  MSG_REPLY_TO = ""
4445  MSG_SUBJ = "Message from SPEC"
4446  MSG_TO_LIST = ""
4447  MSG_IS_SETUP = 0
4448  MSG_ON = 0
4449
4450  cdef("cleanup_always", "", "msg_key", "delete")
4451
4452}'
4453
4454
4455#------------------------------------------------------------------------------
4456def msg_send_scan_success '{
4457  """
4458  Send the predefined success message "SPEC-scan completed successfully".
4459
4460  USAGE::
4461
4462    > msg_send_scan_success
4463
4464  """
4465
4466  msg_send_message("SPEC-scan completed successfully.")
4467
4468}'
4469
4470
4471#------------------------------------------------------------------------------
4472def msg_send_error '{
4473  """
4474  Send a predefined error message and disable further error messages.
4475
4476  DESCRIPTION:
4477    This command sends the predefined error message
4478    ``SPEC encountered an ERROR. All macros aborted``.
4479    It also disables the sending of further error messages to prevent
4480    accidental floods of messages. The user needs to re-enable error reporting
4481    by typing :spec:def:`msg_on` again.
4482
4483  USAGE::
4484
4485    > msg_send_error
4486
4487  """
4488
4489  msg_send_message("SPEC encountered an ERROR. All macros aborted.")
4490
4491  #: remove error sending from cleanup macro
4492  cdef("cleanup_always", "", "msg_key", "delete")
4493
4494  printf("\n--------------------------\n\n")
4495  printf("Message sent: SPEC encountered an ERROR. All macros aborted.\n")
4496  printf(" (Note: notifications in case of errors has been automatically\n")
4497  printf("  disabled now. To enable, run \'msg_on\' again.)\n\n")
4498
4499}'
4500
4501
4502#------------------------------------------------------------------------------
4503def msg_send_message(_message) '{
4504  """
4505  Send a user defined message.
4506
4507  USAGE::
4508
4509    > msg_send_message("<message>")
4510        # <message> must be a string enclosed in quotation marks ("")
4511
4512  EXAMPLE::
4513
4514    > msg_send_message("This is my message")
4515
4516  NOTES:
4517    #.  Messages may not contain any unix control characters
4518        (such as /;<>@$*~|). This will result in an error.
4519    #.  A timestamp of with the format ``([YYYY][MM][DD] [hh]:[mm])`` will be
4520        automatically appended to each message.
4521
4522  """
4523
4524  if(MSG_ON){
4525
4526    # build timestamp
4527    global _mytempdate
4528    unix("date \"+%Y-%m-%d %R\"",_mytempdate)
4529    _ll = length(_mytempdate)
4530    while ((_ll > 0) && (substr (_mytempdate, _ll, 1) == "\n")) {
4531      _mytempdate = substr (_mytempdate, 1, _ll-1)
4532    }
4533
4534    # add timestamp to message
4535    _message = sprintf("%s (%s)",_message, _mytempdate)
4536
4537    unglobal _mytempdate
4538
4539    if(MSG_METHOD == "mail"){
4540      # command line options:
4541      #        recipients (no option flag)
4542      # -s     Subject
4543      # --     start of sendmail options
4544      # -f     from address (sendmail)
4545      #
4546      unix(sprintf("rm -f %s",MSG_MESSAGE_FILE))
4547      unix(sprintf("echo %s > %s", _message, MSG_MESSAGE_FILE))
4548      _cmd = sprintf("mail -s \'%s\' %s -- -f %s < %s",\
4549                     MSG_SUBJ, MSG_TO, MSG_FROM,\
4550                     MSG_MESSAGE_FILE)
4551    } else if (MSG_METHOD == "sendmail"){
4552      _cmd = sprintf("(cat %s; echo \'%s\') | /usr/lib/sendmail -t",\
4553                     MSG_SETUP_FILE, _message)
4554    }
4555    p _cmd
4556    unix(_cmd)
4557
4558  } else {
4559    printf("Email message service is not enabled. Cannot send message.\n")
4560    printf("Use \'msg_on\' to enable the email message service.\n")
4561  }
4562}'
4563
4564#==============================================================================
4565# End of $Id: msg.mac 1125 2015-05-05 18:38:00Z cschlep $
4566#==============================================================================
4567"""
4568Keep a list of SPEC scans in a text file.
4569
4570Description
4571===========
4572
4573Macro for listing important information about all scans performed during an
4574experimental run. When scan listing is enabled, SPEC writes a separate scanlist
4575file where the information about all the performed scans is stored. Each
4576scan is appended to the list file once it has been executed. Aborted scans are
4577also reported, but marked as "aborted" in contrast to "completed" scans.
4578
4579The information listed includes:
4580
4581* Scan number (:spec:global:`SCAN_N`)
4582* Number of points in scan (:spec:global:`NPTS`)
4583* Scan start timestamp
4584* Scan duration
4585* The SPEC title string (:spec:global:`TITLE`)
4586* Scan status (completed/aborted)
4587* Complete scan heading (:spec:global:`HEADING`)
4588
4589The following is a sample output from ``scanlist.mac``::
4590
4591  #scan  NPTS             started    duration      TITLE    status HEADING
4592      1    45 2012-08-06T18:21:10   0:00:54.4 CA1171_4_1 completed xascan  saz -0.3 0.3  30 0.2 2 2
4593      2    45 2012-08-06T18:24:00   0:00:51.4 CA1171_4_1 completed xascan  saz -0.3 0.3  30 0.2 2 2
4594      3    17 2012-08-06T18:30:32   0:00:11.4 CA1171_4_1   aborted xascan  eta -172.188 -172.088  20 0.5 2 4
4595      5    21 2012-08-06T18:32:35   0:00:13.8 CA1171_4_1 completed ascan  eta -172.506 -172.406  20 0.5
4596      7    61 2012-08-06T18:33:32   0:00:10.1 CA1171_4_1 completed ascan  eta -172.472 -172.372  60 0.1
4597
4598Installation
4599============
4600
4601Setup
4602-----
4603
4604Load the macro file and run the :spec:def:`scanlist_setup` macro::
4605
4606  > qdo scanlist.mac
4607  > scanlist_setup
4608
4609Impact
4610------
4611
4612Chained macro definitions affected by this macro:
4613
4614  * :spec:cdef:`user_postscan_head`
4615  * :spec:cdef:`user_scan_tail`
4616  * :spec:cdef:`cleanup_once`
4617
4618
4619File Information
4620================
4621
4622AUTHORS:
4623
4624  * Christian M. Schlepuetz (CS, cschlep),
4625    Argonne National Laboratory, cschlep@aps.anl.gov [1,2]
4626  * Roger Herger (RH),
4627    Swiss Light Source
4628  * Philip R. Willmott (PR),
4629    Swiss Light Source
4630
4631PREVIOUS FUNDING INSTITUTIONS:
4632
4633  * [1] Swiss Light Source, Paul Scherrer Institute, Switzerland
4634  * [2] Department of Physics, University of Michigan, USA
4635
4636CREATION DATE:
4637
4638  2006-08-07 @ Materials Science Beamline X04SA, Swiss Light Source (SLS)
4639
4640COPYRIGHT:
4641
4642  .. automatically retrieve the current year:
4643  .. |current_year| date:: %Y
4644
4645  Copyright 2010-|current_year| by the above authors (see AUTHOR/AUTHORS).
4646
4647  This program is free software: you can redistribute it and/or modify
4648  it under the terms of the GNU General Public License as published by
4649  the Free Software Foundation, either version 3 of the License, or
4650  (at your option) any later version.
4651
4652  This program is distributed in the hope that it will be useful,
4653  but WITHOUT ANY WARRANTY; without even the implied warranty of
4654  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
4655  GNU General Public License for more details.
4656
4657  You should have received a copy of the GNU General Public License
4658  along with this program.  If not, see http://www.gnu.org/licenses/.
4659
4660VERSION::
4661
4662  $Revision: 1125 $
4663  $Date: 2015-05-05 13:38:00 -0500 (Tue, 05 May 2015) $
4664  $Author: cschlep $
4665  $URL: https://subversion.xray.aps.anl.gov/spec/common/aps/scanlist.mac $
4666
4667CHANGE LOG:
4668
4669  2006-08-07 (CS):
4670
4671  - Created first version by modifying ``scanglog.mac``.
4672
4673  2006-08-11 (CS):
4674
4675  - Added :spec:def:`scanlist_print`.
4676
4677  2006-10-12 (CS):
4678
4679  - Fixed bug in the scanlist output which made the first and last ID to be
4680    wrong by -1.
4681
4682  2007-12-16 (CS):
4683
4684  - Fixed bug: macro used to show finish time instead of start time.
4685    introduced new global variable :spec:global:`SCANLIST_START_DATE`.
4686  - Calculate number of points in scan based on ID if available. This avoids
4687    wrong numbers in case of our house-made hklscans which ignore unphysical
4688    points.
4689
4690  2008-02-12 (CS):
4691
4692  - Fixed bug giving the wrong number of points in a scan when calculated based
4693    on ID.
4694
4695  2010-04-01 (CS):
4696
4697  - Modified this version such that it will run with any standard SPEC.
4698    installation, no special features needed.
4699
4700  2010-07-23 (CS):
4701
4702  - Added SVN keywords (replacing CVS keywords).
4703
4704  2011-04-05 (CS):
4705
4706  - Changed all macro names to lower case and underscore naming convention.
4707
4708  2012-09-19 (CS):
4709
4710  - Modified documentation for Sphinx specdomain markup.
4711  - Cleaned up global variable declarations.
4712  - Simplified some of the code.
4713  - Removed :spec:global:`COUNT_ID` variable and associated information (this
4714    was very non-standard SPEC and specific to the SLS setup).
4715
4716"""
4717
4718#==============================================================================
4719# Global variable definitions
4720#==============================================================================
4721
4722    #: Save the name and path of the scanlist macro file [str]
4723    global SCANLIST_MAC
4724           SCANLIST_MAC = DOFILE
4725
4726    #: Flag to signal whether scanlist is enabled [int]
4727    global SCANLIST_IS_ON
4728
4729    #: Path where the scanlist file is stored [str]
4730    global SCANLIST_PATH
4731    #: File name for the scanlist file [str]
4732    global SCANLIST_FILE
4733        #: Default scanlist file name [str]
4734    global SCANLIST_FILE_DEFAULT
4735           SCANLIST_FILE_DEFAULT = "scanlist.txt"
4736
4737    #: Status of the current scan (aborted/completed) [str]
4738    global SCANLIST_STATUS
4739    #: Start timestamp of the current scan [float]
4740    global SCANLIST_START_TIME
4741    #: Start timestamnp of the current scan as a date string [str]
4742    global SCANLIST_START_DATE
4743
4744
4745#==============================================================================
4746# Macro command definitions
4747#==============================================================================
4748
4749#------------------------------------------------------------------------------
4750def scanlist_help '{
4751  """
4752  Displays the scanlist help text.
4753
4754  USAGE::
4755
4756     > scanlist_help
4757
4758  NOTE:
4759    The help text is generated by simply displaying the text file
4760    ``scanlist_mac.txt``, which should reside in the same directory as
4761    ``scanlist.mac``. If the file does not exist, a generic help text defined
4762    in ``scanlist_help`` is shown.
4763
4764  """
4765
4766  unix (sprintf ("dirname %s", SCANLIST_MAC), _1)
4767  ll = length (_1)
4768  if (substr (_1, ll, 1) == "\n") _1 = substr (_1, 1, (ll - 1))
4769  file = sprintf ("%s/scanlist.txt", _1)
4770  if (file_info (file, "-e")) {
4771    unix (sprintf ("cat %s", file))
4772  } else {
4773    printf("\n  Macros available in file scanlist.mac ($Revision: 1125 $):\n")
4774    printf(  "                           ============\n")
4775    printf("\n")
4776    printf("    scanlist_help     - creates this help text\n")
4777    printf("    scanlist_on       - enable listing of scan information\n")
4778    printf("    scanlist_off      - disable listing of scan information\n")
4779    printf("    scanlist_setup    - set up scan list\n")
4780    printf("    scanlist_show     - show current status of scan listing\n")
4781    printf("    scanlist_filename - set filename with path for scanlist\n")
4782    printf("                            current scan\n")
4783  }
4784}'
4785
4786
4787#------------------------------------------------------------------------------
4788def scanlist_on '{
4789  """
4790  Enable listing of scan information into a scanlist file.
4791
4792  USAGE::
4793
4794    > scanlist_on
4795
4796  """
4797
4798  #: Add :spec:def:`_scanlist_user_postscan_head` to the end of :spec:cdef:`user_postscan_head`
4799  cdef("user_postscan_head", "\n{_scanlist_user_postscan_head}; ", \
4800       "scanlist_user_postscan_head_key", 0x20)
4801
4802  #: Add :spec:def:`_scanlist_user_scan_tail` to the end of :spec:cdef:`user_scan_tail`
4803  cdef("user_scan_tail", "\n{_scanlist_user_scan_tail}; ", \
4804       "scanlist_user_scan_tail_key", 0x20)
4805
4806  if (!SCANLIST_FILE){
4807    scanlist_filename
4808  }
4809
4810  SCANLIST_IS_ON = 1
4811  scanlist_show
4812
4813}'
4814
4815
4816#------------------------------------------------------------------------------
4817def scanlist_off '{
4818  """
4819  Disable listing of scan information into a scanlist file.
4820
4821  USAGE::
4822
4823    > scanlist_off
4824
4825  """
4826
4827  #: Remove :spec:def:`_scanlist_cleanup_once` from :spec:cdef:`cleanup_once`
4828  cdef("cleanup_once", "", "scanlist_cleanup_once_key", "delete")
4829
4830  #: Remove :spec:def:`_scanlist_user_postscan_head` from :spec:cdef:`user_postscan_head`
4831  cdef("user_postscan_head", "", "scanlist_user_postscan_head_key", "delete")
4832
4833  #: Remove :spec:def:`_scanlist_user_scan_tail` from :spec:cdef:`user_scan_tail`
4834  cdef("user_scan_tail", "", "scanlist_user_scan_tail_key", "delete")
4835
4836  SCANLIST_IS_ON = 0
4837  scanlist_show
4838
4839}'
4840
4841
4842#------------------------------------------------------------------------------
4843def scanlist_setup '{
4844  """
4845  Set up listing of scan information into a scanlist file.
4846
4847  USAGE::
4848
4849    > scanlist_setup
4850        # then answer the questions in the setup dialogue.
4851
4852  """
4853
4854  if(yesno("Enable listing of scan information into scanlist file",1)){
4855    scanlist_filename
4856    scanlist_on
4857  } else{
4858    scanlist_off
4859  }
4860
4861}'
4862
4863
4864#------------------------------------------------------------------------------
4865def scanlist_show '{
4866  """
4867  Display the scanlist status and settings.
4868
4869  USAGE::
4870
4871    > scanlist_show
4872
4873  """
4874
4875  if(SCANLIST_IS_ON == 0){
4876    printf("\nListing of scan information is currently DISABLED.\n")
4877    printf("To enable logging use \'scanlist_on\' or \'scanlist_setup\'.\n")
4878  } else if(SCANLIST_IS_ON == 1){
4879    printf("\nListing of scan related information is currently ENABLED.\n")
4880    printf("A list of all scans is written to \n  %s\n", SCANLIST_FILE)
4881    printf("To disable scanlist use \'scanlist_off\' or \'scanlist_setup\'.\n")
4882  } else{
4883    printf("\n\aError in \'scanlist_show\': ")
4884    printf("Invalid value of SCANLIST_IS_ON: %s\n", SCANLIST_IS_ON)
4885    exit
4886  }
4887
4888}'
4889
4890
4891#------------------------------------------------------------------------------
4892def scanlist_filename '{
4893  """
4894  Sets or prompts for the path and file name for the scan list.
4895
4896  USAGE::
4897
4898    > scanlist_filename [<filename>]
4899
4900  ARGUMENTS:
4901    :filename: The name of the scanlist file, including the path (absolute or
4902      relative) [str].
4903
4904    If no input argument is given, the user is prompted for a path and file
4905    name.
4906
4907  NOTE:
4908
4909
4910             Note : Path must be absolute.
4911                    Run this macro once before taking the first scan wich uses
4912                    the listing functions.
4913
4914  """
4915
4916  local _input, _checked1
4917
4918  if(!(($#==1) || ($#==0))){
4919    eprint "\n\aWrong number or illegal arguments in \'scanlist_filename\'"
4920    eprint "Usage:"
4921    eprint "  scanlist_filename [<filename>]"
4922    eprint ""
4923    eprint "The <filename> argument specifies the name of the file into which"
4924    eprint "the scan information is written and is optional. If none is"
4925    eprint "supplied, the user will be prompted for the path."
4926    exit
4927  } else if($# ==1){
4928    _input = "$1"
4929  } else if($# ==0){
4930    if (!SCANLIST_FILE){
4931      _input = getval("Filename for the scanlis file?\n",\\
4932        sprintf("%s/logs/%s",CWD, SCANLIST_FILE_DEFAULT))
4933    } else{
4934      _input = getval("Filename for scanlist?\n", SCANLIST_FILE)
4935    }
4936  }
4937
4938  # check whether path exists and user has write-rights
4939  unix (sprintf ("dirname %s", _input), _path)
4940  _ll = length(_path)
4941  if ((_ll > 0) && (substr(_path, _ll, 1) == "\n")) {
4942    _path = substr(_path, 1, _ll-1)
4943  }
4944
4945  if((file_info(sprintf("%s/",_path),"-d")) != 1){
4946    printf("\n\aError in \'scanlist_setup\': Path does not exist:\n%s ", _path)
4947    printf("\nAborting ...\n")
4948    exit
4949  }
4950
4951  if(!(file_info(_path,"-w"))){
4952    printf("\n\aError in \'scanlist_setup\': No write permission in path\n")
4953    printf("%s.\nAborting ...\n", _path)
4954    exit
4955  }
4956
4957  # check whether file exists already
4958  _checked1 = 0
4959  while (_checked1 == 0){
4960    if(file_info(_input,"-e")){
4961      printf("\n\aFilename %s already exists.\n", _input)
4962      printf("New scan information will be appended to the end of the file. ")
4963      if (yesno("\nDo you want to keep using this file?",1)){
4964        if (file_info(_input,"-w") != 1){
4965          printf("\n\aError in \'scanlist_setup\': You do not have write ")
4966          printf(" permissions for \n%s !\n",_input)
4967          printf("Change permissions or choose another filename. Aborting...")
4968          printf("\n")
4969          exit
4970        }
4971        _checked1 = 1
4972      } else{
4973        _input = getval("Filename for scanlist?\n", \
4974            sprintf("%s/logs/%s",CWD, SCANLIST_FILE_DEFAULT))
4975      }
4976    } else{
4977      _checked1 = 1
4978    }
4979  }
4980
4981  SCANLIST_FILE = _input
4982
4983}'
4984
4985
4986#------------------------------------------------------------------------------
4987def scanlist_print '{
4988  """
4989  Print the scanlist file to a printer.
4990
4991  DESCRIPTION:
4992    Printing is performed using the unix `lpr` command. By default, the
4993    following print options are passed to `lpr`:
4994
4995      ============ ============================================================
4996      Option       Description
4997      ============ ============================================================
4998      prettyprint  Produces nicer output
4999      cpi=13       Font size with 13 characters per inch
5000      landscape    Use landscape orientation
5001      ============ ============================================================
5002
5003    Other print options may be specified as command line arguments, in
5004    particular if a specific printer is to be used::
5005
5006      -P<PrinterName>
5007
5008  USAGE::
5009
5010    > scanlist_print [<options>]
5011
5012  ARGUMENTS:
5013
5014    :options (optional): Any set of valid options for the unix `lpr` command.
5015
5016  NOTE:
5017    The resulting print command is displayed in SPEC and the user will be asked
5018    for confirmation before the file is being sent to the printer.
5019
5020  EXAMPLE:
5021
5022    Use the following command to print to a printer called `MyNetworkPrinter`
5023    using paper with the letter format::
5024
5025      > scanlist_print -P MyNetworkPrinter -o media=letter
5026
5027  """
5028
5029  if (file_info(SCANLIST_FILE,"-e") != 1){
5030    printf("\n\aError in \'scanlist_print\': scanlist file does not exist:\n")
5031    printf(" %s !\n",SCANLISTFILE)
5032    printf("Use \'scanlist_show\' to display status of scan listing or ")
5033    printf("\'scanlist_setup\' for\nsetting up scan listing. Aborting...\n")
5034    exit
5035  }
5036
5037  options = "$*"
5038  pcmd = sprintf("lpr -o prettyprint -o cpi=13 -o landscape %s %s",\
5039                 options, SCANLIST_FILE)
5040  printf("print command:\n%s\n", pcmd)
5041
5042  if(yesno("\nPrint file now?",1)){
5043    printf("Job sent to printer\n")
5044    unix(pcmd)
5045  } else{
5046    printf("printing aborted!\n")
5047  }
5048
5049}'
5050
5051
5052#==============================================================================
5053# Internal macro definitions
5054#==============================================================================
5055
5056#------------------------------------------------------------------------------
5057def _scanlist_header_write(_logfilename) '{
5058  """
5059  Write the header information to the scanlist file.
5060
5061  USAGE::
5062
5063    > _scanlist_header_write(<filename>)
5064
5065  ARGUMENTS:
5066
5067    :filename: File name of the scanlist file [str].
5068
5069  NOTE:
5070    This scanlist file <filename> must be turned on for output before
5071    :spec:def:`_scanlist_header_write` is called. This is done inside
5072    :spec:def:`_scanlist_write`.
5073
5074  """
5075
5076  fprintf(_logfilename,"#%-4s %5s ", "scan", "NPTS")
5077  fprintf(_logfilename,"%19s %11s ", "started", "duration")
5078  fprintf(_logfilename,"%10s %9s ", "TITLE", "status")
5079  fprintf(_logfilename,"%s\n", "HEADING")
5080
5081}'
5082
5083
5084#------------------------------------------------------------------------------
5085def _scanlist_write(_logfilename) '{
5086  """
5087  Write scan information to the scanlist file.
5088
5089  USAGE::
5090
5091    > _scanlist_write(<filename>)
5092
5093  ARGUMENTS:
5094
5095    :filename: File name of the scanlist file [str].
5096
5097  NOTE:
5098
5099    :spec:def:`_scanlist_write` has to be called AFTER the scan has been
5100    executed in order to obtain the correct values listed (usually in
5101    :spec:cdef:`user_scan_tail`).
5102
5103  """
5104
5105  # calculate scan duration
5106  local _duration, _hours, _minutes, _seconds
5107  _duration = time()-SCANLIST_START_TIME
5108  _hours = int(_duration/3600);
5109  _minutes = int((_duration-_hours*3600)/60)
5110  _seconds = _duration-(_hours*3600)-(_minutes*60)
5111  _duration = sprintf("%d:%02d:%04.1f", _hours, _minutes, _seconds)
5112
5113  open(_logfilename)
5114
5115  # print header information if not there yet
5116  _line = getline(_logfilename,0)
5117  if (_line  == -1){
5118    _scanlist_header_write(_logfilename)
5119  } else if (substr(_line,1,1) != "\#"){
5120    _scanlist_header_write(_logfilename)
5121  }
5122
5123  # print scan information
5124  fprintf(_logfilename,"%5d %5d ", SCAN_N, NPTS)
5125  fprintf(_logfilename,"%19s %11s ", SCANLIST_START_DATE, _duration)
5126  fprintf(_logfilename,"%10s %9s ", TITLE, SCANLIST_STATUS)
5127  fprintf(_logfilename,"%s\n", HEADING)
5128
5129  close(_logfilename)
5130
5131}'
5132
5133
5134#------------------------------------------------------------------------------
5135def _scanlist_prescan_info '{
5136  """
5137  Collect information about a scan just before its start.
5138
5139  USAGE::
5140
5141    > _scanlist_prescan_info
5142
5143  """
5144
5145  local _date
5146
5147  SCANLIST_STATUS = "completed"
5148  SCANLIST_START_TIME = time()
5149
5150  # retrieve start timestamp in ISO 8601 format
5151  unix("date +%Y-%m-%dT%H:%M:%S",_date)
5152  _ll = length(_date)
5153  if ((_ll > 0) && (substr (_date, _ll, 1) == "\n")) {
5154    _date = substr (_date, 1, _ll-1)
5155  }
5156  SCANLIST_START_DATE = _date
5157
5158}'
5159
5160
5161#------------------------------------------------------------------------------
5162def _scanlist_cleanup_once '{
5163  """
5164  Clean up and write scan information in case of errors or aborted scans.
5165  """
5166
5167  SCANLIST_STATUS = "aborted"
5168  _scanlist_write(SCANLIST_FILE)
5169
5170}'
5171
5172
5173#------------------------------------------------------------------------------
5174def _scanlist_user_postscan_head '{
5175  """
5176  Prepare gathering of information at the beginning of a scan.
5177  """
5178
5179  if (SCANLIST_IS_ON) {
5180    #: Add :spec:def:`_scanlist_cleanup_once` to :spec:cdef:`cleanup_once`
5181    cdef("cleanup_once", "\n{_scanlist_cleanup_once}; ", \
5182         "scanlist_cleanup_once_key", 0x20)
5183    _scanlist_prescan_info
5184  }
5185}'
5186
5187
5188#------------------------------------------------------------------------------
5189def _scanlist_user_scan_tail '{
5190  """
5191  Write scan information to file at the end of the scan.
5192  """
5193
5194  if (SCANLIST_IS_ON) {
5195    _scanlist_write(SCANLIST_FILE)
5196
5197    #: Remove :spec:def:`_scanlist_cleanup_once` from :spec:cdef:`cleanup_once`
5198    cdef("cleanup_once", "", "scanlist_cleanup_once_key", "delete")
5199  }
5200}'
5201
5202
5203#==============================================================================
5204# End of $Id: scanlist.mac 1125 2015-05-05 18:38:00Z cschlep $
5205#==============================================================================
5206"""
5207Utility macros for determining macros in use and related information
5208 
5209
5210DESCRIPTION
5211===========
5212This file contains macros which will list and helpd describe macros being used.
5213It can determine the macros currently loaded and list where they were loaded and
5214which macros are loaded at startup.
5215
5216The following are macros provided:
5217
5218    * :spec:def:`macro_list`          -> List macros loaded in spec with
5219                                         source file loc
5220    * :spec:def:`mls`                 -> Alias for macro_list
5221    * :spec:def:`macro_specstartlist` -> List macros loaded at startup
5222    * :spec:def:`ssls`                -> Alias for macro_specstartlist
5223
5224
5225
5226LIMITATIONS
5227===========
5228This has only been tested on RHEL5 and RHEL6 hosts. Since Solaris and other
5229Linux flavors may not implement the same application switches for grep, it is
5230unknown whether the macros here will function the same. The user's experience
5231may vary. 
5232
5233Installation
5234============
5235
5236Setup
5237-----
5238No special configuration is needed to run these macros. Simply load the macro
5239file::
5240
5241  > qdo macrolist.mac
5242
5243Dependencies
5244------------
5245There are no dependencies on other macros.
5246
5247
5248Impact
5249------
5250
5251No chained macro definitions are affected by this macro.
5252
5253File information
5254================
5255
5256AUTHORS:
5257
5258  * J Kirchman (JAK, jkirchman),
5259    Argonne National Laboratory
5260
5261CREATION DATE:
5262
5263  2013-10-10
5264
5265COPYRIGHT:
5266
5267  .. automatically retrieve the current year:
5268  .. |current_year| date:: %Y
5269
5270  Copyright (c) 2014-|current_year|, UChicago Argonne, LLC
5271
5272  All Rights Reserved
5273
5274  APS SPEC macros
5275
5276  APS SPEC development team,
5277  X-ray Science Division and APS Engineering Support Division,
5278  Argonne National Laboratory
5279
5280LICENSE::
5281
5282  OPEN SOURCE LICENSE
5283
5284  Redistribution and use in source and binary forms, with or without
5285  modification, are permitted provided that the following conditions are met:
5286
5287  1. Redistributions of source code must retain the above copyright notice,
5288     this list of conditions and the following disclaimer.  Software changes,
5289     modifications, or derivative works, should be noted with comments and
5290     the author and organization's name.
5291
5292  2. Redistributions in binary form must reproduce the above copyright notice,
5293     this list of conditions and the following disclaimer in the documentation
5294     and/or other materials provided with the distribution.
5295
5296  3. Neither the names of UChicago Argonne, LLC or the Department of Energy
5297     nor the names of its contributors may be used to endorse or promote
5298     products derived from this software without specific prior written
5299     permission.
5300
5301  4. The software and the end-user documentation included with the
5302     redistribution, if any, must include the following acknowledgment:
5303
5304     "This product includes software produced by UChicago Argonne, LLC
5305     under Contract No. DE-AC02-06CH11357 with the Department of Energy."
5306
5307  *****************************************************************************
5308  *****************************************************************************
5309
5310  DISCLAIMER
5311
5312  THE SOFTWARE IS SUPPLIED "AS IS" WITHOUT WARRANTY OF ANY KIND.
5313
5314  Neither the United States GOVERNMENT, nor the United States Department
5315  of Energy, NOR uchicago argonne, LLC, nor any of their employees, makes
5316  any warranty, express or implied, or assumes any legal liability or
5317  responsibility for the accuracy, completeness, or usefulness of any
5318  information, data, apparatus, product, or process disclosed, or
5319  represents that its use would not infringe privately owned rights.
5320
5321  *****************************************************************************
5322
5323VERSION::
5324
5325  $Revision: 1135 $
5326  $Date: 2015-05-13 $
5327  $Author: jkirchman $
5328  $URL: https://subversion.xray.aps.anl.gov/spec/common/bcda/macrolist.mac $
5329
5330CHANGE LOG:
5331
5332  2014-05-06 (JAK):
5333
5334  - Original
5335
5336  2014-08-29 (JAK):
5337
5338  - Misc changes to "where_used":
5339  - Remove match if in commented lines
5340  - Warns if no matches found
5341  - Cleanup line consolidated 
5342
5343  2015-05-13 (JAK):
5344
5345  - Added geoms surf and new sevc
5346  - Changed print statement for geometry
5347
5348TO DO:
5349
5350  - Where used doesn't handle def wrappers very well 
5351
5352"""
5353
5354#==============================================================================
5355# Global variable definitions
5356#==============================================================================
5357
5358#==============================================================================
5359# Macro command definitions
5360#==============================================================================
5361
5362
5363#------------------------------------------------------------------------------
5364def mls 'macro_list'
5365
5366#------------------------------------------------------------------------------
5367def macro_list '{
5368  """
5369  Spec macro which lists all non-standard macros loaded and from where (file).
5370  This can be useful if one needs to know if any non-standard macros have
5371  been utilized ot would be lost if planning to restart fresh.
5372
5373  USAGE::
5374
5375    > macro_list
5376
5377  ARGUMENTS:
5378    :none:
5379
5380  NOTE:
5381    This macro uses temporary files which it creates in the /tmp directory
5382    after which it cleans up after itself and deletes the files.
5383
5384   
5385  """
5386  local random logfile deflist cmd
5387
5388  random = rand()
5389  logfile = "/tmp/" random ".log"
5390  deflist = "/tmp/" random ".list"
5391
5392  # Cannot use fon/foff due to parsing of single quotes
5393  if (on(logfile)!=0) eprint "Could not open logfile"
5394  offt
5395  prdef
5396  close(logfile)
5397  ont
5398
5399
5400  # Create command to: 1) grep out standard macros,
5401  #                    2&3) parse together filename and def name
5402  #                    4) remove -- lines
5403  #                    5) sort by filename
5404  #                    6) space out and remove hash
5405  #                    7) use sed to remove if any parenthesis
5406  #                    8) put into columns
5407  if ($# == 1) {
5408      macfilter = "\'\'"
5409      printf("***%s ***",$1)
5410  }
5411  else
5412    macfilter = "-v -i standard"
5413
5414  cmd = sprintf("grep %s %s \
5415                 | egrep -A 1 \'^#.*mac\' \
5416                 | perl -p -e \'s/mac\n/mac\t/\' \
5417                 | grep def \
5418                 | sort \
5419                 | awk \'{print \$2 \" \" \$3 \" \" \$4}\' \
5420                 | sed -e \'s/\(\.\*\$//\' \
5421                 | column -t > %s" \
5422                 , macfilter, logfile, deflist)
5423  unix (cmd)
5424
5425  # Print def list
5426  unix (sprintf("cat %s", deflist))
5427
5428  # Cleanup
5429  unix (sprintf("rm %s %s", logfile, deflist))
5430
5431}'
5432
5433
5434
5435
5436
5437#------------------------------------------------------------------------------
5438def where_used(macro) '{
5439  """
5440  Spec macro which lists all of the macros using a specified macro.
5441
5442  USAGE::
5443
5444    > where_used (macro)
5445
5446  ARGUMENTS:
5447    :macro:   specified macro whose use is to be shown
5448
5449  NOTE:
5450    This macro uses temporary files which it creates in the /tmp directory
5451    after which it cleans up after itself and deletes the files.
5452
5453   
5454  """
5455  local random logfile deflist cmd usesize
5456
5457  if (macro == "") {
5458      eprintf("No macro provided! Please provide a macro name.\n")
5459      return(-1)
5460  }
5461  else {
5462      #printf("All occurrences of \'%s\' will be displayed.\n",macro)
5463  }
5464
5465  random = rand()
5466  logfile = "/tmp/" random ".log"
5467  uselist = "/tmp/" random ".use"
5468
5469  # Cannot use fon/foff due to parsing of single quotes
5470  if (on(logfile)!=0) eprint "Could not open logfile"
5471  offt
5472  prdef
5473  close(logfile)
5474  ont
5475
5476
5477  # Create command to: 1) grep the macro everywhere used, including all defs
5478  #                    2) remove its own def and usage lines
5479  #                    3) remove any print lines
5480  #                    4) remove comment lines containing matches
5481  #                    5) grep the exact match with the line preceding (where used)
5482 
5483  cmd = sprintf("egrep -w --color=auto \'%s|^def|^#\ \*mac\|^#\ \*MAC\' %s \
5484                 | egrep -v \'^def %s|Usage\' \
5485                 | egrep -w -v \'printf\' \
5486                 | egrep -v -E \'^\ \*#\' \
5487                 | grep -w -B 1 %s > %s" \
5488                 , macro, logfile, macro, macro, uselist)
5489  unix (cmd)
5490
5491  # Print which/use list
5492  unix (sprintf("stat -c %s %s", "%s", uselist), usesize)
5493  if ( usesize == "0" ) {
5494    printf("No macros found which use \'%s\'.", macro)
5495  } else {
5496    unix (sprintf("cat %s", uselist))
5497  }
5498
5499  # Cleanup
5500  unix (sprintf("rm -f %s %s", logfile, uselist))
5501
5502}'
5503
5504
5505#------------------------------------------------------------------------------
5506def ssls 'macro_specstartlist'
5507
5508
5509#------------------------------------------------------------------------------
5510def macro_specstartlist '{
5511  """
5512  Spec macro which lists which of the usual macros loaded at startup are present.
5513
5514  USAGE::
5515
5516    > macro_specfilelist
5517
5518  ARGUMENTS:
5519    :none:
5520
5521   
5522  """
5523  local geom geomfile macfile
5524 
5525  # Determine geometry from spec name
5526  if (index(SPEC,"four") != 0)        geom = "fourc"
5527  else if (index(SPEC,"sixc") != 0)   geom = "sixc"
5528  else if (index(SPEC,"psic") != 0)   geom = "psic"
5529  else if (index(SPEC,"kapp") != 0)   geom = "kappa"
5530  else if (index(SPEC,"surf") != 0)   geom = "surf"
5531  else if (index(SPEC,"sevc") != 0)   geom = "sevc"
5532  else                                geom = "spec"
5533  printf("Based on the spec name \'%s\', it is assumed this is a %s geometry.\n", SPEC, geom)
5534
5535
5536  geomfile = sprintf("%s%s", substr(geom,1,4), ".mac")
5537 
5538  macfile["0"] = SPECD "/standard.mac"
5539  macfile["1"] = SPECD "/" geomfile
5540  macfile["2"] = SPECD "/" SPEC "/" geomfile
5541  macfile["3"] = SPECD "/site_f.mac"
5542  macfile["4"] = SPECD "/site.mac"
5543  macfile["5"] = SPECD "/" SPEC "/conf.mac"
5544  macfile["6"] = CWD "/spec.mac"
5545
5546  for (i=0 ; macfile[i] != 0; i++) {
5547    presence = (file_info(macfile[i])) ? "EXISTS" : "DOES NOT EXIST"
5548    printf("%-64s %-15s\n", macfile[i], presence)
5549  }
5550
5551}'
5552
5553#file WARNING.mac
5554###################################################################
5555# WARNING: this file is automatically generated and so should not #
5556# be edited. Find the place which generates it - currently:       #
5557# /home/users/S8SPEC/macros/sites/[machinename|specname]macs      #
5558###################################################################
Note: See TracBrowser for help on using the repository browser.