#Macros for ccdserver spec (quartz?) #=============================================================================== # Modified by: Xuesong Jiao July 05,2005 # # # Modification history: # (as 06/24/2005) -> (1) modified the ccd_series to add the feature to synchron # -ize with the delay generator if one is used. added # ccd_arm, shutter_delay,delay_trig set_delay accordingly. # (2) modified the ccdserver_setup so it always read the # CCD_MODE in short. # (3) added a global variable CCD_THROW, if CCD_THROW not zero # ccd_series will throw first numberof CCD_THROW frames # without saving them. It works for the situation # with and without the delay generator. # (as 07/05/2005) -> (1) changed set_delay so it takes seconds not milliseconds. # ccdbatch in the template do file also changed accordinly. # (2) defined a global variable pvDELAY_CTL to replace the # explicit use of pv 8idi:UnidigBo15.VAL. # (as 03/07/2006) -> (1) cleaned up the code, removed unused comments lines. removed # all initialize commands which should never be used. # (2) modified ccd_series so it should not miss the trigger no # matter CCD_THROW is used or not or external trigger mode. # (as 06/29/2006) -> (1)added _ccd_initialize and changed the delay mode to only arm once # (2) rearranged ccd_series code for use delay and no delay conditions # #=============================================================================== #### macros for Brian Tieman's CCD Sever by epics ############################## #### ccd control macros list in this file: ############################## #### ccdserversetup #### ccd_trig #### ccd_save #### ccd_wait and ccd_wait_nosleep #### ccd_newfile #### ccd_series #### add_batch_par #### #### other related macros: movesample #### movesamth #### takeflux #### enscript #### ################################################################################ def ccdlive 'ccd_live' def ccdnewfile 'ccd_newfile' def ccdseries 'ccd_series' def ccdsetup 'ccdserver_setup' #####global variables ########################################################## global CCDID global MON_ROI SAVED_ROI global CCD_SPEED CCD_PRESET global XBIN global YBIN global CCD_MODE CCD_KINWINSIZE CCD_SLICETOP global CCD_CHILD_DIR CCD_PARENT_DIR CCD_FILENAME CCD_PREFIX CCD_SUFFIX CCD_N global CCD_SLEEP global INFO_DIR SAMBA_MAP global MULTI_IMGS MULTI_FILENAME ################################################################################# #=============================================================================== # global varibales for the delay generator settings #=============================================================================== global USE_DELAY SHUTTER_OPEN_TIME SHUTTER_CLOSE_TIME SHUTTER_TIME CCD_THROW global pvDELAY_CTL #SAMBA_MAP["win_dir"]="F:\\data\\" #SAMBA_MAP["lin_dir"]="/mnt/smb/" SAMBA_MAP["win_dir"]="Y:\\" SAMBA_MAP["lin_dir"]="/home/8-idi-c/" CCDID="08IDI:PIDD1" SAVED_ROI=CCDID ".R01" def ccdserver_setup '{ CCDID=getval("The EPICs prefix of the CCD device:",CCDID) p "CCDManufacturer:" epics_get(sprintf("%s.CCDManufacturer",CCDID)) p "CCDModel:" epics_get(sprintf("%s.CCDModel",CCDID)) p "CCDChip Temperature:" epics_get(sprintf("%s.MeasuredTemp",CCDID)) "C" smb_map fileformat #Modified by Suresh to get short value while( epics_get(sprintf("%s.Idle",CCDID),"short")==0) { p "ccd not ready, wait...." sleep(0.1) } CCD_SPEED= getval("ADC Speed 0 (slow), 1 (fast):",epics_get(sprintf("%s.ADC",CCDID))) XBIN=getval("BinX=",epics_get(sprintf("%s.BinX",CCDID))) YBIN=getval("BinY=",epics_get(sprintf("%s.BinY",CCDID))) CCD_MODE=getval("Use Full Frame (0) or Kinetics Mode(3):", epics_get(sprintf("%s.CameraMode",CCDID),"short")) #reset camera general PVs epics_put(sprintf("%s.ADC",CCDID),CCD_SPEED) epics_put(sprintf("%s.BinX",CCDID),XBIN) epics_put(sprintf("%s.BinY",CCDID),YBIN) epics_put(sprintf("%s.CameraMode",CCDID),CCD_MODE) if(CCD_MODE==3) { CCD_KINWINSIZE = getval("Kinetics WindowSize:",CCD_KINWINSIZE) CCD_SLICETOP = getval("Slice top:",CCD_SLICETOP) epics_put(sprintf("%s.KinStripSize",CCDID),CCD_KINWINSIZE) } SAVED_ROI=CCDID "." getval("Saved ROI# (1-50) i.e R35:","R01") set_roi SAVED_ROI MON_ROI=CCDID "." getval("USE Monitor ROI:","R02") if(CCD_MODE==3) { p "The Monitor R0I has been automatically set for kinetics mode" epics_put(sprintf("%s.Use",MON_ROI),1) epics_put(sprintf("%s.UseCalcs",MON_ROI),1) epics_put(sprintf("%s.Save",MON_ROI),0) epics_put(sprintf("%s.VStart",MON_ROI),CCD_SLICETOP-3*CCD_KINWINSIZE) epics_put(sprintf("%s.VLength",MON_ROI),2*CCD_KINWINSIZE) epics_put( sprintf("%s.HStart",MON_ROI),epics_get(sprintf("%s.HStart",SAVED_ROI))) epics_put(sprintf("%s.HLength",MON_ROI),epics_get(sprintf("%s.HLength",SAVED_ROI))) sleep(1.0) } else set_roi MON_ROI p CCDID "reset done" }' def fileformat '{ local parms if($#==0){ MULTI_IMGS=getval("Multiple Images per File 0(off) 1(on)?",epics_get(sprintf("%s.MultiImgFiles",CCDID))) epics_put(sprintf("%s.MultiImgFiles",CCDID),MULTI_IMGS) } if($#==1) { parms=$1 if(parms >1){ p "Usage fileformat 0/1" exit } MULTI_IMGS=parms epics_put(sprintf("%s.MultiImgFiles",CCDID),MULTI_IMGS) if(parms==1) { p "\nMultiple images _will be_ written to _a single_ file\n" } if(parms==0) { p "\nMultiple images _will be_ written to _separate_ files\n" } } }' def set_roi '{ local vstart,hstart,vlength,hlength if($#<1) { p "Usage:set_roi ROI( i.e. TST:ccd.R01) or set_roi ROI vstart vlength hstart hlength" exit } if($#==5) { vstart=$2 vlength=$3 hstart=$4 hlength=$5 } else { p "Set up dimensions for " "$1" vstart=getval(sprintf("%s row_beg:",ROI),epics_get(sprintf("%s.VStart",$1))) vlength=getval(sprintf("%s number of rows:",ROI),epics_get(sprintf("%s.VLength",$1))) hstart=getval(sprintf("%s col_beg:",ROI),epics_get(sprintf("%s.HStart",$1))) hlength=getval(sprintf("%s number of cols:",ROI),epics_get(sprintf("%s.HLength",$1))) } epics_put(sprintf("%s.Use",$1),1) epics_put(sprintf("%s.UseCalcs",$1),1) epics_put(sprintf("%s.Save",$1),0) epics_put(sprintf("%s.VStart",$1),vstart) epics_put(sprintf("%s.HStart",$1),hstart) epics_put(sprintf("%s.VLength",$1),vlength) epics_put(sprintf("%s.HLength",$1),hlength) sleep(1.0) }' def ccd_save '{ local seqn seqn =CCD_N-1 if(!MULTI_IMGS){ p sprintf("save last img to %s%s%s_%05d.imm",CCD_PARENT_DIR,CCD_CHILD_DIR,CCD_FILENAME,seqn) } else { p sprintf("save last img (sequence# %05d) to %s%s%s",seqn,CCD_PARENT_DIR,CCD_CHILD_DIR,MULTI_FILENAME) } }' def ccd_trig'{ epics_put(sprintf("%s.AcquirePOLL",CCDID),1) }' def ccd_wait_nosleep '{ local n r r=$1 n=$2+$1 #for ( n=0;n %s",file_path,tmpfile)) if((line=getline(tmpfile))!=-1 ) { printf("Directory: %s is not empty. May overwrite existed file!",file_path) ow=1 sn=epics_get(sprintf("%s.SeqNumber",CCDID)) printf("Start at current Sequence Number %d",sn) } getline(tmpfile,"close") unix(sprintf("/bin/rm -f %s",tmpfile)) epics_put(sprintf("%s.FileTemplate",CCDID),sprintf("%s_\$#.imm",CCD_FILENAME)) epics_put(sprintf("%s.SeqNumber",CCDID),sn) sleep(1.0) CCD_N=epics_get(sprintf("%s.SeqNumber",CCDID)) } }' def newmultifile'{ local nstart,nend if($#!=1) { p "Usage newmultifile #ofimages" exit } nstart=epics_get(sprintf("%s.SeqNumber",CCDID)) nend=nstart+$1-1 MULTI_FILENAME=sprintf("%s_%05d-%05d.imm",CCD_FILENAME,nstart,nend) epics_put(sprintf("%s.FileTemplate",CCDID),MULTI_FILENAME) printf("Create multiple images file: %s",MULTI_FILENAME) }' def closemultifile '{ epics_put(sprintf("%s.CloseMultiImgFile",CCDID),1) printf("\nMultiImage file %s closed.\n",MULTI_FILENAME) MULTIFILENAME="dummy" }' def ccd_arm ' ccd_trig #sleep(2.0); while(epics_get(sprintf("%s.AcquirePOLL",CCDID),"short") == 0) sleep(0.1); ' def set_delay '{ if ($# != 1) { eprint "Usage: set_delay exptime(seconds)" exit } local nrows exptime exptime= $1 nrows= epics_get(sprintf("%s.VLength",SAVED_ROI)); if (CCD_MODE==0) { SHUTTER_TIME = exptime }; if (CCD_MODE==3) { SHUTTER_TIME = int(nrows/CCD_KINWINSIZE)*exptime}; shutter_delay SHUTTER_OPEN_TIME SHUTTER_TIME SHUTTER_CLOSE_TIME; }' def shutter_delay ' if ($# != 3) { eprint "Usage: shutter_delay shutter_open_delay time_per_frame shutter_close_delay" exit } _foo=$1; epics_put("8idi:DG1:cDelaySetAO",_foo); sleep(0.01); _foo=($1+$2-$3); epics_put("8idi:DG1:bDelaySetAO",_foo); sleep(0.01); ' def delay_trig ' epics_put(pvDELAY_CTL,1) sleep(0.010); epics_put(pvDELAY_CTL,0) ' def _ccdinitialize ' { epics_put(sprintf("%s.Initialize",CCDID),1); sleep(2.0); }' def ccd_series '{ local exposure repeats s if($# !=2) { eprint "Usage: ccd_series repeats exposuretime" } rdef cleanup \' undef cleanup epics_put(sprintf("%s.Abort",CCDID),1) epics_put(sprintf("%s.Save",SAVED_ROI),0) closemultifile if(CCD_N>series_pars["ndata0"]) { set_more_series_pars writeinfo series_pars } \' repeats=$1 exposure=$2 if (repeats >=1) { CCD_PRESET=exposure epics_put(sprintf("%s.FocusMode",CCDID),0) epics_put(sprintf("%s.Minutes",CCDID),int(exposure/60)) epics_put(sprintf("%s.Seconds",CCDID),int(exposure)%60) epics_put(sprintf("%s.Milliseconds",CCDID),int((exposure-int(exposure))*1000)) epics_put(sprintf("%s.NumExposures",CCDID),1) if((USE_DELAY==0) && CCD_THROW ) { for(foo=1;foo<=CCD_THROW;foo++) {ccd_trig;wait_ccd;} } if( USE_DELAY==1 ) { _ccdinitialize if(CCD_THROW) { ccd_arm; epics_put(sprintf("%s.NumExposures",CCDID),CCD_THROW) for(foo=1;foo<=CCD_THROW;foo++) { delay_trig;wait_ccd; } } } epics_put(sprintf("%s.Save",SAVED_ROI),1) CCD_N=epics_get(sprintf("%s.SeqNumber",CCDID)) set_series_pars; d0=date() if( USE_DELAY) { epics_put(sprintf("%s.NumExposures",CCDID),repeats) ccd_arm; for(s=0;s4) ? $5 : 1 if(SHORTFILE != "/dev/null") { open(SHORTFILE); open(OUTFILE); on(OUTFILE) } print "" #xccdnewfile CCD_PREFIX CCD_SUFFIX firstframe fprintf(SHORTFILE,"\n\n%s%g ms data%s\t%s\n",ENSCRIPT_CTL,\ xtime*1000,ENSCRIPT_CTL_END,date()) }' def takedata '{ rdef batch_cleanup \' { emptydef batch_cleanup finish_data gateoff; } \' epics_put("8idi:scaler1.TP",$2) epics_put("8idi:scaler1.TP1",$2) gateon; printf("\nMoving bstop to %g\n",bstopdata) umv bstop bstopdata; waitmove printf("\nDATA %d - %d (%d) \t%g msec exposures\n",CCD_N,CCD_N-1+$1,$1,$2*1000) showbeam;waitmove ccd_series $1 $2 finish_data gateoff; emptydef batch_cleanup }' def finish_data '{ blockbeam; waitmove # do nothing unless ccdseries got somewhere if (exists("series_pars","ndataend")) { if (!exists("batch_pars","ndataend") && \ !exists("batch_pars","ndarkend")) { # no data or dark has been taken yet, # copy all parameters for (field in series_pars) batch_pars[field] = series_pars[field] batch_pars["nbatch0"] = series_pars["ndata0"] } else { # update only a few specific parameters add_batch_par samx series_pars["samx"] add_batch_par samz series_pars["samz"] add_batch_par samth series_pars["samth"] add_batch_par ring_i_beg series_pars["ring_i_beg"] add_batch_par ring_i_end series_pars["ring_i_end"] add_batch_par ring_i series_pars["ring_i"] add_batch_par start_time series_pars["start_time"] add_batch_par end_time series_pars["end_time"] add_batch_par ndata0 series_pars["ndata0"] add_batch_par ndataend series_pars["ndataend"] add_batch_par preset series_pars["preset"] } batch_pars["nbatchend"] = series_pars["ndataend"] fprintf(SHORTFILE,"\t%sDATA %4d - %4d (%d)%s\t",ENSCRIPT_CTL,\ series_pars["ndata0"],series_pars["ndataend"],\ series_pars["ndataend"]-series_pars["ndata0"]+1,\ ENSCRIPT_CTL_END) fprintf(SHORTFILE,"%s - %s\t%5.2f mA - %5.2f mA\n",\ tod(series_pars["start_time"]),tod(series_pars["end_time"]),\ series_pars["ring_i_beg"],series_pars["ring_i_end"]) } }' def takedark '{ rdef batch_cleanup \'{ emptydef batch_cleanup finish_dark gateoff; }\' epics_put("8idi:scaler1.TP",$2) epics_put("8idi:scaler1.TP1",$2) gateon; printf("\ndark %d - %d (%d)\t%g msec exposures\n",\ CCD_N,CCD_N-1+$1,$1,$2*1000) blockbeam; waitmove ccd_series $1 $2 finish_dark gateoff; emptydef batch_cleanup }' def finish_dark '{ local field # do nothing unless ccdseries got somewhere if (exists("series_pars","ndataend")) { if (!exists("batch_pars","ndataend") && \ !exists("batch_pars","ndarkend")) { # no data or dark has been taken yet, # copy all parameters and then remove a few for (field in series_pars) batch_pars[field] = series_pars[field] delete batch_pars["samx"] delete batch_pars["samz"] delete batch_pars["samth"] delete batch_pars["ring_i_beg"] delete batch_pars["ring_i_end"] delete batch_pars["ring_i"] delete batch_pars["start_time"] delete batch_pars["end_time"] delete batch_pars["ndata0"] delete batch_pars["ndataend"] delete batch_pars["preset"] batch_pars["nbatch0"] = series_pars["ndata0"] } # update a few specific parameters add_batch_par dark_start_time series_pars["start_time"] add_batch_par dark_end_time series_pars["end_time"] add_batch_par ndark0 series_pars["ndata0"] add_batch_par ndarkend series_pars["ndataend"] add_batch_par dark_preset series_pars["preset"] batch_pars["nbatchend"] = series_pars["ndataend"] fprintf(SHORTFILE,"\t%sdark %4d - %4d (%d)%s\t",ENSCRIPT_CTL,\ series_pars["ndata0"],series_pars["ndataend"],\ series_pars["ndataend"]-series_pars["ndata0"]+1,\ ENSCRIPT_CTL_END) fprintf(SHORTFILE,"%s - %s\n",tod(series_pars["start_time"]),\ tod(series_pars["end_time"])) } }' def add_batch_par '{ # note: $2 must be a variable name local field varid field = \'$1\' varid = whatis(\'$2\') # if the variable $2 exists at all . . . if (varid && varid != 137363460) { if (!exists("batch_pars",field)) batch_pars[field] = $2 else batch_pars[field] = grow(batch_pars[field],$2) } }' def start_set '{ global batch_pars ENSCRIPT_CTL ENSCRIPT_CTL_END nextpos SHORTFILE OUTFILE if (batch_name == "") { print "ccd_batch: Please define the variable batch_name in the .Do file." exit } if (index(batch_name,"\\")) { print "ccd_batch: Please do not use \ characters in batch_name." exit } ccd_newfile data_dir batch_name CCD_SUFFIX = ".imm" if (log_dir != "") { makedir log_dir SHORTFILE = trailslash(log_dir) batch_name ".short" OUTFILE = trailslash(log_dir) batch_name ".out" print "\nWriting short log to " SHORTFILE } else OUTFILE = SHORTFILE = "/dev/null" # for no enscript tricks, set ENSCRIPT_CTL = ENSCRIPT_CTL_END = "" # otherwise, make sure the first character will not appear anywhere # in the file to be printed (e.g. @ or %) ENSCRIPT_CTL = "@font{Courier-Bold9}" ENSCRIPT_CTL_END = "@font{default}" empty_array batch_pars }' def finish_set '{ # if any data has been taken, make a .batchinfo file if (exists("batch_pars","ndataend")) { writebatchinfo batch_pars } off(OUTFILE); close(OUTFILE); close(SHORTFILE) # print out short log file enscript SHORTFILE garnet #enscript SHORTFILE graphite # enscript SHORTFILE chalk # right now enscript and quartz do not get along printf("\ndisabling counter gating\n"); gateoff; }' def writebatchinfo '{ local field format info_name INFOFILE bp bp = $1 info_name = sprintf("%s%04d-%04d%s",bp["name"],bp["nbatch0"],\ bp["nbatchend"],".batchinfo") INFOFILE = CCD_PARENT_DIR CCD_CHILD_DIR info_name # delete some parameters that are for internal use only delete bp["nbatch0"] delete bp["nbatchend"] delete bp["norm_vac_flux"] # add " " around strings bp["parent"] = inquotes(bp["parent"]) bp["child"] = inquotes(bp["child"]) bp["name"] = inquotes(bp["name"]) bp["info_name"] = inquotes(info_name) print "\nWriting batch parameters to " INFOFILE open(INFOFILE) format = "%15s = %s\n" for (field in bp) fprintf(INFOFILE,format,field,bp[field]) # make sure these go at the end of the file if (exists("$1","ndarkend")) fprintf(INFOFILE,format,"ndark","ndarkend - ndark0 + 1") if (exists("$1","ndataend")) fprintf(INFOFILE,format,"ndata","ndataend - ndata0 + 1") close(INFOFILE) fprintf(SHORTFILE,"\nbatch parameters in %s\n\n",INFOFILE) }' ############################################################################################################## #### other macros for ccd_batch ############################################################################################################## def movesample '{ local xi zi xi = nextpos % array_op("cols", samxdata) zi = nextpos % array_op("cols", samzdata) printf("\nMoving samx to %g, samz to %g\n",samxdata[xi],samzdata[zi]) umv samx samxdata[xi]; umv samz samzdata[zi] waitmove fprintf(SHORTFILE,"\nAt samx = %g, samz = %g, ccdx = %g, ccdz = %g, T_%s = %g:\n",A[samx],A[samz], A[ccdx],\ A[ccdz], epics_get("8idi:LS331:TC1:CtlInput.SVAL"), epics_get("8idi:LS331:TC1:Control")); nextpos++ }' def movesamth '{ # designed to run AFTER movesample local thi thi = (nextpos-1) % array_op("cols", samthdata) printf("Moving samth to %g\n", samthdata[thi]) umv samth samthdata[thi] waitmove fprintf(SHORTFILE,"At samth = %g:\n",A[samth]) }' def movesamth0 '{ # designed to run AFTER movesample local thi thi = (nextpos-1) % array_op("cols", samthdata0) printf("Moving samth to %g\n", samthdata0[thi]) umv samth samthdata[thi] waitmove }' def enscript '{ local enscriptcmd if ($# < 1) { print "Usage: enscript filename_variable [printer]" exit } enscriptcmd = "enscript -h -f Courier8" if (ENSCRIPT_CTL != "") enscriptcmd = enscriptcmd " -e" substr(ENSCRIPT_CTL,1,1) if ($# > 1) enscriptcmd = enscriptcmd " -P " "$2" enscriptcmd = enscriptcmd " " $1 print "Running " enscriptcmd if ($1 != "/dev/null") unix(enscriptcmd) # Note that enscript syntax is: # print "enscript -h -f Courier8 --escapes=@ -P garnet " # print "enscript -h -f Courier8 --escapes=@ -P graphite " }' def emptydef 'rdef $1 \'\'' def trailslash(dirname) '{ if (dirname == "." || dirname == "./" || dirname == 0) return("") else if (dirname == "" || substr(dirname,length(dirname))=="/") return(dirname) else return(sprintf("%s/",dirname)) }' def makedir '{ # takes a string or a variable of type string if (unix(sprintf("test -d %s",$1))) { if (unix(sprintf("mkdir -p %s",$1))) exit else printf("Created directory %s.\n",$1) } else if (unix(sprintf("test -w %s",$1))) { printf("Cannot write to directory %s: Permission denied.\n",$1) exit } }' def grow(a,b) '{ # takes 2 strings and returns a string in # the form of a yorick-syntax array; # if the first variable is already a # yorick-syntax array string, appends the # second element to it if (substr(a,1,1) != "[") return( sprintf("[%s,%s]",a,b) ) else return( sprintf("%s,%s]",substr(a,1,length(a)-1),b) ) }' def tod(timestr) '{ if (substr(timestr,1,1)=="\"") return(substr(timestr,13,8)) else return(substr(timestr,12,8)) }' def span '{ if ($# < 4) { print "Usage: span variable min max #points" exit } local npts npts = int($4) array $1[npts] # if npts == 1 use min if (npts == 1) $1[0] = 0 else array_op("fill",$1,($3-($2))/(npts-1)) $1 += $2 }'