6 Commits

Author SHA1 Message Date
c8a69460bc updates: igor 7, map projections, hemi cuts, longitudinal section
- pearl procedures compile under igor 7.
  some features may not work, e.g. 3D graphics with gizmo.
- add orthographic map projection to angle scans.
- add functions for azimuthal and polar cuts through hemispherical scan.
- add function to load longitudinal section from pshell data file.
2016-10-14 16:56:20 +02:00
600061f684 bugfixes in pshell import and preview
changes:
- fix null string exception in preview
- fix transposition of two-dimensional datasets
2016-09-23 19:11:07 +02:00
0dc6ca820b bugfix release: pshell import and preview
changes:
- catch runtime errors due to empty datasets
- improve window titles and graph names
- fix scaling of scienta image from XPSSpectrum script
- remove unnecessary spaces and underscores from folder names
2016-09-22 14:15:09 +02:00
a87975d1e6 update data explorer: axis scale and labels in preview 2016-08-17 12:12:52 +02:00
86cf328961 README.md: fix heading levels 2016-06-06 16:07:19 +02:00
2479582c08 README.md: add release notes 2016-06-06 16:04:56 +02:00
7 changed files with 1025 additions and 234 deletions

View File

@ -11,16 +11,20 @@ PEARL Procedures should be installed according to the regular Igor Pro guideline
- Make a `pearl-procs` directory in your private or shared `User Procedures` folder, and copy the PEARL Procedures distribution there. - Make a `pearl-procs` directory in your private or shared `User Procedures` folder, and copy the PEARL Procedures distribution there.
- Create shortcuts of the `pearl-arpes.ipf` and `pearl-menu.ipf` files, and move them to the `Igor Procedures` folder next to your `User Procedures` folder. - Create shortcuts of the `pearl-arpes.ipf` and `pearl-menu.ipf` files, and move them to the `Igor Procedures` folder next to your `User Procedures` folder.
- Find the `HDF5.XOP` extension in the `Igor Pro Folder` under `More Extensions/File Loaders`, create a shortcut, and move the shortcut to the `Igor Extensions` folder next to your `User Procedures` folder. - Find the `HDF5.XOP` (`HDF5-64.xop` for Igor 7 64-bit) extension in the `Igor Pro Folder` under `More Extensions/File Loaders` (`More Extensions (64-bit)/File Loaders`), create a shortcut, and move the shortcut to the `Igor Extensions` folder next to your `User Procedures` folder.
- Find the `HDF5 Help.ihf` next to `HDF5.XOP`, create a shortcut, and move the shortcut to the `Igor Help Files` folder next to your `User Procedures` folder. - Find the `HDF5 Help.ihf` next to `HDF5.XOP`, create a shortcut, and move the shortcut to the `Igor Help Files` folder next to your `User Procedures` folder.
PEARL Procedures has been tested under Igor Pro version 6.37 (32-bit). Older versions prior to 6.36 are not be compatible. Please update to the latest Igor Pro 6 version before reporting any problems.
PEARL Procedures compiles under Igor 7.00. Some features, in particular 3D graphics, may not work properly.
License License
======= =======
The source code of PEARL Procedures is available under the [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) at <https://git.psi.ch/pearl-public/igor-procs>. The source code of PEARL Procedures is available under the [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) at <https://git.psi.ch/pearl-public/igor-procs>.
Users of PEARL Procedures are requested to coordinate and share the development of the code with the original author.
Please read and respect the respective license agreements. Please read and respect the respective license agreements.
Please share your extensions of the code with the original author.
Author Author
------ ------
@ -32,3 +36,12 @@ Copyright
Copyright 2009-2016 by [Paul Scherrer Institut](http://www.psi.ch) Copyright 2009-2016 by [Paul Scherrer Institut](http://www.psi.ch)
Release Notes
=============
## rev-distro-1.1.1
- If you have upgraded PEARL Procedures from pre-1.1.1 and Igor breaks in pearl-elog.ipf while opening an experiment, please delete the ELOG preferences file `pearl-elog/preferences.pxp`. (Check the Igor Help to find the package preferences folder on your system.)

View File

@ -6,14 +6,14 @@
#include "pearl-polar-coordinates" #include "pearl-polar-coordinates"
#include <New Polar Graphs> #include <New Polar Graphs>
// $Id$ // copyright (c) 2013-16 Paul Scherrer Institut
//
// copyright (c) 2013-15 Paul Scherrer Institut
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // You may obtain a copy of the License at
// http:///www.apache.org/licenses/LICENSE-2.0 // http:///www.apache.org/licenses/LICENSE-2.0
//
// Please acknowledge the use of this code.
/// @file /// @file
/// @brief processing and holographic mapping of angle scanned XPD data. /// @brief processing and holographic mapping of angle scanned XPD data.
@ -64,7 +64,7 @@
/// ///
/// @author matthias muntwiler, matthias.muntwiler@psi.ch /// @author matthias muntwiler, matthias.muntwiler@psi.ch
/// ///
/// @copyright 2013-15 Paul Scherrer Institut @n /// @copyright 2013-16 Paul Scherrer Institut @n
/// Licensed under the Apache License, Version 2.0 (the "License"); @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 not use this file except in compliance with the License. @n
/// You may obtain a copy of the License at /// You may obtain a copy of the License at
@ -79,15 +79,38 @@
/// ///
/// PearlAnglescanProcess is declared in @ref pearl-anglescan-process.ipf. /// PearlAnglescanProcess is declared in @ref pearl-anglescan-process.ipf.
/// @warning experimental
function strip_remove_frames(strip, yscale, ylo, yhi) /// delete a contiguous range of frames from a strip.
///
/// this can be used to remove a region of bad frames due to, e.g., measurement problems.
/// the function operates on 2D intensity data and manipulator coordinates at the same time.
///
/// @param[in,out] strip 2D data, X-axis = analyser angle, Y-axis = arbitrary manipulator scan.
/// the result is written to the original wave.
///
/// @param[in,out] theta 1D data, manipulator scan.
/// the result is written to the original wave.
///
/// @param[in,out] tilt 1D data, manipulator scan.
/// the result is written to the original wave.
///
/// @param[in,out] phi 1D data, manipulator scan.
/// the result is written to the original wave.
///
/// @param[in] qlo point index of first frame to delete.
///
/// @param[in] qhi point index of last frame to delete.
/// qhi must be greater or equal than qlo.
///
function strip_delete_frames(strip, qlo, qhi, theta, tilt, phi)
wave strip // 2D data, X-axis = analyser angle, Y-axis = arbitrary manipulator scan wave strip // 2D data, X-axis = analyser angle, Y-axis = arbitrary manipulator scan
wave /z yscale // Y scaling, e.g. ManipulatorPhi variable qlo
// if unassigned, point scaling is assumed variable qhi
variable ylo wave theta
variable yhi wave tilt
wave phi
if (ylo > yhi) if (qlo > qhi)
return -1 return -1
endif endif
@ -95,8 +118,8 @@ function strip_remove_frames(strip, yscale, ylo, yhi)
variable snx = dimsize(strip, 0) variable snx = dimsize(strip, 0)
variable sny = dimsize(strip, 1) variable sny = dimsize(strip, 1)
variable sq1lo = 0 variable sq1lo = 0
variable sq1hi = max(round((ylo - dimoffset(strip, 1)) / dimdelta(strip, 1)), 0) variable sq1hi = max(qlo-1, 0)
variable sq2lo = min(round((ylo - dimoffset(strip, 1)) / dimdelta(strip, 1)), sny - 1) variable sq2lo = min(qhi+1, sny - 1)
variable sq2hi = dimsize(strip, 1) - 1 variable sq2hi = dimsize(strip, 1) - 1
// dest indices // dest indices
@ -111,10 +134,24 @@ function strip_remove_frames(strip, yscale, ylo, yhi)
duplicate /free strip, strip_copy duplicate /free strip, strip_copy
redimension /n=(dnx,dny) strip redimension /n=(dnx,dny) strip
strip[][dq1lo,dq1hi] = strip_copy[p][q + q1ofs] strip[][dq1lo,dq1hi] = strip_copy[p][q + q1ofs]
strip[][dq2lo,dq2hi] = strip_copy[p][q + q2ofs] strip[][dq2lo,dq2hi] = strip_copy[p][q + q2ofs]
duplicate /free theta, theta_copy
redimension /n=(dny) theta
theta[dq1lo,dq1hi] = theta_copy[p + q1ofs]
theta[dq2lo,dq2hi] = theta_copy[p + q2ofs]
duplicate /free tilt, tilt_copy
redimension /n=(dny) tilt
tilt[dq1lo,dq1hi] = tilt_copy[p + q1ofs]
tilt[dq2lo,dq2hi] = tilt_copy[p + q2ofs]
duplicate /free phi, phi_copy
redimension /n=(dny) phi
phi[dq1lo,dq1hi] = phi_copy[p + q1ofs]
phi[dq2lo,dq2hi] = phi_copy[p + q2ofs]
return 0 return 0
end end
@ -144,6 +181,7 @@ end
/// @return if check waves are enabled, the following waves are created (overwritten if existing): /// @return if check waves are enabled, the following waves are created (overwritten if existing):
/// @arg check_dist average X distribution /// @arg check_dist average X distribution
/// @arg check_smoo smoothed distribution used to normalize the strip /// @arg check_smoo smoothed distribution used to normalize the strip
///
function normalize_strip_x(strip, [smooth_method, smooth_factor, check]) function normalize_strip_x(strip, [smooth_method, smooth_factor, check])
wave strip wave strip
variable smooth_method variable smooth_method
@ -233,6 +271,7 @@ end
/// @return if check waves are enabled, the following waves are created (overwritten if existing): /// @return if check waves are enabled, the following waves are created (overwritten if existing):
/// @arg check_dist average theta distribution /// @arg check_dist average theta distribution
/// @arg check_smoo smoothed distribution used to normalize the strip /// @arg check_smoo smoothed distribution used to normalize the strip
///
function normalize_strip_theta(strip, theta, [theta_offset, smooth_method, smooth_factor, check]) function normalize_strip_theta(strip, theta, [theta_offset, smooth_method, smooth_factor, check])
wave strip wave strip
wave theta wave theta
@ -300,6 +339,70 @@ function normalize_strip_theta(strip, theta, [theta_offset, smooth_method, smoot
endif endif
end end
/// divide the strip by a two-dimensional normalization function.
///
/// @warning experimental. this function is under development.
///
/// @param check enable output of intermediate results
/// @arg 0 (default) don't create additional waves
/// @arg 1 create check waves in the current folder
/// @arg 2 calculate check waves only, do not modify strip
///
/// @return if check waves are enabled, the following waves are created (overwritten if existing):
/// @arg check_dist average theta distribution
/// @arg check_smoo smoothed distribution used to normalize the strip
///
function normalize_strip_2d(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
variable nx = dimsize(strip, 0)
variable ny = dimsize(strip, 1)
duplicate /free strip, dist, alpha_int, theta_int
theta_int = theta[q] - theta_offset
alpha_int = dimoffset(strip, 0) + p * dimdelta(strip, 0)
redimension /n=(nx * ny) dist, alpha_int, theta_int
switch(smooth_method)
case 4:
loess /dest=dist_smoo /smth=(smooth_factor) srcWave=dist, factors={alpha_int, theta_int}
redimension /n=(nx, ny) dist_smoo
break
default:
Abort "undefined smooth method"
break
endswitch
// divide
if (check != 2)
strip /= dist_smoo
endif
// check
if (check)
//duplicate /o dist, check_dist
duplicate /o dist_smoo, check_smoo
endif
end
/// crop a strip at the sides. /// crop a strip at the sides.
/// ///
/// the strip is cropped in place, data outside the region of interest is lost. /// the strip is cropped in place, data outside the region of interest is lost.
@ -705,9 +808,9 @@ function convert_angles_ttpa2polar(theta, tilt, phi, analyser, polar, azi)
// this is simply a polar-cartesian mapping, independent of the manipulator // this is simply a polar-cartesian mapping, independent of the manipulator
// phi=0 is in the polar rotation plane // phi=0 is in the polar rotation plane
make /n=(3,na) /d /free w_orig_polar, w_orig_cart, w_rot_cart, w_rot_polar make /n=(3,na) /d /free w_orig_polar, w_orig_cart, w_rot_cart, w_rot_polar
w_orig_polar[0] = radius w_orig_polar[0][] = radius
w_orig_polar[1] = analyser[q] w_orig_polar[1][] = analyser[q]
w_orig_polar[2] = 0 w_orig_polar[2][] = 0
polar2cart_wave(w_orig_polar, w_orig_cart) polar2cart_wave(w_orig_polar, w_orig_cart)
// if the angle-dispersive axis was horizontal, we'd need to rotate the detector // if the angle-dispersive axis was horizontal, we'd need to rotate the detector
//rotate_z_wave(w_orig_cart, 90) //rotate_z_wave(w_orig_cart, 90)
@ -1802,21 +1905,46 @@ function /s display_scanlines(nickname, alpha_lo, alpha_hi, m_theta, m_tilt, m_p
return graphname return graphname
end end
static constant kProjScaleLinear = 2 /// @page PageProjections Projections
///
/// the functions of the anglescan package support the following map projections.
/// for a description of the different projections, see, for example,
/// https://en.wikipedia.org/wiki/Map_projection
///
/// | Selector | Projection | Function | Properties |
/// | :----: | :----: | :----: | :---- |
/// | kProjDist = 0 | azimuthal equidistant | r = c * theta | radius is proportional to polar angle. |
/// | kProjStereo = 1 | stereographic | r = c * tan theta/2 | circles on sphere map to circles. |
/// | kProjArea = 2 | azimuthal equal-area | r = c * sin theta/2 | preserves area measure. |
/// | kProjGnom = 3 | gnomonic | r = c * tan theta | great circles map to straight lines. |
/// | kProjOrtho = 4 | orthographic | r = c * sin theta | k-space mapping in ARPES and LEED. |
///
/// the projections in this package are defined for 0 <= theta < 90.
///
constant kProjDist = 0
constant kProjStereo = 1
constant kProjArea = 2
constant kProjGnom = 3
constant kProjOrtho = 4
static constant kProjScaleDist = 2
static constant kProjScaleStereo = 2 static constant kProjScaleStereo = 2
static constant kProjScaleAzim = 2 static constant kProjScaleArea = 2
// scaled so that radius(gnom) = radius(stereo) for polar = 88 // scaled so that radius(gnom) = radius(stereo) for polar = 88
static constant kProjScaleGnomonic = 0.06744519021 static constant kProjScaleGnom = 0.06744519021
static constant kProjScaleOrtho = 2
/// calculate the projected polar angle /// calculate the projected polar angle
/// ///
/// @param polar polar angle in degrees /// @param polar polar angle in degrees
/// ///
/// @param projection mapping function from polar to cartesian coordinates /// @param projection mapping function from polar to cartesian coordinates.
/// @arg 0 linear /// see @ref PageProjections for details.
/// @arg 1 stereographic (default) /// @arg kProjDist = 0 azimuthal equidistant
/// @arg 2 azimuthal /// @arg kProjStereo = 1 stereographic (default)
/// @arg 3 gnomonic (0 <= polar < 90) /// @arg kProjArea = 2 azimuthal equal-area
/// @arg kProjGnom = 3 gnomonic (0 <= polar < 90)
/// @arg kProjOrtho = 4 orthographic
/// ///
/// @return projected radius. /// @return projected radius.
/// the radius is scaled such that grazing emission maps to 2. /// the radius is scaled such that grazing emission maps to 2.
@ -1830,17 +1958,20 @@ threadsafe function calc_graph_radius(polar, [projection])
variable radius variable radius
switch(projection) switch(projection)
case 1: // stereographic case kProjStereo: // stereographic
radius = kProjScaleStereo * tan(polar / 2 * pi / 180) radius = kProjScaleStereo * tan(polar / 2 * pi / 180)
break break
case 2: // azimuthal case kProjArea: // equal area
radius = kProjScaleAzim * cos((180 - polar) / 2 * pi / 180) radius = kProjScaleArea * sin(polar / 2 * pi / 180)
break break
case 3: // gnomonic case kProjGnom: // gnomonic
radius = polar < 90 ? kProjScaleGnomonic * tan(polar * pi / 180) : inf radius = polar < 90 ? kProjScaleGnom * tan(polar * pi / 180) : inf
break break
default: // linear case kProjOrtho: // orthographic
radius = kProjScaleLinear * polar / 90 radius = kProjScaleOrtho * sin(polar * pi / 180)
break
default: // equidistant
radius = kProjScaleDist * polar / 90
endswitch endswitch
return radius return radius
@ -1852,10 +1983,13 @@ end
/// ///
/// @param x, y projected Cartesian coordinate /// @param x, y projected Cartesian coordinate
/// ///
/// @param projection mapping function from polar to cartesian coordinates /// @param projection mapping function from polar to cartesian coordinates.
/// @arg 0 linear /// see @ref PageProjections for details.
/// @arg 1 stereographic (default) /// @arg kProjDist = 0 azimuthal equidistant
/// @arg 2 azimuthal /// @arg kProjStereo = 1 stereographic (default)
/// @arg kProjArea = 2 azimuthal equal-area
/// @arg kProjGnom = 3 gnomonic (0 <= polar < 90)
/// @arg kProjOrtho = 4 orthographic
/// ///
/// @returns polar angle in degrees /// @returns polar angle in degrees
/// ///
@ -1873,17 +2007,20 @@ threadsafe function calc_graph_polar(x, y, [projection])
radius = sqrt(x^2 + y^2) radius = sqrt(x^2 + y^2)
switch(projection) switch(projection)
case 1: // stereographic case kProjStereo: // stereographic
polar = 2 * atan(radius / kProjScaleStereo) * 180 / pi polar = 2 * atan(radius / kProjScaleStereo) * 180 / pi
break break
case 2: // azimuthal case kProjArea: // equal area
polar = 180 - 2 * acos(radius / kProjScaleAzim) * 180 / pi polar = 2 * asin(radius / kProjScaleArea) * 180 / pi
break break
case 3: // gnomonic case kProjGnom: // gnomonic
polar = atan(radius / kProjScaleGnomonic) * 180 / pi polar = atan(radius / kProjScaleGnom) * 180 / pi
break break
default: // linear case kProjOrtho: // orthographic
polar = 90 * radius / kProjScaleLinear polar = asin(radius / kProjScaleOrtho) * 180 / pi
break
default: // equidistant
polar = 90 * radius / kProjScaleDist
endswitch endswitch
return polar return polar
@ -1894,10 +2031,13 @@ end
/// @param x, y projected Cartesian coordinate /// @param x, y projected Cartesian coordinate
/// ///
/// @param projection mapping function from polar to cartesian coordinates. /// @param projection mapping function from polar to cartesian coordinates.
/// projections 0-2 have no effect on the azimuthal coordinate. /// all supported projections are azimuthal, they have no effect on the azimuthal coordinate.
/// @arg 0 linear /// see @ref PageProjections for details.
/// @arg 1 stereographic (default) /// @arg kProjDist = 0 azimuthal equidistant
/// @arg 2 azimuthal /// @arg kProjStereo = 1 stereographic (default)
/// @arg kProjArea = 2 azimuthal equal-area
/// @arg kProjGnom = 3 gnomonic (0 <= polar < 90)
/// @arg kProjOrtho = 4 orthographic
/// ///
/// @param zeroAngle zeroAngleWhere parameter of polar graphs /// @param zeroAngle zeroAngleWhere parameter of polar graphs
/// @arg 0 (default) zero is at the 3 o'clock position /// @arg 0 (default) zero is at the 3 o'clock position
@ -2483,4 +2623,158 @@ function import_tpi_scan(nickname, theta, phi, intensity, [folding, npolar, nogr
endfor endfor
display_hemi_scan(nickname) display_hemi_scan(nickname)
end end
/// extract a polar cut from a hemispherical scan.
///
/// for each polar angle, the function first extracts all azimuthal angles.
/// the intensity is then interpolated between the nearest neighbours of the given azimuth.
///
/// the hemi grid must have been created in the current data folder by the make_hemi_grid function.
/// correct ordering is required.
///
/// @param nickname name of the scan dataset.
/// can be empty if no prefix is used.
/// the dataset must be in the current datafolder.
///
/// @param azim azimuthal angle in degrees
///
/// @return reference of the created wave.
/// the wave has the same name as the intensity wave of the dataset
/// with the suffix "_azi" and the azimuthal angle rounded to integer.
/// it is created in the same datafolder as the original data.
///
function /wave hemi_polar_cut(nickname, azim)
string nickname
variable azim
if (strlen(nickname))
string s_prefix = nickname + "_"
string s_int = s_prefix + "i"
else
s_prefix = ""
s_int = "values"
endif
string s_totals = s_prefix + "tot"
string s_weights = s_prefix + "wt"
string s_polar = s_prefix + "pol"
string s_azim = s_prefix + "az"
string s_index = s_prefix + "index"
string s_theta = s_prefix + "th"
string s_dphi = s_prefix + "dphi"
string s_nphis = s_prefix + "nphis"
string s_cut
sprintf s_cut, "%s_azi%03u", s_int, round(azim)
wave w_polar = $s_polar
wave w_azim = $s_azim
wave w_values = $s_int
wave w_totals = $s_totals
wave w_weights = $s_weights
wave w_index = $s_index
wave w_theta = $s_theta
wave w_dphi = $s_dphi
wave w_nphis = $s_nphis
variable npol = numpnts(w_theta)
variable ipol
variable pol_st = abs(w_theta[1] - w_theta[0])
variable pol
variable pol1, pol2
variable nsel
make /n=(npol) /o $s_cut
wave w_cut = $s_cut
setscale /i x w_theta[0], w_theta[numpnts(w_theta)-1], "deg", w_cut
make /n=1 /free azi_slice
make /n=1 /free values_slice
for (ipol = 0; ipol < npol; ipol += 1)
pol = w_theta[ipol]
pol1 = pol - pol_st / 2
pol2 = pol + pol_st / 2
extract /free /indx w_polar, sel, (pol1 < w_polar) && (w_polar <= pol2)
nsel = numpnts(sel)
if (nsel > 0)
redimension /n=(nsel+2) azi_slice, values_slice
azi_slice[1, nsel] = w_azim[sel[p-1]]
azi_slice[0] = azi_slice[nsel] - 360
azi_slice[nsel+1] = azi_slice[1] + 360
values_slice[1, nsel] = w_values[sel[p-1]]
values_slice[0] = values_slice[nsel]
values_slice[nsel+1] = values_slice[1]
w_cut[ipol] = interp(azim, azi_slice, values_slice)
else
w_cut[ipol] = nan
endif
endfor
return w_cut
end
/// extract an azimuthal cut from a hemispherical scan
///
/// the function extracts all azimuthal angles that are present for the given polar angle.
///
/// the hemi grid must have been created in the current data folder by the make_hemi_grid function.
/// correct ordering is required.
///
/// @param nickname name of the scan dataset.
/// can be empty if no prefix is used.
/// the dataset must be in the current datafolder.
///
/// @param pol polar angle in degrees
///
/// @return reference of the created wave.
/// the wave has the same name as the intensity wave of the dataset
/// with the suffix "_azi" and the azimuthal angle rounded to integer.
/// it is created in the same datafolder as the original data.
///
function /wave hemi_azi_cut(nickname, pol)
string nickname
variable pol
if (strlen(nickname))
string s_prefix = nickname + "_"
string s_int = s_prefix + "i"
else
s_prefix = ""
s_int = "values"
endif
string s_totals = s_prefix + "tot"
string s_weights = s_prefix + "wt"
string s_polar = s_prefix + "pol"
string s_azim = s_prefix + "az"
string s_index = s_prefix + "index"
string s_theta = s_prefix + "th"
string s_dphi = s_prefix + "dphi"
string s_nphis = s_prefix + "nphis"
string s_cut
sprintf s_cut, "%s_pol%03u", s_int, round(pol)
wave w_polar = $s_polar
wave w_azim = $s_azim
wave w_values = $s_int
wave w_totals = $s_totals
wave w_weights = $s_weights
wave w_index = $s_index
wave w_theta = $s_theta
wave w_dphi = $s_dphi
wave w_nphis = $s_nphis
variable pol_st = abs(w_theta[1] - w_theta[0])
variable pol1, pol2
variable nsel
pol1 = pol - pol_st / 2
pol2 = pol + pol_st / 2
extract /free /indx w_polar, sel, (pol1 < w_polar) && (w_polar <= pol2)
nsel = numpnts(sel)
if (nsel > 0)
make /n=(nsel) /o $s_cut
wave w_cut = $s_cut
w_cut = w_values[sel]
setscale /i x w_azim[sel[0]], w_azim[sel[nsel-1]], "deg", w_cut
return w_cut
else
return $""
endif
end

View File

@ -52,6 +52,25 @@
/// PearlAreaDisplay is declared in @ref pearl-area-display.ipf. /// PearlAreaDisplay is declared in @ref pearl-area-display.ipf.
/// ///
/// compose a valid and unique graph name from a data folder reference
static function /s graphname_from_dfref(df, prefix)
dfref df
string prefix
string name
name = GetDataFolder(1, df)
name = ReplaceString("root:", name, "")
name = name[0, strlen(name) - 2]
name = ReplaceString(" ", name, "")
name = CleanupName(prefix + name, 0)
if (CheckName(name, 6))
name = UniqueName(name, 6, 0)
endif
return name
end
/// open a new graph window with a 2D image. /// open a new graph window with a 2D image.
/// ///
/// this is essentially <code>display; appendimage</code>. /// this is essentially <code>display; appendimage</code>.
@ -72,7 +91,7 @@ function /s ad_display(image)
string dfname = ReplaceString("root:", GetDataFolder(1, imagedf), "") string dfname = ReplaceString("root:", GetDataFolder(1, imagedf), "")
string graphtitle = dfname + " View" string graphtitle = dfname + " View"
string /g view_graphname = CleanupName("view_" + dfname, 0) string /g view_graphname = graphname_from_dfref(imagedf, "view_")
svar graphname = view_graphname svar graphname = view_graphname
display /k=1/n=$graphname as graphtitle display /k=1/n=$graphname as graphtitle
graphname = s_name graphname = s_name
@ -104,7 +123,7 @@ function /s ad_display_histogram(image)
string dfname = ReplaceString("root:", GetDataFolder(1, imagedf), "") string dfname = ReplaceString("root:", GetDataFolder(1, imagedf), "")
string graphtitle = dfname + " Histogram" string graphtitle = dfname + " Histogram"
string /g hist_graphname = CleanupName("hist_" + dfname, 0) string /g hist_graphname = graphname_from_dfref(imagedf, "hist_")
svar graphname = hist_graphname svar graphname = hist_graphname
display /k=1/n=$graphname as graphtitle display /k=1/n=$graphname as graphtitle
graphname = s_name graphname = s_name
@ -171,16 +190,15 @@ function /s ad_display_profiles(image, [filter])
duplicate /o image, $viewname /wave=view duplicate /o image, $viewname /wave=view
make /n=(3,3)/o xprofiles // NX x 3 wave with 3 one-dimensional profiles along Y dimension make /n=(3,3)/o xprofiles // NX x 3 wave with 3 one-dimensional profiles along Y dimension
make /n=(3,3)/o yprofiles // NY x 3 wave with 3 one-dimensional profiles along X dimension make /n=(3,3)/o yprofiles // NY x 3 wave with 3 one-dimensional profiles along X dimension
make /n=(1)/o hist // histogram
string /g view_filter string /g view_filter
string /g view_filter_options string /g view_filter_options
view_filter = filter view_filter = filter
view_filter_options = "" view_filter_options = ""
variable /g view_filter_smoothing_x = 1 variable /g view_filter_smoothing_x = 1
variable /g view_filter_smoothing_y = 1 variable /g view_filter_smoothing_y = 1
string dfname = GetDataFolder(0, imagedf) string dfname = ReplaceString("root:", GetDataFolder(1, imagedf), "")
string graphtitle = dfname + ":" + NameOfWave(image) + " Profiles" string graphtitle = dfname + NameOfWave(image) + " Profiles"
string /g prof_graphname = CleanupName("prof_" + dfname, 0) string /g prof_graphname = graphname_from_dfref(imagedf, "prof_")
svar graphname = prof_graphname svar graphname = prof_graphname
variable /g graph_avg // average value in ROI (ROI is defined by the crosshairs A and B) variable /g graph_avg // average value in ROI (ROI is defined by the crosshairs A and B)
variable /g graph_min // minimum value in ROI variable /g graph_min // minimum value in ROI
@ -193,16 +211,13 @@ function /s ad_display_profiles(image, [filter])
graphname = s_name graphname = s_name
AppendToGraph /w=$graphname /L=xprofiles xprofiles[*][0],xprofiles[*][1],xprofiles[*][2] AppendToGraph /w=$graphname /L=xprofiles xprofiles[*][0],xprofiles[*][1],xprofiles[*][2]
AppendToGraph /w=$graphname /VERT/B=yprofiles yprofiles[*][0],yprofiles[*][1],yprofiles[*][2] AppendToGraph /w=$graphname /VERT/B=yprofiles yprofiles[*][0],yprofiles[*][1],yprofiles[*][2]
AppendToGraph /w=$graphname /R=hist/B=yprofiles hist
AppendImage /w=$graphname view AppendImage /w=$graphname view
string imgname = StringFromList(0, ImageNameList(graphname, ";")) string imgname = StringFromList(0, ImageNameList(graphname, ";"))
ModifyImage /w=$graphname $imgname ctab= {*,*,BlueGreenOrange,0} ModifyImage /w=$graphname $imgname ctab= {*,*,BlueGreenOrange,0}
ModifyGraph /w=$graphname rgb(xprofiles)=(39168,0,0),rgb(yprofiles)=(39168,0,0) ModifyGraph /w=$graphname rgb(xprofiles)=(39168,0,0),rgb(yprofiles)=(39168,0,0)
ModifyGraph /w=$graphname rgb(xprofiles#1)=(0,26112,0),rgb(yprofiles#1)=(0,26112,0) ModifyGraph /w=$graphname rgb(xprofiles#1)=(0,26112,0),rgb(yprofiles#1)=(0,26112,0)
ModifyGraph /w=$graphname rgb(xprofiles#2)=(0,9472,39168),rgb(yprofiles#2)=(0,9472,39168) ModifyGraph /w=$graphname rgb(xprofiles#2)=(0,9472,39168),rgb(yprofiles#2)=(0,9472,39168)
ModifyGraph /w=$graphname rgb(hist)=(43520,43520,43520) ModifyGraph /w=$graphname mirror(xprofiles)=2,mirror(bottom)=3,mirror(yprofiles)=2,mirror(left)=3
ModifyGraph /w=$graphname mode(hist)=5,hbFill(hist)=2
ModifyGraph /w=$graphname mirror(xprofiles)=0,mirror(bottom)=3,mirror(yprofiles)=3,mirror(left)=3
ModifyGraph /w=$graphname nticks=3 ModifyGraph /w=$graphname nticks=3
ModifyGraph /w=$graphname minor=1 ModifyGraph /w=$graphname minor=1
ModifyGraph /w=$graphname axThick=0.5 ModifyGraph /w=$graphname axThick=0.5
@ -210,21 +225,33 @@ function /s ad_display_profiles(image, [filter])
ModifyGraph /w=$graphname btLen=4 ModifyGraph /w=$graphname btLen=4
ModifyGraph /w=$graphname freePos(xprofiles)=0 ModifyGraph /w=$graphname freePos(xprofiles)=0
ModifyGraph /w=$graphname freePos(yprofiles)=0 ModifyGraph /w=$graphname freePos(yprofiles)=0
ModifyGraph /w=$graphname freePos(hist)=0
ModifyGraph /w=$graphname axisEnab(xprofiles)={0.64,1} ModifyGraph /w=$graphname axisEnab(xprofiles)={0.64,1}
ModifyGraph /w=$graphname axisEnab(hist)={0.64,1}
ModifyGraph /w=$graphname axisEnab(bottom)={0,0.6} ModifyGraph /w=$graphname axisEnab(bottom)={0,0.6}
ModifyGraph /w=$graphname axisEnab(yprofiles)={0.64,1} ModifyGraph /w=$graphname axisEnab(yprofiles)={0.64,1}
ModifyGraph /w=$graphname axisEnab(left)={0,0.6} ModifyGraph /w=$graphname axisEnab(left)={0,0.6}
ModifyGraph /w=$graphname zero(left)=8 ModifyGraph /w=$graphname zero(left)=8
ModifyGraph /w=$graphname margin(left)=40,margin(bottom)=30,margin(top)=20,margin(right)=40 ModifyGraph /w=$graphname margin(left)=40,margin(bottom)=30,margin(top)=20,margin(right)=40
ModifyGraph /w=$graphname gfSize=10 ModifyGraph /w=$graphname gfSize=10
Label /w=$graphname xprofiles "value (\\U)"
Label /w=$graphname bottom "X (\\U)" // axis labels
Label /w=$graphname yprofiles "value (\\U)" string labels = note(image)
Label /w=$graphname left "Y (\\U)" string lab
Label /w=$graphname hist "\\Epixels" lab = StringByKey("AxisLabelX", labels, "=", "\r")
SetAxis /w=$graphname /A /E=1 hist if (!strlen(lab))
lab = "X"
endif
Label /w=$graphname bottom lab + " (\\U)"
lab = StringByKey("AxisLabelY", labels, "=", "\r")
if (!strlen(lab))
lab = "Y"
endif
Label /w=$graphname left lab + " (\\U)"
lab = StringByKey("AxisLabelD", labels, "=", "\r")
if (!strlen(lab))
lab = "value"
endif
Label /w=$graphname xprofiles lab + " (\\U)"
Label /w=$graphname yprofiles lab + " (\\U)"
// legend // legend
if (show_legend) if (show_legend)
@ -233,13 +260,18 @@ function /s ad_display_profiles(image, [filter])
AppendText /w=$graphname "\\s(xprofiles#2)\tROI average" AppendText /w=$graphname "\\s(xprofiles#2)\tROI average"
AppendText /w=$graphname "min\t\\{" + s_viewdf + "graph_min}" AppendText /w=$graphname "min\t\\{" + s_viewdf + "graph_min}"
AppendText /w=$graphname "max\t\\{" + s_viewdf + "graph_max}" AppendText /w=$graphname "max\t\\{" + s_viewdf + "graph_max}"
AppendText /w=$graphname "avg\t\\{" + s_viewdf + "graph_avg}"
AppendText /w=$graphname "sum\t\\{" + s_viewdf + "graph_sum}" AppendText /w=$graphname "sum\t\\{" + s_viewdf + "graph_sum}"
AppendText /w=$graphname "avg\t\\{" + s_viewdf + "graph_avg}"
AppendText /w=$graphname "sdev\t\\{" + s_viewdf + "graph_sdev}" AppendText /w=$graphname "sdev\t\\{" + s_viewdf + "graph_sdev}"
else else
TextBox /w=$graphname /C/N=text_sum/F=0/B=1/X=1.00/Y=1.00 "sum \\{" + s_viewdf + "graph_sum}" TextBox /w=$graphname /C/N=text0 /F=0 /B=1 /X=1.00 /Y=1.00
TextBox /w=$graphname /C/N=text_avg/F=0/B=1/X=1.00/Y=6.00 "avg \\{" + s_viewdf + "graph_avg}" lab = StringByKey("Dataset", labels, "=", "\r")
TextBox /w=$graphname /C/N=text_sdev/F=0/B=1/X=1.00/Y=11.00 "sdev \\{" + s_viewdf + "graph_sdev}" if (strlen(lab))
AppendText /w=$graphname lab
endif
AppendText /w=$graphname "sum\t\\{" + s_viewdf + "graph_sum}"
AppendText /w=$graphname "avg\t\\{" + s_viewdf + "graph_avg}"
AppendText /w=$graphname "sdev\t\\{" + s_viewdf + "graph_sdev}"
endif endif
// interactive elements // interactive elements
@ -991,7 +1023,7 @@ function /s ad_display_brick(data)
setdatafolder viewdf setdatafolder viewdf
string dfname = ReplaceString("root:", s_datadf, "") string dfname = ReplaceString("root:", s_datadf, "")
string graphtitle = dfname + " Gizmo" string graphtitle = dfname + " Gizmo"
string /g gizmo_graphname = CleanupName("giz_" + dfname, 0) string /g gizmo_graphname = graphname_from_dfref(datadf, "giz_")
svar graphname = gizmo_graphname svar graphname = gizmo_graphname
if ((strlen(graphname) > 0) && (wintype(graphname) == 13)) if ((strlen(graphname) > 0) && (wintype(graphname) == 13))
@ -1115,13 +1147,32 @@ function ad_brick_slicer(data)
variable /g x_autoinc = 0 variable /g x_autoinc = 0
variable /g y_autoinc = 0 variable /g y_autoinc = 0
variable /g z_autoinc = 0 variable /g z_autoinc = 0
// axis labels
string labels = note(data)
string xlabel = StringByKey("AxisLabelX", labels, "=", "\r")
if (!strlen(xlabel))
xlabel = "X"
endif
string ylabel = StringByKey("AxisLabelY", labels, "=", "\r")
if (!strlen(ylabel))
ylabel = "Y"
endif
string zlabel = StringByKey("AxisLabelZ", labels, "=", "\r")
if (!strlen(zlabel))
zlabel = "Z"
endif
string dlabel = StringByKey("Dataset", labels, "=", "\r")
if (!strlen(dlabel))
dlabel = NameOfWave(data)
endif
// this section copied from slicer panel // this section copied from slicer panel
NewPanel /k=1 /W=(500,600,890,940) /N=SlicerPanel as "Brick Slicer" NewPanel /k=1 /W=(500,600,890,940) /N=SlicerPanel as "Brick Slicer"
string /g slicer_panelname = S_name string /g slicer_panelname = S_name
string panel = s_name string panel = s_name
GroupBox g_xslice win=$panel,pos={8,8},size={376,96},title="X Slice" GroupBox g_xslice win=$panel,pos={8,8},size={376,96},title=xlabel
Slider sl_xslice_position win=$panel,pos={16,32},size={240,56},proc=PearlAreaDisplay#slp_slice_position Slider sl_xslice_position win=$panel,pos={16,32},size={240,56},proc=PearlAreaDisplay#slp_slice_position
Slider sl_xslice_position win=$panel,limits={0,100,1},variable=x_slice_pos,vert= 0 Slider sl_xslice_position win=$panel,limits={0,100,1},variable=x_slice_pos,vert= 0
SetVariable sv_xslice_position win=$panel,pos={20,80},size={92,16},proc=PearlAreaDisplay#svp_slice_position,title="X" SetVariable sv_xslice_position win=$panel,pos={20,80},size={92,16},proc=PearlAreaDisplay#svp_slice_position,title="X"
@ -1141,7 +1192,7 @@ function ad_brick_slicer(data)
Button b_xslice_stop win=$panel,pos={336,48},size={20,20},proc=PearlAreaDisplay#bp_move_slice,title="\\W616" Button b_xslice_stop win=$panel,pos={336,48},size={20,20},proc=PearlAreaDisplay#bp_move_slice,title="\\W616"
Button b_xslice_stop win=$panel,help={"stop animation"} Button b_xslice_stop win=$panel,help={"stop animation"}
GroupBox g_yslice win=$panel,pos={8,108},size={376,96},title="Y Slice" GroupBox g_yslice win=$panel,pos={8,108},size={376,96},title=ylabel
Slider sl_yslice_position win=$panel,pos={16,132},size={240,56},proc=PearlAreaDisplay#slp_slice_position Slider sl_yslice_position win=$panel,pos={16,132},size={240,56},proc=PearlAreaDisplay#slp_slice_position
Slider sl_yslice_position win=$panel,limits={0,100,1},variable=y_slice_pos,vert= 0 Slider sl_yslice_position win=$panel,limits={0,100,1},variable=y_slice_pos,vert= 0
SetVariable sv_yslice_position win=$panel,pos={20,180},size={92,16},proc=PearlAreaDisplay#svp_slice_position,title="Y" SetVariable sv_yslice_position win=$panel,pos={20,180},size={92,16},proc=PearlAreaDisplay#svp_slice_position,title="Y"
@ -1161,7 +1212,7 @@ function ad_brick_slicer(data)
Button b_yslice_stop win=$panel,pos={336,148},size={20,20},proc=PearlAreaDisplay#bp_move_slice,title="\\W616" Button b_yslice_stop win=$panel,pos={336,148},size={20,20},proc=PearlAreaDisplay#bp_move_slice,title="\\W616"
Button b_yslice_stop win=$panel,help={"stop animation"} Button b_yslice_stop win=$panel,help={"stop animation"}
GroupBox g_zslice win=$panel,pos={8,208},size={376,96},title="Z Slice" GroupBox g_zslice win=$panel,pos={8,208},size={376,96},title=zlabel
Slider sl_zslice_position win=$panel,pos={16,232},size={240,56},proc=PearlAreaDisplay#slp_slice_position Slider sl_zslice_position win=$panel,pos={16,232},size={240,56},proc=PearlAreaDisplay#slp_slice_position
Slider sl_zslice_position win=$panel,limits={0,100,1},variable=z_slice_pos,vert= 0 Slider sl_zslice_position win=$panel,limits={0,100,1},variable=z_slice_pos,vert= 0
SetVariable sv_zslice_position win=$panel,pos={20,280},size={92,16},proc=PearlAreaDisplay#svp_slice_position,title="Z" SetVariable sv_zslice_position win=$panel,pos={20,280},size={92,16},proc=PearlAreaDisplay#svp_slice_position,title="Z"
@ -1181,7 +1232,7 @@ function ad_brick_slicer(data)
Button b_zslice_stop win=$panel,pos={336,248},size={20,20},proc=PearlAreaDisplay#bp_move_slice,title="\\W616" Button b_zslice_stop win=$panel,pos={336,248},size={20,20},proc=PearlAreaDisplay#bp_move_slice,title="\\W616"
Button b_zslice_stop win=$panel,help={"stop animation"} Button b_zslice_stop win=$panel,help={"stop animation"}
TitleBox t_slicerpath win=$panel,pos={8,316},size={128,20},disable=2,title=GetDataFolder(1,viewdf) TitleBox t_slicerpath win=$panel,pos={8,316},size={128,20},disable=2,title=dlabel
//SetVariable setvar0 win=$panel,pos={240,316},size={120,16},title="slab thickness" //SetVariable setvar0 win=$panel,pos={240,316},size={120,16},title="slab thickness"
//SetVariable setvar0 win=$panel,limits={1,inf,1},value=slab_thickness //SetVariable setvar0 win=$panel,limits={1,inf,1},value=slab_thickness

View File

@ -613,3 +613,36 @@ threadsafe function calc_y_profile_mins(image)
yminlocs[ix] = v_minloc yminlocs[ix] = v_minloc
endfor endfor
end end
/// collect profiles from a multi-scan.
///
/// @warning experimental: name and interface of this function may change.
///
function ad_collect_multiscan_y(dataset, positions, destwave, [noavg])
wave dataset
wave positions
wave destwave
variable noavg
variable tol = (wavemax(positions) - wavemin(positions)) / numpnts(positions) / 100
duplicate /free positions, positions_sorted
sort positions_sorted, positions_sorted
duplicate /free positions_sorted, positions_diff
differentiate /p /meth=2 positions_sorted /d=positions_diff
positions_diff[0] = 1
extract /free positions_sorted, positions_unique, positions_diff > tol
variable n_unique = numpnts(positions_unique)
redimension /n=(dimsize(dataset, 0), n_unique) destwave
variable i
variable nx, ny
for (i = 0; i < n_unique; i += 1)
extract /free dataset, data_extract, abs(positions[q] - positions_unique[i]) < tol
nx = dimsize(dataset, 0)
ny = dimsize(data_extract, 0) / nx
redimension /n=(nx, ny) data_extract
wave profile = ad_profile_x(data_extract, -inf, inf, "", noavg=noavg)
destwave[][i] = profile[p]
endfor
end

View File

@ -759,18 +759,21 @@ static function /s show_preview_graph(data, [xdata])
svar s_profiles_graph svar s_profiles_graph
svar s_preview_file svar s_preview_file
svar s_preview_source svar s_preview_source
svar s_preview_trace_graph
if ((strlen(s_profiles_graph) > 0) && (WinType(s_profiles_graph) == 1))
KillWindow $s_profiles_graph
endif
if ((strlen(s_preview_trace_graph) > 0) && (WinType(s_preview_trace_graph) == 1))
KillWindow $s_preview_trace_graph
endif
string graphname string graphname
if (wavedims(data) == 2) if (wavedims(data) == 2)
if ((strlen(s_profiles_graph) > 0) && (WinType(s_profiles_graph) == 1)) s_profiles_graph = ad_display_profiles(data)
ad_update_profiles(data) ModifyGraph /w=$s_profiles_graph /z wbRGB=(48640,56832,60160)
else
s_profiles_graph = ad_display_profiles(data)
ModifyGraph /w=$s_profiles_graph /z wbRGB=(48640,56832,60160)
endif
graphname = s_profiles_graph graphname = s_profiles_graph
elseif (wavedims(data) == 1) elseif (wavedims(data) == 1)
svar s_preview_trace_graph
duplicate /o data, preview_trace duplicate /o data, preview_trace
if (!ParamIsDefault(xdata)) if (!ParamIsDefault(xdata))
duplicate /o xdata, preview_trace_x duplicate /o xdata, preview_trace_x
@ -779,20 +782,8 @@ static function /s show_preview_graph(data, [xdata])
preview_trace_x = x preview_trace_x = x
setscale d 0, 0, WaveUnits(data, 0), preview_trace_x setscale d 0, 0, WaveUnits(data, 0), preview_trace_x
endif endif
if ((strlen(s_preview_trace_graph) == 0) || (WinType(s_preview_trace_graph) != 1)) s_preview_trace_graph = display_preview_trace(preview_trace_x, preview_trace)
display /n=pearl_explorer_1d /k=1 preview_trace vs preview_trace_x as "Preview" ModifyGraph /w=$s_preview_trace_graph wbRGB=(48640,56832,60160)
s_preview_trace_graph = s_name
ModifyGraph /w=$s_preview_trace_graph wbRGB=(48640,56832,60160)
ModifyGraph /w=$s_preview_trace_graph rgb[0]=(0,0,0)
ModifyGraph /w=$s_preview_trace_graph grid=2
ModifyGraph /w=$s_preview_trace_graph mirror=1
ModifyGraph /w=$s_preview_trace_graph minor=1
ModifyGraph /w=$s_preview_trace_graph axThick=0.5
ModifyGraph /w=$s_preview_trace_graph gridRGB=(52224,52224,52224)
ModifyGraph /w=$s_preview_trace_graph gridHair=0
ModifyGraph /w=$s_preview_trace_graph tick=0
ModifyGraph /w=$s_preview_trace_graph btLen=4
endif
graphname = s_preview_trace_graph graphname = s_preview_trace_graph
else else
return "" return ""
@ -808,6 +799,39 @@ static function /s show_preview_graph(data, [xdata])
return graphname return graphname
end end
static function /s display_preview_trace(xtrace, ytrace)
wave xtrace
wave ytrace
display /n=pearl_explorer_1d /k=1 ytrace vs xtrace as "Preview"
string graphname = s_name
ModifyGraph /w=$graphname rgb[0]=(0,0,0)
ModifyGraph /w=$graphname grid=2
ModifyGraph /w=$graphname mirror=1
ModifyGraph /w=$graphname minor=1
ModifyGraph /w=$graphname axThick=0.5
ModifyGraph /w=$graphname gridRGB=(52224,52224,52224)
ModifyGraph /w=$graphname gridHair=0
ModifyGraph /w=$graphname tick=0
ModifyGraph /w=$graphname btLen=4
// axis labels
string labels = note(ytrace)
string lab
lab = StringByKey("AxisLabelX", labels, "=", "\r")
if (!strlen(lab))
lab = "X"
endif
Label /w=$graphname bottom lab + " (\\U)"
lab = StringByKey("AxisLabelD", labels, "=", "\r")
if (!strlen(lab))
lab = "value"
endif
Label /w=$graphname left lab + " (\\U)"
return s_name
end
static function load_selected_files([options]) static function load_selected_files([options])
string options string options
@ -1426,6 +1450,9 @@ static function bp_dataset_folder(ba) : ButtonControl
string cmd string cmd
sprintf cmd, "setdatafolder root:%s", PossiblyQuoteName(dataset) sprintf cmd, "setdatafolder root:%s", PossiblyQuoteName(dataset)
execute /q /z cmd execute /q /z cmd
cmd = "setdatafolder :scan1"
execute /q /z cmd
sprintf cmd, "setdatafolder %s", GetDataFolder(1)
print cmd print cmd
endif endif
break break

View File

@ -454,7 +454,7 @@ function Au4f(w, x): fitfunc
vc1 = w[ip] / sqrt(pi) * vc2 vc1 = w[ip] / sqrt(pi) * vc2
vc3 = w[ip+1] vc3 = w[ip+1]
vc4 = vc2 * w[ip+2] / 2 vc4 = vc2 * w[ip+2] / 2
v += vc1 * Voigt(vc2 * (x - vc3), vc4) v += vc1 * VoigtFunc(vc2 * (x - vc3), vc4)
endfor endfor
return v return v
@ -491,25 +491,25 @@ function Au4f_2p2(w, x): fitfunc
vc1 = w[3] / sqrt(pi) * vc2 vc1 = w[3] / sqrt(pi) * vc2
vc3 = w[4] vc3 = w[4]
vc4 = vc2 * w[5] / 2 vc4 = vc2 * w[5] / 2
v += vc1 * Voigt(vc2 * (x - vc3), vc4) v += vc1 * VoigtFunc(vc2 * (x - vc3), vc4)
// 5/2 surface // 5/2 surface
vc1 = w[3] / sqrt(pi) * vc2 * w[9] vc1 = w[3] / sqrt(pi) * vc2 * w[9]
vc3 = w[4] + w[10] vc3 = w[4] + w[10]
vc4 = vc2 * w[5] / 2 vc4 = vc2 * w[5] / 2
v += vc1 * Voigt(vc2 * (x - vc3), vc4) v += vc1 * VoigtFunc(vc2 * (x - vc3), vc4)
// 7/2 bulk // 7/2 bulk
vc1 = w[6] / sqrt(pi) * vc2 vc1 = w[6] / sqrt(pi) * vc2
vc3 = w[7] vc3 = w[7]
vc4 = vc2 * w[8] / 2 vc4 = vc2 * w[8] / 2
v += vc1 * Voigt(vc2 * (x - vc3), vc4) v += vc1 * VoigtFunc(vc2 * (x - vc3), vc4)
// 7/2 surface // 7/2 surface
vc1 = w[6] / sqrt(pi) * vc2 * w[9] vc1 = w[6] / sqrt(pi) * vc2 * w[9]
vc3 = w[7] + w[10] vc3 = w[7] + w[10]
vc4 = vc2 * w[8] / 2 vc4 = vc2 * w[8] / 2
v += vc1 * Voigt(vc2 * (x - vc3), vc4) v += vc1 * VoigtFunc(vc2 * (x - vc3), vc4)
return v return v
@ -578,37 +578,37 @@ function Au4f_2p3(w, x): fitfunc
vc1 = w[3] / sqrt(pi) * vc2 vc1 = w[3] / sqrt(pi) * vc2
vc3 = w[4] vc3 = w[4]
vc4 = vc2 * w[5] / 2 vc4 = vc2 * w[5] / 2
v += vc1 * Voigt(vc2 * (x - vc3), vc4) v += vc1 * VoigtFunc(vc2 * (x - vc3), vc4)
// 5/2 surface // 5/2 surface
vc1 = w[3] / sqrt(pi) * vc2 * w[9] vc1 = w[3] / sqrt(pi) * vc2 * w[9]
vc3 = w[4] + w[10] vc3 = w[4] + w[10]
vc4 = vc2 * w[5] / 2 vc4 = vc2 * w[5] / 2
v += vc1 * Voigt(vc2 * (x - vc3), vc4) v += vc1 * VoigtFunc(vc2 * (x - vc3), vc4)
// 5/2 2nd layer // 5/2 2nd layer
vc1 = w[3] / sqrt(pi) * vc2 * w[11] vc1 = w[3] / sqrt(pi) * vc2 * w[11]
vc3 = w[4] + w[12] vc3 = w[4] + w[12]
vc4 = vc2 * w[5] / 2 vc4 = vc2 * w[5] / 2
v += vc1 * Voigt(vc2 * (x - vc3), vc4) v += vc1 * VoigtFunc(vc2 * (x - vc3), vc4)
// 7/2 bulk // 7/2 bulk
vc1 = w[6] / sqrt(pi) * vc2 vc1 = w[6] / sqrt(pi) * vc2
vc3 = w[7] vc3 = w[7]
vc4 = vc2 * w[8] / 2 vc4 = vc2 * w[8] / 2
v += vc1 * Voigt(vc2 * (x - vc3), vc4) v += vc1 * VoigtFunc(vc2 * (x - vc3), vc4)
// 7/2 surface // 7/2 surface
vc1 = w[6] / sqrt(pi) * vc2 * w[9] vc1 = w[6] / sqrt(pi) * vc2 * w[9]
vc3 = w[7] + w[10] vc3 = w[7] + w[10]
vc4 = vc2 * w[8] / 2 vc4 = vc2 * w[8] / 2
v += vc1 * Voigt(vc2 * (x - vc3), vc4) v += vc1 * VoigtFunc(vc2 * (x - vc3), vc4)
// 7/2 2nd layer // 7/2 2nd layer
vc1 = w[6] / sqrt(pi) * vc2 * w[11] vc1 = w[6] / sqrt(pi) * vc2 * w[11]
vc3 = w[7] + w[12] vc3 = w[7] + w[12]
vc4 = vc2 * w[8] / 2 vc4 = vc2 * w[8] / 2
v += vc1 * Voigt(vc2 * (x - vc3), vc4) v += vc1 * VoigtFunc(vc2 * (x - vc3), vc4)
return v return v

View File

@ -1,5 +1,5 @@
#pragma rtGlobals=3 // Use modern global access method and strict wave access. #pragma rtGlobals=3 // Use modern global access method and strict wave access.
#pragma IgorVersion = 6.2 #pragma IgorVersion = 6.36
#pragma ModuleName = PearlPShellImport #pragma ModuleName = PearlPShellImport
#pragma version = 1.02 #pragma version = 1.02
#include <HDF5 Browser> #include <HDF5 Browser>
@ -66,6 +66,15 @@ strconstant kScanDimLabel = "scan"
/// This label may be used to store the parameters for the `setscale d` operation. /// This label may be used to store the parameters for the `setscale d` operation.
strconstant kDataDimLabel = "data" strconstant kDataDimLabel = "data"
/// List of preferred datasets to load for preview
strconstant kPreviewDatasets = "ScientaImage;ScientaSpectrum;ImageAngleDistribution;ImageEnergyDistribution;Counts;SampleCurrent;"
/// List of datasets that must be loaded to determine the axis scaling of a Scienta image
strconstant kScientaScalingDatasets = "LensMode;ScientaChannelBegin;ScientaChannelEnd;ScientaSliceBegin;ScientaSliceEnd;"
/// List of datasets that should be transposed upon loading
strconstant kTransposedDatasets = "ScientaImage;"
/// open a HDF5 file created by the PShell data acquisition program and prepare the data folder. /// open a HDF5 file created by the PShell data acquisition program and prepare the data folder.
/// ///
/// the function opens a specified or interactively selected HDF5 file, /// the function opens a specified or interactively selected HDF5 file,
@ -183,7 +192,9 @@ function /s psh5_load_complete(ANickName, APathName, AFileName, [load_data, load
for (ig = 0; ig < ng; ig += 1) for (ig = 0; ig < ng; ig += 1)
sg = StringFromList(ig, s_scanpaths, ";") sg = StringFromList(ig, s_scanpaths, ";")
folder = CleanupName(ReplaceString("/", sg, ""), 0) folder = ReplaceString("/", sg, "")
folder = ReplaceString(" ", folder, "")
folder = CleanupName(folder, 0)
setdatafolder fileDF setdatafolder fileDF
newdatafolder /s /o $folder newdatafolder /s /o $folder
psh5_load_scan_complete(fileID, sg, load_data=load_data, load_attr=load_attr) psh5_load_scan_complete(fileID, sg, load_data=load_data, load_attr=load_attr)
@ -219,14 +230,26 @@ end
/// @param load_attr 1 (default): load attributes; 0: do not load attributes /// @param load_attr 1 (default): load attributes; 0: do not load attributes
/// note: for correct scaling of the image, the attributes need to be loaded /// note: for correct scaling of the image, the attributes need to be loaded
/// ///
/// @param pref_scans semicolon-separated list of preferred scans.
/// the items of the list are match strings for the Igor StringMatch function.
/// the first matching scan (i.e. top-level HDF5 group with a matching name) is loaded from the file.
/// if no match is found, the first scan is loaded.
///
/// @param pref_datasets semicolon-separated list of preferred datasets.
/// the items of the list are match strings for the Igor StringMatch function.
/// the first matching dataset is loaded from the file.
/// if no match is found, the first dataset listed in the file is loaded.
///
/// @return name of loaded preview wave. /// @return name of loaded preview wave.
/// ///
function /s psh5_load_preview(ANickName, APathName, AFileName, [load_data, load_attr]) function /s psh5_load_preview(ANickName, APathName, AFileName, [load_data, load_attr, pref_scans, pref_datasets])
string ANickName string ANickName
string APathName string APathName
string AFileName string AFileName
variable load_data variable load_data
variable load_attr variable load_attr
string pref_scans
string pref_datasets
if (ParamIsDefault(load_data)) if (ParamIsDefault(load_data))
load_data = 1 load_data = 1
@ -234,7 +257,13 @@ function /s psh5_load_preview(ANickName, APathName, AFileName, [load_data, load_
if (ParamIsDefault(load_attr)) if (ParamIsDefault(load_attr))
load_attr = 1 load_attr = 1
endif endif
if (ParamIsDefault(pref_scans))
pref_scans = "*scan1*;"
endif
if (ParamIsDefault(pref_datasets))
pref_datasets = ""
endif
dfref saveDF = GetDataFolderDFR() dfref saveDF = GetDataFolderDFR()
setdatafolder root: setdatafolder root:
newdatafolder /o/s pearl_area newdatafolder /o/s pearl_area
@ -253,26 +282,53 @@ function /s psh5_load_preview(ANickName, APathName, AFileName, [load_data, load_
if (v_flag == 0) if (v_flag == 0)
AFileName = s_path + s_filename AFileName = s_path + s_filename
dfref fileDF = GetDataFolderDFR() dfref fileDF = GetDataFolderDFR()
scanpaths = psh5_list_scans(fileID) scanpaths = psh5_list_scans(fileID)
variable ng = ItemsInList(scanpaths)
variable ig variable ig
string sg string sg
ig = 0 variable np = ItemsInList(pref_scans)
sg = StringFromList(ig, scanpaths, ";") variable ip
dataname = psh5_load_scan_preview(fileID, sg, set_scale=load_attr) string sp
variable found = 0
if (ng > 0)
for (ip = 0; ip < np; ip += 1)
for (ig = 0; ig < ng; ig += 1)
sg = StringFromList(ig, scanpaths)
sp = StringFromList(ip, pref_scans)
if (StringMatch(sg, sp))
found = 1
break
endif
endfor
if (found)
break
endif
endfor
if (!found)
ig = 0
endif
sg = StringFromList(ig, scanpaths)
dataname = psh5_load_scan_preview(fileID, sg, set_scale=load_attr, pref_datasets=pref_datasets)
wave /z data = $dataname wave /z data = $dataname
string destpath = GetDataFolder(1, saveDF) + ANickName string destpath = GetDataFolder(1, saveDF) + ANickName
if (waveexists(data)) if (waveexists(data))
duplicate /o data, $destpath duplicate /o data, $destpath
wave /z data = $destpath wave /z data = $destpath
endif else
print "no data found in file " + AFileName
if (load_attr) endif
setdatafolder saveDF
newdatafolder /o/s attr if (load_attr)
killwaves /a/z setdatafolder saveDF
psh5_load_scan_attrs(fileID, sg) newdatafolder /o/s attr
setdatafolder :: killwaves /a/z
psh5_load_scan_attrs(fileID, sg)
setdatafolder ::
endif
else
print "no scans found in file " + AFileName
endif endif
HDF5CloseFile fileID HDF5CloseFile fileID
@ -396,6 +452,9 @@ end
/// ///
/// data is loaded into the current data folder. /// data is loaded into the current data folder.
/// ///
/// this function does not scale the datasets.
/// call ps_scale_datasets() separately.
///
/// @param fileID ID of open HDF5 file from psh5_open_file(). /// @param fileID ID of open HDF5 file from psh5_open_file().
/// ///
/// @param scanpath path to the scan group in the HDF5 file, e.g. "/scan 1". /// @param scanpath path to the scan group in the HDF5 file, e.g. "/scan 1".
@ -464,17 +523,21 @@ function /s psh5_load_scan_attrs(fileID, scanpath, [attr_sets])
endif endif
endif endif
variable ids
variable nds
string sds
if (attr_sets & 2) if (attr_sets & 2)
attr_list = AddListItem("LensMode", attr_list, ";", inf) nds = ItemsInList(kScientaScalingDatasets, ";")
attr_list = AddListItem("ScientaChannelBegin", attr_list, ";", inf) for (ids = 0; ids < nds; ids += 1)
attr_list = AddListItem("ScientaChannelEnd", attr_list, ";", inf) sds = StringFromList(ids, kScientaScalingDatasets)
attr_list = AddListItem("ScientaSliceBegin", attr_list, ";", inf) if (WhichListItem(sds, attr_list) < 0)
attr_list = AddListItem("ScientaSliceEnd", attr_list, ";", inf) attr_list = AddListItem(sds, attr_list, ";", inf)
endif
endfor
endif endif
variable ids nds = ItemsInList(attr_list, ";")
variable nds = ItemsInList(attr_list, ";")
string sds
string wavenames = "" string wavenames = ""
for (ids = 0; ids < nds; ids += 1) for (ids = 0; ids < nds; ids += 1)
sds = StringFromList(ids, attr_list, ";") sds = StringFromList(ids, attr_list, ";")
@ -483,6 +546,7 @@ function /s psh5_load_scan_attrs(fileID, scanpath, [attr_sets])
wavenames = AddListItem(s_wavenames, wavenames, ";", inf) wavenames = AddListItem(s_wavenames, wavenames, ";", inf)
endif endif
endfor endfor
wavenames = ReplaceString(";;", wavenames, ";")
return wavenames return wavenames
end end
@ -517,27 +581,29 @@ function /s psh5_load_scan_meta(fileID, scanpath)
HDF5LoadData /O /Q /Z /A="Dimensions" /N=ScanDimensions /TYPE=1 fileID, scanpath HDF5LoadData /O /Q /Z /A="Dimensions" /N=ScanDimensions /TYPE=1 fileID, scanpath
if (!v_flag) if (!v_flag)
wavenames = AddListItem(s_wavenames, wavenames, ";", inf) wavenames = AddListItem(s_wavenames, wavenames, ";", inf)
HDF5LoadData /O /Q /Z /A="Writables" /N=ScanWritables /TYPE=1 fileID, scanpath
if (!v_flag)
wavenames = AddListItem(s_wavenames, wavenames, ";", inf)
endif
HDF5LoadData /O /Q /Z /A="Readables" /N=ScanReadables /TYPE=1 fileID, scanpath
if (!v_flag)
wavenames = AddListItem(s_wavenames, wavenames, ";", inf)
endif
HDF5LoadData /O /Q /Z /A="Steps" /N=ScanSteps /TYPE=1 fileID, scanpath
if (!v_flag)
wavenames = AddListItem(s_wavenames, wavenames, ";", inf)
endif
else else
make /n=1 /o ScanDimensions make /n=1 /o ScanDimensions
ScanDimensions = 0 ScanDimensions = 0
wavenames = AddListItem("ScanDimensions", wavenames, ";", inf) wavenames = AddListItem("ScanDimensions", wavenames, ";", inf)
endif
HDF5LoadData /O /Q /Z /A="Readables" /N=ScanReadables /TYPE=1 fileID, scanpath
if (!v_flag)
wavenames = AddListItem(s_wavenames, wavenames, ";", inf)
else
make /n=1 /o /t ScanReadables make /n=1 /o /t ScanReadables
ScanReadables[0] = "ScientaSpectrum" ScanReadables[0] = "ScientaSpectrum"
wavenames = AddListItem("ScanReadables", wavenames, ";", inf) wavenames = AddListItem("ScanReadables", wavenames, ";", inf)
endif endif
HDF5LoadData /O /Q /Z /A="Writables" /N=ScanWritables /TYPE=1 fileID, scanpath
if (!v_flag)
wavenames = AddListItem(s_wavenames, wavenames, ";", inf)
endif
HDF5LoadData /O /Q /Z /A="Steps" /N=ScanSteps /TYPE=1 fileID, scanpath
if (!v_flag)
wavenames = AddListItem(s_wavenames, wavenames, ";", inf)
endif
wavenames = ReplaceString(";;", wavenames, ";")
return wavenames return wavenames
end end
@ -572,6 +638,10 @@ function /s psh5_load_dataset(fileID, scanpath, datasetname, [set_scale])
string datasetname string datasetname
variable set_scale variable set_scale
if (ParamIsDefault(set_scale))
set_scale = 1
endif
string datasetpath string datasetpath
datasetpath = scanpath + "/" + datasetname datasetpath = scanpath + "/" + datasetname
datasetpath = ReplaceString("//", datasetpath, "/") datasetpath = ReplaceString("//", datasetpath, "/")
@ -585,7 +655,7 @@ function /s psh5_load_dataset(fileID, scanpath, datasetname, [set_scale])
endif endif
string dataname string dataname
if (di.ndims < 3) if (di.ndims < 2)
HDF5LoadData /O /Q /Z fileID, datasetpath HDF5LoadData /O /Q /Z fileID, datasetpath
dataname = StringFromList(0, S_waveNames) dataname = StringFromList(0, S_waveNames)
else else
@ -606,6 +676,56 @@ function /s psh5_load_dataset(fileID, scanpath, datasetname, [set_scale])
return dataname return dataname
end end
/// select the preferred dataset from a list of available datasets.
///
/// @param file_datasets semicolon-separated list of datasets that are available in the file.
///
/// @param pref_datasets semicolon-separated list of preferred datasets.
/// the items of the list are match strings for the Igor StringMatch function.
/// the first matching dataset is loaded from the file.
/// if no match is found, the first file dataset is selected.
///
/// @return name of selected dataset.
///
static function /s select_dataset(file_datasets, pref_datasets)
string file_datasets
string pref_datasets
variable index
variable nds = ItemsInList(file_datasets)
variable ids
string sds = ""
variable np = ItemsInList(pref_datasets)
variable ip
string sp
variable found = 0
if (nds > 0)
for (ip = 0; ip < np; ip += 1)
for (ids = 0; ids < nds; ids += 1)
sds = StringFromList(ids, file_datasets)
index = ItemsInList(sds, "/") - 1
sds = StringFromList(index, sds, "/")
sp = StringFromList(ip, pref_datasets)
if (StringMatch(sds, sp))
found = 1
break
endif
endfor
if (found)
break
endif
endfor
if (!found)
ids = 0
sds = StringFromList(ids, file_datasets)
index = ItemsInList(sds, "/") - 1
sds = StringFromList(index, sds, "/")
endif
endif
return sds
end
/// load a preview dataset from an open PShell HDF5 file. /// load a preview dataset from an open PShell HDF5 file.
/// ///
/// if the dataset has a maximum of two dimensions, the function loads it at once. /// if the dataset has a maximum of two dimensions, the function loads it at once.
@ -616,53 +736,42 @@ end
/// ///
/// @param scanpath path to the scan group in the HDF5 file, e.g. "/scan 1". /// @param scanpath path to the scan group in the HDF5 file, e.g. "/scan 1".
/// ///
/// @param dataset name of the dataset.
/// the name of the loaded wave is a cleaned up version of the dataset name.
///
/// @param set_scale by default, the function tries to set the wave scaling if the attributes have been loaded. /// @param set_scale by default, the function tries to set the wave scaling if the attributes have been loaded.
/// if multiple datasets are loaded from a file, /// if multiple datasets are loaded from a file,
/// it is more efficient to set the scaling of all loaded datasets at the end by calling ps_scale_datasets(). /// it is more efficient to set the scaling of all loaded datasets at the end by calling ps_scale_datasets().
/// @arg 1 (default) set the wave scaling. /// @arg 1 (default) set the wave scaling.
/// @arg 0 do not set the wave scaling. /// @arg 0 do not set the wave scaling.
/// ///
/// @param pref_datasets semicolon-separated list of preferred datasets.
/// the items of the list are match strings for the Igor StringMatch function.
/// the first matching dataset is loaded from the file.
/// if no match is found, the first dataset listed in the file is loaded.
/// if empty, a hard-coded default preference list is used.
///
/// @return name of loaded wave if successful. empty string otherwise. /// @return name of loaded wave if successful. empty string otherwise.
/// ///
function /s psh5_load_scan_preview(fileID, scanpath, [set_scale]) function /s psh5_load_scan_preview(fileID, scanpath, [set_scale, pref_datasets])
variable fileID variable fileID
string scanpath string scanpath
variable set_scale variable set_scale
string pref_datasets
if (ParamIsDefault(set_scale))
set_scale = 1
endif
if (ParamIsDefault(pref_datasets) || (strlen(pref_datasets) == 0))
pref_datasets = kPreviewDatasets
endif
dfref saveDF = GetDataFolderDFR() dfref saveDF = GetDataFolderDFR()
dfref dataDF = saveDF dfref dataDF = saveDF
string datasets = psh5_list_scan_datasets(fileID, scanpath) string datasets = psh5_list_scan_datasets(fileID, scanpath)
string datasetname = "" string datasetname = select_dataset(datasets, pref_datasets)
variable index
// todo: this should be generalized
if (strsearch(datasets, "ScientaImage", 0) >= 0)
datasetname = "ScientaImage"
elseif (strsearch(datasets, "ScientaSpectrum", 0) >= 0)
datasetname = "ScientaSpectrum"
elseif (strsearch(datasets, "ScientaEnergyDistribution", 0) >= 0)
datasetname = "ScientaEnergyDistribution"
elseif (strsearch(datasets, "ImageEnergyDistribution", 0) >= 0)
datasetname = "ImageEnergyDistribution"
elseif (strsearch(datasets, "Counts", 0) >= 0)
datasetname = "Counts"
elseif (strsearch(datasets, "SampleCurrent", 0) >= 0)
datasetname = "SampleCurrent"
else
datasetname = StringFromList(0, datasets)
index = ItemsInList(datasetname, "/") - 1
datasetname = StringFromList(index, datasetname, "/")
endif
if (strlen(datasetname) == 0)
return ""
endif
string datasetpath string datasetpath
datasetpath = scanpath + "/" + datasetname datasetpath = scanpath + "/" + datasetname
datasetpath = ReplaceString("//", datasetpath, "/") datasetpath = ReplaceString("//", datasetpath, "/")
STRUCT HDF5DataInfo di // Defined in HDF5 Browser.ipf. STRUCT HDF5DataInfo di // Defined in HDF5 Browser.ipf.
InitHDF5DataInfo(di) InitHDF5DataInfo(di)
variable err = HDF5DatasetInfo(fileID, datasetpath, 0, di) variable err = HDF5DatasetInfo(fileID, datasetpath, 0, di)
@ -672,7 +781,7 @@ function /s psh5_load_scan_preview(fileID, scanpath, [set_scale])
endif endif
string dataname string dataname
if (di.ndims < 3) if (di.ndims < 2)
HDF5LoadData /O /Q /Z fileID, datasetpath HDF5LoadData /O /Q /Z fileID, datasetpath
dataname = StringFromList(0, S_waveNames) dataname = StringFromList(0, S_waveNames)
wave /z data = $dataname wave /z data = $dataname
@ -699,6 +808,21 @@ function /s psh5_load_scan_preview(fileID, scanpath, [set_scale])
wave /z data = $dataname wave /z data = $dataname
if (waveexists(data)) if (waveexists(data))
if (set_scale) if (set_scale)
setdatafolder dataDF
string positioners
string positioner
string positionerpath
positioners = psh5_load_scan_meta(fileID, scanpath)
wave /t /z ScanWritables
if (waveexists(ScanWritables) && (numpnts(ScanWritables) >= 1))
positioner = ScanWritables[0]
if (strlen(positioner) > 0)
positionerpath = scanpath + "/" + positioner
positionerpath = ReplaceString("//", positionerpath, "/")
HDF5LoadData /O /Q /Z fileID, positionerpath
endif
endif
setdatafolder dataDF setdatafolder dataDF
newdatafolder /o/s attr newdatafolder /o/s attr
killwaves /a/z killwaves /a/z
@ -713,6 +837,153 @@ function /s psh5_load_scan_preview(fileID, scanpath, [set_scale])
return dataname return dataname
end end
/// load a longitudinal section of a scan from an open PShell HDF5 file.
///
/// the dataset must have three dimensions.
///
///
/// @param fileID ID of open HDF5 file from psh5_open_file().
///
/// @param scanpath path to the scan group in the HDF5 file, e.g. "/scan 1".
///
/// @param dim reserved, must be 0.
///
/// @param set_scale by default, the function tries to set the wave scaling if the attributes have been loaded.
/// if multiple datasets are loaded from a file,
/// it is more efficient to set the scaling of all loaded datasets at the end by calling ps_scale_datasets().
/// @arg 1 (default) set the wave scaling.
/// @arg 0 do not set the wave scaling.
///
/// @param pref_datasets semicolon-separated list of preferred datasets.
/// the items of the list are match strings for the Igor StringMatch function.
/// the first matching dataset is loaded from the file.
/// if no match is found, the first dataset listed in the file is loaded.
/// if empty, a hard-coded default preference list is used.
///
/// @return name of loaded wave if successful. empty string otherwise.
///
/// @warning EXPERIMENTAL: this function is under development.
///
function /s psh5_load_scan_section(fileID, scanpath, dim, [set_scale, pref_datasets])
variable fileID
string scanpath
variable dim
variable set_scale
string pref_datasets
// select first dimension (future argument)
// 0 = first dimension is x axis (energy of scienta image)
dim = 0
if (ParamIsDefault(set_scale))
set_scale = 1
endif
if (ParamIsDefault(pref_datasets) || (strlen(pref_datasets) == 0))
pref_datasets = kPreviewDatasets
endif
dfref saveDF = GetDataFolderDFR()
dfref dataDF = saveDF
string datasets = psh5_list_scan_datasets(fileID, scanpath)
string datasetname = select_dataset(datasets, pref_datasets)
string datasetpath
datasetpath = scanpath + "/" + datasetname
datasetpath = ReplaceString("//", datasetpath, "/")
string dataname = StringFromList(ItemsInList(datasetpath, "/") - 1, datasetpath, "/")
string destname = dataname[0,29] + num2str(dim)
STRUCT HDF5DataInfo di // Defined in HDF5 Browser.ipf.
InitHDF5DataInfo(di)
variable err = HDF5DatasetInfo(fileID, datasetpath, 0, di)
if (err != 0)
print "error accessing detector/data"
return ""
elseif (di.ndims != 3)
print "error: rank of dataset != 3"
return ""
endif
variable idx, idy, idz, idt
variable transpose = WhichListItem(dataname, kTransposedDatasets) >= 0
if (transpose)
idx = 1
idy = 0
else
idx = 0
idy = 1
endif
idz = 2
idt = 3
variable nx, ny, nz
nx = di.dims[idx]
ny = di.dims[idy]
nz = di.dims[idz]
HDF5MakeHyperslabWave(GetDataFolder(1) + "slab", max(di.ndims, 4))
wave slab
slab[][%Start] = 0
slab[][%Stride] = 1
slab[][%Count] = 1
slab[][%Block] = 1
if (dim == 0)
slab[idy][%Start] = floor(ny / 2)
slab[idx][%Block] = nx
make /n=(nx,nz) /o $destname
else
slab[idx][%Start] = floor(nx / 2)
slab[idy][%Block] = ny
make /n=(ny,nz) /o $destname
endif
slab[idz][%Block] = nz
wave data = $destname
data = 0
HDF5LoadData /O /Q /Z /SLAB=slab /N=slabdata fileID, datasetpath
if (!v_flag)
wave slabdata
if (transpose)
data += slabdata[0][p][q][0]
else
data += slabdata[p][0][q][0]
endif
endif
killwaves /z slab, slabdata
if (set_scale)
make /n=(1,1,1) /free dummy
ps_set_dimlabels2(dummy, dataname)
setdimlabel 0, -1, $GetDimLabel(dummy, dim, -1), data
setdimlabel 1, -1, $kScanDimLabel, data
setdatafolder dataDF
string positioners
string positioner
string positionerpath
positioners = psh5_load_scan_meta(fileID, scanpath)
wave /t /z ScanWritables
if (waveexists(ScanWritables) && (numpnts(ScanWritables) >= 1))
positioner = ScanWritables[0]
if (strlen(positioner) > 0)
positionerpath = scanpath + "/" + positioner
positionerpath = ReplaceString("//", positionerpath, "/")
HDF5LoadData /O /Q /Z fileID, positionerpath
endif
endif
setdatafolder dataDF
newdatafolder /o/s attr
killwaves /a/z
psh5_load_scan_attrs(fileID, scanpath, attr_sets=2)
setdatafolder dataDF
ps_scale_dataset(data)
endif
return destname
end
/// load metadata of a PShell dataset. /// load metadata of a PShell dataset.
/// ///
/// "metadata" are the HDF5 attributes attached to the scan dataset. /// "metadata" are the HDF5 attributes attached to the scan dataset.
@ -814,11 +1085,19 @@ function /s psh5_load_dataset_slabs(fileID, datapath, datasetname, [progress])
if (di.ndims < 2) if (di.ndims < 2)
print "error: rank of dataset < 2" print "error: rank of dataset < 2"
return "" return ""
elseif (di.ndims < 3)
progress = 0
endif endif
variable idx, idy, idz, idt, izt variable idx, idy, idz, idt, izt
idx = 1 variable transpose = WhichListItem(datawavename, kTransposedDatasets) >= 0
idy = 0 if (transpose)
idx = 1
idy = 0
else
idx = 0
idy = 1
endif
idz = 2 idz = 2
idt = 3 idt = 3
@ -855,7 +1134,11 @@ function /s psh5_load_dataset_slabs(fileID, datapath, datasetname, [progress])
slab[idt][%Start] = it slab[idt][%Start] = it
HDF5LoadData /O /Q /Z /SLAB=slab /N=slabdata fileID, datasetpath HDF5LoadData /O /Q /Z /SLAB=slab /N=slabdata fileID, datasetpath
wave slabdata // 2D, 3D, or 4D with singletons wave slabdata // 2D, 3D, or 4D with singletons
data[][][iz][it] = slabdata[q][p][0][0] if (transpose)
data[][][iz][it] = slabdata[q][p][0][0]
else
data[][][iz][it] = slabdata[p][q][0][0]
endif
// progress window // progress window
izt += 1 izt += 1
@ -939,8 +1222,14 @@ function /s psh5_load_dataset_slab(fileID, datapath, datasetname, dim2start, dim
endif endif
variable idx, idy, idz, idt variable idx, idy, idz, idt
idx = 1 variable transpose = WhichListItem(datawavename, kTransposedDatasets) >= 0
idy = 0 if (transpose)
idx = 1
idy = 0
else
idx = 0
idy = 1
endif
idz = 2 idz = 2
idt = 3 idt = 3
@ -971,7 +1260,11 @@ function /s psh5_load_dataset_slab(fileID, datapath, datasetname, dim2start, dim
HDF5LoadData /O /Q /Z /SLAB=slab /N=slabdata fileID, datasetpath HDF5LoadData /O /Q /Z /SLAB=slab /N=slabdata fileID, datasetpath
if (!v_flag) if (!v_flag)
wave slabdata wave slabdata
data += slabdata[q][p][0][0] if (transpose)
data += slabdata[q][p][0][0]
else
data += slabdata[p][q][0][0]
endif
navg += 1 navg += 1
endif endif
endfor endfor
@ -994,36 +1287,81 @@ end
/// ///
/// dimension labels are required by scaling functions. /// dimension labels are required by scaling functions.
/// ///
/// @param data data wave as loaded from PShell file
///
/// @return @arg 0 all labels set successfully.
/// @arg 1 unidentified data source.
/// @arg 2 wave does not contain data.
///
function ps_set_dimlabels(data) function ps_set_dimlabels(data)
wave data wave data
string name = NameOfWave(data) ps_set_dimlabels2(data, NameOfWave(data))
end
/// set dimension labels according to the axis type
///
/// same as ps_set_dimlabels() except that the dimension labels are set
/// according to a separate name argument instead of the wave name.
///
/// @param data data wave as loaded from PShell file.
///
/// @param name original name of the dataset in the PShell file.
///
/// @return @arg 0 all labels set successfully.
/// @arg 1 unidentified data source.
/// @arg 2 wave does not contain data.
///
function ps_set_dimlabels2(data, name)
wave data
string name
// intrinsic dimensions variable dummy
strswitch(name) try
case "ScientaImage": // intrinsic dimensions
setdimlabel 0, -1, $kEnergyDimLabel, data strswitch(name)
setdimlabel 1, -1, $kAngleDimLabel, data case "ScientaImage":
if (WaveDims(data) >= 3) setdimlabel 0, -1, $kEnergyDimLabel, data
setdimlabel 2, -1, $kScanDimLabel, data setdimlabel 1, -1, $kAngleDimLabel, data
endif if (WaveDims(data) >= 3)
break setdimlabel 2, -1, $kScanDimLabel, data
case "ScientaSpectrum": endif
setdimlabel 0, -1, $kEnergyDimLabel, data AbortOnRTE
break break
case "ImageAngleDistribution": case "ImageAngleDistribution":
case "ScientaAngleDistribution": case "ScientaAngleDistribution":
setdimlabel 0, -1, $kScanDimLabel, data if (WaveDims(data) >= 2)
setdimlabel 1, -1, $kAngleDimLabel, data setdimlabel 0, -1, $kScanDimLabel, data
break setdimlabel 1, -1, $kAngleDimLabel, data
case "ImageEnergyDistribution": else
case "ScientaEnergyDistribution": setdimlabel 0, -1, $kAngleDimLabel, data
setdimlabel 0, -1, $kScanDimLabel, data endif
setdimlabel 1, -1, $kEnergyDimLabel, data AbortOnRTE
break break
default: case "ScientaSpectrum":
setdimlabel 0, -1, $kScanDimLabel, data case "ImageEnergyDistribution":
endswitch case "ScientaEnergyDistribution":
if (WaveDims(data) >= 2)
setdimlabel 0, -1, $kScanDimLabel, data
setdimlabel 1, -1, $kEnergyDimLabel, data
else
setdimlabel 0, -1, $kEnergyDimLabel, data
endif
AbortOnRTE
break
default:
if (WaveDims(data) == 1)
setdimlabel 0, -1, $kScanDimLabel, data
AbortOnRTE
else
return 1
endif
endswitch
catch
dummy = GetRTError(1)
return 2
endtry
return 0
end end
/// set the dimension scales of loaded PShell Scienta datasets according to attributes. /// set the dimension scales of loaded PShell Scienta datasets according to attributes.
@ -1040,8 +1378,8 @@ function ps_scale_datasets()
dfref attrDF = :attr dfref attrDF = :attr
make /n=3 /free lo, hi make /n=3 /free lo, hi
make /n=3 /t /free un make /n=3 /t /free ax, un
ps_detect_scale(lo, hi, un) ps_detect_scale(ax, lo, hi, un)
wave /t /z /SDFR=dataDF ScanReadables wave /t /z /SDFR=dataDF ScanReadables
if (WaveExists(ScanReadables)) if (WaveExists(ScanReadables))
@ -1051,7 +1389,7 @@ function ps_scale_datasets()
for (isr = 0; isr < nsr; isr += 1) for (isr = 0; isr < nsr; isr += 1)
wave /z /SDFR=dataDF wsr = $ScanReadables[isr] wave /z /SDFR=dataDF wsr = $ScanReadables[isr]
if (WaveExists(wsr)) if (WaveExists(wsr))
ps_scale_dataset_2(wsr, lo, hi, un) ps_scale_dataset_2(wsr, ax, lo, hi, un)
endif endif
endfor endfor
endif endif
@ -1078,9 +1416,9 @@ function ps_scale_dataset(data)
setdatafolder dataDF setdatafolder dataDF
make /n=3 /free lo, hi make /n=3 /free lo, hi
make /n=3 /t /free un make /n=3 /t /free ax, un
ps_detect_scale(lo, hi, un) ps_detect_scale(ax, lo, hi, un)
ps_scale_dataset_2(data, lo, hi, un) ps_scale_dataset_2(data, ax, lo, hi, un)
setdatafolder saveDF setdatafolder saveDF
end end
@ -1096,7 +1434,7 @@ end
/// @arg `lo[%%energy]` analyser energy dimension. /// @arg `lo[%%energy]` analyser energy dimension.
/// @arg `lo[%%angle]` analyser angle dimension. /// @arg `lo[%%angle]` analyser angle dimension.
/// @arg `lo[%%scan]` scan dimension. /// @arg `lo[%%scan]` scan dimension.
/// @arg `lo[%%data]` data dimension (units). /// @arg `lo[%%data]` data dimension.
/// ///
/// the function tries to read the following waves, /// the function tries to read the following waves,
/// and may fall back to more or less reasonable default values if they are not found. /// and may fall back to more or less reasonable default values if they are not found.
@ -1108,15 +1446,18 @@ end
/// @arg `ScanWritables` /// @arg `ScanWritables`
/// @arg wave referenced by `ScanWritables[0]` /// @arg wave referenced by `ScanWritables[0]`
/// ///
/// @param ax text wave to receive the axis labels.
///
/// @param lo wave to receive the lower limits. /// @param lo wave to receive the lower limits.
/// ///
/// @param hi wave to receive the upper limits. /// @param hi wave to receive the upper limits.
/// ///
/// @param un text wave to receive the unit labels. /// @param un text wave to receive the unit labels.
/// ///
/// @return the function results are written to the lo, hi, un waves. /// @return the function results are written to the lo, hi, un, and ax waves.
/// ///
function ps_detect_scale(lo, hi, un) function ps_detect_scale(ax, lo, hi, un)
wave /t ax
wave lo wave lo
wave hi wave hi
wave /t un wave /t un
@ -1124,28 +1465,32 @@ function ps_detect_scale(lo, hi, un)
dfref dataDF = GetDataFolderDFR() dfref dataDF = GetDataFolderDFR()
dfref attrDF = :attr dfref attrDF = :attr
redimension /n=4 lo, hi, un redimension /n=4 lo, hi, un, ax
setdimlabel 0, 0, $kEnergyDimLabel, lo, hi, un setdimlabel 0, 0, $kEnergyDimLabel, lo, hi, un, ax
setdimlabel 0, 1, $kAngleDimLabel, lo, hi, un setdimlabel 0, 1, $kAngleDimLabel, lo, hi, un, ax
setdimlabel 0, 2, $kScanDimLabel, lo, hi, un setdimlabel 0, 2, $kScanDimLabel, lo, hi, un, ax
setdimlabel 0, 3, $kDataDimLabel, lo, hi, un setdimlabel 0, 3, $kDataDimLabel, lo, hi, un, ax
// default values // default values
lo[%$kEnergyDimLabel] = 0 lo[%$kEnergyDimLabel] = 0
hi[%$kEnergyDimLabel] = 1 hi[%$kEnergyDimLabel] = 1
un[%$kEnergyDimLabel] = "eV" un[%$kEnergyDimLabel] = "eV"
ax[%$kEnergyDimLabel] = "Ekin"
lo[%$kAngleDimLabel] = -1 lo[%$kAngleDimLabel] = -1
hi[%$kAngleDimLabel] = 1 hi[%$kAngleDimLabel] = 1
un[%$kAngleDimLabel] = "" un[%$kAngleDimLabel] = "arb."
un[%$kAngleDimLabel] = "slice"
lo[%$kScanDimLabel] = 0 lo[%$kScanDimLabel] = 0
hi[%$kScanDimLabel] = 1 hi[%$kScanDimLabel] = 1
un[%$kScanDimLabel] = "" un[%$kScanDimLabel] = "arb."
ax[%$kScanDimLabel] = "scan"
lo[%$kDataDimLabel] = 0 lo[%$kDataDimLabel] = 0
hi[%$kDataDimLabel] = 0 hi[%$kDataDimLabel] = 0
un[%$kDataDimLabel] = "arb." un[%$kDataDimLabel] = "arb."
ax[%$kDataDimLabel] = "value"
wave /SDFR=attrDF /T /Z LensMode wave /SDFR=attrDF /T /Z LensMode
wave /SDFR=attrDF /Z ChannelBegin = ScientaChannelBegin wave /SDFR=attrDF /Z ChannelBegin = ScientaChannelBegin
@ -1160,14 +1505,17 @@ function ps_detect_scale(lo, hi, un)
lo[%$kAngleDimLabel] = -45/2 lo[%$kAngleDimLabel] = -45/2
hi[%$kAngleDimLabel] = +45/2 hi[%$kAngleDimLabel] = +45/2
un[%$kAngleDimLabel] = "deg" un[%$kAngleDimLabel] = "deg"
ax[%$kAngleDimLabel] = "angle"
break break
case "Angular60": case "Angular60":
lo[%$kAngleDimLabel] = -60/2 lo[%$kAngleDimLabel] = -60/2
hi[%$kAngleDimLabel] = +60/2 hi[%$kAngleDimLabel] = +60/2
un[%$kAngleDimLabel] = "deg" un[%$kAngleDimLabel] = "deg"
ax[%$kAngleDimLabel] = "angle"
break break
case "Transmission": case "Transmission":
un[%$kAngleDimLabel] = "arb." un[%$kAngleDimLabel] = "arb."
ax[%$kAngleDimLabel] = "offset"
break break
endswitch endswitch
endif endif
@ -1187,9 +1535,10 @@ function ps_detect_scale(lo, hi, un)
if (!WaveExists(scanner)) if (!WaveExists(scanner))
wave /z /SDFR=attrDF scanner = $ScanWritables[0] wave /z /SDFR=attrDF scanner = $ScanWritables[0]
endif endif
if (WaveExists(scanner)) if (WaveExists(scanner) && (numpnts(scanner) >= 1))
lo[%$kScanDimLabel] = scanner[0] lo[%$kScanDimLabel] = scanner[0]
hi[%$kScanDimLabel] = scanner[numpnts(scanner)-1] hi[%$kScanDimLabel] = scanner[numpnts(scanner)-1]
ax[%$kScanDimLabel] = NameOfWave(scanner)
endif endif
endif endif
end end
@ -1211,14 +1560,23 @@ end
/// @param data data wave to be scaled. /// @param data data wave to be scaled.
/// dimension labels (index -1) must be set to match the limit waves. /// dimension labels (index -1) must be set to match the limit waves.
/// ///
/// @param ax axis labels.
/// the axis labels are written to the wave note in the format `AxisLabel%%s=%%s`
/// where `X`, `Y`, `Z`, `D` is substituted for the first place holder
/// and the label for the second one.
///
/// @param lo lower limits. /// @param lo lower limits.
/// the lower limits are applied using the SetScale operation.
/// ///
/// @param hi upper limits. /// @param hi upper limits.
/// the upper limits are applied using the SetScale operation.
/// ///
/// @param un unit labels. /// @param un unit labels.
/// the unit labels are applied using the SetScale operation.
/// ///
function ps_scale_dataset_2(data, lo, hi, un) function ps_scale_dataset_2(data, ax, lo, hi, un)
wave data wave data
wave /t ax
wave lo wave lo
wave hi wave hi
wave /t un wave /t un
@ -1227,19 +1585,24 @@ function ps_scale_dataset_2(data, lo, hi, un)
sdim = GetDimLabel(data, 0, -1) sdim = GetDimLabel(data, 0, -1)
if (strlen(sdim)) if (strlen(sdim))
setscale /i x lo[%$sdim], hi[%$sdim], un[%$sdim], data setscale /i x lo[%$sdim], hi[%$sdim], un[%$sdim], data
Note data, "AxisLabelX=" + ax[%$sdim]
endif endif
sdim = GetDimLabel(data, 1, -1) sdim = GetDimLabel(data, 1, -1)
if (strlen(sdim)) if (strlen(sdim))
setscale /i y lo[%$sdim], hi[%$sdim], un[%$sdim], data setscale /i y lo[%$sdim], hi[%$sdim], un[%$sdim], data
Note data, "AxisLabelY=" + ax[%$sdim]
endif endif
sdim = GetDimLabel(data, 2, -1) sdim = GetDimLabel(data, 2, -1)
if (strlen(sdim)) if (strlen(sdim))
setscale /i z lo[%$sdim], hi[%$sdim], un[%$sdim], data setscale /i z lo[%$sdim], hi[%$sdim], un[%$sdim], data
Note data, "AxisLabelZ=" + ax[%$sdim]
endif endif
setscale d 0, 0, un[%$kDataDimLabel], data setscale d 0, 0, un[%$kDataDimLabel], data
Note data, "AxisLabelD=" + ax[%$kDataDimLabel]
Note data, "Dataset=" + NameOfWave(data)
end end
/// load and reduce the ScientaImage dataset of the first scan of a PShell data file. /// load and reduce the ScientaImage dataset of the first scan of a PShell data file.
@ -1315,7 +1678,9 @@ function /s psh5_load_reduced(ANickName, APathName, AFileName, reduction_func, r
string folder string folder
sg = StringFromList(ig, s_scanpaths) sg = StringFromList(ig, s_scanpaths)
folder = CleanupName(ReplaceString("/", sg, ""), 0) folder = ReplaceString("/", sg, "")
folder = ReplaceString(" ", folder, "")
folder = CleanupName(folder, 0)
setdatafolder fileDF setdatafolder fileDF
newdatafolder /s /o $folder newdatafolder /s /o $folder
dfref dataDF = GetDataFolderDFR() dfref dataDF = GetDataFolderDFR()
@ -1417,11 +1782,19 @@ function /s psh5_load_dataset_reduced(fileID, scanpath, datasetname, reduction_f
print "error: rank of dataset < 2" print "error: rank of dataset < 2"
result = -2 result = -2
return wavenames return wavenames
elseif (di.ndims < 3)
progress = 0
endif endif
variable idx, idy, idz, idt variable idx, idy, idz, idt
idx = 1 variable transpose = WhichListItem(datawavename, kTransposedDatasets) >= 0
idy = 0 if (transpose)
idx = 1
idy = 0
else
idx = 0
idy = 1
endif
idz = 2 idz = 2
idt = 3 idt = 3