distro release 2.1.1
This commit is contained in:
@ -1,11 +1,11 @@
|
||||
#pragma rtGlobals=3 // Use modern global access method and strict wave access.
|
||||
#pragma version = 1.7
|
||||
#pragma version = 1.8
|
||||
#pragma IgorVersion = 6.2
|
||||
#pragma ModuleName = PearlAnglescanPanel
|
||||
#include "pearl-anglescan-process"
|
||||
#include "pearl-pmsco-import"
|
||||
|
||||
// copyright (c) 2018 Paul Scherrer Institut
|
||||
// copyright (c) 2018-20 Paul Scherrer Institut
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@ -29,7 +29,7 @@
|
||||
///
|
||||
/// @author matthias muntwiler, matthias.muntwiler@psi.ch
|
||||
///
|
||||
/// @copyright 2018 Paul Scherrer Institut @n
|
||||
/// @copyright 2018-20 Paul Scherrer Institut @n
|
||||
/// Licensed under the Apache License, Version 2.0 (the "License"); @n
|
||||
/// you may not use this file except in compliance with the License. @n
|
||||
/// You may obtain a copy of the License at
|
||||
@ -45,8 +45,6 @@
|
||||
static strconstant package_name = "pearl_anglescan_panel"
|
||||
/// data folder path
|
||||
static strconstant package_path = "root:packages:pearl_anglescan_panel:"
|
||||
/// semicolon-separated list of persistent variable, string, and wave names
|
||||
static strconstant prefs_objects = "theta_offset;tilt_offset;phi_offset;alpha_offset;crop_alpha_enable;crop_alpha_value;norm_alpha_enable;norm_alpha_mode;norm_alpha_smoothing;norm_phi_enable;norm_phi_mode;norm_phi_thetarange;norm_theta_enable;norm_theta_mode;norm_theta_smoothing;norm_thetaphi_enable;norm_thetaphi_mode;norm_theta_smoothing;output_folding;output_horizon;graph_mode;graph_projection;graph_colortable;graph_contrast;"
|
||||
|
||||
/// initialize package data once when the procedure is first loaded
|
||||
static function AfterCompiledHook()
|
||||
@ -82,19 +80,26 @@ static function init_package()
|
||||
|
||||
// configuration (persistent)
|
||||
string /g graphname = "graph_anglescan_panel"
|
||||
string /g prefs_objects = "prefs_objects;theta_offset;tilt_offset;phi_offset;alpha_offset;crop_enable;crop_alpha;crop_theta;"
|
||||
prefs_objects += "norm_alpha_enable;norm_alpha_mode;norm_alpha_smoothing;norm_phi_enable;norm_phi_mode;norm_phi_thetarange;"
|
||||
prefs_objects += "norm_theta_enable;norm_theta_mode;norm_theta_domain;norm_theta_smoothing;norm_thetaphi_enable;norm_thetaphi_mode;norm_thetaphi_smoothing;"
|
||||
prefs_objects += "output_folding;output_horizon;graph_mode;graph_projection;graph_colortable;graph_contrast;"
|
||||
|
||||
// recently used (persistent)
|
||||
variable /g theta_offset = 0
|
||||
variable /g tilt_offset = 0
|
||||
variable /g phi_offset = 0
|
||||
variable /g alpha_offset = 0
|
||||
variable /g crop_alpha_enable = 0
|
||||
variable /g crop_alpha_value = 25
|
||||
variable /g crop_enable = 0
|
||||
variable /g crop_alpha = 25
|
||||
variable /g crop_theta = 88
|
||||
string /g crop_rows = ""
|
||||
variable /g norm_alpha_enable = 0
|
||||
variable /g norm_alpha_mode = 4
|
||||
variable /g norm_alpha_smoothing = 0.25
|
||||
variable /g norm_theta_enable = 0
|
||||
variable /g norm_theta_mode = 4
|
||||
variable /g norm_theta_domain = 0
|
||||
variable /g norm_theta_smoothing = 0.25
|
||||
variable /g norm_thetaphi_enable = 0
|
||||
variable /g norm_thetaphi_mode = 4
|
||||
@ -136,6 +141,8 @@ end
|
||||
///
|
||||
static function save_prefs()
|
||||
dfref saveDF = GetDataFolderDFR()
|
||||
dfref df = $(package_path)
|
||||
svar /sdfr=df prefs_objects
|
||||
|
||||
string fullPath = SpecialDirPath("Packages", 0, 0, 0)
|
||||
fullPath += package_name
|
||||
@ -337,7 +344,7 @@ static function do_init_process(check)
|
||||
setscale /p x dimoffset(raw, 0) - alpha_offset, dimdelta(raw, 0), waveunits(raw, 0), process_data
|
||||
end
|
||||
|
||||
/// alpha-crop the process data.
|
||||
/// crop the process data.
|
||||
///
|
||||
/// @param[in] check select which output to generate (currently not used).
|
||||
/// @arg 0 (default) process data, don't calculate check waves.
|
||||
@ -348,7 +355,7 @@ end
|
||||
/// @arg 0 (default) apply this filter only if its global enable flag is set.
|
||||
/// @arg 1 apply this filter even if it is not enabled.
|
||||
///
|
||||
static function do_crop_alpha(check, [force])
|
||||
static function do_crop(check, [force])
|
||||
variable check
|
||||
variable force
|
||||
|
||||
@ -358,14 +365,80 @@ static function do_crop_alpha(check, [force])
|
||||
|
||||
dfref df = $(package_path)
|
||||
wave /sdfr=df process_data
|
||||
nvar /sdfr=df crop_alpha_enable
|
||||
nvar /sdfr=df crop_alpha_value
|
||||
wave /sdfr=df process_theta
|
||||
wave /sdfr=df process_tilt
|
||||
wave /sdfr=df process_phi
|
||||
nvar /sdfr=df crop_enable
|
||||
nvar /sdfr=df crop_alpha
|
||||
nvar /sdfr=df crop_theta
|
||||
svar /sdfr=df crop_rows
|
||||
|
||||
if ((force || crop_alpha_enable) && (crop_alpha_value > abs(dimdelta(process_data, 0))))
|
||||
crop_strip(process_data, -crop_alpha_value, +crop_alpha_value)
|
||||
if (force || crop_enable)
|
||||
|
||||
if (crop_alpha > abs(dimdelta(process_data, 0)))
|
||||
crop_strip(process_data, -crop_alpha, +crop_alpha)
|
||||
endif
|
||||
|
||||
if ((crop_theta >= 10) && (crop_theta < 90))
|
||||
crop_strip_theta(process_data, 0, crop_theta, process_theta, process_tilt, process_phi)
|
||||
endif
|
||||
|
||||
if (strlen(crop_rows) > 0)
|
||||
delete_rows(crop_rows, process_data, process_theta, process_tilt, process_phi)
|
||||
endif
|
||||
endif
|
||||
end
|
||||
|
||||
/// delete individual rows from the data strip
|
||||
///
|
||||
/// @param[in] rows comma-separated list of row indices or ranges.
|
||||
/// ranges are specified by joining the start and end index with a hyphen, e.g. 24-46.
|
||||
/// the list does not need to be ordered.
|
||||
/// @param[in,out] data 2D data
|
||||
/// the original wave is modified.
|
||||
/// @param[in,out] theta theta positions along Y dimension of data.
|
||||
/// the original wave is modified.
|
||||
/// @param[in,out] tilt tilt positions along Y dimension of data
|
||||
/// the original wave is modified.
|
||||
/// @param[in,out] phi phi positions along Y dimension of data
|
||||
/// the original wave is modified.
|
||||
///
|
||||
static function delete_rows(rows, data, theta, tilt, phi)
|
||||
string rows
|
||||
wave data
|
||||
wave theta
|
||||
wave tilt
|
||||
wave phi
|
||||
|
||||
make /n=(numpnts(theta)) /i /free idx
|
||||
idx = p
|
||||
variable nrows = ItemsInList(rows, ",")
|
||||
variable irow
|
||||
string srow
|
||||
variable q1, q2
|
||||
for (irow = 0; irow < nrows; irow += 1)
|
||||
srow = StringFromList(irow, rows, ",")
|
||||
q1 = str2num(StringFromList(0, srow, "-"))
|
||||
q2 = str2num(StringFromList(1, srow, "-"))
|
||||
if (numtype(q2))
|
||||
q2 = q1
|
||||
endif
|
||||
if (q1 <= q2)
|
||||
idx[q1,q2] = -1
|
||||
endif
|
||||
endfor
|
||||
extract /free idx, idx, idx >= 0
|
||||
variable nx = dimsize(data, 0)
|
||||
variable ny = numpnts(idx)
|
||||
theta = theta[idx]
|
||||
tilt = tilt[idx]
|
||||
phi = phi[idx]
|
||||
redimension /n=(ny) theta, tilt, phi
|
||||
duplicate /free data, data_copy
|
||||
redimension /n=(nx,ny) data
|
||||
data = data_copy[p][idx[q]]
|
||||
end
|
||||
|
||||
/// alpha-normalize the process data.
|
||||
///
|
||||
/// @param[in] check select which output to generate.
|
||||
@ -475,12 +548,17 @@ static function do_norm_theta(check, [force])
|
||||
wave /sdfr=df process_theta
|
||||
nvar /sdfr=df norm_theta_enable
|
||||
nvar /sdfr=df norm_theta_mode
|
||||
nvar /sdfr=df norm_theta_domain
|
||||
nvar /sdfr=df norm_theta_smoothing
|
||||
|
||||
if (force || norm_theta_enable)
|
||||
dfref temp_df = newfreedatafolder()
|
||||
setdatafolder temp_df
|
||||
normalize_strip_theta(process_data, process_theta, smooth_method=norm_theta_mode, smooth_factor=norm_theta_smoothing, check=check)
|
||||
if (norm_theta_domain==1)
|
||||
normalize_strip_theta_scans(process_data, process_theta, smooth_method=norm_theta_mode, smooth_factor=norm_theta_smoothing, check=check)
|
||||
else
|
||||
normalize_strip_theta(process_data, process_theta, smooth_method=norm_theta_mode, smooth_factor=norm_theta_smoothing, check=check)
|
||||
endif
|
||||
if (check)
|
||||
wave check_dist
|
||||
wave check_smoo
|
||||
@ -554,7 +632,7 @@ function asp_calculate_output()
|
||||
nvar horizon=output_horizon
|
||||
|
||||
do_init_process(0)
|
||||
do_crop_alpha(0)
|
||||
do_crop(0)
|
||||
do_norm_alpha(0)
|
||||
do_norm_phi(0)
|
||||
do_norm_theta(0)
|
||||
@ -757,62 +835,62 @@ end
|
||||
|
||||
static function check_norm_alpha()
|
||||
do_init_process(0)
|
||||
do_crop_alpha(0)
|
||||
do_crop(0)
|
||||
do_norm_alpha(2, force=1)
|
||||
asp_display_dist_check(1, 0)
|
||||
end
|
||||
|
||||
static function check_norm_phi()
|
||||
do_init_process(0)
|
||||
do_crop_alpha(0)
|
||||
do_crop(0)
|
||||
do_norm_phi(2, force=1)
|
||||
asp_display_dist_check(0, 1)
|
||||
end
|
||||
|
||||
static function check_norm_theta()
|
||||
do_init_process(0)
|
||||
do_crop_alpha(0)
|
||||
do_crop(0)
|
||||
do_norm_theta(2, force=1)
|
||||
asp_display_dist_check(0, 1)
|
||||
end
|
||||
|
||||
static function check_norm_thetaphi()
|
||||
do_init_process(0)
|
||||
do_crop_alpha(0)
|
||||
do_crop(0)
|
||||
do_norm_thetaphi(2, force=1)
|
||||
asp_display_dist_check(0, 1)
|
||||
end
|
||||
|
||||
static function preview_crop_alpha()
|
||||
static function preview_crop()
|
||||
do_init_process(0)
|
||||
do_crop_alpha(0, force=1)
|
||||
do_crop(0, force=1)
|
||||
asp_display_previews()
|
||||
end
|
||||
|
||||
static function preview_norm_alpha()
|
||||
do_init_process(0)
|
||||
do_crop_alpha(0)
|
||||
do_crop(0)
|
||||
do_norm_alpha(1, force=1)
|
||||
asp_display_previews()
|
||||
end
|
||||
|
||||
static function preview_norm_phi()
|
||||
do_init_process(0)
|
||||
do_crop_alpha(0)
|
||||
do_crop(0)
|
||||
do_norm_phi(1, force=1)
|
||||
asp_display_previews()
|
||||
end
|
||||
|
||||
static function preview_norm_theta()
|
||||
do_init_process(0)
|
||||
do_crop_alpha(0)
|
||||
do_crop(0)
|
||||
do_norm_theta(1, force=1)
|
||||
asp_display_previews()
|
||||
end
|
||||
|
||||
static function preview_norm_thetaphi()
|
||||
do_init_process(0)
|
||||
do_crop_alpha(0)
|
||||
do_crop(0)
|
||||
do_norm_thetaphi(1, force=1)
|
||||
asp_display_previews()
|
||||
end
|
||||
@ -828,7 +906,7 @@ function asp_show_panel()
|
||||
return 0
|
||||
endif
|
||||
|
||||
NewPanel /K=1 /N=anglescan_panel /W=(200,100,479,854) as "angle scan processing"
|
||||
NewPanel /K=1 /N=anglescan_panel /W=(200,50,480,874) as "angle scan processing"
|
||||
panel_name = s_name
|
||||
|
||||
GroupBox gb_source, title="data source"
|
||||
@ -857,15 +935,21 @@ function asp_show_panel()
|
||||
Button b_load_prefs, size={80,20},proc=PearlAnglescanPanel#bp_load_prefs,title="load prefs"
|
||||
Button b_load_prefs, help={"load settings from preferences."}
|
||||
|
||||
GroupBox gb_crop_alpha, title="crop alpha"
|
||||
CheckBox cb_crop_alpha_enable, size={50,14}, title="enable"
|
||||
CheckBox cb_crop_alpha_enable, help={"enable cropping at +/- alpha"}
|
||||
CheckBox cb_crop_alpha_enable,variable= root:packages:pearl_anglescan_panel:crop_alpha_enable
|
||||
SetVariable sv_crop_alpha_value, size={90,16},bodyWidth=60,title="angle"
|
||||
SetVariable sv_crop_alpha_value,limits={0,30,1},value= root:packages:pearl_anglescan_panel:crop_alpha_value
|
||||
SetVariable sv_crop_alpha_value, help={"alpha (detection angle) cropping angle"}
|
||||
Button b_crop_alpha_preview, size={80,20},proc=PearlAnglescanPanel#bp_crop_alpha_preview,title="preview"
|
||||
Button b_crop_alpha_preview, help={"show a preview of the cropped dataset."}
|
||||
GroupBox gb_crop, title="crop and delete"
|
||||
CheckBox cb_crop_enable, size={50,14}, title="enable"
|
||||
CheckBox cb_crop_enable, help={"crop at +/-alpha and +theta, delete arbitrary rows"}
|
||||
CheckBox cb_crop_enable, variable= root:packages:pearl_anglescan_panel:crop_enable
|
||||
SetVariable sv_crop_alpha, size={90,16},bodyWidth=60,title="alpha"
|
||||
SetVariable sv_crop_alpha, limits={0,30,1},value= root:packages:pearl_anglescan_panel:crop_alpha
|
||||
SetVariable sv_crop_alpha, help={"alpha (detection angle) cropping angle (positive boundary), relative to normal emission"}
|
||||
SetVariable sv_crop_theta, size={90,16},bodyWidth=60,title="theta"
|
||||
SetVariable sv_crop_theta, limits={10,90,1},value= root:packages:pearl_anglescan_panel:crop_theta
|
||||
SetVariable sv_crop_theta, help={"theta (polar angle) upper limit, relative to normal emission"}
|
||||
SetVariable sv_crop_rows, size={200,16},bodyWidth=160,title="rows"
|
||||
SetVariable sv_crop_rows, limits={10,90,1},value= root:packages:pearl_anglescan_panel:crop_rows
|
||||
SetVariable sv_crop_rows, help={"rows to delete from the raw data. comma-separated point indices, hyphen for range."}
|
||||
Button b_crop_preview, size={80,20},proc=PearlAnglescanPanel#bp_crop_preview,title="preview"
|
||||
Button b_crop_preview, help={"show a preview of the cropped dataset."}
|
||||
|
||||
GroupBox gb_norm_alpha, title="normalize alpha"
|
||||
CheckBox cb_norm_alpha_enable, size={50,14}, title="enable"
|
||||
@ -898,6 +982,9 @@ function asp_show_panel()
|
||||
CheckBox cb_norm_theta_enable, size={50,14},title="enable"
|
||||
CheckBox cb_norm_theta_enable, variable= root:packages:pearl_anglescan_panel:norm_theta_enable
|
||||
CheckBox cb_norm_theta_enable, help={"enable normalization of the theta distribution (integrated over phi)"}
|
||||
PopupMenu pm_norm_theta_domain, size={138,21}, bodyWidth=100, proc=PearlAnglescanPanel#pmp_norm_theta_domain, title="domain"
|
||||
PopupMenu pm_norm_theta_domain, mode=5, popvalue="loess", value= #"\"global;scans;\""
|
||||
PopupMenu pm_norm_theta_domain, help={"smoothing domain: global or individual scans. use global unless there is a stronga or irregular phi variation."}
|
||||
PopupMenu pm_norm_theta_mode, size={138,21},bodyWidth=100,proc=PearlAnglescanPanel#pmp_norm_theta_mode,title="method"
|
||||
PopupMenu pm_norm_theta_mode,mode=5,popvalue="loess",value= #"\"none;binomial;boxcar;polynomial;loess;\""
|
||||
PopupMenu pm_norm_theta_mode, help={"theta normalization method. recommended: loess"}
|
||||
@ -1014,15 +1101,19 @@ static function arrange_controls()
|
||||
GroupBox gb_offsets, size={272,gb_ht}
|
||||
|
||||
gb_top += gb_ht + gb_space
|
||||
GroupBox gb_crop_alpha,pos={4,gb_top}
|
||||
GroupBox gb_crop,pos={4,gb_top}
|
||||
gb_ht = gb_internal_top
|
||||
CheckBox cb_crop_alpha_enable,pos={73, gb_top + gb_ht + cb_adj},size={50,14}
|
||||
CheckBox cb_crop_enable,pos={73, gb_top + gb_ht + cb_adj},size={50,14}
|
||||
gb_ht += line_space
|
||||
SetVariable sv_crop_alpha_value,pos={44, gb_top + gb_ht + sv_adj},size={90,16}
|
||||
Button b_crop_alpha_preview,pos={186, gb_top + gb_ht + b_adj},size={80,20}
|
||||
SetVariable sv_crop_alpha, pos={44, gb_top + gb_ht + sv_adj}, size={90,16}
|
||||
Button b_crop_preview,pos={186, gb_top + gb_ht + b_adj},size={80,20}
|
||||
gb_ht += line_space
|
||||
SetVariable sv_crop_theta, pos={44, gb_top + gb_ht + sv_adj}, size={90,16}
|
||||
gb_ht += line_space
|
||||
SetVariable sv_crop_rows, pos={44, gb_top + gb_ht + sv_adj}, size={190,16}
|
||||
gb_ht += line_space
|
||||
gb_ht += gb_internal_bot
|
||||
GroupBox gb_crop_alpha, size={272,gb_ht}
|
||||
GroupBox gb_crop, size={272,gb_ht}
|
||||
|
||||
gb_top += gb_ht + gb_space
|
||||
GroupBox gb_norm_alpha,pos={4,gb_top}
|
||||
@ -1055,12 +1146,14 @@ static function arrange_controls()
|
||||
gb_ht = gb_internal_top
|
||||
CheckBox cb_norm_theta_enable,pos={73, gb_top + gb_ht + cb_adj},size={50,14}
|
||||
gb_ht += line_space
|
||||
PopupMenu pm_norm_theta_mode,pos={35, gb_top + gb_ht + pm_adj},size={138,21}
|
||||
PopupMenu pm_norm_theta_domain, pos={35, gb_top + gb_ht + pm_adj}, size={138,21}
|
||||
Button b_norm_theta_check,pos={186, gb_top + gb_ht + b_adj},size={80,20}
|
||||
gb_ht += line_space
|
||||
SetVariable sv_norm_theta_smoothing,pos={21, gb_top + gb_ht + sv_adj},size={112,16}
|
||||
PopupMenu pm_norm_theta_mode,pos={35, gb_top + gb_ht + pm_adj},size={138,21}
|
||||
Button b_norm_theta_preview,pos={186, gb_top + gb_ht + b_adj},size={80,20}
|
||||
gb_ht += line_space
|
||||
SetVariable sv_norm_theta_smoothing,pos={21, gb_top + gb_ht + sv_adj},size={112,16}
|
||||
gb_ht += line_space
|
||||
gb_ht += gb_internal_bot
|
||||
GroupBox gb_norm_theta, size={272,gb_ht}
|
||||
|
||||
@ -1122,6 +1215,9 @@ static function update_menus()
|
||||
nvar /sdfr=df norm_alpha_mode
|
||||
m = norm_alpha_mode + 1
|
||||
PopupMenu pm_norm_alpha_mode win=$panel_name, mode=m
|
||||
nvar /sdfr=df norm_theta_domain
|
||||
m = norm_theta_domain + 1
|
||||
PopupMenu pm_norm_theta_domain win=$panel_name, mode=m
|
||||
nvar /sdfr=df norm_theta_mode
|
||||
m = norm_theta_mode + 1
|
||||
PopupMenu pm_norm_theta_mode win=$panel_name, mode=m
|
||||
@ -1271,12 +1367,12 @@ static function bp_norm_thetaphi_check(ba) : ButtonControl
|
||||
return 0
|
||||
End
|
||||
|
||||
static function bp_crop_alpha_preview(ba) : ButtonControl
|
||||
static function bp_crop_preview(ba) : ButtonControl
|
||||
STRUCT WMButtonAction &ba
|
||||
|
||||
switch( ba.eventCode )
|
||||
case 2: // mouse up
|
||||
preview_crop_alpha()
|
||||
preview_crop()
|
||||
break
|
||||
case -1: // control being killed
|
||||
break
|
||||
@ -1462,6 +1558,22 @@ static function pmp_norm_alpha_mode(pa) : PopupMenuControl
|
||||
return 0
|
||||
End
|
||||
|
||||
static function pmp_norm_theta_domain(pa) : PopupMenuControl
|
||||
STRUCT WMPopupAction &pa
|
||||
|
||||
switch( pa.eventCode )
|
||||
case 2: // mouse up
|
||||
dfref df = $(package_path)
|
||||
nvar /sdfr=df norm_theta_domain
|
||||
norm_theta_domain = pa.popNum - 1
|
||||
break
|
||||
case -1: // control being killed
|
||||
break
|
||||
endswitch
|
||||
|
||||
return 0
|
||||
End
|
||||
|
||||
static function pmp_norm_theta_mode(pa) : PopupMenuControl
|
||||
STRUCT WMPopupAction &pa
|
||||
|
||||
|
@ -515,6 +515,88 @@ function normalize_strip_thetaphi(strip, theta, phi, [theta_offset, smooth_metho
|
||||
endif
|
||||
end
|
||||
|
||||
/// divide the strip piecewise by a smooth polar distribution.
|
||||
///
|
||||
/// @warning experimental. this function is under development.
|
||||
///
|
||||
///
|
||||
function normalize_strip_theta_scans(strip, theta, [theta_offset, smooth_method, smooth_factor, check])
|
||||
wave strip
|
||||
wave theta
|
||||
variable theta_offset
|
||||
variable smooth_method
|
||||
variable smooth_factor
|
||||
variable check
|
||||
|
||||
if (ParamIsDefault(check))
|
||||
check = 0
|
||||
endif
|
||||
if (ParamIsDefault(theta_offset))
|
||||
theta_offset = 0
|
||||
endif
|
||||
if (ParamIsDefault(smooth_method))
|
||||
smooth_method = 4
|
||||
endif
|
||||
if (ParamIsDefault(smooth_factor))
|
||||
smooth_factor = 0.5
|
||||
endif
|
||||
|
||||
// average over analyser angles
|
||||
wave dist = ad_profile_y(strip, -inf, inf, "")
|
||||
|
||||
// smooth distribution function
|
||||
duplicate /free dist, dist_smoo
|
||||
duplicate /free theta, theta_int
|
||||
theta_int = theta - theta_offset
|
||||
setscale /p x theta_int[0], theta_int[1] - theta_int[0], waveunits(theta,-1), dist, dist_smoo
|
||||
|
||||
// analyse scanning scheme
|
||||
duplicate /free theta_int, d1_theta, d2_theta
|
||||
Differentiate /METH=2 theta_int /D=d1_theta
|
||||
Differentiate /METH=2 d1_theta /D=d2_theta
|
||||
d2_theta = abs(d2_theta)
|
||||
make /free w_levels
|
||||
FindLevels /edge=1 /p /q /d=w_levels d2_theta, 0.1
|
||||
if (v_flag != 1)
|
||||
abort "unrecognized scanning scheme"
|
||||
endif
|
||||
w_levels = ceil(w_levels)
|
||||
InsertPoints 0, 1, w_levels
|
||||
w_levels[0] = 0
|
||||
InsertPoints numpnts(w_levels), 1, w_levels
|
||||
w_levels[numpnts(w_levels)-1] = numpnts(theta_int)
|
||||
|
||||
variable n_scans = numpnts(w_levels) - 1
|
||||
variable i_scan
|
||||
variable p1, p2
|
||||
for (i_scan = 0; i_scan < n_scans; i_scan += 1)
|
||||
p1 = w_levels[i_scan]
|
||||
p2 = w_levels[i_scan+1] - 1
|
||||
duplicate /free /r=[p1, p2] dist, dist_piece, smooth_piece
|
||||
duplicate /free /r=[p1, p2] theta_int, theta_piece
|
||||
switch(smooth_method)
|
||||
case 4:
|
||||
loess /dest=smooth_piece /smth=(smooth_factor) srcWave=dist_piece, factors={theta_piece}
|
||||
break
|
||||
default:
|
||||
abort "smooth method not supported"
|
||||
endswitch
|
||||
dist_smoo[p1, p2] = smooth_piece[p - p1]
|
||||
endfor
|
||||
|
||||
// divide
|
||||
if (check != 2)
|
||||
strip /= dist_smoo[q]
|
||||
endif
|
||||
|
||||
// check
|
||||
if (check)
|
||||
duplicate /o dist, check_dist
|
||||
duplicate /o dist_smoo, check_smoo
|
||||
setscale /p x dimoffset(dist,0), dimdelta(dist,0), waveunits(dist,0), check_dist, check_smoo
|
||||
endif
|
||||
end
|
||||
|
||||
/// divide the strip by a two-dimensional normalization function.
|
||||
///
|
||||
/// @warning experimental. this function is under development.
|
||||
@ -606,6 +688,42 @@ function crop_strip(strip, xlo, xhi)
|
||||
setscale /i x xlo, xhi, waveunits(strip, 0), strip
|
||||
end
|
||||
|
||||
/// crop a strip in theta.
|
||||
///
|
||||
/// the strip is cropped in place, data outside the region of interest is lost.
|
||||
///
|
||||
/// @param[in,out] strip 2D data, X-axis = analyser angle, Y-axis = arbitrary manipulator scan
|
||||
/// @param[in] ylo lowest polar angle to keep (will be rounded to nearest existing point)
|
||||
/// @param[in] yhi highest polar angle to keep (will be rounded to nearest existing point)
|
||||
/// @param[in,out] theta polar angle along the Y dimension of strip.
|
||||
/// this wave is modified: cropped rows are deleted.
|
||||
/// @param[in,out] tilt tilt angle along the Y dimension of strip.
|
||||
/// this wave is modified: cropped rows are deleted.
|
||||
/// @param[in,out] phi azimuthal angle along the Y dimension of strip.
|
||||
/// this wave is modified: cropped rows are deleted.
|
||||
///
|
||||
function crop_strip_theta(strip, theta_lo, theta_hi, theta, tilt, phi)
|
||||
wave strip
|
||||
variable theta_lo
|
||||
variable theta_hi
|
||||
wave theta
|
||||
wave tilt
|
||||
wave phi
|
||||
|
||||
extract /indx /free theta, idx, (theta >= theta_lo) && (theta <= theta_hi)
|
||||
variable nx = dimsize(strip, 0)
|
||||
variable ny = numpnts(idx)
|
||||
|
||||
theta = theta[idx]
|
||||
tilt = tilt[idx]
|
||||
phi = phi[idx]
|
||||
redimension /n=(ny) theta, tilt, phi
|
||||
|
||||
duplicate /free strip, strip_copy
|
||||
redimension /n=(nx,ny) strip
|
||||
strip = strip_copy[p][idx[q]]
|
||||
end
|
||||
|
||||
/// create a pizza plot from a measured (energy-integrated) data strip
|
||||
///
|
||||
/// accepts angle-scan data as returned by adh5_load_reduced(),
|
||||
@ -3198,3 +3316,37 @@ function set_contrast(pcmin, pcmax, [graphname, colortable])
|
||||
|
||||
setdatafolder save_df
|
||||
end
|
||||
|
||||
/// k-space mapping of 2D angle-energy distribution (scienta image)
|
||||
///
|
||||
/// courtesy of F. Matsui
|
||||
///
|
||||
/// @param inwave 2D wave, x = kinetic energy (eV), y = polar angle (deg)
|
||||
/// note: the kinetic energy is with reference to the vacuum level at the sample.
|
||||
/// if the work functions of the analyser and the sample differ:
|
||||
/// Ekin,sample = Ekin,analyser + WFanalyser - WFsample
|
||||
/// where WFanalyser = Ephot - EFermi
|
||||
///
|
||||
/// @return the output wave has the name of the input wave with the suffix "_k".
|
||||
///
|
||||
Function AngleToK(inwave)
|
||||
Wave inwave
|
||||
String newname = NameofWave(inwave)+"_k"
|
||||
Duplicate/O inwave, $newname
|
||||
Wave outwave = $newname
|
||||
Variable rows,columns,xdelta,xoffset,ydelta,yoffset,kmin,kmax,Emax
|
||||
// inwave parameters
|
||||
rows = DimSize(inwave,0)
|
||||
columns = DimSize(inwave,1)
|
||||
xdelta = DimDelta(inwave,0)
|
||||
xoffset = DimOffset(inwave,0)
|
||||
ydelta = DimDelta(inwave,1)
|
||||
yoffset = DimOffset(inwave,1)
|
||||
Emax= xoffset + xdelta*(rows-1)
|
||||
kmin = 0.5123*sqrt(Emax)*sin(pi/180*(yoffset)) // calculate the k boundaries
|
||||
kmax = 0.5123*sqrt(Emax)*sin(pi/180*(yoffset+(columns-1)*ydelta))
|
||||
SetScale/I y kmin,kmax,"Ang^-1", outwave
|
||||
// scale the y axis
|
||||
outwave = interp2D(inwave, x, 180/pi*asin(y/ (0.5123*sqrt(x)))) // recalculate to k
|
||||
outwave = (NumType(outwave)==2) ? 0 : outwave // replace NaNs (optional)
|
||||
End
|
||||
|
@ -805,8 +805,13 @@ end
|
||||
|
||||
static function epics_disconnect()
|
||||
dfref savedf = GetDataFolderDFR()
|
||||
setdatafolder $(package_path)
|
||||
|
||||
|
||||
if (DataFolderExists(package_path))
|
||||
SetDataFolder $(package_path)
|
||||
else
|
||||
return nan
|
||||
endif
|
||||
|
||||
nvar connected
|
||||
if (connected)
|
||||
connected = 0
|
||||
|
@ -314,6 +314,59 @@ function /s ad_display_profiles(image, [filter])
|
||||
return graphname
|
||||
end
|
||||
|
||||
/// add an overlay on top of the displayed image
|
||||
///
|
||||
/// the function creates the overlay wave and returns it as function result.
|
||||
/// the name of the wave is "view_overlay" and is created in the same folder as the "view_image" wave.
|
||||
///
|
||||
/// @param image image wave that identifies the profiles window.
|
||||
///
|
||||
/// @return overlay overlay wave.
|
||||
/// same dimensions and scales as image, but unsigned binary.
|
||||
/// pixels that are 0 are overlaid with semi-transparent color.
|
||||
/// other pixels should be 64 (igor's mask convention).
|
||||
///
|
||||
function /wave ad_add_overlay(image, [rgba])
|
||||
wave image
|
||||
string rgba
|
||||
|
||||
if (ParamIsDefault(rgba))
|
||||
rgba = "65535,65532,16385,32767"
|
||||
elseif (ItemsInList(rgba, ",") == 3)
|
||||
rgba += ",32767"
|
||||
endif
|
||||
|
||||
dfref savedf = GetDataFolderDFR()
|
||||
wave view_image = get_view_image(image)
|
||||
dfref viewdf = GetWavesDataFolderDFR(view_image)
|
||||
svar /sdfr=viewdf graphname = prof_graphname
|
||||
setdatafolder viewdf
|
||||
|
||||
string overlayname = "view_overlay"
|
||||
duplicate /o image, $overlayname /wave=overlay
|
||||
redimension /b/u overlay
|
||||
overlay = 64
|
||||
|
||||
string imagenames = ImageNameList(graphname, ";")
|
||||
if (whichlistItem(overlayname, imagenames, ";") < 0)
|
||||
AppendImage /w=$graphname $overlayname
|
||||
rgba = replacestring("(", rgba, "")
|
||||
rgba = replacestring(")", rgba, "")
|
||||
variable rr = str2num(StringFromList(0, rgba, ","))
|
||||
variable gg = str2num(StringFromList(1, rgba, ","))
|
||||
variable bb = str2num(StringFromList(2, rgba, ","))
|
||||
variable aa = str2num(StringFromList(3, rgba, ","))
|
||||
#if IgorVersion() >= 8
|
||||
ModifyImage /w=$graphname $overlayname explicit=1,eval={0,rr,gg,bb,aa},eval={255,-1,-1,-1}
|
||||
#else
|
||||
ModifyImage /w=$graphname $overlayname explicit=1,eval={0,rr,gg,bb},eval={255,-1,-1,-1}
|
||||
#endif
|
||||
endif
|
||||
|
||||
setdatafolder savedf
|
||||
return overlay
|
||||
end
|
||||
|
||||
/// update a profiles graph with new data.
|
||||
///
|
||||
/// @param image wave which contains the image data.
|
||||
@ -333,7 +386,12 @@ function ad_update_profiles(image)
|
||||
// data structures
|
||||
string viewname = "view_image"
|
||||
duplicate /o image, $viewname /wave=view
|
||||
|
||||
string overlayname = "view_overlay"
|
||||
wave /z overlay = $overlayname
|
||||
if (waveexists(overlay))
|
||||
redimension /n=(dimsize(view,0), dimsize(view,1)) overlay
|
||||
endif
|
||||
|
||||
// data processing
|
||||
svar view_filter
|
||||
svar view_filter_options
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "pearl-epics" // EPICS access under Igor
|
||||
#include "pearl-arpes-scans" // run ARPES scans under Igor
|
||||
#include "pearl-sample-tracker" // live tracking and adjustment of sample position
|
||||
#include "pearl-scienta-countrate"
|
||||
#endif
|
||||
|
||||
/// @file
|
||||
|
@ -94,24 +94,25 @@ static function init_package()
|
||||
SetDataFolder savefolder
|
||||
end
|
||||
|
||||
/// save persistent package data to the preferences file.
|
||||
///
|
||||
/// this function is called when the user clicks the corresponding button.
|
||||
/// the data saved in the file are: data file path, attributes filter
|
||||
///
|
||||
static function save_prefs()
|
||||
// saves persistent package data to the preferences file
|
||||
// the data saved in the file are: data file path, attributes filter
|
||||
dfref saveDF = GetDataFolderDFR()
|
||||
|
||||
string fullPath = SpecialDirPath("Packages", 0, 0, 0)
|
||||
fullPath += package_name
|
||||
NewPath/O/C/Q tempPackagePrefsPath, fullPath
|
||||
fullPath += ":preferences.pxp"
|
||||
|
||||
SetDataFolder root:packages
|
||||
SetDataFolder $package_name
|
||||
string objects = "attr_filter;attr_filter_summary;s_filepath;s_hdf_options;s_reduction_params;s_preview_pvs"
|
||||
SaveData /O /Q /J=objects fullPath
|
||||
|
||||
KillPath/Z tempPackagePrefsPath
|
||||
|
||||
SetDataFolder saveDF
|
||||
dfref df = $package_path
|
||||
if (DataFolderRefStatus(df) == 1)
|
||||
string fullPath = SpecialDirPath("Packages", 0, 0, 0)
|
||||
fullPath += package_name
|
||||
NewPath/O/C/Q tempPackagePrefsPath, fullPath
|
||||
fullPath += ":preferences.pxp"
|
||||
SetDataFolder df
|
||||
string objects = "attr_filter;attr_filter_summary;s_filepath;s_hdf_options;s_reduction_params;s_preview_pvs"
|
||||
SaveData /O /Q /J=objects fullPath
|
||||
KillPath/Z tempPackagePrefsPath
|
||||
endif
|
||||
SetDataFolder saveDF
|
||||
end
|
||||
|
||||
static function load_prefs()
|
||||
|
@ -272,14 +272,14 @@ function elog_init_pearl_templates()
|
||||
|
||||
// attributes (persistent)
|
||||
// available attributes
|
||||
string /g attributes = "author;project;sample;source;task;technique;file;valid;"
|
||||
string /g attributes = "author;project;p-group;sample;source;task;technique;file;valid;"
|
||||
// controls corresponding to attributes
|
||||
// prefix determines the control type: sv_ = setvariable (string), pm_ = popup menu, cb = check box
|
||||
string /g controls = "sv_author;sv_project;sv_sample;pm_source;pm_task;pm_technique;sv_file;cb_valid;"
|
||||
string /g controls = "sv_author;sv_project;sv_pgroup;sv_sample;pm_source;pm_task;pm_technique;sv_file;cb_valid;"
|
||||
// attributes with fixed options, value item declares the options string
|
||||
string /g options = "source=sources;task=tasks;technique=techniques"
|
||||
// attributes which must be defined
|
||||
string /g required_attributes = "author;project;sample;source;task;technique;valid"
|
||||
string /g required_attributes = "author;project;p-group;sample;source;task;technique;valid"
|
||||
|
||||
// option lists
|
||||
string /g sources = "Manual Entry;PShell;Scienta Data;SScan Data;Prosilica Data;OTF Data;Beamline Status;LEED Data;QMS Data;Matrix Data;Igor Pro;Other"
|
||||
@ -292,10 +292,10 @@ function elog_init_pearl_templates()
|
||||
|
||||
// attributes (persistent)
|
||||
// available attributes
|
||||
string /g attributes = "author;project;sample;program;revision;machine;job;experiment;source path;result path;valid"
|
||||
string /g attributes = "author;project;p-group;sample;program;revision;machine;job;experiment;source path;result path;valid"
|
||||
// controls corresponding to attributes
|
||||
// prefix determines the control type: sv_ = setvariable (string), pm_ = popup menu, cb = check box
|
||||
string /g controls = "sv_author;sv_project;sv_sample;pm_program;sv_revision;pm_machine;sv_job;sv_experiment;sv_sourcepath;sv_resultpath;cb_valid"
|
||||
string /g controls = "sv_author;sv_project;sv_pgroup;sv_sample;pm_program;sv_revision;pm_machine;sv_job;sv_experiment;sv_sourcepath;sv_resultpath;cb_valid"
|
||||
// attributes with fixed options, value item declares the options string
|
||||
string /g options = "program=programs;machine=machines"
|
||||
// attributes which must be defined
|
||||
@ -322,7 +322,7 @@ function elog_init_pearl_templates()
|
||||
|
||||
// option lists
|
||||
string /g types = "Installation;Repair;Maintenance;Test;Commissioning;Bakeout;Incident;Cool-down;Warm-up;Storage;Other"
|
||||
string /g systems = "Vacuum;Control System;BL;XA;XP;SA;SP;T;LL;Monochromator;Carving;Scienta;STM;PC-Scienta;PC-Matrix;PC-Console;PC-Console-Win;PC-XP;EPS;LAC;Desiccator"
|
||||
string /g systems = "Vacuum;Control System;BL;XA;XP;SA;SP;T;LL;Monochromator;Carving;Scienta;STM;PC-Scienta;PC-Matrix;PC-Console;PC-Console-Win;PC-XP;EPS;LAC;Desiccator;Other"
|
||||
string /g sources = "Manual Entry;PShell;Scienta Data;SScan Data;Prosilica Data;OTF Data;Beamline Status;LEED Data;QMS Data;Matrix Data;Igor Pro;Other"
|
||||
|
||||
setdatafolder savedf
|
||||
@ -1298,7 +1298,8 @@ function /s PearlElogPanel(logbook)
|
||||
break
|
||||
endswitch
|
||||
endfor
|
||||
|
||||
ypos = max(ypos, 80)
|
||||
|
||||
TitleBox t_attach, win=$win_name, pos={308,5}, size={70,14}, title="Attachments", frame=0
|
||||
height = ypos - 21 - 4
|
||||
ListBox lb_attach, win=$win_name, pos={308,21}, size={264,height}
|
||||
@ -1819,6 +1820,12 @@ static function /s set_panel_attributes(windowname, attributes, [clear])
|
||||
endif
|
||||
|
||||
string path
|
||||
|
||||
string logbook = GetUserData(windowname, "", "logbook")
|
||||
dfref df_persistent = get_elog_df(logbook, kdfPersistent)
|
||||
string persistent_path = GetDataFolder(1, df_persistent)
|
||||
svar /sdfr=df_persistent options
|
||||
string options_path
|
||||
|
||||
string controls = ControlNameList(windowname, ";")
|
||||
string control
|
||||
@ -1845,7 +1852,12 @@ static function /s set_panel_attributes(windowname, attributes, [clear])
|
||||
endif
|
||||
break
|
||||
case 3: // popupmenu
|
||||
PopupMenu $control, popvalue=value, win=$windowname
|
||||
options_path = persistent_path + StringByKey(attribute, options, "=", ";")
|
||||
svar values = $options_path
|
||||
numval = WhichListItem(value, values, ";") + 1
|
||||
if (numval >= 1)
|
||||
PopupMenu $control, mode=numval, win=$windowname
|
||||
endif
|
||||
break
|
||||
case 5: // setvariable
|
||||
SetVariable /z $control, value= _STR:value, win=$windowname
|
||||
|
@ -893,3 +893,23 @@ function FermiGaussConv(pw, yw, xw) : FitFunc
|
||||
|
||||
yw = pw[2] * resultwave(xw[p] - pw[3]) + pw[0] + pw[1] * xw[p]
|
||||
end
|
||||
|
||||
|
||||
/// calculate the shirley background
|
||||
///
|
||||
///
|
||||
function ShirleyBG(w, bg, p1, p2)
|
||||
wave w
|
||||
wave bg
|
||||
variable p1, p2
|
||||
|
||||
duplicate /o w, bg
|
||||
integrate /meth=1 w /d=bg
|
||||
|
||||
variable bg1 = bg[p1]
|
||||
variable bg2 = bg[p2]
|
||||
bg -= bg1
|
||||
bg /= bg2 - bg1
|
||||
bg *= w[p2] - w[p1]
|
||||
bg += w[p1]
|
||||
end
|
||||
|
@ -36,12 +36,14 @@ menu "PEARL"
|
||||
help = {"Display preview panel with latest image from Scienta", "Requires ARPES package and EPICS XOP"}
|
||||
PearlMenuEnableFunc("ast_setup") + "Angle Scan Tracker", /Q, PearlAnglescanTracker("X03DA-SCIENTA:", "(65280,54528,48896)")
|
||||
help = {"Preview of acquired angle scan data and current detection angles.", "Requires ARPES package and EPICS XOP"}
|
||||
PearlMenuEnableFunc("sample_tracker") + "Sample Tracker", /Q, PearlSampleTracker(1)
|
||||
help = {"Live tracking and adjustment of sample position.", "Requires ARPES package and EPICS XOP"}
|
||||
end
|
||||
|
||||
submenu "Cameras"
|
||||
PearlMenuEnableFunc("ad_display_profiles") + "Exit Slit Live View", /Q, PearlLiveDisplay("X03DA-OP-PS1:", "OP", "(65280,54528,48896)")
|
||||
PearlMenuEnableFunc("ad_display_profiles") + "Exit Slit Camera", /Q, PearlLiveDisplay("X03DA-OP-PS1:", "OP", "(65280,54528,48896)")
|
||||
help = {"Display preview panel with latest image from Scienta", "Requires ARPES package and EPICS XOP"}
|
||||
PearlMenuEnableFunc("ad_display_profiles") + "Manipulator Live View", /Q, PearlLiveDisplay("X03DA-ES-PS1:", "ES", "(65280,54528,48896)")
|
||||
PearlMenuEnableFunc("ad_display_profiles") + "Manipulator Camera", /Q, PearlCameraDisplay("X03DA-ES-PS1:", "ES", "(32767,32767,32767)")
|
||||
help = {"Display live panel of the exit slit camera", "Requires ARPES package and EPICS XOP"}
|
||||
end
|
||||
|
||||
@ -65,7 +67,7 @@ menu "PEARL"
|
||||
end
|
||||
|
||||
submenu "Sample Preparation"
|
||||
PearlMenuEnableFunc("ann_ramp_start") + "Annealing Ramp", /Q, panel_ramp_gen()
|
||||
PearlMenuEnableFunc("ramp_generator") + "Annealing Ramp", /Q, ramp_generator()
|
||||
help = {"Sample annealing ramp generator"}
|
||||
end
|
||||
|
||||
@ -79,10 +81,12 @@ menu "PEARL"
|
||||
end
|
||||
end
|
||||
|
||||
/// check whether a function name exists
|
||||
///
|
||||
/// return a prefix which disables the menu item
|
||||
/// if the function does not exist
|
||||
///
|
||||
function /s PearlMenuEnableFunc(funcname)
|
||||
// checks whether a function name exists
|
||||
// and conditionally returns a prefix which disables the menu item
|
||||
// if the function does not exist
|
||||
string funcname
|
||||
if (exists(funcname) >= 3)
|
||||
return ""
|
||||
@ -94,7 +98,6 @@ end
|
||||
function LoadPearlOptics()
|
||||
execute /p/q/z "INSERTINCLUDE \"pearl-optics\""
|
||||
execute /p/q/z "COMPILEPROCEDURES "
|
||||
execute /p/q/z "PearlOpticsPanel#po_InitPanel()"
|
||||
execute /p/q/z "BuildMenu \"PEARL\""
|
||||
end
|
||||
|
||||
@ -165,33 +168,100 @@ function DisplayGizmoSlicer()
|
||||
endif
|
||||
end
|
||||
|
||||
/// area detector live display
|
||||
///
|
||||
/// display an area detector channel in an ad_display_profiles() window.
|
||||
///
|
||||
/// @param epicsname base name of the detector, e.g. X03DA-SCIENTA:
|
||||
/// image1: and cam1: are appended by the function.
|
||||
/// see ad_connect().
|
||||
///
|
||||
/// @param nickname nick name under which this detector is referred to in Igor.
|
||||
/// must be a valid name for a data folder.
|
||||
/// see ad_connect().
|
||||
///
|
||||
/// @param wbRGB window background color, e.g. "(32768,49152,55296)"
|
||||
///
|
||||
function PearlLiveDisplay(epicsname, nickname, wbRGB)
|
||||
string epicsname // base name of the detector, e.g. X03DA-SCIENTA:
|
||||
// image1: and cam1: are appended by the function
|
||||
// see ad_connect
|
||||
string nickname // nick name under which this detector is referred to in Igor
|
||||
// must be a valid data folder name
|
||||
// see ad_connect
|
||||
string wbRGB // window background color, e.g. "(32768,49152,55296)"
|
||||
string epicsname
|
||||
string nickname
|
||||
string wbRGB
|
||||
|
||||
string cmd
|
||||
sprintf cmd, "ad_connect(\"%s\", \"%s\")", epicsname, nickname
|
||||
execute /q/z cmd
|
||||
sprintf cmd, "ad_display_profiles(root:pearl_epics:%s:image)", nickname
|
||||
execute /q/z cmd
|
||||
//sprintf cmd, "ad_add_overlay(root:pearl_epics:%s:image)", nickname
|
||||
//execute /q/z cmd
|
||||
sprintf cmd, "ModifyGraph wbRGB=%s", wbRGB
|
||||
execute /q/z cmd
|
||||
sprintf cmd, "add_roi_controls()"
|
||||
execute /q/z cmd
|
||||
end
|
||||
|
||||
/// area detector surveillance camera display
|
||||
///
|
||||
/// display an area detector channel in a simple image window
|
||||
/// without any interactive controls.
|
||||
///
|
||||
/// @param epicsname base name of the detector, e.g. X03DA-SCIENTA:
|
||||
/// image1: and cam1: are appended by the function.
|
||||
/// see ad_connect().
|
||||
///
|
||||
/// @param nickname nick name under which this detector is referred to in Igor.
|
||||
/// must be a valid name for a data folder.
|
||||
/// see ad_connect().
|
||||
///
|
||||
/// @param wbRGB window background color, e.g. "(32768,49152,55296)"
|
||||
///
|
||||
function PearlCameraDisplay(epicsname, nickname, wbRGB)
|
||||
string epicsname
|
||||
string nickname
|
||||
string wbRGB
|
||||
|
||||
string cmd
|
||||
sprintf cmd, "ad_connect(\"%s\", \"%s\")", epicsname, nickname
|
||||
execute /q/z cmd
|
||||
sprintf cmd, "display; appendimage root:pearl_epics:%s:image", nickname
|
||||
execute /q/z cmd
|
||||
sprintf cmd, "ModifyGraph wbRGB=%s", wbRGB
|
||||
execute /q/z cmd
|
||||
cmd = "ModifyGraph height={Plan,1,left,bottom}"
|
||||
execute /q/z cmd
|
||||
end
|
||||
|
||||
/// display the angle scan tracker window
|
||||
///
|
||||
/// @param epicsname base name of the detector, e.g. X03DA-SCIENTA:
|
||||
/// image1: and cam1: are appended by the function.
|
||||
/// see ad_connect().
|
||||
///
|
||||
/// @param wbRGB window background color, e.g. "(32768,49152,55296)"
|
||||
///
|
||||
function PearlAnglescanTracker(epicsname, wbRGB)
|
||||
string epicsname // base name of the detector, e.g. X03DA-SCIENTA:
|
||||
// image1: and cam1: are appended by the function
|
||||
// see ast_setup
|
||||
string wbRGB // window background color, e.g. "(32768,49152,55296)"
|
||||
string epicsname
|
||||
string wbRGB
|
||||
|
||||
string cmd
|
||||
sprintf cmd, "ast_setup()"
|
||||
execute /q/z cmd
|
||||
sprintf cmd, "ModifyGraph wbRGB=%s", wbRGB
|
||||
execute /q/z cmd
|
||||
end
|
||||
|
||||
/// display the sample tracker window
|
||||
///
|
||||
/// @param epicsname base name of the detector, e.g. X03DA-SCIENTA:
|
||||
/// image1: and cam1: are appended by the function.
|
||||
/// see ad_connect().
|
||||
///
|
||||
/// @param wbRGB window background color, e.g. "(32768,49152,55296)"
|
||||
///
|
||||
function PearlSampleTracker(action)
|
||||
variable action
|
||||
string cmd
|
||||
sprintf cmd, "sample_tracker(%u)", action
|
||||
execute /q/z cmd
|
||||
end
|
||||
|
||||
|
213
pearl/pearl-scienta-countrate.ipf
Normal file
213
pearl/pearl-scienta-countrate.ipf
Normal file
@ -0,0 +1,213 @@
|
||||
#pragma rtGlobals=3 // Use modern global access method and strict wave access.
|
||||
#pragma IgorVersion = 6.35
|
||||
#pragma ModuleName = PearlScientaCountrate
|
||||
#include "pearl-area-display"
|
||||
|
||||
// Copyright (c) 2019 Paul Scherrer Institut
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
/// @file
|
||||
/// @brief count rate functions for Scienta detector images.
|
||||
/// @ingroup ArpesPackage
|
||||
///
|
||||
/// this procedure contains functions for working with true count rates.
|
||||
///
|
||||
/// @author matthias muntwiler, matthias.muntwiler@psi.ch
|
||||
///
|
||||
/// @copyright 2019 Paul Scherrer Institut @n
|
||||
/// Licensed under the Apache License, Version 2.0 (the "License"); @n
|
||||
/// you may not use this file except in compliance with the License. @n
|
||||
/// You may obtain a copy of the License at
|
||||
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
/// @namespace PearlScientaCountrate
|
||||
/// @brief count rate functions for Scienta detector images.
|
||||
///
|
||||
/// PearlScientaCountrate is declared in @ref pearl-scienta-countrate.ipf.
|
||||
|
||||
/// open live display of most recent scienta measurement
|
||||
///
|
||||
///
|
||||
/// @param epicsname base name of the detector, e.g. X03DA-SCIENTA:
|
||||
/// image1: and cam1: are appended by the function.
|
||||
/// see @ref ad_connect.
|
||||
/// @param nickname nick name under which this detector is referred to in Igor.
|
||||
/// must be a valid data folder name.
|
||||
/// see @ref ad_connect.
|
||||
/// @param wbRGB window background color, e.g. "32768,49152,55296"
|
||||
///
|
||||
function ScientaLiveDisplay(epicsname, nickname, wbRGB)
|
||||
string epicsname
|
||||
string nickname
|
||||
string wbRGB
|
||||
|
||||
ad_connect(epicsname, nickname)
|
||||
string df_name
|
||||
sprintf df_name, "ad_display_profiles(root:pearl_epics:%s)", nickname
|
||||
dfref df = $df_name
|
||||
wave /sdfr=df img = image
|
||||
string graphname = ad_display(img)
|
||||
wbRGB = replacestring("(", wbRGB, "")
|
||||
wbRGB = replacestring(")", wbRGB, "")
|
||||
variable rr = str2num(StringFromList(0, wbRGB, ","))
|
||||
variable gg = str2num(StringFromList(1, wbRGB, ","))
|
||||
variable bb = str2num(StringFromList(2, wbRGB, ","))
|
||||
ModifyGraph /w=$graphname wbRGB=(rr,gg,bb)
|
||||
add_roi_controls()
|
||||
ad_add_overlay(img)
|
||||
end
|
||||
|
||||
#if igorVersion() >= 8
|
||||
/// check exposure and calculate overexposure indicator mask
|
||||
///
|
||||
/// calculate the local count rate density and return a mask
|
||||
/// to indicate where the maximum count rate is exceeded.
|
||||
/// the raw image is filtered by FFT with a gaussian kernel.
|
||||
///
|
||||
/// the raw image must have been acquired in fixed mode.
|
||||
/// slicing and dwell time are accounted for.
|
||||
///
|
||||
/// all intermediate waves are created ad-hoc as free waves.
|
||||
/// this function requires igor 8.
|
||||
///
|
||||
/// @param[i] image raw image from scienta in fixed mode.
|
||||
///
|
||||
/// @param[o] outmask mask wave.
|
||||
/// must have same dimensions as image.
|
||||
/// suggested data type /b/u.
|
||||
/// the mask value in overexposed regions is 0,
|
||||
/// in regular regions 64.
|
||||
///
|
||||
/// @param[i] dwelltime in seconds.
|
||||
///
|
||||
function check_exposure(image, outmask, dwelltime)
|
||||
wave image
|
||||
wave outmask
|
||||
variable dwelltime
|
||||
|
||||
variable xbin = 1
|
||||
variable ybin = 902 / dimsize(image, 1)
|
||||
variable thresh = 1e5 / 900 / 900
|
||||
|
||||
duplicate /free image, filt
|
||||
setscale /p x -dimsize(image, 0)/2, 1, "", filt // energy
|
||||
setscale /p y -dimsize(image, 1)/2, 1, "", filt // angle
|
||||
variable wx = sqrt(500) / xbin
|
||||
variable wy = sqrt(500) / ybin
|
||||
filt = exp(-((x/wx)^2 + (y/wy)^2))
|
||||
variable nfilt = sum(filt)
|
||||
filt /= nfilt
|
||||
fft /free /dest=filt_fft filt
|
||||
|
||||
duplicate /free image, img
|
||||
img /= dwelltime
|
||||
setscale /p x -dimsize(image, 0)/2, 1, "", img
|
||||
setscale /p y -dimsize(image, 1)/2, 1, "", img
|
||||
fft /free /dest=img_fft img
|
||||
img_fft *= filt_fft
|
||||
ifft /free /dest=img_ifft img_fft
|
||||
imagetransform swap img_ifft
|
||||
|
||||
outmask = (img_ifft < thresh) * 64
|
||||
end
|
||||
#endif
|
||||
|
||||
/// optimized check exposure and calculate overexposure indicator mask
|
||||
///
|
||||
/// calculate the local count rate density and return a mask
|
||||
/// to indicate where the maximum count rate is exceeded.
|
||||
/// the raw image is filtered by FFT with a gaussian kernel.
|
||||
///
|
||||
/// the raw image must have been acquired in fixed mode.
|
||||
/// slicing and dwell time are accounted for.
|
||||
///
|
||||
/// this function does the same as check_exposure()
|
||||
/// but keeps intermediate waves for time-optimized processing.
|
||||
/// moreover it is compatible with igor 6.
|
||||
///
|
||||
/// @param[i] image raw image from scienta in fixed mode.
|
||||
///
|
||||
/// @param[o] outmask mask wave.
|
||||
/// must have same dimensions as image.
|
||||
/// suggested data type /b/u.
|
||||
/// the mask value in overexposed regions is 0, in regular regions 64.
|
||||
///
|
||||
/// @param[i] dwelltime in seconds.
|
||||
///
|
||||
/// @param[i] calc_df (optional) data folder reference where intermediate and cached waves should be stored.
|
||||
/// by default, the data folder is named "psc_" plus the name of the image wave
|
||||
/// and inserted in the folder where the image wave is stored.
|
||||
///
|
||||
/// the possible gain can be estimated from the following test data:
|
||||
/// - total execution time 510 ms
|
||||
/// - gain from re-using (but recalculating) waves: 20 ms
|
||||
/// - gain from re-using co_filt_fft: 220 ms
|
||||
///
|
||||
function check_exposure_opt(image, outmask, dwelltime, [calc_df])
|
||||
wave image
|
||||
wave outmask
|
||||
variable dwelltime
|
||||
dfref calc_df
|
||||
|
||||
variable xbin = 1
|
||||
variable ybin = 902 / dimsize(image, 1)
|
||||
variable thresh = 1e5 / 900 / 900
|
||||
|
||||
dfref save_df = GetDataFolderDFR()
|
||||
if (ParamIsDefault(calc_df))
|
||||
dfref source_df = GetWavesDataFolderDFR(image)
|
||||
string calc_df_name = PearlCleanupName("psc_" + NameOfWave(image))
|
||||
dfref calc_df = source_df:$calc_df_name
|
||||
endif
|
||||
NewDataFolder /o /s calc_df
|
||||
|
||||
wave /z co_filt
|
||||
wave /z /c co_filt_fft
|
||||
wave /z co_img
|
||||
wave /z /c co_img_fft
|
||||
wave /z co_img_ifft
|
||||
nvar /z co_img_size_x
|
||||
nvar /z co_img_size_y
|
||||
|
||||
variable cache = 0
|
||||
if (waveexists(co_filt))
|
||||
cache = (dimsize(image, 0) == co_img_size_x) && (dimsize(image, 1) == co_img_size_y)
|
||||
if (!cache)
|
||||
redimension /n=(dimsize(image, 0), dimsize(image, 1)) co_filt, co_filt_fft, co_img, co_img_fft, co_img_ifft
|
||||
endif
|
||||
else
|
||||
duplicate /o image, co_filt, co_img, co_img_ifft
|
||||
make /n=(dimsize(image, 0), dimsize(image, 1)) /c co_filt_fft, co_img_fft
|
||||
variable /g co_img_size_x
|
||||
variable /g co_img_size_y
|
||||
endif
|
||||
|
||||
co_img_size_x = dimsize(image, 0)
|
||||
co_img_size_y = dimsize(image, 1)
|
||||
setscale /p x -co_img_size_x/2, 1, "", co_filt, co_filt_fft, co_img, co_img_fft, co_img_ifft
|
||||
setscale /p y -co_img_size_y/2, 1, "", co_filt, co_filt_fft, co_img, co_img_fft, co_img_ifft
|
||||
|
||||
if (!cache)
|
||||
variable wx = sqrt(500) / xbin
|
||||
variable wy = sqrt(500) / ybin
|
||||
co_filt = exp(-((x/wx)^2 + (y/wy)^2))
|
||||
variable nfilt = sum(co_filt)
|
||||
co_filt /= nfilt
|
||||
fft /dest=co_filt_fft co_filt
|
||||
endif
|
||||
|
||||
co_img /= dwelltime
|
||||
fft /dest=co_img_fft co_img
|
||||
co_img_fft *= co_filt_fft
|
||||
ifft /dest=co_img_ifft co_img_fft
|
||||
imagetransform swap co_img_ifft
|
||||
|
||||
redimension /n=(dimsize(co_img_ifft, 0), dimsize(co_img_ifft, 1)) outmask
|
||||
outmask = (co_img_ifft < thresh) * 64
|
||||
|
||||
SetDataFolder save_df
|
||||
end
|
@ -62,7 +62,33 @@ function prompt_int_linbg_reduction(param)
|
||||
return v_flag
|
||||
end
|
||||
|
||||
/// this function is for testing only, until we implement a proper interface
|
||||
/// capture linear background reduction parameters from cursors in a graph.
|
||||
///
|
||||
/// PRELIMINARY - function arguments may change
|
||||
///
|
||||
/// sets reduction parameters from cursors in a graph.
|
||||
/// the resulting parameters are copied to the global `s_reduction_params` string
|
||||
/// used by the data explorer.
|
||||
///
|
||||
/// an even number of cursors (2 or more) must be set on the image.
|
||||
/// cursor names and order do not matter,
|
||||
/// except that the alphabetically first cursor which is attached to an image selects the image.
|
||||
/// the cursors mark the following positions, from innermost to outermost pair:
|
||||
///
|
||||
/// 1. low and high limits of peak region.
|
||||
/// if no cursors are present, the limits are set at 40% and 60% of the x-scale.
|
||||
/// 2. peak-side boundary of lower and upper background region.
|
||||
/// if two or less cursors are present, the default background region applies,
|
||||
/// which extends from the peak limits up to the default cropping region.
|
||||
/// the background region extends up to the cropping region defined by the third pair.
|
||||
/// 3. lower and upper cropping region.
|
||||
/// if four or less cursors are present, the default cropping region applies,
|
||||
/// which is 11% on either side of the image in fixed mode, and 0% otherwise.
|
||||
/// fixed mode is detected by the number of pixels (>= 992).
|
||||
///
|
||||
/// @note on profile graphs, the necessary cursors can be configured easily
|
||||
/// by calling the ad_profile_cursor_mode() function, e.g.
|
||||
/// `ad_profiles_cursor_mode(root:packages:pearl_explorer:preview_image, 1)`.
|
||||
///
|
||||
function /s capture_int_linbg_cursors()
|
||||
string param = csr_int_linbg_reduction("")
|
||||
@ -73,18 +99,36 @@ function /s capture_int_linbg_cursors()
|
||||
return param
|
||||
end
|
||||
|
||||
/// set reduction parameters from cursors in a graph.
|
||||
/// calculate linear background reduction parameters from cursors in a graph.
|
||||
///
|
||||
/// PRELIMINARY - function arguments may change
|
||||
///
|
||||
/// sets reduction parameters from cursors in a graph.
|
||||
/// calculates reduction parameters from cursors in a graph.
|
||||
/// the resulting parameters are returned in a string.
|
||||
///
|
||||
/// an even number of cursors (2 or more) must be set on the image.
|
||||
/// cursor names and order do not matter,
|
||||
/// except that the alphabetically first cursor which is attached to an image selects the image.
|
||||
/// the cursors mark the following positions, from innermost to outermost pair:
|
||||
/// 1) low and high limits of peak region.
|
||||
/// 2) peak-side boundary of lower and upper background region.
|
||||
/// 3) lower and upper cropping region.
|
||||
///
|
||||
/// 1. low and high limits of peak region.
|
||||
/// if no cursors are present, the limits are set at 40% and 60% of the x-scale.
|
||||
/// 2. peak-side boundary of lower and upper background region.
|
||||
/// if two or less cursors are present, the default background region applies,
|
||||
/// which extends from the peak limits up to the default cropping region.
|
||||
/// the background region extends up to the cropping region defined by the third pair.
|
||||
/// 3. lower and upper cropping region.
|
||||
/// if four or less cursors are present, the default cropping region applies,
|
||||
/// which is 11% on either side of the image in fixed mode, and 0% otherwise.
|
||||
/// fixed mode is detected by the number of pixels (>= 992).
|
||||
///
|
||||
/// @note on profile graphs, the necessary cursors can be configured easily
|
||||
/// by calling the ad_profile_cursor_mode() function, e.g.
|
||||
/// `ad_profiles_cursor_mode(root:packages:pearl_explorer:preview_image, 1)`.
|
||||
///
|
||||
/// @param win graph window name or empty string for top window.
|
||||
///
|
||||
/// @return parameter string for linear background subtraction
|
||||
///
|
||||
function /s csr_int_linbg_reduction(win)
|
||||
string win
|
||||
@ -127,8 +171,8 @@ function /s csr_int_linbg_reduction(win)
|
||||
// map innermost cursor pair to peak center and size
|
||||
variable ip2 = np / 2
|
||||
variable ip1 = ip2 - 1
|
||||
variable Cpos = (positions[ip1] + positions[ip2]) / 2
|
||||
variable Csize = positions[ip2] - positions[ip1]
|
||||
variable Cpos
|
||||
variable Csize
|
||||
if (ip1 >= 0)
|
||||
Cpos = (positions[ip1] + positions[ip2]) / 2
|
||||
Csize = positions[ip2] - positions[ip1]
|
||||
@ -155,15 +199,17 @@ function /s csr_int_linbg_reduction(win)
|
||||
// crop region
|
||||
ip1 -= 1
|
||||
ip2 += 1
|
||||
variable Lcrop
|
||||
variable Hcrop
|
||||
variable Lcrop = 0
|
||||
variable Hcrop = 0
|
||||
if (ip1 >= 0)
|
||||
Lcrop = positions[ip1]
|
||||
Hcrop = 1 - positions[ip2]
|
||||
else
|
||||
// default: dead corners of the EW4000 at PEARL
|
||||
Lcrop = 0.11
|
||||
Hcrop = 0.11
|
||||
// default: in fixed mode: dark corners of the EW4000 at PEARL, 0 otherwise
|
||||
if (dimsize(image, 0) >= 992)
|
||||
Lcrop = 0.11
|
||||
Hcrop = 0.11
|
||||
endif
|
||||
endif
|
||||
Lsize = max(Lsize - Lcrop, 0)
|
||||
Hsize = max(Hsize - Hcrop, 0)
|
||||
|
@ -1,41 +1,97 @@
|
||||
#pragma rtGlobals=3
|
||||
#pragma version = 2.0
|
||||
#pragma version = 2.1
|
||||
#pragma IgorVersion = 6.1
|
||||
#pragma ModuleName = PearlVectorOperations
|
||||
|
||||
// author: matthias.muntwiler@psi.ch
|
||||
// Copyright (c) 2011-13 Paul Scherrer Institut
|
||||
// $Id$
|
||||
// copyright (c) 2011-17 Paul Scherrer Institut
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http:///www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Please acknowledge the use of this code.
|
||||
|
||||
/// @file
|
||||
/// @brief basic vector geometry operations.
|
||||
/// @ingroup ArpesPackage
|
||||
///
|
||||
/// this procedure file contains basic vector geometry functions,
|
||||
/// such as rotations.
|
||||
///
|
||||
/// @author matthias muntwiler, matthias.muntwiler@psi.ch
|
||||
///
|
||||
/// @copyright 2011-17 Paul Scherrer Institut @n
|
||||
/// Licensed under the Apache License, Version 2.0 (the "License"); @n
|
||||
/// you may not use this file except in compliance with the License. @n
|
||||
/// You may obtain a copy of the License at
|
||||
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||
///
|
||||
|
||||
/// @namespace PearlVectorOperations
|
||||
/// @brief basic vector geometry operations.
|
||||
///
|
||||
/// PearlVectorOperations is declared in @ref pearl-vector-operations.ipf.
|
||||
|
||||
|
||||
/// rotate a 2D cartesian vector and returns its x component.
|
||||
///
|
||||
/// @param xx x coordinate.
|
||||
/// @param yy y coordinate.
|
||||
/// @param angle rotation angle in degrees.
|
||||
///
|
||||
/// @return x coordinate of the rotated vector.
|
||||
///
|
||||
function rotate2d_x(xx, yy, angle)
|
||||
// rotates a 2D cartesian vector and returns its x component
|
||||
variable xx, yy
|
||||
variable angle // rotation angle in degrees
|
||||
variable angle
|
||||
|
||||
return xx * cos(angle * pi / 180) - yy * sin(angle * pi / 180)
|
||||
end
|
||||
|
||||
/// rotate a 2D cartesian vector and returns its y component.
|
||||
///
|
||||
/// @param xx x coordinate.
|
||||
/// @param yy y coordinate.
|
||||
/// @param angle rotation angle in degrees.
|
||||
///
|
||||
/// @return y coordinate of the rotated vector.
|
||||
///
|
||||
function rotate2d_y(xx, yy, angle)
|
||||
// rotates a 2D cartesian vector and returns its y component
|
||||
variable xx, yy
|
||||
variable angle // rotation angle in degrees
|
||||
variable angle
|
||||
|
||||
return xx * sin(angle * pi / 180) + yy * cos(angle * pi / 180)
|
||||
end
|
||||
|
||||
/// create a free matrix wave which represents the 3-vector identity.
|
||||
///
|
||||
/// the matrix is initialized as identity.
|
||||
///
|
||||
/// @return 3x3 identity matrix in a free wave.
|
||||
///
|
||||
function /wave create_rotation_matrix_free()
|
||||
// creates a matrix which represents a 3-vector rotation
|
||||
// the matrix is initialized as identity
|
||||
|
||||
make /n=(3,3)/free matrix
|
||||
matrix = p == q // identity
|
||||
return matrix
|
||||
end
|
||||
|
||||
/// calculate a matrix representing a 3-vector rotation around the x axis.
|
||||
///
|
||||
/// the function calculates the matrix elements of a rotation about the x axis.
|
||||
///
|
||||
/// @param[in,out] matrix 3x3 wave to receive the rotation matrix elements.
|
||||
/// the function calculates only the 2x2 block of the rotation.
|
||||
/// the other elements must be initialized by the caller,
|
||||
/// e.g. set to the identity matrix.
|
||||
/// @param[in] angle rotation angle in degrees.
|
||||
///
|
||||
/// @return rotation matrix.
|
||||
/// this is the same wave instance as the matrix input.
|
||||
///
|
||||
function /wave set_rotation_x(matrix, angle)
|
||||
// calculates a matrix representing a 3-vector rotation around the x axis
|
||||
wave matrix // rotation matrix
|
||||
variable angle // rotation angle in degrees
|
||||
wave matrix
|
||||
variable angle
|
||||
|
||||
variable si = sin(angle * pi / 180)
|
||||
variable co = cos(angle * pi / 180)
|
||||
@ -48,10 +104,22 @@ function /wave set_rotation_x(matrix, angle)
|
||||
return matrix
|
||||
end
|
||||
|
||||
/// calculate a matrix representing a 3-vector rotation around the y axis
|
||||
///
|
||||
/// the function calculates the matrix elements of a rotation about the y axis.
|
||||
///
|
||||
/// @param[in,out] matrix 3x3 wave to receive the rotation matrix elements.
|
||||
/// the function calculates only the 2x2 block of the rotation.
|
||||
/// the other elements must be initialized by the caller,
|
||||
/// e.g. set to the identity matrix.
|
||||
/// @param[in] angle rotation angle in degrees.
|
||||
///
|
||||
/// @return rotation matrix.
|
||||
/// this is the same wave instance as the matrix input.
|
||||
///
|
||||
function /wave set_rotation_y(matrix, angle)
|
||||
// calculates a matrix representing a 3-vector rotation around the y axis
|
||||
wave matrix // rotation matrix
|
||||
variable angle // rotation angle in degrees
|
||||
wave matrix
|
||||
variable angle
|
||||
|
||||
variable si = sin(angle * pi / 180)
|
||||
variable co = cos(angle * pi / 180)
|
||||
@ -64,10 +132,22 @@ function /wave set_rotation_y(matrix, angle)
|
||||
return matrix
|
||||
end
|
||||
|
||||
/// calculate a matrix representing a 3-vector rotation around the z axis
|
||||
///
|
||||
/// the function calculates the matrix elements of a rotation about the z axis.
|
||||
///
|
||||
/// @param[in,out] matrix 3x3 wave to receive the rotation matrix elements.
|
||||
/// the function calculates only the 2x2 block of the rotation.
|
||||
/// the other elements must be initialized by the caller,
|
||||
/// e.g. set to the identity matrix.
|
||||
/// @param[in] angle rotation angle in degrees.
|
||||
///
|
||||
/// @return rotation matrix.
|
||||
/// this is the same wave instance as the matrix input.
|
||||
///
|
||||
function /wave set_rotation_z(matrix, angle)
|
||||
// calculates a matrix representing a 3-vector rotation around the z axis
|
||||
wave matrix // rotation matrix
|
||||
variable angle // rotation angle in degrees
|
||||
wave matrix
|
||||
variable angle
|
||||
|
||||
variable si = sin(angle * pi / 180)
|
||||
variable co = cos(angle * pi / 180)
|
||||
@ -80,11 +160,21 @@ function /wave set_rotation_z(matrix, angle)
|
||||
return matrix
|
||||
end
|
||||
|
||||
/// rotate a wave of 3-vectors about the x axis.
|
||||
///
|
||||
/// this function rotates multiple vectors.
|
||||
///
|
||||
/// @param[in,out] inout wave with dimensions (M, N), M >= 3 (x, y, z), N >= 1.
|
||||
/// the result will be in same wave.
|
||||
/// only the first three rows of dimension 0 are used,
|
||||
/// extra rows are left unchanged.
|
||||
/// @param[in] angle rotation angle in degrees.
|
||||
///
|
||||
/// @return none
|
||||
///
|
||||
function rotate_x_wave(inout, angle)
|
||||
// rotates a wave of 3-vectors about the x axis
|
||||
wave inout // wave with dimensions (3, N), N >= 1, (x, y, z)
|
||||
// result will be in same wave
|
||||
variable angle // rotation angle in degrees
|
||||
wave inout
|
||||
variable angle
|
||||
|
||||
wave m_rotation_x = create_rotation_matrix_free()
|
||||
make /n=3/d/free w_temp_rotate_x
|
||||
@ -94,15 +184,25 @@ function rotate_x_wave(inout, angle)
|
||||
set_rotation_x(m_rotation_x, angle)
|
||||
w_temp_rotate_x = inout[p][ivec]
|
||||
matrixop /free w_temp_rotate_x_result = m_rotation_x x w_temp_rotate_x
|
||||
inout[][ivec] = w_temp_rotate_x_result[p]
|
||||
endfor
|
||||
inout[0,2][ivec] = w_temp_rotate_x_result[p]
|
||||
endfor
|
||||
end
|
||||
|
||||
/// rotates a wave of 3-vectors about the y axis
|
||||
///
|
||||
/// this function rotates multiple vectors.
|
||||
///
|
||||
/// @param[in,out] inout wave with dimensions (M, N), M >= 3 (x, y, z), N >= 1.
|
||||
/// the result will be in same wave.
|
||||
/// only the first three rows of dimension 0 are used,
|
||||
/// extra rows are left unchanged.
|
||||
/// @param[in] angle rotation angle in degrees.
|
||||
///
|
||||
/// @return none
|
||||
///
|
||||
function rotate_y_wave(inout, angle)
|
||||
// rotates a wave of 3-vectors about the y axis
|
||||
wave inout // wave with dimensions (3, N), N >= 1, (x, y, z)
|
||||
// result will be in same wave
|
||||
variable angle // rotation angle in degrees
|
||||
wave inout
|
||||
variable angle
|
||||
|
||||
wave m_rotation_y = create_rotation_matrix_free()
|
||||
make /n=3/d/free w_temp_rotate_y
|
||||
@ -112,15 +212,25 @@ function rotate_y_wave(inout, angle)
|
||||
set_rotation_y(m_rotation_y, angle)
|
||||
w_temp_rotate_y = inout[p][ivec]
|
||||
matrixop /free w_temp_rotate_y_result = m_rotation_y x w_temp_rotate_y
|
||||
inout[][ivec] = w_temp_rotate_y_result[p]
|
||||
inout[0,2][ivec] = w_temp_rotate_y_result[p]
|
||||
endfor
|
||||
end
|
||||
|
||||
/// rotates a wave of 3-vectors about the z axis
|
||||
///
|
||||
/// this function rotates multiple vectors.
|
||||
///
|
||||
/// @param[in,out] inout wave with dimensions (M, N), M >= 3 (x, y, z), N >= 1.
|
||||
/// the result will be in same wave.
|
||||
/// only the first three rows of dimension 0 are used,
|
||||
/// extra rows are left unchanged.
|
||||
/// @param[in] angle rotation angle in degrees.
|
||||
///
|
||||
/// @return none
|
||||
///
|
||||
function rotate_z_wave(inout, angle)
|
||||
// rotates a wave of 3-vectors about the z axis
|
||||
wave inout // wave with dimensions (3, N), N >= 1, (x, y, z)
|
||||
// result will be in same wave
|
||||
variable angle // rotation angle in degrees
|
||||
wave inout
|
||||
variable angle
|
||||
|
||||
wave m_rotation_z = create_rotation_matrix_free()
|
||||
make /n=3/d/free w_temp_rotate_z
|
||||
@ -130,6 +240,6 @@ function rotate_z_wave(inout, angle)
|
||||
set_rotation_z(m_rotation_z, angle)
|
||||
w_temp_rotate_z = inout[p][ivec]
|
||||
matrixop /free w_temp_rotate_z_result = m_rotation_z x w_temp_rotate_z
|
||||
inout[][ivec] = w_temp_rotate_z_result[p]
|
||||
inout[0,2][ivec] = w_temp_rotate_z_result[p]
|
||||
endfor
|
||||
end
|
||||
|
Reference in New Issue
Block a user