@ -1204,6 +1204,7 @@ function duplicate_hemi_scan(source_nickname, dest_folder, dest_nickname, [xpdpl
string s_theta = s_prefix + "th"
string s_tot = s_prefix + "tot"
string s_weight = s_prefix + "wt"
string s_matrix = s_prefix + "matrix"
wave theta1 = $s_theta
wave polar1 = $s_polar
@ -1211,6 +1212,7 @@ function duplicate_hemi_scan(source_nickname, dest_folder, dest_nickname, [xpdpl
wave tot1 = $s_tot
wave weight1 = $s_weight
wave values1 = $s_int
wave /z matrix1 = $s_matrix
variable npol = numpnts (theta1)
@ -1230,6 +1232,7 @@ function duplicate_hemi_scan(source_nickname, dest_folder, dest_nickname, [xpdpl
s_theta = s_prefix + "th"
s_tot = s_prefix + "tot"
s_weight = s_prefix + "wt"
s_matrix = s_prefix + "matrix"
wave theta2 = $s_theta
wave polar2 = $s_polar
@ -1241,6 +1244,9 @@ function duplicate_hemi_scan(source_nickname, dest_folder, dest_nickname, [xpdpl
tot2 = tot1
weight2 = weight1
values2 = values1
if (waveexists (matrix1))
duplicate /o matrix1, $s_matrix
endif
if (!(NumberByKey ("version" , note (azim1), "=" , "\r" ) >= 1.6))
azim2 += 180 // changed 151030 (v1.6)
@ -1250,6 +1256,48 @@ function duplicate_hemi_scan(source_nickname, dest_folder, dest_nickname, [xpdpl
setdatafolder saveDF
end
/// azimuthally rotate a hemispherical scan dataset.
///
/// this function works only for hemi scans created by make_hemi_grid() (or compatible functions).
///
/// @param nickname name prefix for waves. source data must be in current data folder.
/// @param angle azimuthal rotation angle in degrees.
///
function rotate_hemi_scan(nickname, angle)
string nickname
variable angle
dfref savedf = getdatafolderdfr ()
if (strlen (nickname))
string s_prefix = nickname + "_"
string s_int = s_prefix + "i"
else
s_prefix = ""
s_int = "values"
endif
string s_polar = s_prefix + "pol"
string s_azim = s_prefix + "az"
string s_tot = s_prefix + "tot"
string s_weight = s_prefix + "wt"
wave polar = $s_polar
wave azim = $s_azim
wave tot = $s_tot
wave weight = $s_weight
wave values = $s_int
azim += angle
azim = azim < 0 ? azim + 360 : azim
azim = azim >= 360 ? azim - 360 : azim
duplicate /free polar, neg_polar
neg_polar = -polar
sort {neg_polar, azim}, polar, azim, tot, weight, values
setdatafolder saveDF
end
/// display a plot of a hemispherical angle scan.
///
/// the scan data must exist in the current data folder.
@ -1264,10 +1312,29 @@ end
/// @arg 0 linear
/// @arg 1 stereographic (default)
/// @arg 2 azimuthal
/// @arg 3 gnomonic (0 <= polar < 90).
///
/// @param graphtype type of graph
/// @arg 1 Igor "New Polar" (default)
/// @arg 2 XPDplot (reserved, not implemented)
/// @arg 1 (pol, az) trace in Igor "New Polar" (default).
/// @arg 2 XPDplot (reserved, not implemented).
/// @arg 3 matrix in Igor "New Polar".
/// the matrix wave is a 2D wave with X and Y scaling corresponding to the selected projection.
/// matrix waves can be created by interpolate_hemi_scan().
/// note: the pol and az waves are required as well.
///
/// @param do_ticks select which ticks to draw.
/// value must be the arithmetic OR of all selected items.
/// default: 3
/// @arg 0 none
/// @arg 1 major azimuthal
/// @arg 2 minor azimuthal
///S
/// @param do_grids select which grids to draw.
/// value must be the arithmetic OR of all selected items.
/// default: 3
/// @arg 0 none
/// @arg 1 radius at 0 and 90 degree azimuth
/// @arg 2 circle at 30 and 60 degree polar
///
/// @param graphname name of graph window. default: nickname
/// if empty, a default name is assigned.
@ -1275,10 +1342,12 @@ end
///
/// @returns the name of the graph window
///
function /s display_hemi_scan(nickname, [projection, graphtype, graphname])
function /s display_hemi_scan(nickname, [projection, graphtype, do_ticks, do_grids, graphname])
string nickname
variable projection
variable graphtype
variable do_ticks
variable do_grids
string graphname
if (ParamIsDefault (projection))
@ -1287,6 +1356,12 @@ function /s display_hemi_scan(nickname, [projection, graphtype, graphname])
if (ParamIsDefault (graphtype))
graphtype = 1
endif
if (ParamIsDefault (do_ticks))
do_ticks = 3
endif
if (ParamIsDefault (do_grids))
do_grids = 3
endif
if (ParamIsDefault (graphname))
if (strlen (nickname) > 0)
graphname = nickname
@ -1305,9 +1380,12 @@ function /s display_hemi_scan(nickname, [projection, graphtype, graphname])
endif
string s_polar = s_prefix + "pol"
string s_azim = s_prefix + "az"
string s_matrix = s_prefix + "matrix"
wave /z values = $s_int
wave /z azim = $s_azim
wave /z polar = $s_polar
wave /z matrix = $s_matrix
string s_ster_rad = s_prefix + "ster_rad"
duplicate /o polar, $s_ster_rad /wave =ster_rad
@ -1325,11 +1403,12 @@ function /s display_hemi_scan(nickname, [projection, graphtype, graphname])
azim_offset = 180 // changed 151030 (v1.6)
endif
string s_trace
switch (graphtype)
case 1:
graphname = display_polar_graph(graphname, angle_offset=azim_offset)
graphname = display_polar_graph(graphname, angle_offset=azim_offset, do_ticks=do_ticks )
string s_trace = WMPolarAppendTrace(graphname, ster_rad, azim, 360)
s_trace = WMPolarAppendTrace(graphname, ster_rad, azim, 360)
ModifyGraph /W=$graphname mode($s_trace)=2, lsize($s_trace)=2
ModifyGraph /W=$graphname zColor($s_trace)={values,*,*,BlueGreenOrange,0}
@ -1338,7 +1417,21 @@ function /s display_hemi_scan(nickname, [projection, graphtype, graphname])
ColorScale /W=$graphname /C /N=text0 nticks=2, minor=1, tickLen=4.00, tickThick=0.50
SetWindow $graphname, userdata(projection)=num2str (projection)
draw_hemi_axes(graphname)
draw_hemi_axes(graphname, do_grids=do_grids )
break
case 3:
graphname = display_polar_graph(graphname, angle_offset=azim_offset, do_ticks=do_ticks)
s_trace = WMPolarAppendTrace(graphname, ster_rad, azim, 360)
ModifyGraph /W=$graphname mode($s_trace)=0, lsize($s_trace)=0
AppendImage /L=VertCrossing /B=HorizCrossing matrix
ColorScale /W=$graphname /C /N=text0 /E=2 /F=0 /B=1 /A=RB /X=0.00 /Y=0.00 image=$s_matrix
ColorScale /W=$graphname /C /N=text0 side=2, width=5, heightPct=40, frame=0.50, lblMargin=0
ColorScale /W=$graphname /C /N=text0 nticks=2, minor=1, tickLen=4.00, tickThick=0.50
SetWindow $graphname, userdata(projection)=num2str (projection)
draw_hemi_axes(graphname, do_grids=do_grids)
break
endswitch
@ -1373,22 +1466,33 @@ end
/// for hemi grids created with earlier versions,
/// it should be set to 180 for correct orientation.
///
/// @param do_ticks select which ticks to draw.
/// value must be the arithmetic OR of all selected items.
/// default: 3
/// @arg 0 none
/// @arg 1 major azimuthal
/// @arg 2 minor azimuthal
///
/// @returns the name of the graph window.
///
/// @version 1.7
/// interface change: the trace drawing code is moved to display_hemi_scan,
/// so that this function can be reused by other graph types, e.g. display_scanlines.
///
static function /s display_polar_graph(graphname, [angle_offset])
static function /s display_polar_graph(graphname, [angle_offset, do_ticks ])
string graphname
variable angle_offset
variable do_ticks
dfref savedf = GetDataFolderDFR ()
if (ParamIsDefault (angle_offset))
angle_offset = 0
endif
if (ParamIsDefault (do_ticks))
do_ticks = 3
endif
if ((strlen (graphname) == 0) || (wintype (graphname) == 0))
Display /k=1 /W=(10,45,360,345)
@ -1408,15 +1512,28 @@ static function /s display_polar_graph(graphname, [angle_offset])
WMPolarGraphSetVar(graphname, "doPolarGrids" , 0)
WMPolarGraphSetVar(graphname, "doRadiusTickLabels" , 0)
WMPolarGraphSetStr(graphname, "radiusAxi sWhere" , " Off " )
WMPolarGraphSetStr(graphname, "radiusAxe sWhere" , " Off" ) // note the leading spaces, cf. WMPolarAnglesForRadiusAxes
WMPolarGraphSetStr(graphname, "radiusTicksLocation" , "Off" )
WMPolarGraphSetVar(graphname, "majorTickLength" , 5 )
WMPolarGraphSetVar(graphname, "majorTickLength" , 2 )
WMPolarGraphSetVar(graphname, "majorTickThick" , 0.5)
WMPolarGraphSetVar(graphname, "minorTickLength" , 3 )
WMPolarGraphSetVar(graphname, "minorTickLength" , 1 )
WMPolarGraphSetVar(graphname, "minorTickThick" , 0.5)
WMPolarGraphSetVar(graphname, "tickLabelOpaque" , 0)
WMPolarGraphSetVar(graphname, "tickLabelFontSize" , 7)
// changes
if (do_ticks & 1)
WMPolarGraphSetStr(graphname, "angleTicksLocation" , "Outside" )
else
WMPolarGraphSetStr(graphname, "angleTicksLocation" , "Off" )
endif
if (do_ticks & 2)
WMPolarGraphSetVar(graphname, "doMinorAngleTicks" , 1)
else
WMPolarGraphSetVar(graphname, "doMinorAngleTicks" , 0)
endif
DoWindow /T $graphname, graphname
// cursor info in angles
@ -1452,11 +1569,11 @@ static function /s display_polar_graph(graphname, [angle_offset])
return graphname
end
/// draw polar and azimuthal axe s in an existing polar graph
/// draw polar and azimuthal grid s in an existing polar graph.
///
/// the function adds the following draw objects to a polar graph:
/// * concentric circles at polar angles 0, 30, 60, and 9 0 degrees with labels.
/// * labels for azimuth al angl es at 0, 30, 60, and 90 degrees .
/// * concentric circles at polar angles 0, 30, and 6 0 degrees with labels.
/// * radi al ax es at 0 and 90 degree azimuth .
///
/// the objects are added to the ProgFront drawing layer and will appear in front of the data trace.
/// in interactive drawing mode, you can select the active drawing layer by clicking the tree icon
@ -1467,11 +1584,23 @@ end
///
/// @param graphname name of graph window.
///
/// @param do_grids select which optional grids to draw.
/// value must be the arithmetic OR of all selected items.
/// default: 3
/// @arg 0 none
/// @arg 1 radius at 0 and 90 degree azimuth
/// @arg 2 circle at 30 and 60 degree polar
///
/// @warning EXPERIMENTAL!
/// this function is under development.
/// the interface and behaviour of this function may change significantly in future versions.
static function /s draw_hemi_axes(graphname)
static function /s draw_hemi_axes(graphname, [do_grids] )
string graphname
variable do_grids
if (ParamIsDefault (do_grids))
do_grids = 3
endif
dfref savedf = GetDataFolderDFR ()
@ -1490,26 +1619,96 @@ static function /s draw_hemi_axes(graphname)
//SetDrawEnv /W=$graphname linefgc=(65535,65535,65535)
SetDrawEnv /W=$graphname save
variable radi
radi = calc_graph_radius(0.5, projection=projection)
DrawOval /W=$graphname -radi, radi, radi, -radi
radi = calc_graph_radius(30, projection=projection)
DrawOval /W=$graphname -radi, radi, radi, -radi
radi = calc_graph_radius(60, projection=projection)
DrawOval /W=$graphname -radi, radi, radi, -radi
DrawLine /W=$graphname 0, -2, 0, 2
DrawLine /W=$graphname -2, 0, 2, 0
if (do_grids & 1)
DrawLine /W=$graphname 0, -2, 0, 2
DrawLine /W=$graphname -2, 0, 2, 0
endif
SetDrawEnv /W=$graphname textxjust= 1,textyjust= 2
SetDrawEnv /W=$graphname save
radi = calc_graph_radius(3 0, projection=projection)
DrawText /W=$graphname radi, -0.1, "30<33> "
radi = calc_graph_radius(6 0, projection=projection)
DrawText /W=$graphname radi, -0.1, "60<36> "
variable radi
if (do_grids & 2)
radi = calc_graph_radius(0.5 , projection=projection)
DrawOval /W=$graphname - radi, radi, radi, -radi
radi = calc_graph_radius(3 0, projection=projection)
DrawOval /W=$graphname - radi, radi, radi, -radi
radi = calc_graph_radius(60, projection=projection)
DrawOval /W=$graphname -radi, radi, radi, -radi
SetDrawEnv /W=$graphname textxjust= 1,textyjust= 2
SetDrawEnv /W=$graphname save
radi = calc_graph_radius(30, projection=projection)
DrawText /W=$graphname radi, -0.1, "30<33> "
radi = calc_graph_radius(60, projection=projection)
DrawText /W=$graphname radi, -0.1, "60<36> "
endif
setdatafolder savedf
end
/// draw the circle of a diffraction cone in a stereographic polar graph.
///
/// the diffraction cone consists of a circle marking the diffraction ring, and a dot marking the axis.
/// the cone is drawn as a group of draw objects on the UserFront layer.
/// the objects can be edited interactively.
///
/// @param graphname name of graph window (not implemented yet).
///
/// @param groupname name of a drawing group.
/// if the group exists (from a previous cone) it is replaced.
/// if the group doesn't exist, a new one is created.
///
/// @param theta_axis polar angle of the cone axis in degrees.
///
/// @param theta_inner polar angle of the innermost point of the circle in degrees.
///
/// @param phi azimuthal angle of the cone axis in degrees.
///
/// @warning EXPERIMENTAL!
/// this function is under development.
/// the interface and behaviour of this function may change significantly in future versions.
///
function draw_diffraction_cone(graphname, groupname, theta_axis, theta_inner, phi)
string graphname
string groupname
variable theta_axis
variable theta_inner
variable phi
variable r_axis = calc_graph_radius(theta_axis)
variable r_inner = calc_graph_radius(theta_inner)
variable r_outer = calc_graph_radius(2 * theta_axis - theta_inner)
SetDrawEnv push
SetDrawLayer UserFront
DrawAction getgroup=$groupname, delete
SetDrawEnv gstart, gname=$groupname
variable xc, yc, xr, yr
// cone periphery
variable r_center = (r_outer + r_inner) / 2
variable r_radius = (r_outer - r_inner) / 2
xc = r_center * cos (phi * pi / 180)
yc = r_center * sin (phi * pi / 180)
xr = r_radius
yr = r_radius
SetDrawEnv xcoord=HorizCrossing, ycoord=VertCrossing
SetDrawEnv dash=11, fillpat=0
DrawOval xc - xr, yc - yr, xc + xr, yc + yr
// cone axis
xc = r_axis * cos (phi * pi / 180)
yc = r_axis * sin (phi * pi / 180)
r_radius = calc_graph_radius(2)
xr = r_radius
yr = r_radius
SetDrawEnv xcoord=HorizCrossing, ycoord=VertCrossing
SetDrawEnv fillfgc=(0,0,0)
DrawOval xc - xr, yc - yr, xc + xr, yc + yr
SetDrawEnv gstop
SetDrawEnv pop
end
/// display a polar graph with lines indicating the angles covered by an angle scan.
///
/// @param nickname nick name for output data.
@ -2021,7 +2220,13 @@ function hemi_add_aziscan(nickname, values, polar, azi, [weights])
w_values[d1, d1 + nd - 1] = w_totals[p] / w_weights[p]
end
/// interpolate a hemispherical scan onto a rectangular grid
///
/// @warning experimental
/// this function has been tested for one specific set of scan parameters.
/// the interface and code may change at any time.
/// the function depends on the ster_x and ster_y waves that are created by display_hemi_scan.
///
function interpolate_hemi_scan(nickname)
string nickname
@ -2044,21 +2249,26 @@ function interpolate_hemi_scan(nickname)
wave ster_x = $s_ster_x
wave ster_y = $s_ster_y
wavestats /q/m=0 ster_x
variable x0 = v_min
variable min_ster_x = wavemin ( ster_x)
variable max_ster_x = wavemax (ster_x)
variable x0 = min_ster_x
variable xn = 181
variable dx = (v_ max - v_ min) / (xn - 1)
make /n=(v_npnts , 3) /free triplet
variable dx = (max_ster_ x - min_ster_x ) / (xn - 1)
make /n=(numpnts (ster_x) , 3) /free triplet
triplet[][0] = ster_x[p]
triplet[][1] = ster_y[p]
triplet[][2] = values[p]
//ImageInterpolate /stw /s={x0, dx, xn, x0, dx, xn} voronoi triplet
make /n=(181, 181) /d /o $(s_prefix + "matrix" ) /wave =matrix
make /n=(181, 181) /free mnorm
variable size = 181
make /n=(size, size) /d /o $(s_prefix + "matrix" ) /wave =matrix
make /n=(size, size) /free mnorm
ImageFromXYZ /as {ster_x, ster_y, values}, matrix, mnorm
matrix /= mnorm
// matrixfilter NanZapMedian, matrix
matrixfilter NanZapMedian, matrix
matrixfilter gauss , matrix
matrix = (x^2 + y^2) < 4 ? matrix : nan
end
/// map angle scan data onto a rectangular grid in stereographic projection
@ -2234,3 +2444,44 @@ function load_hemi_scan(nickname, pathname, filename)
setdatafolder saveDF
end
/// import a hemispherical scan from theta-phi-intensity waves and display it
///
/// @warning EXPERIMENTAL
/// the interface and behaviour of this function may change
///
function import_tpi_scan(nickname, theta, phi, intensity, [folding, npolar, nograph, xpdplot])
string nickname
wave theta
wave phi
wave intensity
variable folding
variable npolar
variable nograph
variable xpdplot
if (ParamIsDefault (npolar))
npolar = 91
endif
if (ParamIsDefault (nograph))
nograph = 0
endif
if (ParamIsDefault (folding))
folding = 1
endif
if (ParamIsDefault (xpdplot))
xpdplot = 0
endif
make_hemi_grid(npolar, nickname, xpdplot=xpdplot)
variable ifold
duplicate /free phi, fold_phi
for (ifold = 0; ifold < folding; ifold += 1)
hemi_add_anglescan(nickname, intensity, theta, fold_phi)
fold_phi = fold_phi >= 180 ? fold_phi + 360 / folding - fold_phi : fold_phi + 360 / folding
endfor
display_hemi_scan(nickname)
end