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
This commit is contained in:
muntwiler_m 2016-09-22 14:15:09 +02:00
parent a87975d1e6
commit 0dc6ca820b
4 changed files with 324 additions and 96 deletions

View File

@ -6,14 +6,14 @@
#include "pearl-polar-coordinates"
#include <New Polar Graphs>
// $Id$
//
// copyright (c) 2013-15 Paul Scherrer Institut
// copyright (c) 2013-16 Paul Scherrer Institut
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http:///www.apache.org/licenses/LICENSE-2.0
//
// Please acknowledge the use of this code.
/// @file
/// @brief processing and holographic mapping of angle scanned XPD data.
@ -64,7 +64,7 @@
///
/// @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
/// you may not use this file except in compliance with the License. @n
/// You may obtain a copy of the License at
@ -79,15 +79,38 @@
///
/// 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 /z yscale // Y scaling, e.g. ManipulatorPhi
// if unassigned, point scaling is assumed
variable ylo
variable yhi
variable qlo
variable qhi
wave theta
wave tilt
wave phi
if (ylo > yhi)
if (qlo > qhi)
return -1
endif
@ -95,8 +118,8 @@ function strip_remove_frames(strip, yscale, ylo, yhi)
variable snx = dimsize(strip, 0)
variable sny = dimsize(strip, 1)
variable sq1lo = 0
variable sq1hi = max(round((ylo - dimoffset(strip, 1)) / dimdelta(strip, 1)), 0)
variable sq2lo = min(round((ylo - dimoffset(strip, 1)) / dimdelta(strip, 1)), sny - 1)
variable sq1hi = max(qlo-1, 0)
variable sq2lo = min(qhi+1, sny - 1)
variable sq2hi = dimsize(strip, 1) - 1
// dest indices
@ -111,10 +134,24 @@ function strip_remove_frames(strip, yscale, ylo, yhi)
duplicate /free strip, strip_copy
redimension /n=(dnx,dny) strip
strip[][dq1lo,dq1hi] = strip_copy[p][q + q1ofs]
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
end
@ -144,6 +181,7 @@ end
/// @return if check waves are enabled, the following waves are created (overwritten if existing):
/// @arg check_dist average X distribution
/// @arg check_smoo smoothed distribution used to normalize the strip
///
function normalize_strip_x(strip, [smooth_method, smooth_factor, check])
wave strip
variable smooth_method
@ -233,6 +271,7 @@ end
/// @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_theta(strip, theta, [theta_offset, smooth_method, smooth_factor, check])
wave strip
wave theta
@ -300,6 +339,70 @@ function normalize_strip_theta(strip, theta, [theta_offset, smooth_method, smoot
endif
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.
///
/// the strip is cropped in place, data outside the region of interest is lost.

View File

@ -52,6 +52,25 @@
/// 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.
///
/// this is essentially <code>display; appendimage</code>.
@ -72,7 +91,7 @@ function /s ad_display(image)
string dfname = ReplaceString("root:", GetDataFolder(1, imagedf), "")
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
display /k=1/n=$graphname as graphtitle
graphname = s_name
@ -104,7 +123,7 @@ function /s ad_display_histogram(image)
string dfname = ReplaceString("root:", GetDataFolder(1, imagedf), "")
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
display /k=1/n=$graphname as graphtitle
graphname = s_name
@ -177,9 +196,9 @@ function /s ad_display_profiles(image, [filter])
view_filter_options = ""
variable /g view_filter_smoothing_x = 1
variable /g view_filter_smoothing_y = 1
string dfname = GetDataFolder(0, imagedf)
string graphtitle = dfname + ":" + NameOfWave(image) + " Profiles"
string /g prof_graphname = CleanupName("prof_" + dfname, 0)
string dfname = ReplaceString("root:", GetDataFolder(1, imagedf), "")
string graphtitle = dfname + NameOfWave(image) + " Profiles"
string /g prof_graphname = graphname_from_dfref(imagedf, "prof_")
svar graphname = prof_graphname
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
@ -1004,7 +1023,7 @@ function /s ad_display_brick(data)
setdatafolder viewdf
string dfname = ReplaceString("root:", s_datadf, "")
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
if ((strlen(graphname) > 0) && (wintype(graphname) == 13))

View File

@ -1450,7 +1450,7 @@ static function bp_dataset_folder(ba) : ButtonControl
string cmd
sprintf cmd, "setdatafolder root:%s", PossiblyQuoteName(dataset)
execute /q /z cmd
cmd = "setdatafolder :scan_1"
cmd = "setdatafolder :scan1"
execute /q /z cmd
sprintf cmd, "setdatafolder %s", GetDataFolder(1)
print cmd

View File

@ -183,7 +183,9 @@ function /s psh5_load_complete(ANickName, APathName, AFileName, [load_data, load
for (ig = 0; ig < ng; ig += 1)
sg = StringFromList(ig, s_scanpaths, ";")
folder = CleanupName(ReplaceString("/", sg, ""), 0)
folder = ReplaceString("/", sg, "")
folder = ReplaceString(" ", folder, "")
folder = CleanupName(folder, 0)
setdatafolder fileDF
newdatafolder /s /o $folder
psh5_load_scan_complete(fileID, sg, load_data=load_data, load_attr=load_attr)
@ -219,14 +221,26 @@ end
/// @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
///
/// @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.
///
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 APathName
string AFileName
variable load_data
variable load_attr
string pref_scans
string pref_datasets
if (ParamIsDefault(load_data))
load_data = 1
@ -234,7 +248,13 @@ function /s psh5_load_preview(ANickName, APathName, AFileName, [load_data, load_
if (ParamIsDefault(load_attr))
load_attr = 1
endif
if (ParamIsDefault(pref_scans))
pref_scans = "*scan1*;"
endif
if (ParamIsDefault(pref_datasets))
pref_datasets = ""
endif
dfref saveDF = GetDataFolderDFR()
setdatafolder root:
newdatafolder /o/s pearl_area
@ -253,12 +273,35 @@ function /s psh5_load_preview(ANickName, APathName, AFileName, [load_data, load_
if (v_flag == 0)
AFileName = s_path + s_filename
dfref fileDF = GetDataFolderDFR()
scanpaths = psh5_list_scans(fileID)
variable ng = ItemsInList(scanpaths)
variable ig
string sg
ig = 0
sg = StringFromList(ig, scanpaths, ";")
dataname = psh5_load_scan_preview(fileID, sg, set_scale=load_attr)
variable np = ItemsInList(pref_scans)
variable ip
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)
endif
wave /z data = $dataname
string destpath = GetDataFolder(1, saveDF) + ANickName
@ -396,6 +439,9 @@ end
///
/// 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 scanpath path to the scan group in the HDF5 file, e.g. "/scan 1".
@ -517,28 +563,29 @@ function /s psh5_load_scan_meta(fileID, scanpath)
HDF5LoadData /O /Q /Z /A="Dimensions" /N=ScanDimensions /TYPE=1 fileID, scanpath
if (!v_flag)
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
make /n=1 /o ScanDimensions
ScanDimensions = 0
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
ScanReadables[0] = "ScientaSpectrum"
wavenames = AddListItem("ScanReadables", wavenames, ";", inf)
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
end
@ -573,6 +620,10 @@ function /s psh5_load_dataset(fileID, scanpath, datasetname, [set_scale])
string datasetname
variable set_scale
if (ParamIsDefault(set_scale))
set_scale = 1
endif
string datasetpath
datasetpath = scanpath + "/" + datasetname
datasetpath = ReplaceString("//", datasetpath, "/")
@ -586,7 +637,7 @@ function /s psh5_load_dataset(fileID, scanpath, datasetname, [set_scale])
endif
string dataname
if (di.ndims < 3)
if (di.ndims < 2)
HDF5LoadData /O /Q /Z fileID, datasetpath
dataname = StringFromList(0, S_waveNames)
else
@ -626,42 +677,68 @@ end
/// @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.
///
function /s psh5_load_scan_preview(fileID, scanpath, [set_scale])
function /s psh5_load_scan_preview(fileID, scanpath, [set_scale, pref_datasets])
variable fileID
string scanpath
variable set_scale
string pref_datasets
if (ParamIsDefault(set_scale))
set_scale = 1
endif
if (ParamIsDefault(pref_datasets) || (strlen(pref_datasets) == 0))
pref_datasets = "ScientaImage;ScientaSpectrum;ImageAngleDistribution;ImageEnergyDistribution;Counts;SampleCurrent"
endif
dfref saveDF = GetDataFolderDFR()
dfref dataDF = saveDF
string datasets = psh5_list_scan_datasets(fileID, scanpath)
string datasetname = ""
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"
variable nds = ItemsInList(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, 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, datasets)
index = ItemsInList(sds, "/") - 1
sds = StringFromList(index, sds, "/")
endif
else
datasetname = StringFromList(0, datasets)
index = ItemsInList(datasetname, "/") - 1
datasetname = StringFromList(index, datasetname, "/")
endif
if (strlen(datasetname) == 0)
return ""
endif
string datasetpath
string datasetname = sds
datasetpath = scanpath + "/" + datasetname
datasetpath = ReplaceString("//", datasetpath, "/")
STRUCT HDF5DataInfo di // Defined in HDF5 Browser.ipf.
@ -673,7 +750,7 @@ function /s psh5_load_scan_preview(fileID, scanpath, [set_scale])
endif
string dataname
if (di.ndims < 3)
if (di.ndims < 2)
HDF5LoadData /O /Q /Z fileID, datasetpath
dataname = StringFromList(0, S_waveNames)
wave /z data = $dataname
@ -803,6 +880,9 @@ end
///
/// @return name of loaded wave if successful. empty string otherwise.
///
/// @todo images are transposed in the first two dimensions.
/// this is useful for Scienta images but may not be appropriate for other sources.
///
function /s psh5_load_dataset_slabs(fileID, datapath, datasetname, [progress])
variable fileID
string datapath
@ -927,6 +1007,9 @@ end
///
/// @return name of loaded wave if successful. empty string otherwise.
///
/// @todo images are transposed in the first two dimensions.
/// this is useful for Scienta images but may not be appropriate for other data sources.
///
function /s psh5_load_dataset_slab(fileID, datapath, datasetname, dim2start, dim2count, dim3start, dim3count)
variable fileID
string datapath
@ -1010,42 +1093,63 @@ end
///
/// 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)
wave data
string name = NameOfWave(data)
// intrinsic dimensions
strswitch(name)
case "ScientaImage":
setdimlabel 0, -1, $kEnergyDimLabel, data
setdimlabel 1, -1, $kAngleDimLabel, data
if (WaveDims(data) >= 3)
setdimlabel 2, -1, $kScanDimLabel, data
endif
break
case "ImageAngleDistribution":
case "ScientaAngleDistribution":
if (WaveDims(data) >= 2)
setdimlabel 0, -1, $kScanDimLabel, data
setdimlabel 1, -1, $kAngleDimLabel, data
else
setdimlabel 0, -1, $kAngleDimLabel, data
endif
break
case "ScientaSpectrum":
case "ImageEnergyDistribution":
case "ScientaEnergyDistribution":
if (WaveDims(data) >= 2)
setdimlabel 0, -1, $kScanDimLabel, data
setdimlabel 1, -1, $kEnergyDimLabel, data
else
variable dummy
try
// intrinsic dimensions
strswitch(name)
case "ScientaImage":
setdimlabel 0, -1, $kEnergyDimLabel, data
endif
break
default:
setdimlabel 0, -1, $kScanDimLabel, data
endswitch
setdimlabel 1, -1, $kAngleDimLabel, data
if (WaveDims(data) >= 3)
setdimlabel 2, -1, $kScanDimLabel, data
endif
AbortOnRTE
break
case "ImageAngleDistribution":
case "ScientaAngleDistribution":
if (WaveDims(data) >= 2)
setdimlabel 0, -1, $kScanDimLabel, data
setdimlabel 1, -1, $kAngleDimLabel, data
else
setdimlabel 0, -1, $kAngleDimLabel, data
endif
AbortOnRTE
break
case "ScientaSpectrum":
case "ImageEnergyDistribution":
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
/// set the dimension scales of loaded PShell Scienta datasets according to attributes.
@ -1219,7 +1323,7 @@ function ps_detect_scale(ax, lo, hi, un)
if (!WaveExists(scanner))
wave /z /SDFR=attrDF scanner = $ScanWritables[0]
endif
if (WaveExists(scanner))
if (WaveExists(scanner) && (numpnts(scanner) >= 1))
lo[%$kScanDimLabel] = scanner[0]
hi[%$kScanDimLabel] = scanner[numpnts(scanner)-1]
ax[%$kScanDimLabel] = NameOfWave(scanner)
@ -1362,7 +1466,9 @@ function /s psh5_load_reduced(ANickName, APathName, AFileName, reduction_func, r
string folder
sg = StringFromList(ig, s_scanpaths)
folder = CleanupName(ReplaceString("/", sg, ""), 0)
folder = ReplaceString("/", sg, "")
folder = ReplaceString(" ", folder, "")
folder = CleanupName(folder, 0)
setdatafolder fileDF
newdatafolder /s /o $folder
dfref dataDF = GetDataFolderDFR()