igor-public/pearl/pearl-data-explorer.ipf

2365 lines
69 KiB
Igor

#pragma TextEncoding = "UTF-8"
#pragma rtGlobals=3 // Use modern global access method and strict wave access.
#pragma IgorVersion = 6.36
#pragma ModuleName = PearlDataExplorer
#pragma version = 2.1
#include <HierarchicalListWidget>, version >= 1.14
#include "pearl-area-import"
#include "pearl-area-profiles"
#include "pearl-area-display"
#include "pearl-compat"
#include "pearl-pshell-import"
// copyright (c) 2013-22 Paul Scherrer Institut
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http:///www.apache.org/licenses/LICENSE-2.0
/// @file
/// @brief preview and import panel for PEARL data
/// @ingroup ArpesPackage
///
///
/// preview and import panel for PEARL data:
/// @arg area detector (HDF5) files from scienta analyser and prosilica cameras (if HDF5.xop is installed).
/// @arg igor text files from s-scans and otf-scans.
/// @arg pshell (HDF5) data files (if HDF5.xop is installed).
/// @namespace PearlDataExplorer
/// @brief preview and import panel for PEARL data
///
/// PearlDataExplorer is declared in @ref pearl-data-explorer.ipf.
static strconstant package_name = "pearl_explorer"
static strconstant package_path = "root:packages:pearl_explorer:"
static strconstant ks_filematch_adh5 = "*.h5"
static strconstant ks_filematch_pshell = "psh*.h5"
static strconstant ks_filematch_itx = "*.itx"
/// show the pearl data explorer window
///
/// create a pearl data explorer window or bring the existing one to the front.
/// if a new window is created, also initialize all package variables and load package preferences.
///
function pearl_data_explorer()
DoWindow /HIDE=0 /F PearlDataExplorer
if (v_flag == 0)
init_package()
load_prefs()
execute /q/z "PearlDataExplorer()"
MakeListIntoHierarchicalList("PearlDataExplorer", "lb_contents", "PearlDataExplorer#hlp_contents_open", selectionMode=WMHL_SelectionNonContinguous, pathSeparator="/")
WMHL_AddColumns("PearlDataExplorer", "lb_contents", 1)
WMHL_SetNotificationProc("PearlDataExplorer", "lb_contents", "PearlDataExplorer#hlp_contents_selection", WMHL_SetSelectNotificationProc)
ListBox lb_contents win=PearlDataExplorer, widths={6,60,20}
update_controls()
endif
end
static function init_package()
dfref save_df = GetDataFolderDFR()
SetDataFolder root:
newdatafolder /o/s packages
newdatafolder /o/s $package_name
if (exists("v_InitPanelDone") == 2)
SetDataFolder save_df
return 0
endif
make /o/n=0/t wtFiles
make /o/n=0/i wSelectedFiles,wSelectedDatasets
make /o/n=0/t wtDatasets
make /o/n=0/t wtPositioners,wtDetectors
make /o/n=0/i wSelectedPositioners,wSelectedDetectors
make /o/n=(1,1) preview_image // preview 2D data
make /o/n=0 preview_trace // preview 1D data
make /o/n=0/t attr_names, attr_values, attr_filter, attr_filter_summary
// persistent strings and variables. persistent = saved in preferences
string /g s_filepath = "" // directory path to be listed
string /g s_hdf_options = "" // recently used HDF5 load options
string /g s_reduction_params = "" // recently used reduction parameters
string /g s_preview_pvs = "" // semicolon-separated list of EPICS PVs to display in preview.
// the list items can contain wildcards for StringMatch
s_preview_pvs = "*OP:CURRENT*;*Stats*Total*;*KEITHLEY*READOUT;*CADC*"
redimension /n=26 attr_filter_summary
attr_filter_summary[0] = "MonoEnergy"
attr_filter_summary[1] = "MonoGrating"
attr_filter_summary[2] = "ExitSlit"
attr_filter_summary[3] = "FrontendHSize"
attr_filter_summary[4] = "FrontendVSize"
attr_filter_summary[5] = "ManipulatorPhi"
attr_filter_summary[6] = "ManipulatorTheta"
attr_filter_summary[7] = "ManipulatorTilt"
attr_filter_summary[8] = "ManipulatorX"
attr_filter_summary[9] = "ManipulatorY"
attr_filter_summary[10] = "ManipulatorZ"
attr_filter_summary[11] = "PassEnergy"
attr_filter_summary[12] = "LensMode"
attr_filter_summary[13] = "ScientaDwellTime"
attr_filter_summary[14] = "ScientaCenterEnergy"
attr_filter_summary[15] = "ScientaChannelBegin"
attr_filter_summary[16] = "ScientaChannelEnd"
attr_filter_summary[17] = "ScientaSliceBegin"
attr_filter_summary[18] = "ScientaSliceEnd"
attr_filter_summary[19] = "ScientaNumChannels"
attr_filter_summary[20] = "StepSize"
attr_filter_summary[21] = "ScientaNumSlices"
attr_filter_summary[22] = "ManipulatorTempA"
attr_filter_summary[23] = "ManipulatorTempB"
attr_filter_summary[24] = "RefCurrent"
attr_filter_summary[25] = "SampleCurrent"
// non-persistent strings and variables
string /g s_short_filepath = "" // abbreviated directory path
string /g s_selected_file = ""
string /g s_selected_dataset = ""
string /g s_preview_file = "" // file or folder name of the current preview
string /g s_preview_source = "" // data source, e.g. EPICS channel name, of the current preview
string /g s_profiles_graph = "" // window name of the current preview if the data is two-dimensional
string /g s_preview_trace_graph = "" // window name of the current preview if the data is one-dimensional
string /g s_preview_graph = "" // window name of the most recent preview graph
string /g s_file_info = "" // description of selected file
string /g s_result = "" // result of last operation
variable/g v_InitPanelDone = 1
SetDataFolder save_df
end
/// save persistent package data to the preferences file.
///
/// this function is called when the user clicks the corresponding button.
/// the data saved in the file are: data file path, attributes filter
///
static function save_prefs()
dfref save_df = GetDataFolderDFR()
dfref df = $package_path
if (DataFolderRefStatus(df) == 1)
string fullPath = SpecialDirPath("Packages", 0, 0, 0)
fullPath += package_name
NewPath/O/C/Q tempPackagePrefsPath, fullPath
fullPath += ":preferences.pxp"
SetDataFolder df
string objects = "attr_filter;attr_filter_summary;s_filepath;s_hdf_options;s_reduction_params;s_preview_pvs"
SaveData /O /Q /J=objects fullPath
KillPath/Z tempPackagePrefsPath
endif
SetDataFolder save_df
end
static function load_prefs()
// loads persistent package data from the preferences file
// the preferences file is an Igor packed experiment file in a special preferences folder
dfref save_df = GetDataFolderDFR()
variable result = -1
setdatafolder root:
NewDataFolder /O/S packages
NewDataFolder /O/S $package_name
dfref package_df = GetDataFolderDFR()
string fullPath = SpecialDirPath("Packages", 0, 0, 0)
fullPath += package_name
GetFileFolderInfo /Q /Z fullPath
if (V_Flag == 0) // Disk directory exists?
fullPath += ":preferences.pxp"
GetFileFolderInfo /Q /Z fullPath
if (V_Flag == 0) // Preference file exist?
LoadData /O /R /Q fullPath
result = 0
endif
endif
if (result == 0)
svar /sdfr=package_df filepath = s_filepath
NewPath /O/Z pearl_explorer_filepath, filepath
update_filepath()
update_filelist()
endif
SetDataFolder save_df
return result
end
/// check whether a file can be imported by this module.
///
/// the file type is determined by the extension of the file name.
///
/// @return file type
/// @arg 0 not a recognized file type
/// @arg 1 PShell file (HDF5, name starts with psh_)
/// @arg 2 area detector HDF5 file
/// @arg 3 Igor text (itx) file
///
static function pearl_file_type(filename)
string filename
if (StringMatch(filename, ks_filematch_pshell))
return 1
elseif (StringMatch(filename, ks_filematch_adh5))
return 2
elseif (StringMatch(filename, ks_filematch_itx))
return 3
else
return 0
endif
end
/// update the file path after path change
///
/// read the path info from pearl_explorer_filepath
/// and update the path control
///
static function update_filepath()
PathInfo /S pearl_explorer_filepath
svar filepath = $(package_path + "s_filepath")
svar shortpath = $(package_path + "s_short_filepath")
filepath = s_path
shortpath = shorten_filepath(filepath, 40)
end
/// read a list of PEARL files from the file system
///
/// wtFiles and wSelectedFiles in the package data folder are updated.
/// only files for which pearl_file_type() returns non-zero are listed.
///
static function update_filelist()
dfref save_df = GetDataFolderDFR()
string all_files
wave /t wtFiles = $(package_path + "wtFiles")
wave wSelectedFiles = $(package_path + "wSelectedFiles")
variable nn
PathInfo pearl_explorer_filepath
if (v_flag == 1)
all_files = IndexedFile(pearl_explorer_filepath, -1, "????")
nn = ItemsInList(all_files)
else
all_files = ""
nn = 0
endif
make /n=(nn) /t /free wtAllFiles
wtAllFiles = StringFromList(p, all_files)
Extract /o /t wtAllFiles, wtFiles, pearl_file_type(wtAllFiles[p])
Sort /A /R wtFiles, wtFiles
redimension /n=(numpnts(wtFiles)) wSelectedFiles
wSelectedFiles = 0
setdatafolder save_df
end
// ====== metadata ======
/// load the internal structure of a file
///
/// this loads metadata for updating the panels.
///
/// for a pshell file, metadata includes:
/// - list of all datasets with types and dimensions
/// - general group
///
/// @return 0 if successful
/// -1 if no data was loaded because the file was not recognized,
/// -2 if no data is found in file
///
static function get_file_info(filename)
string filename
dfref save_df = GetDataFolderDFR()
dfref package_df = $package_path
variable ft = pearl_file_type(filename)
variable result = 0
switch(ft)
case 1:
case 2:
dfref file_df = get_pshell_info("pearl_explorer_filepath", filename)
result = hl_contents_update(file_df)
result = result >= 3 ? 0 : -2
break
default:
hl_contents_clear()
dfref file_df = package_df:file_info
KillDataFolder /z file_df
result = -1
endswitch
setdatafolder save_df
return result
end
/// load attributes
static function attributes_notebook(filename)
string filename
dfref save_df = GetDataFolderDFR()
dfref temp_df = NewFreeDataFolder()
load_file(filename, options="mode:load_diags", dest_df=temp_df, quiet=1)
svar /sdfr=temp_df /z s_loaded_datasets
string scan
dfref scan_df
if (SVAR_Exists(s_loaded_datasets) && (strlen(s_loaded_datasets) >= 4))
scan = StringFromList(0, psh5_extract_scan_paths(s_loaded_datasets), ";")
scan_df = psh5_dataset_to_folder(temp_df, scan)
else
scan_df = temp_df
endif
dfref attr_df = ps_find_attr_folder(scan_df)
if (DataFolderRefStatus(attr_df))
extract_attributes(attr_df, dest_df=temp_df)
wave /t /sdfr=temp_df /z attr_names
wave /t /sdfr=temp_df /z attr_values
if (WaveExists(attr_names) && WaveExists(attr_values))
create_attributes_notebook(attr_names, attr_values, filename)
endif
endif
setdatafolder save_df
end
/// extract summary from attribute waves
///
/// by default, all existing attributes are copied.
/// if a text wave attr_filter exists in the pear_explorer folder, only the attributes referenced therein are copied.
/// to set up a filter, duplicate the attr_names wave of a template dataset, and remove unwanted items.
///
/// @param attr_df data folder which contains the original data, e.g. the attr, diags or snaps folder in pshell files.
/// @param dest_df destination folder. the output is written to the attr_names and attr_values waves.
/// default = package folder.
/// @param attr_filter (text wave) list of attributes allowed in the output.
/// default = use attr_filter of package folder.
/// @param include_datawaves @arg 1 (default) include data waves (any numeric wave which has a PV=name note).
/// @arg 0 don't include attributes from data waves.
/// @param include_infowaves @arg 1 (default) include attributes from info waves (IN, ID, IV, IU).
/// @arg 0 don't include attributes from info waves.
///
static function extract_attributes(attr_df, [dest_df, attr_filter, include_datawaves, include_infowaves])
dfref attr_df
dfref dest_df
wave /t attr_filter
variable include_datawaves
variable include_infowaves
dfref save_df = GetDataFolderDFR()
dfref package_df = $package_path
if (ParamIsDefault(dest_df))
dest_df = GetDataFolderDFR()
endif
if (ParamIsDefault(attr_filter) || !WaveExists(attr_filter))
wave /t /sdfr=package_df /z attr_filter
endif
if (ParamIsDefault(include_datawaves))
include_datawaves = 1
endif
if (ParamIsDefault(include_infowaves))
include_infowaves = 1
endif
setdatafolder dest_df
wave /t /z attr_names, attr_values
if (!WaveExists(attr_names) || !WaveExists(attr_values))
make /n=(1) /o /t attr_names, attr_values
endif
attr_names = ""
attr_values = ""
setdatafolder attr_df
wave /t /z IN
wave /t /z ID
wave /t /z IV
wave /t /z IU
// compile list of attributes
variable nattr // destination attributes
variable iattr
variable ninfo // info wave elements
variable iinfo
variable nw // attribute waves
variable iw
string sw
string ss
if (WaveExists(IN) && include_infowaves)
ninfo = numpnts(IN)
else
ninfo = 0
endif
if (include_datawaves)
string waves = WaveList("*", ";", "")
string exceptions = "ID;IN;IU;IV"
waves = RemoveFromList(exceptions, waves)
nw = ItemsInList(waves, ";")
else
nw = 0
endif
if (WaveExists(attr_filter) && (numpnts(attr_filter) >= 1))
nattr = numpnts(attr_filter)
redimension /n=(nattr) attr_names
attr_names = attr_filter
else
if(ninfo > 0)
redimension /n=(ninfo) attr_names
attr_names = SelectString(strlen(ID[p]) >= 0, IN[p], ID[p]) // use ID unless empty
endif
nattr = ninfo + nw
iattr = ninfo
redimension /n=(nattr) attr_names
for (iw = 0; iw < nw; iw +=1 )
sw = StringFromList(iw, waves, ";")
ss = StringByKey("PV", note($sw), "=", "\r")
FindValue /text=sw attr_names
if ((v_value < 0) && (strlen(ss) >= 0))
attr_names[iattr] = sw
iattr += 1
endif
endfor
nattr = iattr
endif
redimension /n=(nattr) attr_names, attr_values
sort attr_names, attr_names
// look up attribute values
for (iattr = 0; iattr < nattr; iattr += 1)
sw = attr_names[iattr]
// try info waves
if (ninfo > 0)
FindValue /text=sw ID
if (v_value >= 0)
attr_values[iattr] = IV[v_value]
endif
FindValue /text=sw IN
if (v_value >= 0)
attr_values[iattr] = IV[v_value]
endif
endif
// override from attribute wave if existent
if (nw > 0)
switch (WaveType($sw, 1))
case 1: // numeric
wave /z w = $sw
if (WaveExists(w) && (numpnts(w) >= 1))
sprintf ss, "%g", w[0]
attr_values[iattr] = ss
endif
break
case 2: // text
wave /t/z wt = $sw
if (WaveExists(wt) && (numpnts(wt) >= 1))
attr_values[iattr] = wt[0]
endif
break
endswitch
endif
endfor
setdatafolder save_df
end
function test_attributes_notebook()
dfref df = GetDataFolderDFR()
wave /t /sdfr=df attr_names
wave /t /sdfr=df attr_values
create_attributes_notebook(attr_names, attr_values, GetDataFolder(0))
end
static function create_attributes_notebook(attr_names, attr_values, title)
wave /t attr_names
wave /t attr_values
string title
dfref save_df = GetDataFolderDFR()
setdatafolder $package_path
wave /t/z attr_filter, attr_filter_summary
string name = PearlCleanupName("nb_" + title[0,27])
if (WinType(name) == 5)
Notebook $name selection={startOfFile, endOfFile}
Notebook $name text=""
else
NewNotebook /F=1 /K=1 /N=$name as title
GetWindow $name wsize
v_right = v_left + 260
v_bottom = v_top + 360
MoveWindow /W=$name v_left, v_top, v_right, v_bottom
Notebook $name tabs={2*72}
endif
// summary
if (WaveExists(attr_filter_summary) && (numpnts(attr_filter_summary) >= 1))
notebook $name fStyle=1, text="Summary\r\r"
notebook $name fStyle=0
notebook_add_attributes(name, attr_filter_summary, attr_names, attr_values)
notebook $name text="\r"
endif
// all attributes
notebook $name fStyle=1, text="All Attributes\r\r"
notebook $name fStyle=0
notebook_add_attributes(name, $"", attr_names, attr_values)
notebook $name selection={startOfFile,startOfFile}, findText={"",1}
setdatafolder save_df
end
static function notebook_add_attributes(notebook_name, attr_filter, attr_names, attr_values)
string notebook_name
wave /t /z attr_filter
wave /t attr_names
wave /t attr_values
variable nw = numpnts(attr_names)
variable iw
string sw
string ss
variable do_filter = WaveExists(attr_filter)
for (iw = 0; iw < nw; iw += 1)
if (do_filter)
sw = attr_names[iw]
FindValue /text=sw attr_filter
else
v_value = 0
endif
if (v_value >= 0)
sprintf ss, "%s\t%s\r", attr_names[iw], attr_values[iw]
notebook $notebook_name text=ss
endif
endfor
end
/// send general metadata to ELOG panel - if available
///
/// the following metatdata are sent.
/// they must be present as strings in the specified data folder:
///
/// | ELOG parameter | global string | function argument |
/// | --- | --- | --- |
/// | file | s_filepath | filename |
/// | graph attachment | | graphname |
/// | author | authors | |
/// | p-group | pgroup | |
/// | project | proposal | |
/// | sample | sample | |
///
/// @param file_df data folder that contains the metadata.
///
/// @param filename override file path read from s_filepath global string variable.
/// if neither is declared, the file name is reset to empty field.
///
/// @param graphname select this graph window for attaching.
/// default: do not change the selection.
///
static function set_elog_attributes(file_df, [filename, graphname])
dfref file_df
string filename
string graphname
if (ParamIsDefault(filename))
svar /sdfr=file_df /z loaded_file=s_filepath
if (svar_Exists(loaded_file))
filename = loaded_file
else
filename = ""
endif
endif
if (ParamIsDefault(graphname))
graphname = ""
endif
string cmd
if (exists("PearlElog#set_panel_attributes") == 6)
sprintf cmd, "PearlElog#set_panel_attributes(\"\", \"File=%s\")", ParseFilePath(0, filename, ":", 1, 0)
execute /Q/Z cmd
if ((strlen(graphname) > 0) && (WinType(graphname) == 1))
sprintf cmd, "PearlElog#set_panel_graphs(\"\", \"%s\")", graphname
execute /Q/Z cmd
endif
svar /sdfr=file_df /z authors
if (svar_Exists(authors))
if (strlen(authors)>=1)
sprintf cmd, "PearlElog#set_panel_attributes(\"\", \"author=%s\")", authors
execute /Q/Z cmd
endif
endif
svar /sdfr=file_df /z pgroup
if (svar_Exists(pgroup))
if (strlen(pgroup)>=1)
sprintf cmd, "PearlElog#set_panel_attributes(\"\", \"p-group=%s\")", pgroup
execute /Q/Z cmd
endif
endif
svar /sdfr=file_df /z proposal
if (svar_Exists(proposal))
if (strlen(proposal)>=1)
sprintf cmd, "PearlElog#set_panel_attributes(\"\", \"project=%s\")", proposal
execute /Q/Z cmd
endif
endif
svar /sdfr=file_df /z proposer
svar /sdfr=file_df /z sample
if (svar_Exists(sample))
if (strlen(sample)>=1)
sprintf cmd, "PearlElog#set_panel_attributes(\"\", \"sample=%s\")", sample
execute /Q/Z cmd
endif
endif
endif
end
// ====== preview ======
static function preview_file(filename)
string filename
dfref save_df = GetDataFolderDFR()
dfref preview_df = $package_path
killStrings /z authors, pgroup, proposal, proposer, sample
variable ft = pearl_file_type(filename)
switch(ft)
case 1:
wave /z image = preview_pshell_file(filename)
break
case 2:
wave /z image = preview_hdf_file(filename)
break
case 3:
wave /z image = preview_itx_file(filename)
break
default:
wave /z image = $""
endswitch
if (WaveExists(image))
show_preview_graph(image)
endif
setdatafolder save_df
return 0
end
/// load the preview of a PShell HDF5 file.
///
/// the preview is an arbitrary detector image extracted from the file, see adh5_load_preview().
/// the preview is loaded to the preview_image wave in the pear_explorer data folder.
///
/// the s_file_info string is updated with information about the scan dimensions.
///
/// @param filename name of a file in the directory specified by the pearl_explorer_filepath path object.
///
/// @return wave reference of the preview image
///
static function /wave preview_pshell_file(filename)
string filename
dfref save_df = GetDataFolderDFR()
setdatafolder $package_path
dfref preview_df = GetDataFolderDFR()
svar s_preview_file
svar s_preview_source
svar /z s_file_info
if (! svar_exists(s_file_info))
string /g s_file_info
endif
dfref temp_df = NewFreeDataFolder()
dfref file_df = psh5_preview("pearl_explorer_filepath", filename, dest_df=temp_df)
svar /z /sdfr=temp_df dataname=s_preview_wave
s_preview_file = filename
s_preview_source = ""
wave /z /sdfr=temp_df data = $dataname
if (waveexists(data))
duplicate /o data, preview_df:preview_image
else
print "no data found in file " + filename
endif
s_file_info = ""
setdatafolder save_df
wave /z /sdfr=preview_df preview_image
return preview_image
end
/// load the preview of a PEARL HDF5 file.
///
/// the preview is an arbitrary detector image extracted from the file, see adh5_load_preview().
/// the preview is loaded to the preview_image wave in the pear_explorer data folder.
///
/// the s_file_info string is updated with information about the scan dimensions.
///
/// @param filename name of a file in the directory specified by the pearl_explorer_filepath path object.
///
/// @return wave reference of the preview image
///
static function /wave preview_hdf_file(filename)
string filename
dfref save_df = GetDataFolderDFR()
setdatafolder $package_path
svar s_preview_file
svar s_preview_source
adh5_load_preview("preview_image", "pearl_explorer_filepath", filename)
s_preview_file = filename
s_preview_source = ""
wave /z preview_image
svar /z s_file_info
if (! svar_exists(s_file_info))
string /g s_file_info
endif
if (strlen(s_preview_file) > 0)
s_file_info = adh5_load_info("pearl_explorer_filepath", filename)
else
s_file_info = ""
endif
setdatafolder save_df
return preview_image
end
/// load the preview of a general ITX file.
///
/// the function is designed for PEARL OTF and EPICS scan data converted from MDA files.
/// the function picks the first wave whose PV note matches one from the global string s_preview_pvs
/// (see @ref preview_datafolder and @ref init_package).
///
/// the preview is loaded to the preview_image wave in the pearl_explorer data folder.
/// the s_file_info string is updated with information about the scan dimensions.
///
/// @note: the ITX files should load their waves into the current data folder (a "free" data folder).
/// some early versions of PEARL ITX data files created a data folder of their own.
/// both ways are allowed, while the first one is preferred.
/// on return, the current data folder must point to either the original free folder or the newly created one.
///
/// @param filename name of a file in the directory specified by the pearl_explorer_filepath path object.
///
/// @return wave reference of the preview trace.
/// empty wave reference if the function failed.
///
static function /wave preview_itx_file(filename)
string filename
dfref save_df = GetDataFolderDFR()
setdatafolder $package_path
svar s_preview_file
svar s_preview_source
wave preview_image
dfref data_df = newfreedatafolder()
setdatafolder data_df
LoadWave /t/p=pearl_explorer_filepath/q filename
s_preview_file = s_filename
s_preview_source = ""
preview_datafolder()
setdatafolder save_df
return preview_image
end
/// extract a preview image from a wave of arbitrary dimension
static function extract_preview_image(data, preview)
wave data
wave preview
variable z1, z2
// extract image
switch (WaveDims(data))
case 1:
redimension /n=(numpnts(data)) preview
preview = data[p]
break
case 2:
redimension /n=(dimsize(data, 0), dimsize(data, 1)) preview
preview = data
break
case 3:
redimension /n=(dimsize(data, 0), dimsize(data, 1)) preview
z1 = floor(DimSize(data, 2) / 2)
z2 = z1
wave slab = ad_extract_slab(data, nan, nan, nan, nan, z1, z2, "", pscale=1)
preview = slab
break
case 4:
// not implemented
endswitch
switch (WaveDims(data))
case 4:
case 3:
case 2:
setscale /p y dimoffset(data, 1), dimdelta(data, 1), waveunits(data, 1), preview
case 1:
setscale /p x dimoffset(data, 0), dimdelta(data, 0), waveunits(data, 0), preview
setscale d 0, 0, waveunits(data, -1), preview
endswitch
end
/// preview data in the current data folder
///
/// used by preview_itx_file
///
static function preview_datafolder()
dfref save_df = GetDataFolderDFR()
setdatafolder $package_path
svar s_preview_file
svar s_preview_source
svar s_preview_pvs
wave preview_image
setdatafolder save_df
// select a wave to display
// consider only double-precision waves, i.e. ignore text and other special waves
// filter by matching PV name to s_preview_pvs
string d_names = WaveList("*", ";", "DP:1")
variable nw = ItemsInList(d_names, ";")
variable npv = ItemsInList(s_preview_pvs, ";")
variable iw, ipv
string wname, wnote, pv_name, pv_match
for (iw = 0; iw < nw; iw += 1)
wname = StringFromList(iw, d_names, ";")
wnote = note($wname)
pv_name = StringByKey("PV", wnote, "=", "\r")
// find matching data wave by PV name
for (ipv = 0; ipv < npv; ipv += 1)
pv_match = StringFromList(ipv, s_preview_pvs)
if (StringMatch(pv_name, pv_match))
wave data = $wname
s_preview_source = pv_name
extract_preview_image(data, preview_image)
preview_setscale_x(data, preview_image)
npv = 0
nw = 0
endif
endfor
endfor
setdatafolder save_df
end
static function preview_setscale_x(data, preview)
// sets the approximate x scale of OTF data.
// requires an Axis1 tag with name of x wave in the wave note.
// if any of these conditions is true, the function does not change the scaling:
// 1) Axis1 tag or referenced wave is missing.
// 2) preview wave is not set to point scaling.
// 3) x wave is not monotonic (90% of the steps in the same direction).
wave data
wave preview
if ((DimOffset(preview, 0) == 0) && (DimDelta(preview, 0) == 1))
string xname = StringByKey("Axis1", note(data), "=", "\r")
wave /z xwave = $xname
if (WaveExists(xwave))
// check for monotonicity
variable monotonic = 0
duplicate /free xwave, xdiff
differentiate /p xwave /D=xdiff
duplicate /free xdiff, xflag
xflag = xdiff > 0
monotonic = sum(xflag) > numpnts(xwave) * 0.9
xflag = xdiff < 0
monotonic = monotonic || (sum(xflag) > numpnts(xwave) * 0.9)
if (monotonic)
setscale /i x xwave[0], xwave[numpnts(xwave)-1], waveunits(xwave, -1), preview
endif
endif
endif
end
/// displays the graph of a loaded dataset in its own window
static function display_dataset(file_df, dataset)
dfref file_df // top data folder of file
string dataset // dataset path inside data folder
dfref save_df = GetDataFolderDFR()
dfref data_df = psh5_dataset_to_folder(file_df, dataset)
SetDataFolder data_df
string data_name = StringFromList(ItemsInList(dataset, "/") - 1, dataset, "/")
wave /z data=$data_name
if (WaveExists(data))
switch(WaveDims(data))
case 1:
case 2:
show_preview_graph(data)
break
case 3:
ad_display_slice(data)
ad_brick_slicer(data)
break
endswitch
endif
setdatafolder save_df
return 0
end
static function /s show_preview_graph(data, [xdata])
// displays a preview of one- or two-dimensional data
wave data // data to be displayed. must either one-dimensional or two-dimensional
wave xdata // positions on x axis
dfref save_df = GetDataFolderDFR()
setdatafolder $package_path
svar s_profiles_graph
svar s_preview_file
svar s_preview_source
svar s_preview_trace_graph
svar s_preview_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
if (wavedims(data) == 2)
s_profiles_graph = ad_display_profiles(data)
ModifyGraph /w=$s_profiles_graph /z wbRGB=(48640,56832,60160)
graphname = s_profiles_graph
elseif (wavedims(data) == 1)
duplicate /o data, preview_trace
if (!ParamIsDefault(xdata))
duplicate /o xdata, preview_trace_x
else
duplicate /o data, preview_trace_x
preview_trace_x = x
setscale d 0, 0, WaveUnits(data, 0), preview_trace_x
endif
s_preview_trace_graph = display_preview_trace(preview_trace_x, preview_trace)
ModifyGraph /w=$s_preview_trace_graph wbRGB=(48640,56832,60160)
graphname = s_preview_trace_graph
else
return ""
endif
string title = "Preview " + s_preview_file
if (strlen(s_preview_source) > 0)
title = title + " (" + s_preview_source[0,31] + ")"
endif
dowindow /f/t $graphname, title
s_preview_graph = graphname
setdatafolder save_df
return graphname
end
static function /s display_preview_trace(xtrace, ytrace)
wave /z xtrace
wave ytrace
if (WaveExists(xtrace))
display /n=pearl_explorer_1d /k=1 ytrace vs xtrace as "Preview"
else
display /n=pearl_explorer_1d /k=1 ytrace as "Preview"
endif
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("Dataset", labels, "=", "\r")
if (!strlen(lab))
lab = "value"
endif
Label /w=$graphname left lab + " (\\U)"
return s_name
end
// ====== file loading ======
/// load the selected files
///
/// load the files that are selected in the data explorer panel.
/// the files are loaded using the load_file() function.
///
/// @note this function may change the current data folder!
///
static function load_selected_files([options])
string options
dfref save_df = GetDataFolderDFR()
setdatafolder $package_path
wave wSelectedFiles
wave/t wtFiles
variable nn = numpnts(wSelectedFiles)
variable ii
for (ii = 0; ii < nn; ii += 1)
if (wSelectedFiles[ii])
setdatafolder save_df
if (ParamIsDefault(options))
load_file(wtFiles[ii])
else
load_file(wtFiles[ii], options=options)
endif
endif
endfor
end
/// load one file
///
/// this can be a PShell, HDF5, or ITX file.
///
/// @note this function may change the current data folder!
///
/// @param options `key:value;` list of load options.
/// the recognized keys are: `mode`, `reduction_func` and `reduction_params`.
/// see main text for a description of possible values.
/// by default (options not specified), options are read from `s_hdf_options.
/// if the option string is empty, the user is prompted for options.
///
/// @param dest_df destination data folder. default: a new folder derived from file name under root.
///
/// @param quiet @arg 0 (default) print mode and parameters to history.
/// @arg 1 do not print to history.
///
static function load_file(filename, [options, dest_df, quiet])
string filename
string options
dfref dest_df
variable quiet
if (ParamIsDefault(options))
options = ""
endif
variable ft = pearl_file_type(filename)
switch(ft)
case 1:
load_pshell_file(filename, options=options, dest_df=dest_df, quiet=quiet)
break
case 2:
load_hdf_file(filename, options=options, dest_df=dest_df, quiet=quiet)
break
case 3:
load_itx_file(filename, dest_df=dest_df, quiet=quiet)
break
default:
break
endswitch
end
static function prompt_hdf_options(options)
string &options
string mode = StringByKey("mode", options, ":", ";")
string reduction_func = StringByKey("reduction_func", options, ":", ";")
string modes = "load_scan;load_region;load_dataset;load_diags;load_complete;"
string reduction_funcs = adh5_list_reduction_funcs()
reduction_funcs = RemoveFromList("adh5_default_reduction", reduction_funcs, ";")
if (strlen(mode) == 0)
mode = StringFromList(0, modes, ";")
endif
if (strlen(reduction_func) == 0)
reduction_func = StringFromList(0, reduction_funcs, ";")
endif
prompt mode, "Mode", popup, modes
prompt reduction_func, "Reduction Function", popup, reduction_funcs
doprompt "HDF5 Loading Options", mode, reduction_func
if (v_flag == 0)
options = ReplaceStringByKey("mode", options, mode, ":", ";")
options = ReplaceStringByKey("reduction_func", options, reduction_func, ":", ";")
endif
return v_flag // 0 = OK, 1 = cancel
end
/// prototype for prompting for processing function parameters.
///
/// the function should prompt the user for function parameters,
/// and update the param argument if the user clicked OK.
/// returns 0 if the user clicked OK, 1 if the user cancelled.
///
/// prompt functions must have the same name as the corresponding reduction function
/// with the prefix "prompt_".
/// be aware of the limited length of function names in Igor.
///
/// this function is a prototype. it does nothing but returns OK.
///
function prompt_default_process(param)
string &param
return 0
end
function prompt_func_params(func_name, func_param)
string func_name
string &func_param
string prompt_name = "prompt_" + func_name
if (exists(prompt_name) == 6)
funcref prompt_default_process prompt_func = $prompt_name
return prompt_func(func_param)
else
// ignore missing prompt function
return 0
endif
end
/// load a pshell file
///
/// if options is not specified, the complete file is loaded.
/// if options is an empty string, the package default options are used.
///
/// data selection is extracted from the datasets list box.
///
/// the file can be loaded in one of the following modes (`mode` key of the options argument):
///
/// @arg `load_complete` load all datasets regardless of selection.
/// @arg `load_scan` load default datasets of selected scans.
/// @arg `load_region` load default datasets of selected regions.
/// @arg `load_dataset` load selected datasets.
/// @arg `load_diags` load diagnostic datasets of selected scans.
///
/// 3-dimensional datasets can be loaded with dimension reduction.
/// in this case, the name of the reduction function must be given under the `reduction_func` key.
/// the reduction parameters are prompted for if a prompt function for the reduction function is found.
/// the default reduction parameters are the most recent parameters `s_reduction_params` stored in the package data folder.
///
/// @arg `reduction_func:...` name of the reduction function.
///
/// if a reduction function is specified, default reduction parameters are read from `s_reduction_params` in the package data folder,
/// and the user is prompted to review/update the parameters.
///
/// @param options `key:value;` list of load options.
/// the recognized keys are: `mode`, `reduction_func` and `reduction_params`.
/// see main text for a description of possible values.
/// by default (options not specified), options are read from `s_hdf_options.
/// if the option string is empty, the user is prompted for options.
///
/// @param dest_df destination data folder. default: a new folder derived from file name under root.
///
/// @param quiet @arg 0 (default) print mode and parameters to history.
/// @arg 1 do not print to history.
///
/// @return data folder reference of the loaded data. this is the folder which contains the scan sub-folders.
///
static function /df load_pshell_file(filename, [options, dest_df, quiet])
string filename
string options
dfref dest_df
variable quiet
dfref save_df = GetDataFolderDFR()
svar pref_options = $(package_path + "s_hdf_options")
svar pref_params = $(package_path + "s_reduction_params")
string path = "pearl_explorer_filepath"
if (ParamIsDefault(options))
options = pref_options
endif
if (strlen(options) == 0)
if (prompt_hdf_options(options) == 0)
pref_options = options
else
return $""
endif
endif
string reduction_func = StringByKey("reduction_func", options, ":", ";")
string reduction_params = pref_params
variable max_rank = 2
if (exists(reduction_func) == 6)
max_rank = 3
if (prompt_func_params(reduction_func, reduction_params) == 0)
pref_params = reduction_params
else
return $""
endif
endif
string mode = StringByKey("mode", options, ":", ";")
string selected_datasets = WMHL_SelectedObjectsList("PearlDataExplorer", "lb_contents")
string selected_scans = psh5_extract_scan_paths(selected_datasets)
string selected_regions = psh5_extract_region_paths(selected_datasets)
variable dsc
if (!quiet)
print mode, filename
if (strlen(reduction_func))
print reduction_func, reduction_params
endif
endif
strswitch(mode)
case "load_complete":
dsc = kDSCAll
dfref file_df = psh5_load(path, filename, "", "", "*", classes=dsc, reduction_func=reduction_func, reduction_params=reduction_params, dest_df=dest_df)
break
case "load_diags":
if (ItemsInList(selected_scans, ";") == 0)
if (!quiet)
print "no scan selected - defaulting to scan 1."
endif
selected_scans = "/scan1;"
endif
dsc = kDSCAttrs | kDSCDiags | kDSCSnaps | kDSCMeta | kDSCMonitors
dfref file_df = psh5_load(path, filename, selected_scans, "", "", classes=dsc, dest_df=dest_df)
break
case "load_scan":
if (ItemsInList(selected_scans, ";") == 0)
if (!quiet)
print "no scan selected - defaulting to scan 1."
endif
selected_scans = "/scan1;"
endif
dsc = kDSCPositioners | kDSCDetectors | kDSCScientaScaling | kDSCEssentialDiags
dfref file_df = psh5_load(path, filename, selected_scans, "", "", classes=dsc, max_rank=max_rank, reduction_func=reduction_func, reduction_params=reduction_params, dest_df=dest_df)
break
case "load_region":
if (ItemsInList(selected_regions, ";") == 0)
if (!quiet)
print "no region selected - defaulting to scan 1/region 1."
endif
selected_regions = "/scan1/region1;"
endif
dsc = kDSCPositioners | kDSCDetectors | kDSCScientaScaling | kDSCEssentialDiags
dfref file_df = psh5_load(path, filename, "", selected_regions, "", classes=dsc, max_rank=max_rank, reduction_func=reduction_func, reduction_params=reduction_params, dest_df=dest_df)
break
case "load_dataset":
if (ItemsInList(selected_datasets, ";") > 0)
dsc = kDSCAll
dfref file_df = psh5_load(path, filename, "", "", selected_datasets, classes=dsc, reduction_func=reduction_func, reduction_params=reduction_params, dest_df=dest_df)
else
if (!quiet)
DoAlert /T="PShell Import" 0, "Please select the datasets to load."
endif
endif
break
endswitch
if (DataFolderRefStatus(file_df))
setdatafolder file_df
string /g pearl_explorer_import = "load_pshell_file"
if (!quiet)
print "data loaded to", GetDataFolder(1)
endif
else
setdatafolder save_df
endif
return file_df
end
static function /df load_hdf_file(filename, [options, dest_df, quiet])
string filename
string options
dfref dest_df
variable quiet
dfref save_df = GetDataFolderDFR()
string nickname = ad_suggest_foldername(filename)
string loaded_filename = ""
if (ParamIsDefault(dest_df) || !DataFolderRefStatus(dest_df))
//
else
DoAlert /T="load_hdf_file" 0, "optional argument dest_df not supported."
return $""
endif
if (ParamIsDefault(options))
loaded_filename = adh5_load_complete(nickname, "pearl_explorer_filepath", filename)
else
if (strlen(options) == 0)
svar pref_options = $(package_path + "s_hdf_options")
options = pref_options
if (prompt_hdf_options(options) == 0)
// OK
pref_options = options
else
// cancel
options = ""
endif
endif
string mode = StringByKey("mode", options, ":", ";")
strswitch(mode)
case "load_reduced":
string reduction_func = StringByKey("reduction_func", options, ":", ";")
svar pref_params = $(package_path + "s_reduction_params")
string reduction_params = pref_params
if (prompt_func_params(reduction_func, reduction_params) == 0)
pref_params = reduction_params
print reduction_func, reduction_params
loaded_filename = adh5_load_reduced(nickname, "pearl_explorer_filepath", filename, $reduction_func, reduction_params)
endif
break
endswitch
endif
dfref data_df
if (strlen(loaded_filename) > 0)
setdatafolder $("root:" + nickname)
data_df = GetDataFolderDFR()
string /g pearl_explorer_import = "load_hdf_file"
else
setdatafolder save_df
endif
return data_df
end
static function /df load_itx_file(filename, [options, dest_df, quiet])
string filename
string options
dfref dest_df
variable quiet
dfref save_df = GetDataFolderDFR()
string nickname = itx_suggest_foldername(filename)
if (ParamIsDefault(options))
options = ""
endif
variable own_data_df = 0
if (ParamIsDefault(dest_df) || !DataFolderRefStatus(dest_df))
setdatafolder root:
newdatafolder /s/o $("root:" + nickname)
own_data_df = 1
else
setdatafolder dest_df
endif
dfref data_df = GetDataFolderDFR()
// note: some versions of PEARL data files save data to a new data folder,
// and leave the newly created folder as the current folder.
// the free data folder is used by those files which don't create their own data folder.
// this is the new recommended behaviour
LoadWave /t/p=pearl_explorer_filepath/q filename
svar waves = s_wavenames
dfref act_df = GetDataFolderDFR()
if (v_flag > 0)
string /g pearl_explorer_import = "load_itx_file"
endif
if (!DataFolderRefsEqual(act_df, data_df) && own_data_df)
// the file created its own data folder.
// let's kill the pre-allocated folder
setdatafolder data_df
if (ItemsInList(WaveList("*", ";", ""), ";") == 0)
killdatafolder /z data_df
endif
endif
setdatafolder save_df
return act_df
end
/// suggest the name of a data folder based on an igor-text file name
///
/// if the file name follows the naming convention source-date-index.extension,
/// the function tries to generate the nick name as source_date_index.
/// otherwise it's just a cleaned up version of the file name.
///
/// igor text is used by the on-the-fly scan tool.
///
/// @param filename file name, including extension.
/// can also include a folder path (which is ignored).
/// the extension is currently ignored,
/// but may be used in a later version.
/// @param ignoredate if non-zero, the nick name will not include the date part.
/// defaults to zero
/// @param sourcename nick name of the data source.
/// the function tries to detect the source from the file name.
/// this option can be used to override auto-detection.
/// allowed values: sscan, otf
/// @param unique if non-zero, the resulting name is made a unique data folder name in the current data folder.
/// defaults to zero
///
function /s itx_suggest_foldername(filename, [ignoredate,sourcename,unique])
string filename
variable ignoredate
string sourcename
variable unique
if (ParamIsDefault(ignoredate))
ignoredate = 0
endif
if (ParamIsDefault(unique))
unique = 0
endif
string basename = ParseFilePath(3, filename, ":", 0, 0)
string extension = ParseFilePath(4, filename, ":", 0, 0)
string nickname
string autosource
if (strsearch(basename, "X03DA_PC", 0, 2) >= 0)
autosource = "sscan"
basename = ReplaceString("_", basename, "-")
ignoredate = 1
elseif (strsearch(basename, "otf", 0, 2) >= 0)
autosource = "otf"
endif
if (ParamIsDefault(sourcename))
sourcename = autosource
endif
variable nparts = ItemsInList(basename, "-")
if (nparts >= 3)
string datepart = StringFromList(nparts - 2, basename, "-")
string indexpart = StringFromList(nparts - 1, basename, "-")
if (ignoredate)
sprintf nickname, "%s_%s", sourcename, indexpart
else
sprintf nickname, "%s_%s_%s", sourcename, datepart, indexpart
endif
else
nickname = PearlCleanupName(basename)
endif
if (unique && CheckName(nickname, 11))
nickname = UniqueName(nickname + "_", 11, 0)
endif
return nickname
end
// ====== panel ======
Window PearlDataExplorer() : Panel
PauseUpdate; Silent 1 // building window...
NewPanel /K=1 /W=(510,45,1190,539) as "PEARL Data Explorer"
ModifyPanel cbRGB=(48640,56832,60160)
GroupBox g_data_reduction,pos={355.00,370.00},size={306.00,49.00},title="data reduction"
GroupBox g_data_reduction,help={"data reduction of 3D ScientaImage"}
GroupBox gb_filepath,pos={8.00,4.00},size={328.00,48.00},title="file system folder"
TitleBox tb_filepath,pos={20.00,28.00},size={279.00,21.00},frame=0
TitleBox tb_filepath,variable= root:packages:pearl_explorer:s_short_filepath,fixedSize=1
Button b_browse_filepath,pos={303.00,24.00},size={20.00,20.00},proc=PearlDataExplorer#bp_browse_filepath,title="..."
Button b_browse_filepath,fColor=(65280,48896,32768)
GroupBox gb_prefs,pos={8.00,351.00},size={65.00,131.00},title="prefs"
GroupBox gb_prefs,help={"explorer package preferences"}
Button b_save_prefs,pos={21.00,394.00},size={38.00,17.00},proc=PearlDataExplorer#bp_save_prefs,title="save"
Button b_save_prefs,help={"save preferences of the data explorer package (data file path, attributes filter)"}
Button b_save_prefs,fColor=(65280,48896,32768)
Button b_load_prefs,pos={21.00,374.00},size={38.00,17.00},proc=PearlDataExplorer#bp_load_prefs,title="load"
Button b_load_prefs,help={"load preferences of the data explorer package"}
Button b_load_prefs,fColor=(65280,48896,32768)
GroupBox gb_filelist,pos={8.00,55.00},size={328.00,293.00},title="data files"
ListBox lb_files,pos={20.00,83.00},size={303.00,222.00},proc=PearlDataExplorer#lbp_filelist
ListBox lb_files,listWave=root:packages:pearl_explorer:wtFiles
ListBox lb_files,selWave=root:packages:pearl_explorer:wSelectedFiles,mode= 4
Button b_update_filelist,pos={246.00,315.00},size={76.00,22.00},proc=PearlDataExplorer#bp_update_filelist,title="update list"
Button b_update_filelist,fColor=(65280,48896,32768)
CheckBox cb_file_preview,pos={78.00,318.00},size={59.00,14.00},title="preview"
CheckBox cb_file_preview,help={"enable/disable automatic preview window when selecting a data file"}
CheckBox cb_file_preview,value= 0
Button b_file_prev,pos={20.00,314.00},size={22.00,22.00},proc=PearlDataExplorer#bp_file_prev,title="\\W646"
Button b_file_prev,help={"previous file"},fColor=(65280,48896,32768)
Button b_file_next,pos={44.00,314.00},size={22.00,22.00},proc=PearlDataExplorer#bp_file_next,title="\\W649"
Button b_file_next,help={"next file"},fColor=(65280,48896,32768)
Button b_goto_dataset,pos={355.00,315.00},size={64.00,22.00},disable=2,proc=PearlDataExplorer#bp_goto_dataset,title="goto DF"
Button b_goto_dataset,help={"change the current data folder ot where the selected dataset could be located"}
Button b_goto_dataset,fColor=(65280,48896,32768)
Button b_display_dataset,pos={423.00,315.00},size={64.00,22.00},disable=2,proc=PearlDataExplorer#bp_display_dataset,title="display"
Button b_display_dataset,help={"display the selected dataset in its own window"}
Button b_display_dataset,fColor=(65280,48896,32768)
Button b_load_complete,pos={355.00,451.00},size={92.00,22.00},disable=2,proc=PearlDataExplorer#bp_load_options,title="all data"
Button b_load_complete,help={"load all datasets of the selected file."}
Button b_load_complete,userdata= "mode:load_complete;"
Button b_load_complete,fColor=(65280,48896,32768)
TitleBox tb_selected_file,pos={360.00,28.00},size={309.00,22.00},frame=0
TitleBox tb_selected_file,variable= root:packages:pearl_explorer:s_selected_file,fixedSize=1
GroupBox gb_contents,pos={346.00,55.00},size={327.00,294.00},title="datasets"
Button b_attr_notebook,pos={97.00,375.00},size={64.00,22.00},disable=2,proc=PearlDataExplorer#bp_attr_notebook,title="notebook"
Button b_attr_notebook,help={"show a summary of attributes in a notebook window"}
Button b_attr_notebook,fColor=(65280,48896,32768)
ListBox lb_contents,pos={355.00,84.00},size={305.00,222.00}
ListBox lb_contents,keySelectCol= 1
GroupBox gb_selected_file,pos={346.00,4.00},size={328.00,48.00},title="selected file"
Button b_load_region,pos={355.00,426.00},size={92.00,22.00},disable=2,proc=PearlDataExplorer#bp_load_options,title="region"
Button b_load_region,help={"load the selected region"}
Button b_load_region,userdata= "mode:load_region;",fColor=(65280,48896,32768)
PopupMenu popup_reduction,pos={366.00,391.00},size={200.00,17.00},bodyWidth=200,proc=PearlDataExplorer#pmp_reduction_func
PopupMenu popup_reduction,help={"data reduction of 3d ScientaImage. note: the list may contain unsuitable functions. check the code or documentation!"}
PopupMenu popup_reduction,mode=1,popvalue="None",value= #"PearlDataExplorer#pm_reduction_values()"
GroupBox group_import,pos={346.00,351.00},size={326.00,131.00},title="import"
Button b_load_scan,pos={450.00,426.00},size={94.00,22.00},disable=2,proc=PearlDataExplorer#bp_load_options,title="scan"
Button b_load_scan,help={"load the selected scan"},userdata= "mode:load_scan;"
Button b_load_scan,fColor=(65280,48896,32768)
Button b_load_diags,pos={450.00,451.00},size={94.00,22.00},disable=2,proc=PearlDataExplorer#bp_load_options,title="diagnostics"
Button b_load_diags,help={"load diagnostics of selected scans"},userdata= "mode:load_diags;"
Button b_load_diags,fColor=(65280,48896,32768)
Button b_load_dataset,pos={547.00,426.00},size={101.00,22.00},disable=2,proc=PearlDataExplorer#bp_load_options,title="dataset"
Button b_load_dataset,help={"load the selected datasets"}
Button b_load_dataset,userdata= "mode:load_dataset;",fColor=(65280,48896,32768)
Button b_reduction_params,pos={571.00,390.00},size={71.00,19.00},disable=2,proc=PearlDataExplorer#bp_reduction_params,title="set params"
Button b_reduction_params,help={"set data reduction parameters"}
Button b_reduction_params,fColor=(65280,48896,32768)
GroupBox g_fileinfo,pos={85.00,351.00},size={251.00,131.00},title="file info"
Button b_elog,pos={97.00,401.00},size={64.00,22.00},disable=2,proc=PearlDataExplorer#bp_elog,title="ELOG"
Button b_elog,help={"send file metadata to ELOG panel (does not submit to ELOG)"}
Button b_elog,fColor=(65280,48896,32768)
ToolsGrid grid=(0,28.35,5)
EndMacro
/// update controls state
///
static function update_controls()
dfref package_df = $package_path
svar /z /sdfr=package_df hl_contents_datasets
wave /z /sdfr=package_df wSelectedFiles
variable file_selected = 0
if (WaveExists(wSelectedFiles))
file_selected = sum(wSelectedFiles)
endif
string selected_datasets = WMHL_SelectedObjectsList("PearlDataExplorer", "lb_contents")
variable scan_selected = strsearch(selected_datasets, "scan", 0, 2) == 0
variable region_selected = strsearch(selected_datasets, "region", 0, 2) >= 0
variable dataset_selected = 0
variable nds = ItemsInList(selected_datasets, ";")
variable ids
string ds
if (svar_exists(hl_contents_datasets))
for (ids = 0; ids < nds; ids += 1)
ds = "/" + StringFromList(ids, selected_datasets, ";")
if (NumType(NumberByKey(ds, hl_contents_datasets, ":", ";")) == 0)
dataset_selected = 1
break
endif
endfor
else
nds = 0
endif
variable dis
dis = file_selected ? 0 : 2
Button b_load_complete win=PearlDataExplorer,disable=dis
Button b_load_diags win=PearlDataExplorer,disable=dis
dis = file_selected && scan_selected ? 0 : 2
Button b_attr_notebook win=PearlDataExplorer,disable=dis
dis = file_selected && (strlen(WinList("*ElogPanel*", ";", "WIN:64")) > 1) ? 0 : 2
Button b_elog win=PearlDataExplorer,disable=dis
dis = scan_selected ? 0 : 2
Button b_load_scan win=PearlDataExplorer,disable=dis
dis = region_selected ? 0 : 2
Button b_load_region win=PearlDataExplorer,disable=dis
dis = dataset_selected ? 0 : 2
Button b_load_dataset win=PearlDataExplorer,disable=dis
Button b_display_dataset win=PearlDataExplorer,disable=dis
dis = file_selected && (nds > 0) ? 0 : 2
Button b_goto_dataset win=PearlDataExplorer,disable=dis
ControlInfo /W=PearlDataExplorer popup_reduction
if ((cmpstr(S_Value, "None") != 0) && (exists(S_Value) == 6))
GroupBox g_data_reduction win=PearlDataExplorer,labelBack=(65535,49151,49151)
Button b_reduction_params win=PearlDataExplorer,disable=0
else
GroupBox g_data_reduction win=PearlDataExplorer,labelBack=0
Button b_reduction_params win=PearlDataExplorer,disable=2
endif
return 0
end
static function bp_load_prefs(ba) : ButtonControl
STRUCT WMButtonAction &ba
switch( ba.eventCode )
case 2: // mouse up
load_prefs()
update_controls()
break
case -1: // control being killed
break
endswitch
return 0
End
static function bp_save_prefs(ba) : ButtonControl
STRUCT WMButtonAction &ba
switch( ba.eventCode )
case 2: // mouse up
save_prefs()
break
case -1: // control being killed
break
endswitch
return 0
End
/// shorten a file path for display
///
/// @note the result is not a valid path any more!
///
static function /s shorten_filepath(long_path, max_len)
string long_path
variable max_len
string path = long_path
variable ellipsis = 0
do
if (strlen(path) > max_len)
path = RemoveListItem(1, path, ":")
ellipsis += 1
else
break
endif
while (1)
if (ellipsis >= 1)
path = AddListItem("…", path, ":", 1)
endif
return path
end
static function bp_browse_filepath(ba) : ButtonControl
STRUCT WMButtonAction &ba
dfref save_df = GetDataFolderDFR()
switch( ba.eventCode )
case 2: // mouse up
PathInfo /S pearl_explorer_filepath
NewPath /M="select data file folder" /O/Z pearl_explorer_filepath
if (v_flag == 0)
update_filepath()
update_filelist()
update_controls()
endif
break
case -1: // control being killed
break
endswitch
setdatafolder save_df
return 0
End
static function bp_update_filelist(ba) : ButtonControl
STRUCT WMButtonAction &ba
switch( ba.eventCode )
case 2: // mouse up
update_filelist()
update_controls()
break
case -1: // control being killed
break
endswitch
return 0
End
/// items for data reduction popup
static function /s pm_reduction_values()
string reduction_funcs = adh5_list_reduction_funcs()
reduction_funcs = RemoveFromList("adh5_default_reduction", reduction_funcs, ";")
reduction_funcs = AddListItem("None", reduction_funcs, ";", 0)
return reduction_funcs
end
static function pmp_reduction_func(pa) : PopupMenuControl
STRUCT WMPopupAction &pa
switch( pa.eventCode )
case 2: // mouse up
Variable popNum = pa.popNum
String popStr = pa.popStr
update_controls()
break
case -1: // control being killed
break
endswitch
return 0
End
static function bp_reduction_params(ba) : ButtonControl
STRUCT WMButtonAction &ba
switch( ba.eventCode )
case 2: // mouse up
ControlInfo /W=PearlDataExplorer popup_reduction
if ((cmpstr(S_Value, "None") != 0) && (exists(S_Value) == 6))
svar pref_params = $(package_path + "s_reduction_params")
string reduction_func = S_Value
string reduction_params = pref_params
if (prompt_func_params(reduction_func, reduction_params) == 0)
pref_params = reduction_params
endif
endif
break
case -1: // control being killed
break
endswitch
return 0
End
static function bp_load_options(ba) : ButtonControl
STRUCT WMButtonAction &ba
switch( ba.eventCode )
case 2: // mouse up
// options must be in the button's unnamed user data in the form: "mode:load_complete".
// see load_pshell_file for recognized values.
string options=ba.userData
// data reduction popup
ControlInfo /W=PearlDataExplorer popup_reduction
if ((cmpstr(S_Value, "None") != 0) && (exists(S_Value) == 6))
options = ReplaceStringByKey("reduction_func", options, S_Value, ":", ";")
endif
load_selected_files(options=options)
break
case -1: // control being killed
break
endswitch
return 0
End
/// actions after a file has been selected
///
/// - load metadata
/// - load preview if requested
///
/// @param file name of selected file
/// @param do_preview enable/disable loading of preview data
/// non-zero: load preview,
/// zero: don't load preview
///
static function selected_file(file, do_preview)
string file
variable do_preview
dfref save_df = GetDataFolderDFR()
setdatafolder $package_path
svar s_selected_file
s_selected_file = file
get_file_info(file)
if (do_preview)
preview_file(file)
endif
update_controls()
setdatafolder save_df
return 0
end
static function bp_file_next(ba) : ButtonControl
STRUCT WMButtonAction &ba
dfref save_df = GetDataFolderDFR()
switch( ba.eventCode )
case 2: // mouse up
setdatafolder $package_path
wave /t wtFiles
wave wSelectedFiles
FindValue /i=1 wSelectedFiles
v_value += 1
if (v_value >= numpnts(wtFiles))
v_value = min(numpnts(wtFiles) - 1, 0)
endif
wSelectedFiles = p == v_value
if (v_value >= 0)
variable ifile = v_value
ControlInfo /W=PearlDataExplorer cb_file_preview
selected_file(wtFiles[ifile], v_value)
endif
update_controls()
break
case -1: // control being killed
break
endswitch
setdatafolder save_df
return 0
End
static function bp_file_prev(ba) : ButtonControl
STRUCT WMButtonAction &ba
dfref save_df = GetDataFolderDFR()
switch( ba.eventCode )
case 2: // mouse up
setdatafolder $package_path
wave /t wtFiles
wave wSelectedFiles
FindValue /i=1 wSelectedFiles
v_value -= 1
if (v_value < 0)
v_value = numpnts(wtFiles) - 1
endif
wSelectedFiles = p == v_value
if (v_value >= 0)
variable ifile = v_value
ControlInfo /W=PearlDataExplorer cb_file_preview
selected_file(wtFiles[ifile], v_value)
endif
update_controls()
break
case -1: // control being killed
break
endswitch
setdatafolder save_df
return 0
End
static function lbp_filelist(lba) : ListBoxControl
STRUCT WMListboxAction &lba
dfref save_df = GetDataFolderDFR()
Variable row = lba.row
Variable col = lba.col
WAVE/T/Z listWave = lba.listWave
WAVE/Z selWave = lba.selWave
switch( lba.eventCode )
case -1: // control being killed
break
case 1: // mouse down
setdatafolder $package_path
wave wSelectedFiles
if (selWave[row])
if (sum(wSelectedFiles) == 1)
ControlInfo /W=PearlDataExplorer cb_file_preview
selected_file(listWave[row], v_value)
else
selected_file(listWave[row], 0)
endif
endif
update_controls()
break
case 3: // double click
break
case 4: // cell selection
case 5: // cell selection plus shift key
break
case 6: // begin edit
break
case 7: // finish edit
break
case 13: // checkbox clicked (Igor 6.2 or later)
break
endswitch
setdatafolder save_df
return 0
End
static function bp_attr_notebook(ba) : ButtonControl
STRUCT WMButtonAction &ba
dfref save_df = GetDataFolderDFR()
switch( ba.eventCode )
case 2: // mouse up
setdatafolder $package_path
wave wSelectedFiles
wave/t wtFiles
variable nn = numpnts(wSelectedFiles)
variable ii
for (ii = 0; ii < nn; ii += 1)
if (wSelectedFiles[ii])
attributes_notebook(wtFiles[ii])
break
endif
endfor
break
case -1: // control being killed
break
endswitch
setdatafolder save_df
return 0
End
static function hlp_setup()
dfref save_df = GetDataFolderDFR()
setdatafolder $package_path
MakeListIntoHierarchicalList("PearlDataExplorer", "lb_contents", "hlp_contents_open", selectionMode=WMHL_SelectionSingle, pathSeparator="/")
setdatafolder save_df
return 0
end
static function hl_contents_clear()
do
if (cmpstr(WMHL_GetItemForRowNumber("PearlDataExplorer", "lb_contents", 0), "<uninitialized>") != 0)
WMHL_DeleteRowAndChildren("PearlDataExplorer", "lb_contents", 0)
else
break
endif
while (1)
end
/// populate the contents list box with the internal directory of a HDF5 file
///
/// @return the number of top-level objects
///
static function hl_contents_update(file_df)
dfref file_df
dfref save_df = GetDataFolderDFR()
setdatafolder $package_path
hl_contents_clear()
variable nds
variable ids
string ds
string extra
string /g hl_contents_datasets = ""
if (DataFolderRefStatus(file_df))
svar /sdfr=file_df datasets = s_datasets
svar /sdfr=file_df datatypes = s_datasets_datatypes
svar /sdfr=file_df ranks = s_datasets_ranks
svar /sdfr=file_df dimensions = s_datasets_dimensions
nds = ItemsInList(datasets, ";")
for (ids = 0; ids < nds; ids += 1)
ds = StringFromList(ids, datasets, ";")
extra = StringFromList(ids, dimensions, ";")
hl_contents_datasets = ReplaceStringByKey(ds, hl_contents_datasets, extra, ":", ";")
endfor
endif
variable nobj = hl_add_objects("", hl_contents_datasets)
hl_expand_scans()
hl_default_selection()
setdatafolder save_df
return nobj
end
static function /df get_pshell_info(path_name, file_name, [dest_df])
string path_name
string file_name
dfref dest_df
dfref save_df = GetDataFolderDFR()
if (!ParamIsDefault(dest_df))
setdatafolder dest_df
else
setdatafolder $package_path
NewDataFolder /o /s file_info
endif
dfref file_df = psh5_open_file(path_name, file_name, dest_df=GetDataFolderDFR())
if (DataFolderRefStatus(file_df))
psh5_load_general_group(file_df)
psh5_close_file(file_df)
endif
setdatafolder save_df
return file_df
end
/// populate the contents list box with the given hierarchical paths
///
/// @return the number of top-level objects
///
static function hl_add_objects(parent_path, objects)
string parent_path // e.g. "/a/b"
string objects // all objects that might appear in the list. e.g. "/a/b/c:col0|col1;/a/b/d:col0|col1;/d/e/f:col0|col1;"
if (cmpstr(parent_path[0], "/") != 0)
parent_path = "/" + parent_path
endif
variable nobj = ItemsInList(objects, ";")
variable iobj
string obj
string extra
variable nel
string child_path = ""
string child_name = ""
string child_names = "" // e.g., "child1:1;child3:2;"
string extra_data = "" // e.g., "child1:col0|col1;child2:col0|col1;"
// filter children of parent
for (iobj = 0; iobj < nobj; iobj += 1)
obj = StringFromList(iobj, objects, ";")
if (cmpstr(obj[0, strlen(parent_path)-1], parent_path) == 0)
child_path = StringFromList(0, obj, ":")
child_path = child_path[strlen(parent_path), strlen(child_path)-1]
if (cmpstr(child_path[0], "/") == 0)
child_path = child_path[1, strlen(child_path)-1]
endif
child_name = StringFromList(0, child_path, "/")
nel = ItemsInList(child_path, "/")
child_names = ReplaceNumberByKey(child_name, child_names, nel)
if (nel == 1)
extra = RemoveListItem(0, obj, ":")
extra_data = ReplaceStringByKey(child_name, extra_data, extra)
endif
endif
endfor
// add rows
variable row
variable children
nobj = ItemsInList(child_names)
for (iobj = 0; iobj < nobj; iobj += 1)
obj = StringFromList(iobj, child_names)
child_name = StringFromList(0, obj, ":")
nel = NumberByKey(child_name, child_names)
WMHL_AddObject("PearlDataExplorer", "lb_contents", parent_path[1, strlen(parent_path)], child_name, nel > 1)
if (nel == 1)
extra = StringByKey(child_name, extra_data)
row = WMHL_GetRowNumberForItem("PearlDataExplorer", "lb_contents", parent_path[1, strlen(parent_path)] + "/" + child_name)
if (row >= 0)
WMHL_ExtraColumnData("PearlDataExplorer", "lb_contents", 0, row, StringFromList(0, extra, "|"), 0)
endif
endif
endfor
return nobj
end
static function hl_expand_scans()
dfref save_df = GetDataFolderDFR()
setdatafolder $package_path
svar hl_contents_datasets
variable nds = ItemsInList(hl_contents_datasets, ";")
variable ids
string sds
string scan
string scans = ""
for (ids = 0; ids < nds; ids += 1)
sds = StringFromList(ids, hl_contents_datasets, ";")
if (cmpstr(sds[0,4], "/scan", 0) == 0)
scan = StringFromList(1, sds, "/")
scans = ReplaceNumberByKey(scan, scans, 1)
endif
endfor
variable nscans = ItemsInList(scans)
variable iscan
for (iscan = 0; iscan < nscans; iscan += 1)
scan = StringFromList(iscan, scans)
scan = StringFromList(0, scan, ":")
WMHL_OpenAContainer("PearlDataExplorer", "lb_contents", scan)
endfor
setdatafolder save_df
end
static function hl_default_selection()
variable row
row = WMHL_GetRowNumberForItem("PearlDataExplorer", "lb_contents", "scan 1")
if (row < 0)
row = WMHL_GetRowNumberForItem("PearlDataExplorer", "lb_contents", "scan1")
endif
if (row >= 0)
WMHL_SelectARow("PearlDataExplorer", "lb_contents", row, 1)
endif
end
static function hlp_contents_open(HostWindow, ListControlName, ContainerPath)
String HostWindow, ListControlName, ContainerPath
dfref save_df = GetDataFolderDFR()
setdatafolder $package_path
svar hl_contents_datasets
hl_add_objects(ContainerPath, hl_contents_datasets)
setdatafolder save_df
end
static function hlp_contents_selection(HostWindow, ListControlName, SelectedItem, EventCode)
String HostWindow, ListControlName
String SelectedItem
Variable EventCode
dfref save_df = GetDataFolderDFR()
setdatafolder $package_path
switch (eventCode)
case 3: // double click
// todo: load dataset?
break
case 4: // cell selection
case 5: // cell selection plus shift key
update_controls()
break
endswitch
setdatafolder save_df
return 0
end
/// open data folder corresponding to a file and data path
///
/// the function tries to find where a given dataset has been loaded
/// and selects the corresponding data folder.
/// the data folder must exist (after previous import from the file),
/// else an error code is returned and the folder selection will be the closest accessible parent folder of the target.
///
/// @param filename file name (without path).
/// h5 and otf.itx files are supported.
/// @param datapath dataset or group path inside the hdf5 file.
/// @return 0 if successful,
/// -1 if the file type is unknown
/// -2 if the data path can't be found in the tree.
///
static function goto_dataset_folder(filename, datapath)
string filename
string datapath
dfref save_df = GetDataFolderDFR()
setdatafolder $package_path
variable ft = pearl_file_type(filename)
string parent_folder
string folder
string path
switch(ft)
case 1:
case 2:
parent_folder = ad_suggest_foldername(filename)
path = "root:" + parent_folder
if (DataFolderExists(path))
setdatafolder $path
else
return -2
endif
variable nparts = ItemsInList(datapath, "/")
variable ipart
for (ipart = 0; ipart < nparts; ipart += 1)
folder = StringFromList(ipart, datapath, "/")
path = ":" + ps_fix_folder_name(folder)
if (DataFolderExists(path))
setdatafolder $path
endif
endfor
break
case 3:
parent_folder = "root:" + itx_suggest_foldername(filename)
if (DataFolderExists(parent_folder))
setdatafolder $parent_folder
else
return -2
endif
break
default:
// unsupported file type
return -1
endswitch
return 0
end
/// "goto DF" button
///
/// the button selects the data folder of the selected file and dataset.
/// an error message is shown if the data folder doesn't exist.
///
static function bp_goto_dataset(ba) : ButtonControl
STRUCT WMButtonAction &ba
switch( ba.eventCode )
case 2: // mouse up
dfref save_df = GetDataFolderDFR()
setdatafolder $package_path
svar s_selected_file
svar hl_contents_datasets
string datapath = StringFromList(0, WMHL_SelectedObjectsList("PearlDataExplorer", "lb_contents"))
if (strsearch(hl_contents_datasets, datapath, 0) != 0)
datapath = datapath + "/"
endif
variable result = goto_dataset_folder(s_selected_file, datapath)
if (result != 0)
setdatafolder save_df
string msg
msg = "Can't find data folder. Has the file been loaded?"
DoAlert /T="Goto DF" 0, msg
endif
break
case -1: // control being killed
break
endswitch
return 0
End
/// "display dataset" button
///
///
static function bp_display_dataset(ba) : ButtonControl
STRUCT WMButtonAction &ba
switch( ba.eventCode )
case 2: // mouse up
dfref save_df = GetDataFolderDFR()
setdatafolder $package_path
svar s_selected_file
svar hl_contents_datasets
string datapath = StringFromList(0, WMHL_SelectedObjectsList("PearlDataExplorer", "lb_contents"))
if (strsearch(hl_contents_datasets, datapath, 0) < 0)
// path leads to folder
return 0
endif
goto_dataset_folder(s_selected_file, "")
display_dataset(GetDataFolderDFR(), datapath)
setdatafolder save_df
break
case -1: // control being killed
break
endswitch
return 0
End
/// send file metadata to the ELOG panel
///
/// metadate is looked up in the following locations:
/// 1. data folder if it exists
/// 2. file info folder inside package folder
/// 3. package folder if it contains preview data from the selected file (???)
///
static function send_to_elog()
dfref save_df = GetDataFolderDFR()
dfref preview_df = $package_path
svar /z /sdfr=preview_df s_selected_file
svar /z /sdfr=preview_df s_preview_file
svar /z /sdfr=preview_df s_preview_graph
if (!SVAR_Exists(s_selected_file) || (strlen(s_selected_file) < 1))
return 0
endif
// check data folder
variable result = -1
result = goto_dataset_folder(s_selected_file, "")
if (result == 0)
dfref data_df = GetDataFolderDFR()
svar /sdfr=data_df /z authors
if (!svar_Exists(authors))
result = -1
endif
endif
// file info folder
dfref infoDF = preview_df:file_info
if ((result != 0) && (DataFolderRefStatus(infoDF)))
svar /z /sdfr=infoDF s_filepath
if (SVAR_Exists(s_filepath) && (strsearch(s_filepath, s_selected_file, inf, 1) >= 0))
dfref data_df = infoDF
result = 0
endif
endif
// check preview (package) folder
if ((result != 0) && (SVAR_Exists(s_preview_file) && (cmpstr(s_preview_file, s_selected_file) == 0)))
dfref data_df = preview_df
result = 0
endif
string graphname
if (SVAR_Exists(s_preview_graph) && (WinType(s_preview_graph) == 1))
graphname = s_preview_graph
else
graphname = ""
endif
if (result == 0)
set_elog_attributes(data_df, filename=s_selected_file, graphname=graphname)
string windowname
windowname = StringFromList(0, WinList("*ElogPanel*", ";", "WIN:64"), ";")
DoWindow /F $windowname
endif
setdatafolder save_df
end
static function bp_elog(ba) : ButtonControl
STRUCT WMButtonAction &ba
switch( ba.eventCode )
case 2: // mouse up
send_to_elog()
break
case -1: // control being killed
break
endswitch
return 0
End