369 lines
12 KiB
Igor
369 lines
12 KiB
Igor
#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
|