#pragma rtGlobals=3 // Use modern global access method and strict wave access. #pragma IgorVersion = 6.1 #pragma ModuleName = PearlAreaLive #pragma version = 1.03 #include "pearl-epics", version >= 1.02 // preview panel for EPICS area detectors // such as CCD cameras, 2D electron analysers // the image is read from the NDPluginStdArrays plugin of the area detector // make sure that plugin is enabled // created: matthias.muntwiler@psi.ch, 2013-05-29 // $Id$ static strconstant package_name = "pearl_epics" static strconstant package_path = "root:pearl_epics:" // semicolon-separated list of persistent variable, string, and wave names static strconstant prefs_objects = "" function ad_connect(epicsname, nickname) // connects to the necessary EPICS channels of the detector // to disconnect, call epics_disconnect() // (caution: this will disconnect all EPICS channels of all PEARL EPICS procedures!) string epicsname // base name of the detector, e.g. X03DA-SCIENTA: // image1: and cam1: are appended by the function string nickname // nick name under which this detector is referred to in Igor // must be a valid data folder name // the data folder is created under root:pearl_epics dfref savedf = GetDataFolderDFR() setdatafolder root: // data folder for common EPICS metadata newdatafolder /o/s $package_name dfref epicsdf = GetDataFolderDFR() string /g ad_chids string /g ad_nicknames // data folder this detector string foldername = nickname newdatafolder /s/o $foldername dfref detectordf = GetDataFolderDFR() // create variables and waves make /n=(1)/o arraydata, xscale, yscale make /n=(1,1)/o image variable /g ndimensions variable /g arraysize0, arraysize1 variable /g datatype variable /g colormode string /g controls, monitors string /g xunits, yunits print "connecting EPICS channels..." // channel lists controls = "" monitors = "" string imagename = epicsname + "image1:" string camname = epicsname + "cam1:" // we will set our own monitor on ArrayData, so add this to the controls list controls = ReplaceStringByKey("ArrayData", controls, imagename + "ArrayData", "=") // check whether it has been set already variable chidArrayData = epics_chid(imagename + "ArrayData") variable array_connected = chidArrayData > 0 monitors = ReplaceStringByKey("NDimensions", monitors, imagename + "NDimensions_RBV", "=") monitors = ReplaceStringByKey("ArraySize0", monitors, imagename + "ArraySize0_RBV", "=") monitors = ReplaceStringByKey("ArraySize1", monitors, imagename + "ArraySize1_RBV", "=") monitors = ReplaceStringByKey("DataType", monitors, imagename + "DataType_RBV", "=") monitors = ReplaceStringByKey("ColorMode", monitors, imagename + "ColorMode_RBV", "=") monitors = ReplaceStringByKey("XScale", monitors, camname + "CHANNEL_SCALE_RBV", "=") monitors = ReplaceStringByKey("YScale", monitors, camname + "SLICE_SCALE_RBV", "=") variable nroi = 4 variable iroi string roikey, roiname for (iroi = 0; iroi < nroi; iroi += 1) roikey = "ROI" + num2str(iroi + 1) roiname = epicsname + "ROI" + num2str(iroi + 1) + ":" controls = ReplaceStringByKey(roikey + "Enable", controls, roiname + "EnableCallbacks", "=") controls = ReplaceStringByKey(roikey + "EnableX", controls, roiname + "EnableX", "=") controls = ReplaceStringByKey(roikey + "MinX", controls, roiname + "MinX", "=") controls = ReplaceStringByKey(roikey + "SizeX", controls, roiname + "SizeX", "=") controls = ReplaceStringByKey(roikey + "EnableY", controls, roiname + "EnableY", "=") controls = ReplaceStringByKey(roikey + "MinY", controls, roiname + "MinY", "=") controls = ReplaceStringByKey(roikey + "SizeY", controls, roiname + "SizeY", "=") monitors = ReplaceStringByKey(roikey + "Enable", monitors, roiname + "EnableCallbacks_RBV", "=") monitors = ReplaceStringByKey(roikey + "EnableX", monitors, roiname + "EnableX_RBV", "=") monitors = ReplaceStringByKey(roikey + "MinX", monitors, roiname + "MinX_RBV", "=") monitors = ReplaceStringByKey(roikey + "SizeX", monitors, roiname + "SizeX_RBV", "=") monitors = ReplaceStringByKey(roikey + "EnableY", monitors, roiname + "EnableY_RBV", "=") monitors = ReplaceStringByKey(roikey + "MinY", monitors, roiname + "MinY_RBV", "=") monitors = ReplaceStringByKey(roikey + "SizeY", monitors, roiname + "SizeY_RBV", "=") endfor // connect EPICS channels epics_connect(controls, monitors) // keep track of detector IDs ad_nicknames = AddListItem(nickname, ad_nicknames) variable iad = WhichListItem(nickname, ad_nicknames, ";", 0, 0) ad_chids = AddListItem(num2istr(epics_chid(imagename + "ArrayData")), ad_chids, ";", iad) // set callback function if (!array_connected) pvMonitor /F=ad_live_callback epics_chid(imagename + "ArrayData") endif print "...done" setdatafolder savedf end function ad_live_callback(chan) variable chan dfref savedf = GetDataFolderDFR() setdatafolder $package_path // find the data folder of the detector svar ad_chids svar ad_nicknames variable iad = WhichListItem(num2istr(chan), ad_chids, ";", 0, 0) if (iad >= 0) string nickname = StringFromList(iad, ad_nicknames) else return -1 endif setdatafolder $nickname // retrieve data svar controls svar monitors variable chidArrayData = epics_chid(StringByKey("ArrayData", controls, "=")) variable chidNDimensions = epics_chid(StringByKey("NDimensions", monitors, "=")) variable chidArraySize0 = epics_chid(StringByKey("ArraySize0", monitors, "=")) variable chidArraySize1 = epics_chid(StringByKey("ArraySize1", monitors, "=")) variable chidDataType = epics_chid(StringByKey("DataType", monitors, "=")) variable chidColorMode = epics_chid(StringByKey("ColorMode", monitors, "=")) variable chidXScale = epics_chid(StringByKey("XScale", monitors, "=")) variable chidYScale = epics_chid(StringByKey("YScale", monitors, "=")) wave arraydata wave image nvar ndimensions nvar arraysize0 nvar arraysize1 nvar datatype nvar colormode wave xscale wave yscale pvGet chidNDimensions, ndimensions pvGet chidArraySize0, arraysize0 pvGet chidArraySize1, arraysize1 pvGet chidDataType, datatype pvGet chidColorMode, colormode // sanity checks if (ndimensions != 2) return -2 endif if (colormode != 0) return -3 endif redimension /n=(arraysize0 * arraysize1) arraydata redimension /n=(arraysize0, arraysize1) image redimension /n=(arraysize0) xscale redimension /n=(arraysize1) yscale switch(datatype) case 0: // int8 redimension /b arraydata, image break case 1: // uint8 redimension /b/u arraydata, image break case 2: // int16 redimension /w arraydata, image break case 3: // uint16 redimension /w/u arraydata, image break case 4: // int32 redimension /i arraydata, image break case 5: // uint32 redimension /i/u arraydata, image break case 6: // float32 redimension /s arraydata, image break case 7: // float64 redimension /d arraydata, image break endswitch pvGetWave chidArrayData, arraydata pvGetWave chidXScale, xscale pvGetWave chidYScale, yscale image = arraydata[p + q * arraysize0] setscale /i x xscale[0], xscale[numpnts(xscale)-1], image setscale /i y yscale[0], yscale[numpnts(yscale)-1], image ad_update_profiles(image) // update ROI rectangles svar /z graphname = :view_image:prof_graphname if (svar_exists(graphname)) variable nroi = 4 variable iroi for (iroi = 0; iroi < nroi; iroi += 1) ad_update_ROI(graphname, iroi) endfor endif setdatafolder savedf return 0 end static function ad_update_ROI(graphname, iroi) string graphname variable iroi string roikey variable enable svar monitors wave xscale wave yscale variable enableX = 0 variable minX = 0 variable sizeX = numpnts(xscale) variable enableY = 0 variable minY = 0 variable sizeY = numpnts(yscale) roikey = "ROI" + num2str(iroi + 1) enable = epics_get_num(StringByKey(roikey + "Enable", monitors, "=")) if (enable) enableX = epics_get_num(StringByKey(roikey + "EnableX", monitors, "=")) if (enableX) minX = epics_get_num(StringByKey(roikey + "MinX", monitors, "=")) sizeX = epics_get_num(StringByKey(roikey + "SizeX", monitors, "=")) endif enableY = epics_get_num(StringByKey(roikey + "EnableY", monitors, "=")) if (enableY) minY = epics_get_num(StringByKey(roikey + "MinY", monitors, "=")) sizeY = epics_get_num(StringByKey(roikey + "SizeY", monitors, "=")) endif variable x1 = xscale[minX] variable x2 = xscale[minX + sizeX - 1] variable y1 = yscale[minY] variable y2 = yscale[minY + sizeY - 1] endif ad_update_ROI_rect(graphname, iroi, x1, y1, x2, y2, enable) end static function ad_update_ROI_rect(graphname, iroi, x1, y1, x2, y2, enable) string graphname variable iroi // 0...3 variable x1,y1,x2,y2 variable enable // enable = 1; disable = 0 string roiname = "roi" + num2str(iroi + 1) variable color = 65536 * (1 - iroi/8) - 1 if (enable) DrawAction /w=$graphname getgroup=$roiname, delete, begininsert SetDrawEnv /w=$graphname gstart,gname=$roiname SetDrawEnv /w=$graphname xcoord= bottom,ycoord= left SetDrawEnv /w=$graphname linefgc= (65535,color,color) SetDrawEnv /w=$graphname fillpat= 0 SetDrawEnv /w=$graphname linethick= 0.50 DrawRect /w=$graphname x1,y1,x2,y2 SetDrawEnv /w=$graphname gstop DrawAction /w=$graphname endinsert else DrawAction /w=$graphname getgroup=$roiname, delete endif end function ad_set_ROI(nickname, iroi, p1, q1, p2, q2, enable) // set a ROI rectangle to the given coordinates string nickname variable iroi // 0...3 variable p1,q1,p2,q2 // rectangular coordinates of the new ROI (point scaling) variable enable // enable = 1; disable = 0 string roiname = "roi" + num2str(iroi + 1) string roikey dfref savedf = GetDataFolderDFR() setdatafolder $package_path setdatafolder $nickname svar controls wave xscale wave yscale variable minX = min(p1, p2) variable sizeX = max(p1, p2) - min(p1, p2) + 1 variable enableX = sizeX > 0 variable minY = min(q1, q2) variable sizeY = max(q1, q2) - min(q1, q2) + 1 variable enableY = sizeY > 0 roikey = "ROI" + num2str(iroi + 1) epics_set_num(StringByKey(roikey + "Enable", controls, "="), enable) if (enable) epics_set_num(StringByKey(roikey + "EnableX", controls, "="), enableX) if (enableX) epics_set_num(StringByKey(roikey + "MinX", controls, "="), minX) epics_set_num(StringByKey(roikey + "SizeX", controls, "="), sizeX) endif epics_set_num(StringByKey(roikey + "EnableY", controls, "="), enableY) if (enableY) epics_set_num(StringByKey(roikey + "MinY", controls, "="), minY) epics_set_num(StringByKey(roikey + "SizeY", controls, "="), sizeY) endif endif svar graphname = :view_image:prof_graphname ad_update_ROI(graphname, iroi) setdatafolder savedf end function add_roi_controls() PopupMenu pm_set_roi mode=0,value="ROI 1;ROI 2;ROI 3;ROI 4",title="Set ROI" PopupMenu pm_set_roi pos={400,0},bodyWidth=60,proc=PearlAreaLive#pmp_set_roi PopupMenu pm_set_roi help={"Set a detector ROI to the current cursor selection"} end static function pmp_set_roi(pa) : PopupMenuControl STRUCT WMPopupAction &pa switch( pa.eventCode ) case 2: // mouse up variable popNum = pa.popNum string imgname = StringFromList(0, ImageNameList(pa.win, ";")) wave /z image = ImageNameToWaveRef(pa.win, imgname) if (waveexists(image)) wave /z source = PearlAreaDisplay#get_source_image(image) if (waveexists(source)) dfref sourcedf = GetWavesDataFolderDFR(source) string nickname = GetDataFolder(0, sourcedf) ad_set_ROI(nickname, popNum - 1, pcsr(A, pa.win), qcsr(A, pa.win), pcsr(B, pa.win), qcsr(B, pa.win), 1) endif endif break case -1: // control being killed break endswitch return 0 End