From b7390cb46f90ed84ca5ba1795d4f3ef3a6b01000 Mon Sep 17 00:00:00 2001 From: matthias muntwiler Date: Wed, 14 Aug 2019 17:57:25 +0200 Subject: [PATCH] update documentation for 2.1.0 --- doc/html/PageProjections.html | 135 -- doc/html/_page_projections.html | 4 +- doc/html/anglescan-processing_8dox.html | 4 +- doc/html/annotated.html | 4 +- doc/html/arrowdown.png | Bin 246 -> 0 bytes doc/html/arrowright.png | Bin 229 -> 0 bytes doc/html/classes.html | 4 +- doc/html/deprecated.html | 123 -- .../dir_fe5dc42579d4b99403482a3a637d9f7d.html | 7 +- doc/html/fermi-edge-analysis_8ipf.html | 4 +- doc/html/fermi-edge-analysis_8ipf_source.html | 4 +- doc/html/files.html | 31 +- doc/html/files.js | 1 + doc/html/functions.html | 4 +- doc/html/functions_vars.html | 4 +- doc/html/globals.html | 7 +- doc/html/globals_b.html | 4 +- doc/html/globals_c.html | 4 +- doc/html/globals_d.html | 4 +- doc/html/globals_e.html | 4 +- doc/html/globals_f.html | 4 +- doc/html/globals_func.html | 7 +- doc/html/globals_func_b.html | 4 +- doc/html/globals_func_c.html | 4 +- doc/html/globals_func_d.html | 4 +- doc/html/globals_func_e.html | 4 +- doc/html/globals_func_f.html | 4 +- doc/html/globals_func_g.html | 4 +- doc/html/globals_func_h.html | 4 +- doc/html/globals_func_i.html | 4 +- doc/html/globals_func_k.html | 4 +- doc/html/globals_func_l.html | 4 +- doc/html/globals_func_m.html | 4 +- doc/html/globals_func_n.html | 4 +- doc/html/globals_func_o.html | 4 +- doc/html/globals_func_p.html | 7 +- doc/html/globals_func_q.html | 4 +- doc/html/globals_func_r.html | 11 +- doc/html/globals_func_s.html | 4 +- doc/html/globals_func_t.html | 4 +- doc/html/globals_func_u.html | 4 +- doc/html/globals_func_w.html | 4 +- doc/html/globals_g.html | 4 +- doc/html/globals_h.html | 4 +- doc/html/globals_i.html | 4 +- doc/html/globals_k.html | 4 +- doc/html/globals_l.html | 4 +- doc/html/globals_m.html | 4 +- doc/html/globals_n.html | 4 +- doc/html/globals_o.html | 4 +- doc/html/globals_p.html | 7 +- doc/html/globals_q.html | 4 +- doc/html/globals_r.html | 11 +- doc/html/globals_s.html | 4 +- doc/html/globals_t.html | 4 +- doc/html/globals_u.html | 4 +- doc/html/globals_v.html | 4 +- doc/html/globals_vars.html | 4 +- doc/html/globals_w.html | 4 +- doc/html/group___arpes_package.html | 10 +- doc/html/group___arpes_package.js | 1 + doc/html/group___preparation_package.html | 133 -- doc/html/index.html | 6 +- doc/html/mainpage_8dox.html | 4 +- doc/html/modules.html | 4 +- doc/html/namespace_pearl_anglescan_panel.html | 4 +- .../namespace_pearl_anglescan_process.html | 4 +- doc/html/namespace_pearl_area_display.html | 4 +- doc/html/namespace_pearl_area_import.html | 4 +- doc/html/namespace_pearl_area_profiles.html | 4 +- .../namespace_pearl_area_profiles_test.html | 129 -- doc/html/namespace_pearl_arpes.html | 4 +- ...nneal.html => namespace_pearl_compat.html} | 69 +- doc/html/namespace_pearl_data_explorer.html | 4 +- doc/html/namespace_pearl_elog.html | 4 +- doc/html/namespace_pearl_fit_funcs.html | 4 +- doc/html/namespace_pearl_matrix_import.html | 4 +- doc/html/namespace_pearl_p_shell_import.html | 4 +- doc/html/namespace_pearl_pmsco_import.html | 4 +- doc/html/namespace_pearl_preparation.html | 129 -- .../namespace_pearl_scienta_preprocess.html | 4 +- doc/html/namespaces.html | 19 +- doc/html/namespaces.js | 1 + doc/html/navtreedata.js | 4 +- doc/html/navtreeindex0.js | 18 +- doc/html/navtreeindex1.js | 286 ++-- doc/html/navtreeindex2.js | 310 ++-- doc/html/pag_anglescan_processing.html | 4 +- doc/html/pages.html | 4 +- doc/html/pearl-anglescan-panel_8ipf.html | 4 +- .../pearl-anglescan-panel_8ipf_source.html | 8 +- .../pearl-anglescan-process-test_8ipf.html | 189 --- doc/html/pearl-anglescan-process-test_8ipf.js | 5 - ...rl-anglescan-process-test_8ipf_source.html | 210 --- doc/html/pearl-anglescan-process_8ipf.html | 4 +- .../pearl-anglescan-process_8ipf_source.html | 4 +- doc/html/pearl-anglescan-tracker_8ipf.html | 4 +- .../pearl-anglescan-tracker_8ipf_source.html | 8 +- doc/html/pearl-anneal_8ipf.html | 1303 --------------- doc/html/pearl-anneal_8ipf.js | 43 - doc/html/pearl-anneal_8ipf_source.html | 1488 ----------------- doc/html/pearl-area-display_8ipf.html | 85 +- doc/html/pearl-area-display_8ipf_source.html | 57 +- doc/html/pearl-area-import_8ipf.html | 158 +- doc/html/pearl-area-import_8ipf.js | 2 + doc/html/pearl-area-import_8ipf_source.html | 58 +- doc/html/pearl-area-live_8ipf.html | 478 ------ doc/html/pearl-area-live_8ipf.js | 13 - doc/html/pearl-area-live_8ipf_source.html | 510 ------ doc/html/pearl-area-profiles-test_8ipf.html | 455 ----- doc/html/pearl-area-profiles-test_8ipf.js | 13 - .../pearl-area-profiles-test_8ipf_source.html | 568 ------- doc/html/pearl-area-profiles_8ipf.html | 4 +- doc/html/pearl-area-profiles_8ipf_source.html | 4 +- doc/html/pearl-arpes-scans_8ipf.html | 348 ---- doc/html/pearl-arpes-scans_8ipf.js | 12 - doc/html/pearl-arpes-scans_8ipf_source.html | 287 ---- doc/html/pearl-arpes_8ipf.html | 9 +- doc/html/pearl-arpes_8ipf_source.html | 8 +- ...xport_8ipf.html => pearl-compat_8ipf.html} | 102 +- doc/html/pearl-compat_8ipf.js | 4 + doc/html/pearl-compat_8ipf_source.html | 101 ++ doc/html/pearl-data-explorer_8ipf.html | 117 +- doc/html/pearl-data-explorer_8ipf_source.html | 141 +- doc/html/pearl-data-export_8ipf.js | 4 - doc/html/pearl-data-export_8ipf_source.html | 154 -- doc/html/pearl-elog_8ipf.html | 4 +- doc/html/pearl-elog_8ipf_source.html | 4 +- doc/html/pearl-fitfuncs_8ipf.html | 4 +- doc/html/pearl-fitfuncs_8ipf_source.html | 4 +- doc/html/pearl-gui-tools_8ipf.html | 4 +- doc/html/pearl-gui-tools_8ipf_source.html | 4 +- doc/html/pearl-matrix-import_8ipf.html | 4 +- doc/html/pearl-matrix-import_8ipf_source.html | 4 +- doc/html/pearl-menu_8ipf.html | 4 +- doc/html/pearl-menu_8ipf_source.html | 16 +- doc/html/pearl-otf-import_8ipf.html | 4 +- doc/html/pearl-otf-import_8ipf_source.html | 4 +- doc/html/pearl-pmsco-import_8ipf.html | 4 +- doc/html/pearl-pmsco-import_8ipf_source.html | 4 +- doc/html/pearl-polar-coordinates_8ipf.html | 4 +- .../pearl-polar-coordinates_8ipf_source.html | 4 +- doc/html/pearl-preparation_8ipf.html | 209 --- doc/html/pearl-preparation_8ipf.js | 5 - doc/html/pearl-preparation_8ipf_source.html | 161 -- doc/html/pearl-pshell-import_8ipf.html | 98 +- doc/html/pearl-pshell-import_8ipf_source.html | 45 +- doc/html/pearl-scienta-preprocess_8ipf.html | 4 +- .../pearl-scienta-preprocess_8ipf_source.html | 6 +- doc/html/pearl-tools_8ipf.html | 4 +- doc/html/pearl-tools_8ipf_source.html | 4 +- doc/html/pearl-vector-operations_8ipf.html | 4 +- .../pearl-vector-operations_8ipf_source.html | 4 +- doc/html/search/all_0.js | 1 + doc/html/search/all_10.js | 1 + doc/html/search/all_e.js | 3 + doc/html/search/files_3.js | 1 + doc/html/search/functions_0.js | 1 + doc/html/search/functions_10.js | 1 + doc/html/search/functions_e.js | 1 + doc/html/search/groups_1.html | 26 - doc/html/search/groups_1.js | 4 - doc/html/search/namespaces_0.js | 1 + doc/html/struct_doniach_sunjic_struct.html | 4 +- doc/html/structerror_code.html | 4 +- doc/html/todo.html | 4 +- doc/latex/refman.pdf | Bin 683283 -> 690023 bytes 167 files changed, 1230 insertions(+), 8118 deletions(-) delete mode 100644 doc/html/PageProjections.html delete mode 100644 doc/html/arrowdown.png delete mode 100644 doc/html/arrowright.png delete mode 100644 doc/html/deprecated.html delete mode 100644 doc/html/group___preparation_package.html delete mode 100644 doc/html/namespace_pearl_area_profiles_test.html rename doc/html/{namespace_pearl_anneal.html => namespace_pearl_compat.html} (57%) delete mode 100644 doc/html/namespace_pearl_preparation.html delete mode 100644 doc/html/pearl-anglescan-process-test_8ipf.html delete mode 100644 doc/html/pearl-anglescan-process-test_8ipf.js delete mode 100644 doc/html/pearl-anglescan-process-test_8ipf_source.html delete mode 100644 doc/html/pearl-anneal_8ipf.html delete mode 100644 doc/html/pearl-anneal_8ipf.js delete mode 100644 doc/html/pearl-anneal_8ipf_source.html delete mode 100644 doc/html/pearl-area-live_8ipf.html delete mode 100644 doc/html/pearl-area-live_8ipf.js delete mode 100644 doc/html/pearl-area-live_8ipf_source.html delete mode 100644 doc/html/pearl-area-profiles-test_8ipf.html delete mode 100644 doc/html/pearl-area-profiles-test_8ipf.js delete mode 100644 doc/html/pearl-area-profiles-test_8ipf_source.html delete mode 100644 doc/html/pearl-arpes-scans_8ipf.html delete mode 100644 doc/html/pearl-arpes-scans_8ipf.js delete mode 100644 doc/html/pearl-arpes-scans_8ipf_source.html rename doc/html/{pearl-data-export_8ipf.html => pearl-compat_8ipf.html} (51%) create mode 100644 doc/html/pearl-compat_8ipf.js create mode 100644 doc/html/pearl-compat_8ipf_source.html delete mode 100644 doc/html/pearl-data-export_8ipf.js delete mode 100644 doc/html/pearl-data-export_8ipf_source.html delete mode 100644 doc/html/pearl-preparation_8ipf.html delete mode 100644 doc/html/pearl-preparation_8ipf.js delete mode 100644 doc/html/pearl-preparation_8ipf_source.html delete mode 100644 doc/html/search/groups_1.html delete mode 100644 doc/html/search/groups_1.js diff --git a/doc/html/PageProjections.html b/doc/html/PageProjections.html deleted file mode 100644 index 5b852da..0000000 --- a/doc/html/PageProjections.html +++ /dev/null @@ -1,135 +0,0 @@ - - - - - - -PEARL Procedures: Projections - - - - - - - - - - - - - - - -
-
- - - - - - -
-
PEARL Procedures -  rev-distro-2.0.0-0-gfda49c3-dirty -
-
Igor procedures for the analysis of PEARL data
-
-
- - - - -
-
- -
-
-
- -
- -
-
- - -
- -
- -
-
-
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.

-
-
- - - - diff --git a/doc/html/_page_projections.html b/doc/html/_page_projections.html index 103a183..0741dbf 100644 --- a/doc/html/_page_projections.html +++ b/doc/html/_page_projections.html @@ -29,7 +29,7 @@
PEARL Procedures -  rev-distro-2.0.3-0-g0fb0fd9 +  rev-distro-2.0.3-2-g58135e4-dirty
Igor procedures for the analysis of PEARL data
@@ -107,7 +107,7 @@ $(document).ready(function(){initNavTree('_page_projections.html','');}); @@ -1044,7 +1117,7 @@ Licensed under the Apache License, Version 2.0 (the "License");

set up a one-dimensional wave for a line profile based on a 2D original wave.

redimensions the profile wave to the given dimension. copies the scale and dimension label of the given dimension.

-

Definition at line 1133 of file pearl-area-import.ipf.

+

Definition at line 1134 of file pearl-area-import.ipf.

@@ -1099,7 +1172,7 @@ Licensed under the Apache License, Version 2.0 (the "License");
Returns
a copy of the reduction_param string, possibly modified by the reduction function.
-

Definition at line 1166 of file pearl-area-import.ipf.

+

Definition at line 1167 of file pearl-area-import.ipf.

@@ -1163,7 +1236,7 @@ Licensed under the Apache License, Version 2.0 (the "License");

callback function for drag&drop of HDF5 files into Igor.

-

Definition at line 41 of file pearl-area-import.ipf.

+

Definition at line 42 of file pearl-area-import.ipf.

@@ -1201,7 +1274,7 @@ Licensed under the Apache License, Version 2.0 (the "License");
Returns
data folder reference of the attributes folder. the reference may be invalid (and default to root) if the folder cannot be found, cf. built-in DataFolderRefStatus function.
-

Definition at line 706 of file pearl-area-import.ipf.

+

Definition at line 707 of file pearl-area-import.ipf.

@@ -1256,7 +1329,38 @@ Licensed under the Apache License, Version 2.0 (the "License");
-

Definition at line 1634 of file pearl-area-import.ipf.

+

Definition at line 1872 of file pearl-area-import.ipf.

+ + + + +

◆ reduce_brick_worker()

+ +
+
+ + + + + +
+ + + + + + + + +
static threadsafe variable reduce_brick_worker (funcref reduction_func)
+
+static
+
+ +

thread worker for adh5_reduce_brick

+

this function polls job data folders from thread group 0 and calls the reduction function on their contents. the result waves have prefix "redw_" and are saved in the job folder.

+ +

Definition at line 1377 of file pearl-area-import.ipf.

@@ -1306,7 +1410,7 @@ Licensed under the Apache License, Version 2.0 (the "License");
-

Definition at line 1519 of file pearl-area-import.ipf.

+

Definition at line 1757 of file pearl-area-import.ipf.

@@ -1334,7 +1438,7 @@ Licensed under the Apache License, Version 2.0 (the "License");
-

Definition at line 1480 of file pearl-area-import.ipf.

+

Definition at line 1718 of file pearl-area-import.ipf.

@@ -1344,7 +1448,7 @@ Licensed under the Apache License, Version 2.0 (the "License");
-Go to the documentation of this file.
1 #pragma rtGlobals=3 // Use modern global access method and strict wave access.
2 #pragma IgorVersion = 6.2
3 #pragma ModuleName = PearlAreaImport
4 #include <HDF5 Browser>
5 #include "pearl-gui-tools"
6 
7 // copyright (c) 2013-18 Paul Scherrer Institut
8 //
9 // Licensed under the Apache License, Version 2.0 (the "License");
10 // you may not use this file except in compliance with the License.
11 // You may obtain a copy of the License at
12 // http:///www.apache.org/licenses/LICENSE-2.0
13 
33 
38 
41 static function BeforeFileOpenHook(refNum,fileName,path,type,creator,kind)
42  variable refNum, kind
43  string fileName, path, type, creator
44 
45  variable handledOpen = 0
46 
47  //PathInfo $path
48  //string FilePath = s_path + filename
49  string NickName = CleanupName(ParseFilePath(3, FileName, ":", 0, 0), 0)
50  string FileExt = LowerStr(ParseFilePath(4, FileName, ":", 0, 0))
51  string result = ""
52 
53  // override nickname with custom setting
54  svar /z cnn = gsCustomNickName
55  if (svar_exists(cnn))
56  if (exists("gvNickNameIndex") != 2)
57  variable/g gvNickNameIndex = 1
58  endif
59  nvar nni = gvNickNameIndex
60  NickName = cnn + num2str(nni)
61  nni += 1
62  endif
63 
64  if (stringmatch(FileExt, "h5") == 1)
65  result = adh5_load_complete(NickName, path, FileName)
66  endif
67 
68  string/g s_latest_datafile = result
69  string/g s_latest_nickname = nickname
70 
71  handledOpen = strlen(result) > 0
72  if (handledOpen)
73  close refnum
74  endif
75 
76  return handledOpen // 1 tells Igor not to open the file
77 End
78 
105 function /s ad_suggest_foldername(filename, [ignoredate,sourcename,unique])
106  string filename
107  variable ignoredate
108  string sourcename
109  variable unique
110 
111  if (ParamIsDefault(ignoredate))
112  ignoredate = 0
113  endif
114  if (ParamIsDefault(unique))
115  unique = 0
116  endif
117 
118  string basename = ParseFilePath(3, filename, ":", 0, 0)
119  string extension = ParseFilePath(4, filename, ":", 0, 0)
120  string nickname
121 
122  string autosource
123  if (strsearch(basename, "scienta", 0, 2) >= 0)
124  autosource = "sci"
125  elseif (strsearch(basename, "pshell", 0, 2) >= 0)
126  autosource = "psh"
127  elseif (strsearch(basename, "OP-SL", 0, 2) >= 0)
128  autosource = "sl"
129  elseif (strsearch(basename, "ES-PS", 0, 2) >= 0)
130  autosource = "es"
131  else
132  autosource = "xy"
133  endif
134  if (ParamIsDefault(sourcename))
135  sourcename = autosource
136  endif
137 
138  variable nparts = ItemsInList(basename, "-")
139  if (nparts >= 3)
140  string datepart = StringFromList(1, basename, "-")
141  variable l_datepart = strlen(datepart)
142  if (l_datepart == 8)
143  datepart = datepart[l_datepart-6, l_datepart-1]
144  endif
145  string indexpart = StringFromList(2, basename, "-")
146  if (ignoredate)
147  sprintf nickname, "%s_%s", sourcename, indexpart
148  else
149  sprintf nickname, "%s_%s_%s", sourcename, datepart, indexpart
150  endif
151  else
152  nickname = CleanupName(basename, 0)
153  endif
154 
155  if (unique && CheckName(nickname, 11))
156  nickname = UniqueName(nickname + "_", 11, 0)
157  endif
158 
159  return nickname
160 end
161 
166 function ad_load_dialog(APathName)
167  string APathName
168 
169  variable refNum
170  string message = "Select data files"
171  string filepaths
172  string filefilters = "Area Detector HDF5 Files (*.h5):.h5;"
173  filefilters += "All Files:.*;"
174 
175  PathInfo /S $APathName
176  Open /D /R /F=filefilters /M=message /MULT=1 refNum
177  filepaths = S_fileName
178 
179  dfref saveDF = GetDataFolderDFR()
180  setdatafolder root:
181 
182  if (strlen(filepaths) > 0)
183  variable nfiles = ItemsInList(filepaths, "\r")
184  variable ifile
185  for(ifile = 0; ifile < nfiles; ifile += 1)
186  String path = StringFromList(ifile, filepaths, "\r")
187  string nickname = ad_suggest_foldername(path)
188  adh5_load_complete(nickname, "", path)
189  endfor
190  endif
191 
192  setdatafolder saveDF
193 end
194 
206 function /s adh5_load_complete(ANickName, APathName, AFileName, [load_data, load_attr])
207  string ANickName
208  string APathName
209  string AFileName
210  variable load_data
211  variable load_attr
212 
213  if (ParamIsDefault(load_data))
214  load_data = 1
215  endif
216  if (ParamIsDefault(load_attr))
217  load_attr = 1
218  endif
219 
220  dfref saveDF = GetDataFolderDFR()
221  setdatafolder root:
222  newdatafolder /s/o $("root:" + ANickName)
223 
224  // open file
225  variable fileID
226  string instrumentpath = "/entry/instrument/"
227  string detectorpath = instrumentpath + "detector/"
228  string attributespath = instrumentpath + "NDAttributes/"
229  string datasetname
230  string datawavename
231 
232  // performance monitoring
233  variable timerRefNum
234  variable /g adh5_perf_secs
235  timerRefNum = startMSTimer
236 
237  // avoid compilation error if HDF5 XOP has not been loaded
238  #if Exists("HDF5OpenFile")
239  HDF5OpenFile /P=$APathName/R fileID as AFileName
240  if (v_flag == 0)
241  AFileName = s_path + s_filename
242  print "loading " + s_filename + "\r"
243 
244  if (load_data)
245  adh5_load_detector_slabs(fileID, detectorpath)
246  endif
247  if (load_attr)
248  newdatafolder /o/s attr
249  adh5_loadattr_all(fileID, attributespath)
250  setdatafolder ::
251  endif
252 
253  wave /z data
254  if (waveexists(data))
255  //adh5_redim(data) // not to be used with adh5_load_detector_slabs
256  adh5_scale(data)
257  endif
258 
259  HDF5CloseFile fileID
260  else
261  AFileName = ""
262  endif
263  #else
264  Abort "HDF5 XOP not loaded."
265  #endif
266 
267  if (timerRefNum >= 0)
268  adh5_perf_secs = stopMSTimer(timerRefNum) / 1e6
269  endif
270 
271  setdatafolder saveDF
272  return AFileName
273 end
274 
301 function /s adh5_load_reduced(ANickName, APathName, AFileName, reduction_func, reduction_param, [load_data, load_attr, progress])
302  string ANickName
303  string APathName
304  string AFileName
305 
306  funcref adh5_default_reduction reduction_func
307  string reduction_param
308 
309  variable load_data
310  variable load_attr
311  variable progress
312 
313  if (ParamIsDefault(load_data))
314  load_data = 1
315  endif
316  if (ParamIsDefault(load_attr))
317  load_attr = 1
318  endif
319  if (ParamIsDefault(progress))
320  progress = 1
321  endif
322 
323  dfref saveDF = GetDataFolderDFR()
324  setdatafolder root:
325  newdatafolder /s/o $("root:" + ANickName)
326 
327  // open file
328  variable fileID
329  string instrumentpath = "/entry/instrument/"
330  string detectorpath = instrumentpath + "detector/"
331  string attributespath = instrumentpath + "NDAttributes/"
332  string datasetname
333  string datawavename
334 
335  // performance monitoring
336  variable timerRefNum
337  variable /g adh5_perf_secs
338  timerRefNum = startMSTimer
339 
340  // avoid compilation error if HDF5 XOP has not been loaded
341  #if Exists("HDF5OpenFile")
342  HDF5OpenFile /P=$APathName/R fileID as AFileName
343  if (v_flag == 0)
344  AFileName = s_path + s_filename
345  print "loading " + s_filename + "\r"
346 
347  if (load_attr)
348  newdatafolder /o/s attr
349  adh5_loadattr_all(fileID, attributespath)
350  setdatafolder ::
351  endif
352  if (load_data)
353  adh5_load_reduced_detector(fileID, detectorpath, reduction_func, reduction_param, progress=progress)
354  endif
355 
356  HDF5CloseFile fileID
357  else
358  AFileName = ""
359  endif
360  #else
361  Abort "HDF5 XOP not loaded."
362  #endif
363 
364  if (timerRefNum >= 0)
365  adh5_perf_secs = stopMSTimer(timerRefNum) / 1e6
366  endif
367 
368  setdatafolder saveDF
369  return AFileName
370 end
371 
386 function /s adh5_load_preview(ANickName, APathName, AFileName, [load_data, load_attr])
387  string ANickName
388  string APathName
389  string AFileName
390  variable load_data
391  variable load_attr
392 
393  if (ParamIsDefault(load_data))
394  load_data = 1
395  endif
396  if (ParamIsDefault(load_attr))
397  load_attr = 1
398  endif
399 
400  dfref saveDF = GetDataFolderDFR()
401  setdatafolder root:
402  newdatafolder /o/s pearl_area
403  newdatafolder /o/s preview
404 
405  // open file
406  variable fileID
407  string instrumentpath = "/entry/instrument/"
408  string detectorpath = instrumentpath + "detector/"
409  string attributespath = instrumentpath + "NDAttributes/"
410  string datasetname
411  string datawavename
412 
413  // performance monitoring
414  variable timerRefNum
415  variable /g adh5_perf_secs
416  timerRefNum = startMSTimer
417 
418  // avoid compilation error if HDF5 XOP has not been loaded
419  #if Exists("HDF5OpenFile")
420  HDF5OpenFile /P=$APathName/R/Z fileID as AFileName
421  if (v_flag == 0)
422  AFileName = s_path + s_filename
423 
424  // detector data
425  datasetname = detectorpath + "data"
426  STRUCT HDF5DataInfo di // Defined in HDF5 Browser.ipf.
427  InitHDF5DataInfo(di)
428  variable err = HDF5DatasetInfo(fileID, datasetname, 0, di)
429  if (err != 0)
430  print "error accessing detector/data"
431  return ""
432  endif
433  if (di.ndims < 2)
434  print "error: rank of dataset < 2"
435  return ""
436  endif
437 
438  variable dim2start = 0, dim2count = 1, dim3start = 0, dim3count = 1
439  if (di.ndims >= 3)
440  dim2start = floor(di.dims[di.ndims - 3] / 2)
441  dim2count = 1
442  endif
443  if (di.ndims >= 4)
444  dim3start = floor(di.dims[di.ndims - 4] / 2)
445  dim3count = 1
446  endif
447 
448  if (load_data)
449  adh5_load_detector_image(fileID, detectorpath, dim2start, dim2count, dim3start, dim3count)
450  wave /z data
451  string destpath = GetDataFolder(1, saveDF) + ANickName
452  if (waveexists(data))
453  duplicate /o data, $destpath
454  wave /z data = $destpath
455  endif
456  endif
457 
458  if (load_attr)
459  setdatafolder saveDF
460  newdatafolder /o/s attr
461  killwaves /a/z
462  adh5_loadattr_all(fileID, attributespath)
463  setdatafolder ::
464  if (waveexists(data))
465  adh5_scale(data)
466  endif
467  endif
468 
469  HDF5CloseFile fileID
470  else
471  print "error opening file " + AFileName
472  AFileName = ""
473  endif
474  #else
475  Abort "HDF5 XOP not loaded."
476  #endif
477 
478  if (timerRefNum >= 0)
479  adh5_perf_secs = stopMSTimer(timerRefNum) / 1e6
480  endif
481 
482  setdatafolder saveDF
483  return AFileName
484 end
485 
496 function /s adh5_load_info(APathName, AFileName)
497  string APathName
498  string AFileName
499 
500  dfref saveDF = GetDataFolderDFR()
501 
502  // open file
503  variable fileID
504  string instrumentpath = "/entry/instrument/"
505  string detectorpath = instrumentpath + "detector/"
506  string attributespath = instrumentpath + "NDAttributes/"
507  string datasetname
508  string datawavename
509 
510  string s_info = ""
511  string s
512 
513  variable idim
514 
515  // avoid compilation error if HDF5 XOP has not been loaded
516  #if Exists("HDF5OpenFile")
517  HDF5OpenFile /P=$APathName/R/Z fileID as AFileName
518  if (v_flag == 0)
519  AFileName = s_path + s_filename
520 
521  // detector data
522  datasetname = detectorpath + "data"
523  STRUCT HDF5DataInfo di // Defined in HDF5 Browser.ipf.
524  InitHDF5DataInfo(di)
525  variable err = HDF5DatasetInfo(fileID, datasetname, 0, di)
526  if (err != 0)
527  print "error accessing detector/data"
528  return ""
529  endif
530 
531  for (idim = 0; idim < di.ndims; idim += 1)
532  sprintf s, "dim %u: %u points", idim, di.dims[idim]
533  if (strlen(s_info) > 0)
534  s_info = s_info + "\r" + s
535  else
536  s_info = s
537  endif
538  endfor
539 
540  dfref df = NewFreeDataFolder()
541  setdatafolder df
542  adh5_loadattr_all(fileID, attributespath)
543 
544  for (idim = 1; idim < 5; idim += 1)
545  sprintf s, "Scan%uActive", idim
546  wave /z w = $s
547  if (waveexists(w) && (numpnts(w) > 0) && (w[0] > 0))
548  sprintf s, "Scan%uPositioner1", idim
549  wave /t wt = $s
550  sprintf s, "scan %u: %s", idim, wt[0]
551  if (strlen(s_info) > 0)
552  s_info = s_info + "\r" + s
553  else
554  s_info = s
555  endif
556  endif
557  endfor
558 
559  HDF5CloseFile fileID
560  else
561  print "error opening file " + AFileName
562  AFileName = ""
563  endif
564  #else
565  Abort "HDF5 XOP not loaded."
566  #endif
567 
568  setdatafolder saveDF
569  return s_info
570 end
571 
580 function adh5_load_detector(fileID, detectorpath)
581  variable fileID
582  string detectorpath
583 
584  // avoid compilation error if HDF5 XOP has not been loaded
585  #if Exists("HDF5LoadData")
586  string datasetname
587  string datawavename
588 
589  // detector data
590  datasetname = detectorpath + "data"
591  STRUCT HDF5DataInfo di // Defined in HDF5 Browser.ipf.
592  InitHDF5DataInfo(di)
593  variable err = HDF5DatasetInfo(fileID, datasetname, 0, di)
594  if (err != 0)
595  print "error accessing detector/data"
596  return -1
597  endif
598  if (di.ndims < 2)
599  print "error: rank of dataset < 2"
600  return -2
601  endif
602 
603  HDF5LoadData /O /Q /Z fileID, datasetname
604  wave data
605 
606  #else
607  Abort "HDF5 XOP not loaded."
608  #endif
609 end
610 
625 function adh5_redim(data)
626  wave data
627 
628  duplicate /free data, tempdata
629  variable nd = wavedims(tempdata)
630  variable nx = dimsize(tempdata, nd - 1)
631  variable ny = dimsize(tempdata, nd - 2)
632  variable nz = dimsize(tempdata, nd - 3)
633  variable nt = dimsize(tempdata, nd - 4)
634 
635  switch (nd)
636  case 2:
637  if (nx <= 1)
638  redimension /n=(ny) data
639  setdimlabel 0, -1, AD_Dim1, data
640  data = tempdata[p][0]
641  elseif (ny <= 1)
642  redimension /n=(nx) data
643  setdimlabel 0, -1, AD_Dim0, data
644  data = tempdata[0][p]
645  else
646  redimension /n=(nx,ny) data
647  setdimlabel 0, -1, AD_Dim0, data
648  setdimlabel 1, -1, AD_Dim1, data
649  data = tempdata[q][p]
650  endif
651  break
652  case 3:
653  if (nx <= 1)
654  redimension /n=(ny,nz) data
655  setdimlabel 0, -1, AD_Dim1, data
656  setdimlabel 1, -1, AD_DimN, data
657  multithread data = tempdata[q][p][0]
658  elseif (ny <= 1)
659  redimension /n=(nx,nz) data
660  setdimlabel 0, -1, AD_Dim0, data
661  setdimlabel 1, -1, AD_DimN, data
662  multithread data = tempdata[q][0][p]
663  elseif (nz <= 1)
664  redimension /n=(nx,ny) data
665  setdimlabel 0, -1, AD_Dim0, data
666  setdimlabel 1, -1, AD_Dim1, data
667  multithread data = tempdata[0][q][p]
668  else
669  redimension /n=(nx,ny,nz) data
670  setdimlabel 0, -1, AD_Dim0, data
671  setdimlabel 1, -1, AD_Dim1, data
672  setdimlabel 2, -1, AD_DimN, data
673  multithread data = tempdata[r][q][p]
674  endif
675  break
676  case 4:
677  if (nz <= 1)
678  // singleton "frame number" dimension
679  redimension /n=(nx,ny,nt) data
680  setdimlabel 0, -1, AD_Dim0, data
681  setdimlabel 1, -1, AD_Dim1, data
682  setdimlabel 2, -1, AD_DimX, data
683  multithread data = tempdata[r][0][q][p]
684  else
685  redimension /n=(nx,ny,nz,nt) data
686  setdimlabel 0, -1, AD_Dim0, data
687  setdimlabel 1, -1, AD_Dim1, data
688  setdimlabel 2, -1, AD_DimN, data
689  setdimlabel 3, -1, AD_DimX, data
690  multithread data = tempdata[s][r][q][p]
691  endif
692  break
693  endswitch
694 end
695 
706 static function /DF GetAttrDataFolderDFR(data)
707  wave data
708 
709  dfref dataDF = GetWavesDataFolderDFR(data)
710  dfref attrDF = dataDF:attr
711  if (DataFolderRefStatus(attrDF) == 0)
712  attrDF = dataDF
713  endif
714 
715  return attrDF
716 end
717 
725 function adh5_scale(data,[source])
726  wave data
727  string source
728 
729  dfref saveDF = GetDataFolderDFR()
730  dfref dataDF = GetWavesDataFolderDFR(data)
731  dfref attrDF = GetAttrDataFolderDFR(data)
732 
733  if (ParamIsDefault(source))
734  // is the source a Scienta analyser?
735  wave /SDFR=attrDF /Z AcquisitionMode
736  wave /SDFR=attrDF /T /Z Manufacturer
737  source = "unknown"
738  if (waveexists(Manufacturer) && (numpnts(Manufacturer) >= 1))
739  strswitch(Manufacturer[0])
740  case "VG Scienta":
741  source = "scienta"
742  break
743  case "Prosilica":
744  source = "prosilica"
745  break
746  endswitch
747  elseif (waveexists(AcquisitionMode) && (numpnts(AcquisitionMode) >= 1))
748  if (stringmatch(note(AcquisitionMode), "*SCIENTA*"))
749  source = "scienta"
750  endif
751  endif
752  endif
753 
754  strswitch(source)
755  case "prosilica":
756  // pixel scale - nothing to do
757  break
758  case "scienta":
759  adh5_scale_scienta(data)
760  break
761  endswitch
762 
763  setdatafolder saveDF
764 end
765 
779 function adh5_load_detector_slabs(fileID, detectorpath, [progress])
780  variable fileID
781  string detectorpath
782  variable progress
783 
784  if (ParamIsDefault(progress))
785  progress = 1
786  endif
787  variable result = 0
788 
789  // avoid compilation error if HDF5 XOP has not been loaded
790  #if Exists("HDF5LoadData")
791  string datasetname
792  string datawavename
793 
794  // detector data
795  datasetname = detectorpath + "data"
796  STRUCT HDF5DataInfo di // Defined in HDF5 Browser.ipf.
797  InitHDF5DataInfo(di)
798  variable err = HDF5DatasetInfo(fileID, datasetname, 0, di)
799  if (err != 0)
800  print "error accessing detector/data"
801  return -1
802  endif
803  if (di.ndims < 2)
804  print "error: rank of dataset < 2"
805  return -2
806  endif
807 
808  // nx and nz are the image dimensions
809  variable idx, idy, idz, idt, izt
810  idx = di.ndims - 1
811  idy = di.ndims - 2
812  idz = -1
813  idt = -1
814 
815  variable nx, ny, nz, nt, nzt
816  nx = di.dims[idx]
817  ny = di.dims[idy]
818  nz = 1
819  nt = 1
820 
821  make /n=(nx,ny,nz,nt) /o data
822  string dim_labels = "AD_Dim0;AD_Dim1;AD_DimN;AD_DimX;AD_DimY"
823  string dim_label
824  dim_label = StringFromList(0, dim_labels, ";")
825  setdimlabel 0, -1, $dim_label, data
826  dim_labels = RemoveFromList(dim_label, dim_labels, ";")
827  dim_label = StringFromList(0, dim_labels, ";")
828  setdimlabel 1, -1, $dim_label, data
829  dim_labels = RemoveFromList(dim_label, dim_labels, ";")
830 
831  // find additional dimensions, ignore singletons
832  variable id
833  for (id = idy - 1; (id >= 0) && (nz == 1); id -= 1)
834  if (di.dims[id] > 1)
835  idz = id
836  nz = di.dims[id]
837  dim_label = StringFromList(0, dim_labels, ";")
838  setdimlabel 2, -1, $dim_label, data
839  endif
840  dim_labels = RemoveListItem(0, dim_labels, ";")
841  endfor
842  for (id = idz - 1; (id >= 0) && (nt == 1); id -= 1)
843  if (di.dims[id] > 1)
844  idt = id
845  nt = di.dims[id]
846  dim_label = StringFromList(0, dim_labels, ";")
847  setdimlabel 3, -1, $dim_label, data
848  endif
849  dim_labels = RemoveListItem(0, dim_labels, ";")
850  endfor
851  redimension /n=(nx,ny,nz,nt) data
852 
853  // default values if dimensions are not present in dataset
854  if (idz < 0)
855  idz = idx + 1
856  idt = idz + 1
857  elseif (idt < 0)
858  idt = idx + 1
859  endif
860 
861  nzt = nz * nt
862  izt = 0
863  if (progress)
864  display_progress_panel("HDF5 Import", "Loading data...", nzt)
865  endif
866 
867  // load data image by image
868  HDF5MakeHyperslabWave(GetDataFolder(1) + "slab", max(di.ndims, 4))
869  wave slab
870  slab[][%Start] = 0
871  slab[][%Stride] = 1
872  slab[][%Count] = 1
873  slab[][%Block] = 1
874  slab[idx][%Block] = nx
875  slab[idy][%Block] = ny
876 
877  variable iz, it
878  for (iz = 0; iz < nz; iz += 1)
879  for (it = 0; it < nt; it += 1)
880  slab[idz][%Start] = iz
881  slab[idt][%Start] = it
882  HDF5LoadData /O /Q /Z /SLAB=slab /N=slabdata fileID, datasetname
883  wave slabdata // 2D, 3D, or 4D with singletons
884  switch (WaveDims(slabdata))
885  case 2:
886  data[][][iz][it] = slabdata[q][p]
887  break
888  case 3:
889  data[][][iz][it] = slabdata[0][q][p]
890  break
891  case 4:
892  data[][][iz][it] = slabdata[0][0][q][p]
893  break
894  endswitch
895  // progress window
896  izt += 1
897  if (progress)
898  if (update_progress_panel(izt))
899  result = -4 // user abort
900  break
901  endif
902  endif
903  endfor
904  if (result < 0)
905  break
906  endif
907  endfor
908 
909  if (nz == 1)
910  redimension /n=(nx,ny) data
911  elseif (nt == 1)
912  redimension /n=(nx,ny,nz) data
913  endif
914 
915  if (progress)
917  endif
918  #else
919  Abort "HDF5 XOP not loaded."
920  #endif
921 
922  return result
923 end
924 
944 function adh5_load_detector_image(fileID, detectorpath, dim2start, dim2count, dim3start, dim3count)
945  variable fileID
946  string detectorpath
947  variable dim2start
948  variable dim2count
949  variable dim3start
950  variable dim3count
951 
952  // avoid compilation error if HDF5 XOP has not been loaded
953  #if Exists("HDF5LoadData")
954  string datasetname
955  string datawavename
956 
957  // detector data
958  datasetname = detectorpath + "data"
959  STRUCT HDF5DataInfo di // Defined in HDF5 Browser.ipf.
960  InitHDF5DataInfo(di)
961  variable err = HDF5DatasetInfo(fileID, datasetname, 0, di)
962  if (err != 0)
963  print "error accessing detector/data"
964  return -1
965  endif
966  if (di.ndims < 1)
967  print "error: rank of dataset < 1"
968  return -2
969  endif
970 
971  // nx and nz are the image dimensions
972  variable idx, idy, idz, idt
973  idx = di.ndims - 1
974  idy = di.ndims >= 2 ? di.ndims - 2 : 1
975  idz = di.ndims >= 3 ? di.ndims - 3 : 2
976  idt = di.ndims >= 4 ? di.ndims - 4 : 3
977 
978  variable nx, ny
979  nx = di.dims[idx]
980  ny = di.ndims >= 2 ? di.dims[idy] : 1
981 
982  variable dim2end = dim2start + dim2count - 1
983  variable dim3end = dim3start + dim3count - 1
984 
985  // the slab wave is at least 4-dimensional
986  // it will also load lower-dimensional datasets
987  HDF5MakeHyperslabWave(GetDataFolder(1) + "slab", max(di.ndims, 4))
988  wave slab
989  slab[][%Start] = 0
990  slab[][%Stride] = 1
991  slab[][%Count] = 1
992  slab[][%Block] = 1
993  slab[idx][%Block] = nx
994  slab[idy][%Block] = ny
995 
996  make /n=(nx,ny)/o/d data
997  data = 0
998  variable iz, it
999  variable navg = 0
1000  for (iz = dim2start; iz <= dim2end; iz += 1)
1001  for (it = dim3start; it <= dim3end; it += 1)
1002  slab[idz][%Start] = iz
1003  slab[idt][%Start] = it
1004  HDF5LoadData /O /Q /Z /SLAB=slab /N=slabdata fileID, datasetname
1005  wave slabdata // 2D, 3D, or 4D with singletons
1006  switch (WaveDims(slabdata))
1007  case 1:
1008  data += slabdata[p]
1009  navg += 1
1010  break
1011  case 2:
1012  data += slabdata[q][p]
1013  navg += 1
1014  break
1015  case 3:
1016  data += slabdata[0][q][p]
1017  navg += 1
1018  break
1019  case 4:
1020  data += slabdata[0][0][q][p]
1021  navg += 1
1022  break
1023  endswitch
1024  endfor
1025  endfor
1026  data /= navg
1027  setdimlabel 0, -1, AD_Dim0, data
1028  setdimlabel 1, -1, AD_Dim1, data
1029 
1030  #else
1031  Abort "HDF5 XOP not loaded."
1032  #endif
1033 end
1034 
1041  string all_funcs = FunctionList("*", ";", "KIND:6,NPARAMS:2,VALTYPE:8")
1042  string result = ""
1043 
1044  variable ii
1045  variable nn = ItemsInList(all_funcs, ";")
1046 
1047  string funcname
1048  string info
1049  variable nparams
1050  variable accept
1051 
1052  for (ii = 0; ii < nn; ii += 1)
1053  funcname = StringFromList(ii, all_funcs, ";")
1054  info = FunctionInfo(funcname)
1055  accept = (NumberByKey("RETURNTYPE", info, ":", ";") == 0x4000)
1056  accept = accept && (cmpstr(StringByKey("THREADSAFE", info, ":", ";"), "yes") == 0)
1057  accept = accept && (NumberByKey("N_PARAMS", info, ":", ";") == 2)
1058  accept = accept && (NumberByKey("N_OPT_PARAMS", info, ":", ";") == 0)
1059  if (accept)
1060  // one numeric wave and one pass-by-reference string
1061  accept = accept && (NumberByKey("PARAM_0_TYPE", info, ":", ";") == 0x4002)
1062  accept = accept && (NumberByKey("PARAM_1_TYPE", info, ":", ";") == 0x3000)
1063  endif
1064  if (accept)
1065  result = AddListItem(funcname, result, ";")
1066  endif
1067  endfor
1068 
1069  result = SortList(result, ";", 4)
1070  return result
1071 end
1072 
1110 threadsafe function /wave adh5_default_reduction(source, param)
1111  wave source
1112  string &param
1113 
1114  // demo code
1115  // integrate along the dimensions
1116  make /n=0 /free dest1, dest2
1117  adh5_setup_profile(source, dest1, 0)
1118  ad_profile_x_w(source, 0, -1, dest1)
1119  adh5_setup_profile(source, dest2, 1)
1120  ad_profile_y_w(source, 0, -1, dest2)
1121 
1122  make /n=2 /free /wave results
1123  results[0] = dest1
1124  results[1] = dest2
1125  return results
1126 end
1127 
1133 threadsafe function adh5_setup_profile(image, profile, dim)
1134  wave image // prototype
1135  wave profile // destination wave
1136  variable dim // which dimension to keep: 0 = X, 1 = Y
1137 
1138  redimension /n=(dimsize(image, dim)) profile
1139  setscale /p x dimoffset(image, dim), dimdelta(image, dim), waveunits(image, dim), profile
1140  setscale d 0, 0, waveunits(image, -1), profile
1141  setdimlabel 0, -1, $getdimlabel(image, dim, -1), profile
1142 end
1143 
1166 function /s adh5_test_reduction_func(source, reduction_func, reduction_param, result_prefix)
1167  wave source
1168  funcref adh5_default_reduction reduction_func
1169  string reduction_param
1170  string result_prefix
1171 
1172  wave /wave results = reduction_func(source, reduction_param)
1173  adh5_get_result_waves(results, result_prefix, 1)
1174 
1175  return reduction_param
1176 end
1177 
1192 threadsafe function adh5_get_result_waves(results, result_prefix, start_index)
1193  wave /wave results
1194  string result_prefix
1195  variable start_index
1196 
1197  variable nw = numpnts(results)
1198  variable iw
1199  string sw
1200  for (iw = 0; iw < nw; iw += 1)
1201  sw = result_prefix + num2str(iw + start_index)
1202  duplicate /o results[iw], $sw
1203  endfor
1204 end
1205 
1228 function adh5_load_reduced_detector(fileID, detectorpath, reduction_func, reduction_param, [progress, nthreads])
1229  variable fileID
1230  string detectorpath
1231  funcref adh5_default_reduction reduction_func
1232  string reduction_param
1233  variable progress
1234  variable nthreads
1235 
1236  if (ParamIsDefault(progress))
1237  progress = 1
1238  endif
1239  if (ParamIsDefault(nthreads))
1240  nthreads = -1
1241  endif
1242  variable result = 0
1243 
1244  // avoid compilation error if HDF5 XOP has not been loaded
1245  #if Exists("HDF5LoadData")
1246  string datasetname
1247  string datawavename
1248 
1249  // detector data
1250  datasetname = detectorpath + "data"
1251  STRUCT HDF5DataInfo di // Defined in HDF5 Browser.ipf.
1252  InitHDF5DataInfo(di)
1253  variable err = HDF5DatasetInfo(fileID, datasetname, 0, di)
1254  if (err != 0)
1255  print "error accessing detector/data"
1256  return -1
1257  endif
1258  if (di.ndims < 2)
1259  print "error: rank of dataset < 2"
1260  return -2
1261  endif
1262 
1263  // nx and nz are the image dimensions
1264  variable idx, idy, idz, idt
1265  idx = di.ndims - 1
1266  idy = di.ndims - 2
1267  idz = -1
1268  idt = -1
1269 
1270  variable nx, ny, nz, nt
1271  nx = di.dims[idx]
1272  ny = di.dims[idy]
1273  nz = 1
1274  nt = 1
1275 
1276  // find additional dimensions, ignore singletons
1277  variable id
1278  for (id = idy - 1; (id >= 0) && (nz == 1); id -= 1)
1279  if (di.dims[id] > 1)
1280  idz = id
1281  nz = di.dims[id]
1282  endif
1283  endfor
1284  for (id = idz - 1; (id >= 0) && (nt == 1); id -= 1)
1285  if (di.dims[id] > 1)
1286  idt = id
1287  nt = di.dims[id]
1288  endif
1289  endfor
1290  // default values if dimensions are not present in dataset
1291  if (idz < 0)
1292  idz = idx + 1
1293  idt = idz + 1
1294  elseif (idt < 0)
1295  idt = idx + 1
1296  endif
1297  variable nzt = nz * nt
1298  variable izt
1299 
1300  // load data image by image
1301  HDF5MakeHyperslabWave(GetDataFolder(1) + "slab", max(di.ndims, 4))
1302  wave slab
1303  slab[][%Start] = 0
1304  slab[][%Stride] = 1
1305  slab[][%Count] = 1
1306  slab[][%Block] = 1
1307  slab[idx][%Block] = nx
1308  slab[idy][%Block] = ny
1309 
1310  // set up multi threading
1311  if (nthreads < 0)
1312  nthreads = ThreadProcessorCount
1313  endif
1314  if (nthreads > 0)
1315  variable threadGroupID = ThreadGroupCreate(nthreads)
1316  variable ithread
1317  for (ithread = 0; ithread < nthreads; ithread += 1)
1318  ThreadStart threadGroupID, ithread, reduce_slab_worker(reduction_func)
1319  endfor
1320  else
1321  make /n=(nzt) /df /free processing_folders
1322  endif
1323 
1324  if (progress)
1325  display_progress_panel("HDF5 Import", "Loading data (step 1 of 2)...", nzt)
1326  endif
1327 
1328  make /n=(nx,ny)/d image_template
1329  setdimlabel 0, -1, AD_Dim0, image_template
1330  setdimlabel 1, -1, AD_Dim1, image_template
1331  adh5_scale(image_template)
1332 
1333  variable iz, it
1334  string dfname
1335  variable iw, nw
1336  string sw
1337  make /n=0 /free /wave result_waves
1338 
1339  izt = 0
1340  for (iz = 0; iz < nz; iz += 1)
1341  for (it = 0; it < nt; it += 1)
1342  // load hyperslab
1343  slab[idz][%Start] = iz
1344  slab[idt][%Start] = it
1345  dfname = "processing_" + num2str(izt)
1346  newdatafolder /s $dfname
1347  HDF5LoadData /O /Q /Z /SLAB=slab /N=slabdata fileID, datasetname
1348 
1349  // send to processing queue
1350  duplicate image_template, image
1351  variable /g r_index = iz
1352  variable /g s_index = it
1353  string /g func_param = reduction_param
1354 
1355  if (nthreads > 0)
1356  WaveClear image
1357  ThreadGroupPutDF threadGroupID, :
1358  else
1359  processing_folders[izt] = GetDataFolderDFR()
1360  wave slabdata
1361  wave /wave reduced_waves = reduce_slab_image(slabdata, image, reduction_func, func_param)
1362  variable /g func_result = numpnts(reduced_waves)
1363  adh5_get_result_waves(reduced_waves, "redw_", 0)
1364  WaveClear slabdata, image, reduced_waves
1365  setdatafolder ::
1366  endif
1367 
1368  izt += 1
1369  // progress window
1370  if (progress)
1371  if (update_progress_panel(izt))
1372  result = -4 // user abort
1373  break
1374  endif
1375  endif
1376  endfor
1377  endfor
1378 
1379  killwaves /z slab, image_template
1380  if (progress)
1381  update_progress_panel(0, message="Processing data (step 2 of 2)...")
1382  endif
1383 
1384  dfref dfr
1385  for (izt = 0; (izt < nzt) && (result == 0); izt += 1)
1386  if (nthreads > 0)
1387  do
1388  dfr = ThreadGroupGetDFR(threadGroupID, 1000)
1389  if (DatafolderRefStatus(dfr) != 0)
1390  break
1391  endif
1392  if (progress)
1393  if (update_progress_panel(izt))
1394  result = -4 // user abort
1395  break
1396  endif
1397  endif
1398  while (1)
1399  else
1400  dfr = processing_folders[izt]
1401  if (progress)
1402  if (update_progress_panel(izt))
1403  result = -4 // user abort
1404  break
1405  endif
1406  endif
1407  endif
1408 
1409  if (result != 0)
1410  break
1411  endif
1412 
1413  nvar rr = dfr:r_index
1414  nvar ss = dfr:s_index
1415  nvar func_result = dfr:func_result
1416 
1417  if (func_result < 1)
1418  result = -3 // dimension reduction error
1419  break
1420  endif
1421 
1422  if (numpnts(result_waves) == 0)
1423  redimension /n=(func_result) result_waves
1424  for (iw = 0; iw < func_result; iw += 1)
1425  sw = "redw_" + num2str(iw)
1426  wave profile = dfr:$sw
1427  sw = "ReducedData" + num2str(iw+1)
1428  make /n=(dimsize(profile, 0), nz, nt) /d /o $sw
1429  wave data = $sw
1430  setdimlabel 0, -1, $getdimlabel(profile, 0, -1), data
1431  setscale /p x dimoffset(profile, 0), dimdelta(profile, 0), waveunits(profile, 0), data
1432  setscale d 0, 0, waveunits(profile, -1), data
1433  result_waves[iw] = data
1434  endfor
1435  endif
1436  for (iw = 0; iw < func_result; iw += 1)
1437  sw = "redw_" + num2str(iw)
1438  wave profile = dfr:$sw
1439  wave data = result_waves[iw]
1440  data[][rr][ss] = profile[p]
1441  endfor
1442  endfor
1443 
1444  if (nthreads > 0)
1445  variable tstatus = ThreadGroupRelease(threadGroupID)
1446  if (tstatus == -2)
1447  result = -5 // thread did not terminate properly
1448  endif
1449  else
1450  for (izt = 0; izt < nzt; izt += 1)
1451  KillDataFolder /Z processing_folders[izt]
1452  endfor
1453  endif
1454 
1455  if (result == 0)
1456  nw = numpnts(result_waves)
1457  for (iw = 0; iw < nw; iw += 1)
1458  wave data = result_waves[iw]
1459  if (nz == 1)
1460  redimension /n=(dimsize(data, 0)) data
1461  elseif (nt == 1)
1462  redimension /n=(dimsize(data, 0),nz) data
1463  setdimlabel 1, -1, AD_DimN, data
1464  else
1465  setdimlabel 1, -1, AD_DimN, data
1466  setdimlabel 2, -1, AD_DimX, data
1467  endif
1468  endfor
1469  endif
1470  if (progress)
1472  endif
1473 
1474  #else
1475  Abort "HDF5 XOP not loaded."
1476  #endif
1477  return result
1478 end
1479 
1480 threadsafe static function reduce_slab_worker(reduction_func)
1481  funcref adh5_default_reduction reduction_func
1482  do
1483  // wait for job from main thread
1484  do
1485  dfref dfr = ThreadGroupGetDFR(0, 1000)
1486  if (DataFolderRefStatus(dfr) == 0)
1487  if (GetRTError(2))
1488  return 0 // no more jobs
1489  endif
1490  else
1491  break
1492  endif
1493  while (1)
1494 
1495  // get input data
1496  wave slabdata = dfr:slabdata
1497  wave image = dfr:image
1498  svar func_param = dfr:func_param
1499  nvar rr = dfr:r_index
1500  nvar ss = dfr:s_index
1501 
1502  // do the work
1503  newdatafolder /s outDF
1504  variable /g r_index = rr
1505  variable /g s_index = ss
1506  wave /wave reduced_waves = reduce_slab_image(slabdata, image, reduction_func, func_param)
1507  variable /g func_result = numpnts(reduced_waves)
1508 
1509  // send output to queue and clean up
1510  adh5_get_result_waves(reduced_waves, "redw_", 0)
1511  WaveClear slabdata, image, reduced_waves
1512  ThreadGroupPutDF 0, :
1513  KillDataFolder dfr
1514  while (1)
1515 
1516  return 0
1517 end
1518 
1519 threadsafe static function /wave reduce_slab_image(slabdata, image, reduction_func, reduction_param)
1520  wave slabdata
1521  wave image
1522  funcref adh5_default_reduction reduction_func
1523  string reduction_param
1524 
1525  switch (WaveDims(slabdata))
1526  case 2:
1527  image = slabdata[q][p]
1528  break
1529  case 3:
1530  image = slabdata[0][q][p]
1531  break
1532  case 4:
1533  image = slabdata[0][0][q][p]
1534  break
1535  endswitch
1536 
1537  return reduction_func(image, reduction_param)
1538 end
1539 
1552 function adh5_loadattr_all(fileID, attributespath)
1553  variable fileID
1554  string attributespath
1555 
1556  string datasetname
1557  string datawavename
1558 
1559  // avoid compilation error if HDF5 XOP has not been loaded
1560  #if Exists("HDF5LoadData")
1561 
1562  // datasets in NDAttributes group
1563  HDF5ListGroup /F /TYPE=2 fileID, attributespath
1564  string h5datasets = S_HDF5ListGroup
1565  HDF5ListAttributes /TYPE=1 /Z fileID, attributespath
1566  string h5attributes = S_HDF5ListAttributes
1567 
1568  variable nds = ItemsInList(h5datasets, ";")
1569  variable na = ItemsInList(h5attributes, ";")
1570  variable ids
1571  variable idest = 0
1572  variable n_attr
1573  string s_attr
1574  string s_source
1575 
1576  make /n=(nds+na) /t /o IN, ID, IV, IU
1577 
1578  for (ids = 0; ids < nds; ids += 1)
1579  datasetname = StringFromList(ids, h5datasets, ";")
1580  HDF5LoadData /O/Q fileID, datasetname
1581  if (v_flag == 0)
1582  datawavename = StringFromList(0, s_wavenames)
1583  else
1584  datawavename = ""
1585  endif
1586  HDF5LoadData /A="source"/O/Q/TYPE=2 fileID, datasetname
1587  if (v_flag == 0)
1588  wave /t source
1589  s_source = source[0]
1590  else
1591  s_source = ""
1592  endif
1593  read_attribute_info(datawavename, s_source, idest)
1594  endfor
1595 
1596  // attributes of NDAttributes group
1597  if (v_flag == 0)
1598  nds = ItemsInList(h5attributes, ";")
1599  else
1600  nds = 0
1601  endif
1602  for (ids = 0; ids < nds; ids += 1)
1603  datasetname = StringFromList(ids, h5attributes, ";")
1604  HDF5LoadData /A=datasetname/O/Q/TYPE=1 fileID, attributespath
1605  if (v_flag == 0)
1606  datawavename = StringFromList(0, s_wavenames)
1607  read_attribute_info(datawavename, "", idest) // we don't get the source of these attributes
1608  endif
1609  endfor
1610 
1611  redimension /n=(idest) IN, ID, IV, IU
1612  sort {IN, ID}, IN, ID, IV, IU
1613 
1614  killwaves /z source
1615  #else
1616  Abort "HDF5 XOP not loaded."
1617  #endif
1618 
1619 end
1620 
1634 static function read_attribute_info(datawavename, source, idest)
1635  string datawavename // name of the attribute wave in the current folder.
1636  // can be text or numeric.
1637  string source
1638  // source identifier (EPICS name) of the attribute.
1639  variable &idest
1640  // destination index in IN, ID, IV, IU where the results are written.
1641  // the variable is incremented if data was written, otherwise it is left unchanged.
1642  // make sure IN, ID, IV, IU have at least idest + 1 elements.
1643 
1644  wave /t IN
1645  wave /t ID
1646  wave /t IV
1647  wave /t IU
1648 
1649  variable n_attr
1650  string s_attr
1651 
1652  if (exists(datawavename) == 1)
1653  if (strlen(source) > 0)
1654  Note $datawavename, "PV=" + source
1655  endif
1656  switch(WaveType($datawavename, 1))
1657  case 1: // numeric
1658  wave w_attr = $datawavename
1659  n_attr = numpnts(w_attr)
1660  sprintf s_attr, "%.12g", w_attr[0]
1661  break
1662  case 2: // text
1663  wave /t wt_attr = $datawavename
1664  n_attr = numpnts(wt_attr)
1665  s_attr = wt_attr[0]
1666  break
1667  default: // unknown
1668  n_attr = 0
1669  endswitch
1670  if (n_attr == 1)
1671  IN[idest] = source
1672  ID[idest] = datawavename
1673  IV[idest] = s_attr
1674  IU[idest] = "" // we don't get the units
1675  idest += 1
1676  endif
1677  endif
1678 end
1679 
1687 function adh5_scale_scienta(data)
1688  wave data
1689 
1690  dfref saveDF = GetDataFolderDFR()
1691 
1692  dfref dataDF = GetWavesDataFolderDFR(data)
1693  dfref attrDF = GetAttrDataFolderDFR(data)
1694 
1695  wave /SDFR=attrDF LensMode
1696  wave /SDFR=attrDF /Z ChannelBegin, ChannelEnd
1697  wave /SDFR=attrDF /Z SliceBegin, SliceEnd
1698 
1699  variable EDim, ADim
1700  variable ELow, EHigh, ALow, AHigh
1701  string EUnit, AUnit
1702 
1703  // which dimension is angle and which one is energy?
1704  strswitch(GetDimLabel(data, 0, -1))
1705  case "AD_Dim0":
1706  EDim = 0
1707  break
1708  case "AD_Dim1":
1709  EDim = 1
1710  break
1711  default:
1712  EDim = -1
1713  endswitch
1714  strswitch(GetDimLabel(data, 1, -1))
1715  case "AD_Dim0":
1716  ADim = 0
1717  break
1718  case "AD_Dim1":
1719  ADim = 1
1720  break
1721  default:
1722  ADim = -1
1723  endswitch
1724 
1725  // defaults (point scaling)
1726  if (EDim >= 0)
1727  ELow = dimoffset(data, EDim)
1728  EHigh = dimoffset(data, EDim) + dimdelta(data, EDim) * (dimsize(data, EDim) - 1)
1729  EUnit = "eV"
1730  endif
1731  if (ADim >= 0)
1732  ALow = dimoffset(data, ADim)
1733  AHigh = dimoffset(data, ADim) + dimdelta(data, ADim) * (dimsize(data, ADim) - 1)
1734  AUnit = "arb."
1735  endif
1736 
1737  // lens mode can give more detail
1738  if (waveexists(LensMode) && (numpnts(LensMode) >= 1))
1739  switch(LensMode[0])
1740  case 1: // Angular45
1741  ALow = -45/2
1742  AHigh = +45/2
1743  AUnit = "°"
1744  break
1745  case 2: // Angular60
1746  ALow = -60/2
1747  AHigh = +60/2
1748  AUnit = "°"
1749  break
1750  endswitch
1751  endif
1752 
1753  // best option if scales are explicit in separate waves
1754  if (waveexists(ChannelBegin) && waveexists(ChannelEnd) && (numpnts(ChannelBegin) >= 1) && (numpnts(ChannelEnd) >= 1))
1755  ELow = ChannelBegin[0]
1756  EHigh = ChannelEnd[0]
1757  endif
1758  if (waveexists(SliceBegin) && waveexists(SliceEnd) && (numpnts(SliceBegin) >= 1) && (numpnts(SliceEnd) >= 1))
1759  ALow = SliceBegin[0]
1760  AHigh = SliceEnd[0]
1761  endif
1762 
1763  // apply new scales
1764  switch(EDim)
1765  case 0:
1766  setscale /i x ELow, EHigh, EUnit, data
1767  break
1768  case 1:
1769  setscale /i y ELow, EHigh, EUnit, data
1770  break
1771  endswitch
1772  switch(ADim)
1773  case 0:
1774  setscale /i x ALow, AHigh, AUnit, data
1775  break
1776  case 1:
1777  setscale /i y ALow, AHigh, AUnit, data
1778  break
1779  endswitch
1780 
1781  setscale d 0, 0, "arb.", data
1782 
1783  setdatafolder saveDF
1784 end
1785 
1792 function adh5_scale_scan(data)
1793  wave data
1794 
1795  dfref saveDF = GetDataFolderDFR()
1796 
1797  dfref dataDF = GetWavesDataFolderDFR(data)
1798  wave /SDFR=dataDF AcquisitionMode, DetectorMode, EnergyMode
1799 
1800  wave /SDFR=dataDF /z Scan1Active, Scan2Active
1801  wave /SDFR=dataDF /t /z Scan1Positioner1, Scan1Readback1
1802  wave /SDFR=dataDF /t /z Scan1Positioner2, Scan1Readback2
1803  wave /SDFR=dataDF /t /z Scan2Positioner1, Scan2Readback1
1804  wave /SDFR=dataDF /t /z Scan2Positioner2, Scan2Readback2
1805 
1806  // TODO : search the data folder for positioner waves,
1807  // i.e. waves with the PV name corresponding to Scan1Positioner1 in their wave note.
1808  wave /z zscale
1809 
1810  strswitch(GetDimLabel(data, 0, -1))
1811  case "AD_DimN":
1812  setscale /i x zscale[0], zscale[numpnts(zscale)-1], "", data
1813  break
1814  endswitch
1815  strswitch(GetDimLabel(data, 1, -1))
1816  case "AD_DimN":
1817  setscale /i y zscale[0], zscale[numpnts(zscale)-1], "", data
1818  break
1819  endswitch
1820  strswitch(GetDimLabel(data, 2, -1))
1821  case "AD_DimN":
1822  setscale /i z zscale[0], zscale[numpnts(zscale)-1], "", data
1823  break
1824  endswitch
1825 
1826  setdatafolder saveDF
1827 end
string adh5_load_preview(string ANickName, string APathName, string AFileName, variable load_data=defaultValue, variable load_attr=defaultValue)
load a single image from a HDF5 file created by the Area Detector software.
+Go to the documentation of this file.
1 #pragma rtGlobals=3 // Use modern global access method and strict wave access.
2 #pragma IgorVersion = 6.2
3 #pragma ModuleName = PearlAreaImport
4 #include <HDF5 Browser>
5 #include "pearl-compat"
6 #include "pearl-gui-tools"
7 
8 // copyright (c) 2013-18 Paul Scherrer Institut
9 //
10 // Licensed under the Apache License, Version 2.0 (the "License");
11 // you may not use this file except in compliance with the License.
12 // You may obtain a copy of the License at
13 // http:///www.apache.org/licenses/LICENSE-2.0
14 
34 
39 
42 static function BeforeFileOpenHook(refNum,fileName,path,type,creator,kind)
43  variable refNum, kind
44  string fileName, path, type, creator
45 
46  variable handledOpen = 0
47 
48  //PathInfo $path
49  //string FilePath = s_path + filename
50  string NickName = PearlCleanupName(ParseFilePath(3, FileName, ":", 0, 0))
51  string FileExt = LowerStr(ParseFilePath(4, FileName, ":", 0, 0))
52  string result = ""
53 
54  // override nickname with custom setting
55  svar /z cnn = gsCustomNickName
56  if (svar_exists(cnn))
57  if (exists("gvNickNameIndex") != 2)
58  variable/g gvNickNameIndex = 1
59  endif
60  nvar nni = gvNickNameIndex
61  NickName = cnn + num2str(nni)
62  nni += 1
63  endif
64 
65  if (stringmatch(FileExt, "h5") == 1)
66  result = adh5_load_complete(NickName, path, FileName)
67  endif
68 
69  string/g s_latest_datafile = result
70  string/g s_latest_nickname = nickname
71 
72  handledOpen = strlen(result) > 0
73  if (handledOpen)
74  close refnum
75  endif
76 
77  return handledOpen // 1 tells Igor not to open the file
78 End
79 
106 function /s ad_suggest_foldername(filename, [ignoredate,sourcename,unique])
107  string filename
108  variable ignoredate
109  string sourcename
110  variable unique
111 
112  if (ParamIsDefault(ignoredate))
113  ignoredate = 0
114  endif
115  if (ParamIsDefault(unique))
116  unique = 0
117  endif
118 
119  string basename = ParseFilePath(3, filename, ":", 0, 0)
120  string extension = ParseFilePath(4, filename, ":", 0, 0)
121  string nickname
122 
123  string autosource
124  if (strsearch(basename, "scienta", 0, 2) >= 0)
125  autosource = "sci"
126  elseif (strsearch(basename, "pshell", 0, 2) >= 0)
127  autosource = "psh"
128  elseif (strsearch(basename, "OP-SL", 0, 2) >= 0)
129  autosource = "sl"
130  elseif (strsearch(basename, "ES-PS", 0, 2) >= 0)
131  autosource = "es"
132  else
133  autosource = "xy"
134  endif
135  if (ParamIsDefault(sourcename))
136  sourcename = autosource
137  endif
138 
139  variable nparts = ItemsInList(basename, "-")
140  if (nparts >= 3)
141  string datepart = StringFromList(1, basename, "-")
142  variable l_datepart = strlen(datepart)
143  if (l_datepart == 8)
144  datepart = datepart[l_datepart-6, l_datepart-1]
145  endif
146  string indexpart = StringFromList(2, basename, "-")
147  if (ignoredate)
148  sprintf nickname, "%s_%s", sourcename, indexpart
149  else
150  sprintf nickname, "%s_%s_%s", sourcename, datepart, indexpart
151  endif
152  else
153  nickname = PearlCleanupName(basename)
154  endif
155 
156  if (unique && CheckName(nickname, 11))
157  nickname = UniqueName(nickname + "_", 11, 0)
158  endif
159 
160  return nickname
161 end
162 
167 function ad_load_dialog(APathName)
168  string APathName
169 
170  variable refNum
171  string message = "Select data files"
172  string filepaths
173  string filefilters = "Area Detector HDF5 Files (*.h5):.h5;"
174  filefilters += "All Files:.*;"
175 
176  PathInfo /S $APathName
177  Open /D /R /F=filefilters /M=message /MULT=1 refNum
178  filepaths = S_fileName
179 
180  dfref saveDF = GetDataFolderDFR()
181  setdatafolder root:
182 
183  if (strlen(filepaths) > 0)
184  variable nfiles = ItemsInList(filepaths, "\r")
185  variable ifile
186  for(ifile = 0; ifile < nfiles; ifile += 1)
187  String path = StringFromList(ifile, filepaths, "\r")
188  string nickname = ad_suggest_foldername(path)
189  adh5_load_complete(nickname, "", path)
190  endfor
191  endif
192 
193  setdatafolder saveDF
194 end
195 
207 function /s adh5_load_complete(ANickName, APathName, AFileName, [load_data, load_attr])
208  string ANickName
209  string APathName
210  string AFileName
211  variable load_data
212  variable load_attr
213 
214  if (ParamIsDefault(load_data))
215  load_data = 1
216  endif
217  if (ParamIsDefault(load_attr))
218  load_attr = 1
219  endif
220 
221  dfref saveDF = GetDataFolderDFR()
222  setdatafolder root:
223  newdatafolder /s/o $("root:" + ANickName)
224 
225  // open file
226  variable fileID
227  string instrumentpath = "/entry/instrument/"
228  string detectorpath = instrumentpath + "detector/"
229  string attributespath = instrumentpath + "NDAttributes/"
230  string datasetname
231  string datawavename
232 
233  // performance monitoring
234  variable timerRefNum
235  variable /g adh5_perf_secs
236  timerRefNum = startMSTimer
237 
238  // avoid compilation error if HDF5 XOP has not been loaded
239  #if Exists("HDF5OpenFile")
240  HDF5OpenFile /P=$APathName/R fileID as AFileName
241  if (v_flag == 0)
242  AFileName = s_path + s_filename
243  print "loading " + s_filename + "\r"
244 
245  if (load_data)
246  adh5_load_detector_slabs(fileID, detectorpath)
247  endif
248  if (load_attr)
249  newdatafolder /o/s attr
250  adh5_loadattr_all(fileID, attributespath)
251  setdatafolder ::
252  endif
253 
254  wave /z data
255  if (waveexists(data))
256  //adh5_redim(data) // not to be used with adh5_load_detector_slabs
257  adh5_scale(data)
258  endif
259 
260  HDF5CloseFile fileID
261  else
262  AFileName = ""
263  endif
264  #else
265  Abort "HDF5 XOP not loaded."
266  #endif
267 
268  if (timerRefNum >= 0)
269  adh5_perf_secs = stopMSTimer(timerRefNum) / 1e6
270  endif
271 
272  setdatafolder saveDF
273  return AFileName
274 end
275 
302 function /s adh5_load_reduced(ANickName, APathName, AFileName, reduction_func, reduction_param, [load_data, load_attr, progress])
303  string ANickName
304  string APathName
305  string AFileName
306 
307  funcref adh5_default_reduction reduction_func
308  string reduction_param
309 
310  variable load_data
311  variable load_attr
312  variable progress
313 
314  if (ParamIsDefault(load_data))
315  load_data = 1
316  endif
317  if (ParamIsDefault(load_attr))
318  load_attr = 1
319  endif
320  if (ParamIsDefault(progress))
321  progress = 1
322  endif
323 
324  dfref saveDF = GetDataFolderDFR()
325  setdatafolder root:
326  newdatafolder /s/o $("root:" + ANickName)
327 
328  // open file
329  variable fileID
330  string instrumentpath = "/entry/instrument/"
331  string detectorpath = instrumentpath + "detector/"
332  string attributespath = instrumentpath + "NDAttributes/"
333  string datasetname
334  string datawavename
335 
336  // performance monitoring
337  variable timerRefNum
338  variable /g adh5_perf_secs
339  timerRefNum = startMSTimer
340 
341  // avoid compilation error if HDF5 XOP has not been loaded
342  #if Exists("HDF5OpenFile")
343  HDF5OpenFile /P=$APathName/R fileID as AFileName
344  if (v_flag == 0)
345  AFileName = s_path + s_filename
346  print "loading " + s_filename + "\r"
347 
348  if (load_attr)
349  newdatafolder /o/s attr
350  adh5_loadattr_all(fileID, attributespath)
351  setdatafolder ::
352  endif
353  if (load_data)
354  adh5_load_reduced_detector(fileID, detectorpath, reduction_func, reduction_param, progress=progress)
355  endif
356 
357  HDF5CloseFile fileID
358  else
359  AFileName = ""
360  endif
361  #else
362  Abort "HDF5 XOP not loaded."
363  #endif
364 
365  if (timerRefNum >= 0)
366  adh5_perf_secs = stopMSTimer(timerRefNum) / 1e6
367  endif
368 
369  setdatafolder saveDF
370  return AFileName
371 end
372 
387 function /s adh5_load_preview(ANickName, APathName, AFileName, [load_data, load_attr])
388  string ANickName
389  string APathName
390  string AFileName
391  variable load_data
392  variable load_attr
393 
394  if (ParamIsDefault(load_data))
395  load_data = 1
396  endif
397  if (ParamIsDefault(load_attr))
398  load_attr = 1
399  endif
400 
401  dfref saveDF = GetDataFolderDFR()
402  setdatafolder root:
403  newdatafolder /o/s pearl_area
404  newdatafolder /o/s preview
405 
406  // open file
407  variable fileID
408  string instrumentpath = "/entry/instrument/"
409  string detectorpath = instrumentpath + "detector/"
410  string attributespath = instrumentpath + "NDAttributes/"
411  string datasetname
412  string datawavename
413 
414  // performance monitoring
415  variable timerRefNum
416  variable /g adh5_perf_secs
417  timerRefNum = startMSTimer
418 
419  // avoid compilation error if HDF5 XOP has not been loaded
420  #if Exists("HDF5OpenFile")
421  HDF5OpenFile /P=$APathName/R/Z fileID as AFileName
422  if (v_flag == 0)
423  AFileName = s_path + s_filename
424 
425  // detector data
426  datasetname = detectorpath + "data"
427  STRUCT HDF5DataInfo di // Defined in HDF5 Browser.ipf.
428  InitHDF5DataInfo(di)
429  variable err = HDF5DatasetInfo(fileID, datasetname, 0, di)
430  if (err != 0)
431  print "error accessing detector/data"
432  return ""
433  endif
434  if (di.ndims < 2)
435  print "error: rank of dataset < 2"
436  return ""
437  endif
438 
439  variable dim2start = 0, dim2count = 1, dim3start = 0, dim3count = 1
440  if (di.ndims >= 3)
441  dim2start = floor(di.dims[di.ndims - 3] / 2)
442  dim2count = 1
443  endif
444  if (di.ndims >= 4)
445  dim3start = floor(di.dims[di.ndims - 4] / 2)
446  dim3count = 1
447  endif
448 
449  if (load_data)
450  adh5_load_detector_image(fileID, detectorpath, dim2start, dim2count, dim3start, dim3count)
451  wave /z data
452  string destpath = GetDataFolder(1, saveDF) + ANickName
453  if (waveexists(data))
454  duplicate /o data, $destpath
455  wave /z data = $destpath
456  endif
457  endif
458 
459  if (load_attr)
460  setdatafolder saveDF
461  newdatafolder /o/s attr
462  killwaves /a/z
463  adh5_loadattr_all(fileID, attributespath)
464  setdatafolder ::
465  if (waveexists(data))
466  adh5_scale(data)
467  endif
468  endif
469 
470  HDF5CloseFile fileID
471  else
472  print "error opening file " + AFileName
473  AFileName = ""
474  endif
475  #else
476  Abort "HDF5 XOP not loaded."
477  #endif
478 
479  if (timerRefNum >= 0)
480  adh5_perf_secs = stopMSTimer(timerRefNum) / 1e6
481  endif
482 
483  setdatafolder saveDF
484  return AFileName
485 end
486 
497 function /s adh5_load_info(APathName, AFileName)
498  string APathName
499  string AFileName
500 
501  dfref saveDF = GetDataFolderDFR()
502 
503  // open file
504  variable fileID
505  string instrumentpath = "/entry/instrument/"
506  string detectorpath = instrumentpath + "detector/"
507  string attributespath = instrumentpath + "NDAttributes/"
508  string datasetname
509  string datawavename
510 
511  string s_info = ""
512  string s
513 
514  variable idim
515 
516  // avoid compilation error if HDF5 XOP has not been loaded
517  #if Exists("HDF5OpenFile")
518  HDF5OpenFile /P=$APathName/R/Z fileID as AFileName
519  if (v_flag == 0)
520  AFileName = s_path + s_filename
521 
522  // detector data
523  datasetname = detectorpath + "data"
524  STRUCT HDF5DataInfo di // Defined in HDF5 Browser.ipf.
525  InitHDF5DataInfo(di)
526  variable err = HDF5DatasetInfo(fileID, datasetname, 0, di)
527  if (err != 0)
528  print "error accessing detector/data"
529  return ""
530  endif
531 
532  for (idim = 0; idim < di.ndims; idim += 1)
533  sprintf s, "dim %u: %u points", idim, di.dims[idim]
534  if (strlen(s_info) > 0)
535  s_info = s_info + "\r" + s
536  else
537  s_info = s
538  endif
539  endfor
540 
541  dfref df = NewFreeDataFolder()
542  setdatafolder df
543  adh5_loadattr_all(fileID, attributespath)
544 
545  for (idim = 1; idim < 5; idim += 1)
546  sprintf s, "Scan%uActive", idim
547  wave /z w = $s
548  if (waveexists(w) && (numpnts(w) > 0) && (w[0] > 0))
549  sprintf s, "Scan%uPositioner1", idim
550  wave /t wt = $s
551  sprintf s, "scan %u: %s", idim, wt[0]
552  if (strlen(s_info) > 0)
553  s_info = s_info + "\r" + s
554  else
555  s_info = s
556  endif
557  endif
558  endfor
559 
560  HDF5CloseFile fileID
561  else
562  print "error opening file " + AFileName
563  AFileName = ""
564  endif
565  #else
566  Abort "HDF5 XOP not loaded."
567  #endif
568 
569  setdatafolder saveDF
570  return s_info
571 end
572 
581 function adh5_load_detector(fileID, detectorpath)
582  variable fileID
583  string detectorpath
584 
585  // avoid compilation error if HDF5 XOP has not been loaded
586  #if Exists("HDF5LoadData")
587  string datasetname
588  string datawavename
589 
590  // detector data
591  datasetname = detectorpath + "data"
592  STRUCT HDF5DataInfo di // Defined in HDF5 Browser.ipf.
593  InitHDF5DataInfo(di)
594  variable err = HDF5DatasetInfo(fileID, datasetname, 0, di)
595  if (err != 0)
596  print "error accessing detector/data"
597  return -1
598  endif
599  if (di.ndims < 2)
600  print "error: rank of dataset < 2"
601  return -2
602  endif
603 
604  HDF5LoadData /O /Q /Z fileID, datasetname
605  wave data
606 
607  #else
608  Abort "HDF5 XOP not loaded."
609  #endif
610 end
611 
626 function adh5_redim(data)
627  wave data
628 
629  duplicate /free data, tempdata
630  variable nd = wavedims(tempdata)
631  variable nx = dimsize(tempdata, nd - 1)
632  variable ny = dimsize(tempdata, nd - 2)
633  variable nz = dimsize(tempdata, nd - 3)
634  variable nt = dimsize(tempdata, nd - 4)
635 
636  switch (nd)
637  case 2:
638  if (nx <= 1)
639  redimension /n=(ny) data
640  setdimlabel 0, -1, AD_Dim1, data
641  data = tempdata[p][0]
642  elseif (ny <= 1)
643  redimension /n=(nx) data
644  setdimlabel 0, -1, AD_Dim0, data
645  data = tempdata[0][p]
646  else
647  redimension /n=(nx,ny) data
648  setdimlabel 0, -1, AD_Dim0, data
649  setdimlabel 1, -1, AD_Dim1, data
650  data = tempdata[q][p]
651  endif
652  break
653  case 3:
654  if (nx <= 1)
655  redimension /n=(ny,nz) data
656  setdimlabel 0, -1, AD_Dim1, data
657  setdimlabel 1, -1, AD_DimN, data
658  multithread data = tempdata[q][p][0]
659  elseif (ny <= 1)
660  redimension /n=(nx,nz) data
661  setdimlabel 0, -1, AD_Dim0, data
662  setdimlabel 1, -1, AD_DimN, data
663  multithread data = tempdata[q][0][p]
664  elseif (nz <= 1)
665  redimension /n=(nx,ny) data
666  setdimlabel 0, -1, AD_Dim0, data
667  setdimlabel 1, -1, AD_Dim1, data
668  multithread data = tempdata[0][q][p]
669  else
670  redimension /n=(nx,ny,nz) data
671  setdimlabel 0, -1, AD_Dim0, data
672  setdimlabel 1, -1, AD_Dim1, data
673  setdimlabel 2, -1, AD_DimN, data
674  multithread data = tempdata[r][q][p]
675  endif
676  break
677  case 4:
678  if (nz <= 1)
679  // singleton "frame number" dimension
680  redimension /n=(nx,ny,nt) data
681  setdimlabel 0, -1, AD_Dim0, data
682  setdimlabel 1, -1, AD_Dim1, data
683  setdimlabel 2, -1, AD_DimX, data
684  multithread data = tempdata[r][0][q][p]
685  else
686  redimension /n=(nx,ny,nz,nt) data
687  setdimlabel 0, -1, AD_Dim0, data
688  setdimlabel 1, -1, AD_Dim1, data
689  setdimlabel 2, -1, AD_DimN, data
690  setdimlabel 3, -1, AD_DimX, data
691  multithread data = tempdata[s][r][q][p]
692  endif
693  break
694  endswitch
695 end
696 
707 static function /DF GetAttrDataFolderDFR(data)
708  wave data
709 
710  dfref dataDF = GetWavesDataFolderDFR(data)
711  dfref attrDF = dataDF:attr
712  if (DataFolderRefStatus(attrDF) == 0)
713  attrDF = dataDF
714  endif
715 
716  return attrDF
717 end
718 
726 function adh5_scale(data,[source])
727  wave data
728  string source
729 
730  dfref saveDF = GetDataFolderDFR()
731  dfref dataDF = GetWavesDataFolderDFR(data)
732  dfref attrDF = GetAttrDataFolderDFR(data)
733 
734  if (ParamIsDefault(source))
735  // is the source a Scienta analyser?
736  wave /SDFR=attrDF /Z AcquisitionMode
737  wave /SDFR=attrDF /T /Z Manufacturer
738  source = "unknown"
739  if (waveexists(Manufacturer) && (numpnts(Manufacturer) >= 1))
740  strswitch(Manufacturer[0])
741  case "VG Scienta":
742  source = "scienta"
743  break
744  case "Prosilica":
745  source = "prosilica"
746  break
747  endswitch
748  elseif (waveexists(AcquisitionMode) && (numpnts(AcquisitionMode) >= 1))
749  if (stringmatch(note(AcquisitionMode), "*SCIENTA*"))
750  source = "scienta"
751  endif
752  endif
753  endif
754 
755  strswitch(source)
756  case "prosilica":
757  // pixel scale - nothing to do
758  break
759  case "scienta":
760  adh5_scale_scienta(data)
761  break
762  endswitch
763 
764  setdatafolder saveDF
765 end
766 
780 function adh5_load_detector_slabs(fileID, detectorpath, [progress])
781  variable fileID
782  string detectorpath
783  variable progress
784 
785  if (ParamIsDefault(progress))
786  progress = 1
787  endif
788  variable result = 0
789 
790  // avoid compilation error if HDF5 XOP has not been loaded
791  #if Exists("HDF5LoadData")
792  string datasetname
793  string datawavename
794 
795  // detector data
796  datasetname = detectorpath + "data"
797  STRUCT HDF5DataInfo di // Defined in HDF5 Browser.ipf.
798  InitHDF5DataInfo(di)
799  variable err = HDF5DatasetInfo(fileID, datasetname, 0, di)
800  if (err != 0)
801  print "error accessing detector/data"
802  return -1
803  endif
804  if (di.ndims < 2)
805  print "error: rank of dataset < 2"
806  return -2
807  endif
808 
809  // nx and nz are the image dimensions
810  variable idx, idy, idz, idt, izt
811  idx = di.ndims - 1
812  idy = di.ndims - 2
813  idz = -1
814  idt = -1
815 
816  variable nx, ny, nz, nt, nzt
817  nx = di.dims[idx]
818  ny = di.dims[idy]
819  nz = 1
820  nt = 1
821 
822  make /n=(nx,ny,nz,nt) /o data
823  string dim_labels = "AD_Dim0;AD_Dim1;AD_DimN;AD_DimX;AD_DimY"
824  string dim_label
825  dim_label = StringFromList(0, dim_labels, ";")
826  setdimlabel 0, -1, $dim_label, data
827  dim_labels = RemoveFromList(dim_label, dim_labels, ";")
828  dim_label = StringFromList(0, dim_labels, ";")
829  setdimlabel 1, -1, $dim_label, data
830  dim_labels = RemoveFromList(dim_label, dim_labels, ";")
831 
832  // find additional dimensions, ignore singletons
833  variable id
834  for (id = idy - 1; (id >= 0) && (nz == 1); id -= 1)
835  if (di.dims[id] > 1)
836  idz = id
837  nz = di.dims[id]
838  dim_label = StringFromList(0, dim_labels, ";")
839  setdimlabel 2, -1, $dim_label, data
840  endif
841  dim_labels = RemoveListItem(0, dim_labels, ";")
842  endfor
843  for (id = idz - 1; (id >= 0) && (nt == 1); id -= 1)
844  if (di.dims[id] > 1)
845  idt = id
846  nt = di.dims[id]
847  dim_label = StringFromList(0, dim_labels, ";")
848  setdimlabel 3, -1, $dim_label, data
849  endif
850  dim_labels = RemoveListItem(0, dim_labels, ";")
851  endfor
852  redimension /n=(nx,ny,nz,nt) data
853 
854  // default values if dimensions are not present in dataset
855  if (idz < 0)
856  idz = idx + 1
857  idt = idz + 1
858  elseif (idt < 0)
859  idt = idx + 1
860  endif
861 
862  nzt = nz * nt
863  izt = 0
864  if (progress)
865  display_progress_panel("HDF5 Import", "Loading data...", nzt)
866  endif
867 
868  // load data image by image
869  HDF5MakeHyperslabWave(GetDataFolder(1) + "slab", max(di.ndims, 4))
870  wave slab
871  slab[][%Start] = 0
872  slab[][%Stride] = 1
873  slab[][%Count] = 1
874  slab[][%Block] = 1
875  slab[idx][%Block] = nx
876  slab[idy][%Block] = ny
877 
878  variable iz, it
879  for (iz = 0; iz < nz; iz += 1)
880  for (it = 0; it < nt; it += 1)
881  slab[idz][%Start] = iz
882  slab[idt][%Start] = it
883  HDF5LoadData /O /Q /Z /SLAB=slab /N=slabdata fileID, datasetname
884  wave slabdata // 2D, 3D, or 4D with singletons
885  switch (WaveDims(slabdata))
886  case 2:
887  data[][][iz][it] = slabdata[q][p]
888  break
889  case 3:
890  data[][][iz][it] = slabdata[0][q][p]
891  break
892  case 4:
893  data[][][iz][it] = slabdata[0][0][q][p]
894  break
895  endswitch
896  // progress window
897  izt += 1
898  if (progress)
899  if (update_progress_panel(izt))
900  result = -4 // user abort
901  break
902  endif
903  endif
904  endfor
905  if (result < 0)
906  break
907  endif
908  endfor
909 
910  if (nz == 1)
911  redimension /n=(nx,ny) data
912  elseif (nt == 1)
913  redimension /n=(nx,ny,nz) data
914  endif
915 
916  if (progress)
918  endif
919  #else
920  Abort "HDF5 XOP not loaded."
921  #endif
922 
923  return result
924 end
925 
945 function adh5_load_detector_image(fileID, detectorpath, dim2start, dim2count, dim3start, dim3count)
946  variable fileID
947  string detectorpath
948  variable dim2start
949  variable dim2count
950  variable dim3start
951  variable dim3count
952 
953  // avoid compilation error if HDF5 XOP has not been loaded
954  #if Exists("HDF5LoadData")
955  string datasetname
956  string datawavename
957 
958  // detector data
959  datasetname = detectorpath + "data"
960  STRUCT HDF5DataInfo di // Defined in HDF5 Browser.ipf.
961  InitHDF5DataInfo(di)
962  variable err = HDF5DatasetInfo(fileID, datasetname, 0, di)
963  if (err != 0)
964  print "error accessing detector/data"
965  return -1
966  endif
967  if (di.ndims < 1)
968  print "error: rank of dataset < 1"
969  return -2
970  endif
971 
972  // nx and nz are the image dimensions
973  variable idx, idy, idz, idt
974  idx = di.ndims - 1
975  idy = di.ndims >= 2 ? di.ndims - 2 : 1
976  idz = di.ndims >= 3 ? di.ndims - 3 : 2
977  idt = di.ndims >= 4 ? di.ndims - 4 : 3
978 
979  variable nx, ny
980  nx = di.dims[idx]
981  ny = di.ndims >= 2 ? di.dims[idy] : 1
982 
983  variable dim2end = dim2start + dim2count - 1
984  variable dim3end = dim3start + dim3count - 1
985 
986  // the slab wave is at least 4-dimensional
987  // it will also load lower-dimensional datasets
988  HDF5MakeHyperslabWave(GetDataFolder(1) + "slab", max(di.ndims, 4))
989  wave slab
990  slab[][%Start] = 0
991  slab[][%Stride] = 1
992  slab[][%Count] = 1
993  slab[][%Block] = 1
994  slab[idx][%Block] = nx
995  slab[idy][%Block] = ny
996 
997  make /n=(nx,ny)/o/d data
998  data = 0
999  variable iz, it
1000  variable navg = 0
1001  for (iz = dim2start; iz <= dim2end; iz += 1)
1002  for (it = dim3start; it <= dim3end; it += 1)
1003  slab[idz][%Start] = iz
1004  slab[idt][%Start] = it
1005  HDF5LoadData /O /Q /Z /SLAB=slab /N=slabdata fileID, datasetname
1006  wave slabdata // 2D, 3D, or 4D with singletons
1007  switch (WaveDims(slabdata))
1008  case 1:
1009  data += slabdata[p]
1010  navg += 1
1011  break
1012  case 2:
1013  data += slabdata[q][p]
1014  navg += 1
1015  break
1016  case 3:
1017  data += slabdata[0][q][p]
1018  navg += 1
1019  break
1020  case 4:
1021  data += slabdata[0][0][q][p]
1022  navg += 1
1023  break
1024  endswitch
1025  endfor
1026  endfor
1027  data /= navg
1028  setdimlabel 0, -1, AD_Dim0, data
1029  setdimlabel 1, -1, AD_Dim1, data
1030 
1031  #else
1032  Abort "HDF5 XOP not loaded."
1033  #endif
1034 end
1035 
1042  string all_funcs = FunctionList("*", ";", "KIND:6,NPARAMS:2,VALTYPE:8")
1043  string result = ""
1044 
1045  variable ii
1046  variable nn = ItemsInList(all_funcs, ";")
1047 
1048  string funcname
1049  string info
1050  variable nparams
1051  variable accept
1052 
1053  for (ii = 0; ii < nn; ii += 1)
1054  funcname = StringFromList(ii, all_funcs, ";")
1055  info = FunctionInfo(funcname)
1056  accept = (NumberByKey("RETURNTYPE", info, ":", ";") == 0x4000)
1057  accept = accept && (cmpstr(StringByKey("THREADSAFE", info, ":", ";"), "yes") == 0)
1058  accept = accept && (NumberByKey("N_PARAMS", info, ":", ";") == 2)
1059  accept = accept && (NumberByKey("N_OPT_PARAMS", info, ":", ";") == 0)
1060  if (accept)
1061  // one numeric wave and one pass-by-reference string
1062  accept = accept && (NumberByKey("PARAM_0_TYPE", info, ":", ";") == 0x4002)
1063  accept = accept && (NumberByKey("PARAM_1_TYPE", info, ":", ";") == 0x3000)
1064  endif
1065  if (accept)
1066  result = AddListItem(funcname, result, ";")
1067  endif
1068  endfor
1069 
1070  result = SortList(result, ";", 4)
1071  return result
1072 end
1073 
1111 threadsafe function /wave adh5_default_reduction(source, param)
1112  wave source
1113  string &param
1114 
1115  // demo code
1116  // integrate along the dimensions
1117  make /n=0 /free dest1, dest2
1118  adh5_setup_profile(source, dest1, 0)
1119  ad_profile_x_w(source, 0, -1, dest1)
1120  adh5_setup_profile(source, dest2, 1)
1121  ad_profile_y_w(source, 0, -1, dest2)
1122 
1123  make /n=2 /free /wave results
1124  results[0] = dest1
1125  results[1] = dest2
1126  return results
1127 end
1128 
1134 threadsafe function adh5_setup_profile(image, profile, dim)
1135  wave image // prototype
1136  wave profile // destination wave
1137  variable dim // which dimension to keep: 0 = X, 1 = Y
1138 
1139  redimension /n=(dimsize(image, dim)) profile
1140  setscale /p x dimoffset(image, dim), dimdelta(image, dim), waveunits(image, dim), profile
1141  setscale d 0, 0, waveunits(image, -1), profile
1142  setdimlabel 0, -1, $getdimlabel(image, dim, -1), profile
1143 end
1144 
1167 function /s adh5_test_reduction_func(source, reduction_func, reduction_param, result_prefix)
1168  wave source
1169  funcref adh5_default_reduction reduction_func
1170  string reduction_param
1171  string result_prefix
1172 
1173  wave /wave results = reduction_func(source, reduction_param)
1174  adh5_get_result_waves(results, result_prefix, 1)
1175 
1176  return reduction_param
1177 end
1178 
1198 function adh5_reduce_brick(source, reduction_func, reduction_param, result_prefix, [progress, nthreads])
1199  wave source
1200  funcref adh5_default_reduction reduction_func
1201  string reduction_param
1202  string result_prefix
1203 
1204  variable progress
1205  variable nthreads
1206 
1207  if (ParamIsDefault(progress))
1208  progress = 1
1209  endif
1210  if (ParamIsDefault(nthreads))
1211  nthreads = -1
1212  endif
1213  variable result = 0
1214 
1215  // nx and nz are the image dimensions
1216  variable nx, ny, nz, nt
1217  nx = dimsize(source, 0)
1218  ny = dimsize(source, 1)
1219  nz = dimsize(source, 2)
1220  // force 4th dimension to singleton (ad_extract_slab handles 3 dimensions only)
1221  nt = 0
1222 
1223  variable nzt = max(nz, 1) * max(nt, 1)
1224  variable izt
1225 
1226  // set up multi threading
1227  if (nthreads < 0)
1228  nthreads = ThreadProcessorCount
1229  endif
1230  if (nthreads > 0)
1231  variable threadGroupID = ThreadGroupCreate(nthreads)
1232  variable ithread
1233  for (ithread = 0; ithread < nthreads; ithread += 1)
1234  ThreadStart threadGroupID, ithread, reduce_slab_worker(reduction_func)
1235  endfor
1236  else
1237  make /n=(nzt) /df /free processing_folders
1238  endif
1239 
1240  if (progress)
1241  display_progress_panel("data reduction", "extracting data (step 1 of 2)...", nzt)
1242  endif
1243 
1244  variable iz, it
1245  string dfname
1246  variable iw, nw
1247  string sw
1248  make /n=0 /free /wave result_waves
1249 
1250  izt = 0
1251  for (iz = 0; iz < max(nz, 1); iz += 1)
1252  for (it = 0; it < max(nt, 1); it += 1)
1253  dfname = "processing_" + num2str(izt)
1254  newdatafolder /s $dfname
1255  ad_extract_slab(source, nan, nan, nan, nan, iz, iz, "image", pscale=1)
1256  wave image
1257 
1258  // send to processing queue
1259  variable /g r_index = iz
1260  variable /g s_index = it
1261  string /g func_param = reduction_param
1262 
1263  if (nthreads > 0)
1264  WaveClear image
1265  ThreadGroupPutDF threadGroupID, :
1266  else
1267  processing_folders[izt] = GetDataFolderDFR()
1268  string param = reduction_param
1269  wave /wave reduced_waves = reduction_func(image, param)
1270  variable /g func_result = numpnts(reduced_waves)
1271  adh5_get_result_waves(reduced_waves, "redw_", 0)
1272  WaveClear image, reduced_waves
1273  setdatafolder ::
1274  endif
1275 
1276  izt += 1
1277  // progress window
1278  if (progress)
1279  if (update_progress_panel(izt))
1280  result = -4 // user abort
1281  break
1282  endif
1283  endif
1284  endfor
1285  endfor
1286 
1287  if (progress)
1288  update_progress_panel(0, message="processing data (step 2 of 2)...")
1289  endif
1290 
1291  dfref dfr
1292  for (izt = 0; (izt < nzt) && (result == 0); izt += 1)
1293  if (nthreads > 0)
1294  do
1295  dfr = ThreadGroupGetDFR(threadGroupID, 1000)
1296  if (DatafolderRefStatus(dfr) != 0)
1297  break
1298  endif
1299  if (progress)
1300  if (update_progress_panel(izt))
1301  result = -4 // user abort
1302  break
1303  endif
1304  endif
1305  while (1)
1306  else
1307  dfr = processing_folders[izt]
1308  if (progress)
1309  if (update_progress_panel(izt))
1310  result = -4 // user abort
1311  break
1312  endif
1313  endif
1314  endif
1315 
1316  if (result != 0)
1317  break
1318  endif
1319 
1320  nvar rr = dfr:r_index
1321  nvar ss = dfr:s_index
1322  nvar func_result = dfr:func_result
1323 
1324  if (func_result < 1)
1325  result = -3 // dimension reduction error
1326  break
1327  endif
1328 
1329  if (numpnts(result_waves) == 0)
1330  redimension /n=(func_result) result_waves
1331  for (iw = 0; iw < func_result; iw += 1)
1332  sw = "redw_" + num2str(iw)
1333  wave profile = dfr:$sw
1334  sw = "ReducedData" + num2str(iw+1)
1335  make /n=(dimsize(profile, 0), nz, nt) /d /o $sw
1336  wave data = $sw
1337  setdimlabel 0, -1, $getdimlabel(profile, 0, -1), data
1338  setscale /p x dimoffset(profile, 0), dimdelta(profile, 0), waveunits(profile, 0), data
1339  setscale /p y dimoffset(source, 2), dimdelta(source, 2), waveunits(source, 2), data
1340  setscale /p z dimoffset(source, 3), dimdelta(source, 3), waveunits(source, 3), data
1341  setscale d 0, 0, waveunits(profile, -1), data
1342  result_waves[iw] = data
1343  endfor
1344  endif
1345  for (iw = 0; iw < func_result; iw += 1)
1346  sw = "redw_" + num2str(iw)
1347  wave profile = dfr:$sw
1348  wave data = result_waves[iw]
1349  data[][rr][ss] = profile[p]
1350  endfor
1351  endfor
1352 
1353  if (nthreads > 0)
1354  variable tstatus = ThreadGroupRelease(threadGroupID)
1355  if (tstatus == -2)
1356  result = -5 // thread did not terminate properly
1357  endif
1358  else
1359  for (izt = 0; izt < nzt; izt += 1)
1360  KillDataFolder /Z processing_folders[izt]
1361  endfor
1362  endif
1363 
1364  if (progress)
1366  endif
1367 
1368  return result
1369 end
1370 
1377 threadsafe static function reduce_brick_worker(reduction_func)
1378  funcref adh5_default_reduction reduction_func
1379  do
1380  // wait for job from main thread
1381  do
1382  dfref dfr = ThreadGroupGetDFR(0, 1000)
1383  if (DataFolderRefStatus(dfr) == 0)
1384  if (GetRTError(2))
1385  return 0 // no more jobs
1386  endif
1387  else
1388  break
1389  endif
1390  while (1)
1391 
1392  // get input data
1393  wave image = dfr:image
1394  svar func_param = dfr:func_param
1395  nvar rr = dfr:r_index
1396  nvar ss = dfr:s_index
1397 
1398  // do the work
1399  newdatafolder /s outDF
1400  variable /g r_index = rr
1401  variable /g s_index = ss
1402  string param = func_param
1403  wave /wave reduced_waves = reduction_func(image, param)
1404  variable /g func_result = numpnts(reduced_waves)
1405 
1406  // send output to queue and clean up
1407  adh5_get_result_waves(reduced_waves, "redw_", 0)
1408  WaveClear image, reduced_waves
1409  ThreadGroupPutDF 0, :
1410  KillDataFolder dfr
1411  while (1)
1412 
1413  return 0
1414 end
1415 
1430 threadsafe function adh5_get_result_waves(results, result_prefix, start_index)
1431  wave /wave results
1432  string result_prefix
1433  variable start_index
1434 
1435  variable nw = numpnts(results)
1436  variable iw
1437  string sw
1438  for (iw = 0; iw < nw; iw += 1)
1439  sw = result_prefix + num2str(iw + start_index)
1440  duplicate /o results[iw], $sw
1441  endfor
1442 end
1443 
1466 function adh5_load_reduced_detector(fileID, detectorpath, reduction_func, reduction_param, [progress, nthreads])
1467  variable fileID
1468  string detectorpath
1469  funcref adh5_default_reduction reduction_func
1470  string reduction_param
1471  variable progress
1472  variable nthreads
1473 
1474  if (ParamIsDefault(progress))
1475  progress = 1
1476  endif
1477  if (ParamIsDefault(nthreads))
1478  nthreads = -1
1479  endif
1480  variable result = 0
1481 
1482  // avoid compilation error if HDF5 XOP has not been loaded
1483  #if Exists("HDF5LoadData")
1484  string datasetname
1485  string datawavename
1486 
1487  // detector data
1488  datasetname = detectorpath + "data"
1489  STRUCT HDF5DataInfo di // Defined in HDF5 Browser.ipf.
1490  InitHDF5DataInfo(di)
1491  variable err = HDF5DatasetInfo(fileID, datasetname, 0, di)
1492  if (err != 0)
1493  print "error accessing detector/data"
1494  return -1
1495  endif
1496  if (di.ndims < 2)
1497  print "error: rank of dataset < 2"
1498  return -2
1499  endif
1500 
1501  // nx and nz are the image dimensions
1502  variable idx, idy, idz, idt
1503  idx = di.ndims - 1
1504  idy = di.ndims - 2
1505  idz = -1
1506  idt = -1
1507 
1508  variable nx, ny, nz, nt
1509  nx = di.dims[idx]
1510  ny = di.dims[idy]
1511  nz = 1
1512  nt = 1
1513 
1514  // find additional dimensions, ignore singletons
1515  variable id
1516  for (id = idy - 1; (id >= 0) && (nz == 1); id -= 1)
1517  if (di.dims[id] > 1)
1518  idz = id
1519  nz = di.dims[id]
1520  endif
1521  endfor
1522  for (id = idz - 1; (id >= 0) && (nt == 1); id -= 1)
1523  if (di.dims[id] > 1)
1524  idt = id
1525  nt = di.dims[id]
1526  endif
1527  endfor
1528  // default values if dimensions are not present in dataset
1529  if (idz < 0)
1530  idz = idx + 1
1531  idt = idz + 1
1532  elseif (idt < 0)
1533  idt = idx + 1
1534  endif
1535  variable nzt = nz * nt
1536  variable izt
1537 
1538  // load data image by image
1539  HDF5MakeHyperslabWave(GetDataFolder(1) + "slab", max(di.ndims, 4))
1540  wave slab
1541  slab[][%Start] = 0
1542  slab[][%Stride] = 1
1543  slab[][%Count] = 1
1544  slab[][%Block] = 1
1545  slab[idx][%Block] = nx
1546  slab[idy][%Block] = ny
1547 
1548  // set up multi threading
1549  if (nthreads < 0)
1550  nthreads = ThreadProcessorCount
1551  endif
1552  if (nthreads > 0)
1553  variable threadGroupID = ThreadGroupCreate(nthreads)
1554  variable ithread
1555  for (ithread = 0; ithread < nthreads; ithread += 1)
1556  ThreadStart threadGroupID, ithread, reduce_slab_worker(reduction_func)
1557  endfor
1558  else
1559  make /n=(nzt) /df /free processing_folders
1560  endif
1561 
1562  if (progress)
1563  display_progress_panel("HDF5 Import", "Loading data (step 1 of 2)...", nzt)
1564  endif
1565 
1566  make /n=(nx,ny)/d image_template
1567  setdimlabel 0, -1, AD_Dim0, image_template
1568  setdimlabel 1, -1, AD_Dim1, image_template
1569  adh5_scale(image_template)
1570 
1571  variable iz, it
1572  string dfname
1573  variable iw, nw
1574  string sw
1575  make /n=0 /free /wave result_waves
1576 
1577  izt = 0
1578  for (iz = 0; iz < nz; iz += 1)
1579  for (it = 0; it < nt; it += 1)
1580  // load hyperslab
1581  slab[idz][%Start] = iz
1582  slab[idt][%Start] = it
1583  dfname = "processing_" + num2str(izt)
1584  newdatafolder /s $dfname
1585  HDF5LoadData /O /Q /Z /SLAB=slab /N=slabdata fileID, datasetname
1586 
1587  // send to processing queue
1588  duplicate image_template, image
1589  variable /g r_index = iz
1590  variable /g s_index = it
1591  string /g func_param = reduction_param
1592 
1593  if (nthreads > 0)
1594  WaveClear image
1595  ThreadGroupPutDF threadGroupID, :
1596  else
1597  processing_folders[izt] = GetDataFolderDFR()
1598  wave slabdata
1599  wave /wave reduced_waves = reduce_slab_image(slabdata, image, reduction_func, func_param)
1600  variable /g func_result = numpnts(reduced_waves)
1601  adh5_get_result_waves(reduced_waves, "redw_", 0)
1602  WaveClear slabdata, image, reduced_waves
1603  setdatafolder ::
1604  endif
1605 
1606  izt += 1
1607  // progress window
1608  if (progress)
1609  if (update_progress_panel(izt))
1610  result = -4 // user abort
1611  break
1612  endif
1613  endif
1614  endfor
1615  endfor
1616 
1617  killwaves /z slab, image_template
1618  if (progress)
1619  update_progress_panel(0, message="Processing data (step 2 of 2)...")
1620  endif
1621 
1622  dfref dfr
1623  for (izt = 0; (izt < nzt) && (result == 0); izt += 1)
1624  if (nthreads > 0)
1625  do
1626  dfr = ThreadGroupGetDFR(threadGroupID, 1000)
1627  if (DatafolderRefStatus(dfr) != 0)
1628  break
1629  endif
1630  if (progress)
1631  if (update_progress_panel(izt))
1632  result = -4 // user abort
1633  break
1634  endif
1635  endif
1636  while (1)
1637  else
1638  dfr = processing_folders[izt]
1639  if (progress)
1640  if (update_progress_panel(izt))
1641  result = -4 // user abort
1642  break
1643  endif
1644  endif
1645  endif
1646 
1647  if (result != 0)
1648  break
1649  endif
1650 
1651  nvar rr = dfr:r_index
1652  nvar ss = dfr:s_index
1653  nvar func_result = dfr:func_result
1654 
1655  if (func_result < 1)
1656  result = -3 // dimension reduction error
1657  break
1658  endif
1659 
1660  if (numpnts(result_waves) == 0)
1661  redimension /n=(func_result) result_waves
1662  for (iw = 0; iw < func_result; iw += 1)
1663  sw = "redw_" + num2str(iw)
1664  wave profile = dfr:$sw
1665  sw = "ReducedData" + num2str(iw+1)
1666  make /n=(dimsize(profile, 0), nz, nt) /d /o $sw
1667  wave data = $sw
1668  setdimlabel 0, -1, $getdimlabel(profile, 0, -1), data
1669  setscale /p x dimoffset(profile, 0), dimdelta(profile, 0), waveunits(profile, 0), data
1670  setscale d 0, 0, waveunits(profile, -1), data
1671  result_waves[iw] = data
1672  endfor
1673  endif
1674  for (iw = 0; iw < func_result; iw += 1)
1675  sw = "redw_" + num2str(iw)
1676  wave profile = dfr:$sw
1677  wave data = result_waves[iw]
1678  data[][rr][ss] = profile[p]
1679  endfor
1680  endfor
1681 
1682  if (nthreads > 0)
1683  variable tstatus = ThreadGroupRelease(threadGroupID)
1684  if (tstatus == -2)
1685  result = -5 // thread did not terminate properly
1686  endif
1687  else
1688  for (izt = 0; izt < nzt; izt += 1)
1689  KillDataFolder /Z processing_folders[izt]
1690  endfor
1691  endif
1692 
1693  if (result == 0)
1694  nw = numpnts(result_waves)
1695  for (iw = 0; iw < nw; iw += 1)
1696  wave data = result_waves[iw]
1697  if (nz == 1)
1698  redimension /n=(dimsize(data, 0)) data
1699  elseif (nt == 1)
1700  redimension /n=(dimsize(data, 0),nz) data
1701  setdimlabel 1, -1, AD_DimN, data
1702  else
1703  setdimlabel 1, -1, AD_DimN, data
1704  setdimlabel 2, -1, AD_DimX, data
1705  endif
1706  endfor
1707  endif
1708  if (progress)
1710  endif
1711 
1712  #else
1713  Abort "HDF5 XOP not loaded."
1714  #endif
1715  return result
1716 end
1717 
1718 threadsafe static function reduce_slab_worker(reduction_func)
1719  funcref adh5_default_reduction reduction_func
1720  do
1721  // wait for job from main thread
1722  do
1723  dfref dfr = ThreadGroupGetDFR(0, 1000)
1724  if (DataFolderRefStatus(dfr) == 0)
1725  if (GetRTError(2))
1726  return 0 // no more jobs
1727  endif
1728  else
1729  break
1730  endif
1731  while (1)
1732 
1733  // get input data
1734  wave slabdata = dfr:slabdata
1735  wave image = dfr:image
1736  svar func_param = dfr:func_param
1737  nvar rr = dfr:r_index
1738  nvar ss = dfr:s_index
1739 
1740  // do the work
1741  newdatafolder /s outDF
1742  variable /g r_index = rr
1743  variable /g s_index = ss
1744  wave /wave reduced_waves = reduce_slab_image(slabdata, image, reduction_func, func_param)
1745  variable /g func_result = numpnts(reduced_waves)
1746 
1747  // send output to queue and clean up
1748  adh5_get_result_waves(reduced_waves, "redw_", 0)
1749  WaveClear slabdata, image, reduced_waves
1750  ThreadGroupPutDF 0, :
1751  KillDataFolder dfr
1752  while (1)
1753 
1754  return 0
1755 end
1756 
1757 threadsafe static function /wave reduce_slab_image(slabdata, image, reduction_func, reduction_param)
1758  wave slabdata
1759  wave image
1760  funcref adh5_default_reduction reduction_func
1761  string reduction_param
1762 
1763  switch (WaveDims(slabdata))
1764  case 2:
1765  image = slabdata[q][p]
1766  break
1767  case 3:
1768  image = slabdata[0][q][p]
1769  break
1770  case 4:
1771  image = slabdata[0][0][q][p]
1772  break
1773  endswitch
1774 
1775  return reduction_func(image, reduction_param)
1776 end
1777 
1790 function adh5_loadattr_all(fileID, attributespath)
1791  variable fileID
1792  string attributespath
1793 
1794  string datasetname
1795  string datawavename
1796 
1797  // avoid compilation error if HDF5 XOP has not been loaded
1798  #if Exists("HDF5LoadData")
1799 
1800  // datasets in NDAttributes group
1801  HDF5ListGroup /F /TYPE=2 fileID, attributespath
1802  string h5datasets = S_HDF5ListGroup
1803  HDF5ListAttributes /TYPE=1 /Z fileID, attributespath
1804  string h5attributes = S_HDF5ListAttributes
1805 
1806  variable nds = ItemsInList(h5datasets, ";")
1807  variable na = ItemsInList(h5attributes, ";")
1808  variable ids
1809  variable idest = 0
1810  variable n_attr
1811  string s_attr
1812  string s_source
1813 
1814  make /n=(nds+na) /t /o IN, ID, IV, IU
1815 
1816  for (ids = 0; ids < nds; ids += 1)
1817  datasetname = StringFromList(ids, h5datasets, ";")
1818  HDF5LoadData /O/Q fileID, datasetname
1819  if (v_flag == 0)
1820  datawavename = StringFromList(0, s_wavenames)
1821  else
1822  datawavename = ""
1823  endif
1824  HDF5LoadData /A="source"/O/Q/TYPE=2 fileID, datasetname
1825  if (v_flag == 0)
1826  wave /t source
1827  s_source = source[0]
1828  else
1829  s_source = ""
1830  endif
1831  read_attribute_info(datawavename, s_source, idest)
1832  endfor
1833 
1834  // attributes of NDAttributes group
1835  if (v_flag == 0)
1836  nds = ItemsInList(h5attributes, ";")
1837  else
1838  nds = 0
1839  endif
1840  for (ids = 0; ids < nds; ids += 1)
1841  datasetname = StringFromList(ids, h5attributes, ";")
1842  HDF5LoadData /A=datasetname/O/Q/TYPE=1 fileID, attributespath
1843  if (v_flag == 0)
1844  datawavename = StringFromList(0, s_wavenames)
1845  read_attribute_info(datawavename, "", idest) // we don't get the source of these attributes
1846  endif
1847  endfor
1848 
1849  redimension /n=(idest) IN, ID, IV, IU
1850  sort {IN, ID}, IN, ID, IV, IU
1851 
1852  killwaves /z source
1853  #else
1854  Abort "HDF5 XOP not loaded."
1855  #endif
1856 
1857 end
1858 
1872 static function read_attribute_info(datawavename, source, idest)
1873  string datawavename // name of the attribute wave in the current folder.
1874  // can be text or numeric.
1875  string source
1876  // source identifier (EPICS name) of the attribute.
1877  variable &idest
1878  // destination index in IN, ID, IV, IU where the results are written.
1879  // the variable is incremented if data was written, otherwise it is left unchanged.
1880  // make sure IN, ID, IV, IU have at least idest + 1 elements.
1881 
1882  wave /t IN
1883  wave /t ID
1884  wave /t IV
1885  wave /t IU
1886 
1887  variable n_attr
1888  string s_attr
1889 
1890  if (exists(datawavename) == 1)
1891  if (strlen(source) > 0)
1892  Note $datawavename, "PV=" + source
1893  endif
1894  switch(WaveType($datawavename, 1))
1895  case 1: // numeric
1896  wave w_attr = $datawavename
1897  n_attr = numpnts(w_attr)
1898  sprintf s_attr, "%.12g", w_attr[0]
1899  break
1900  case 2: // text
1901  wave /t wt_attr = $datawavename
1902  n_attr = numpnts(wt_attr)
1903  s_attr = wt_attr[0]
1904  break
1905  default: // unknown
1906  n_attr = 0
1907  endswitch
1908  if (n_attr == 1)
1909  IN[idest] = source
1910  ID[idest] = datawavename
1911  IV[idest] = s_attr
1912  IU[idest] = "" // we don't get the units
1913  idest += 1
1914  endif
1915  endif
1916 end
1917 
1925 function adh5_scale_scienta(data)
1926  wave data
1927 
1928  dfref saveDF = GetDataFolderDFR()
1929 
1930  dfref dataDF = GetWavesDataFolderDFR(data)
1931  dfref attrDF = GetAttrDataFolderDFR(data)
1932 
1933  wave /SDFR=attrDF LensMode
1934  wave /SDFR=attrDF /Z ChannelBegin, ChannelEnd
1935  wave /SDFR=attrDF /Z SliceBegin, SliceEnd
1936 
1937  variable EDim, ADim
1938  variable ELow, EHigh, ALow, AHigh
1939  string EUnit, AUnit
1940 
1941  // which dimension is angle and which one is energy?
1942  strswitch(GetDimLabel(data, 0, -1))
1943  case "AD_Dim0":
1944  EDim = 0
1945  break
1946  case "AD_Dim1":
1947  EDim = 1
1948  break
1949  default:
1950  EDim = -1
1951  endswitch
1952  strswitch(GetDimLabel(data, 1, -1))
1953  case "AD_Dim0":
1954  ADim = 0
1955  break
1956  case "AD_Dim1":
1957  ADim = 1
1958  break
1959  default:
1960  ADim = -1
1961  endswitch
1962 
1963  // defaults (point scaling)
1964  if (EDim >= 0)
1965  ELow = dimoffset(data, EDim)
1966  EHigh = dimoffset(data, EDim) + dimdelta(data, EDim) * (dimsize(data, EDim) - 1)
1967  EUnit = "eV"
1968  endif
1969  if (ADim >= 0)
1970  ALow = dimoffset(data, ADim)
1971  AHigh = dimoffset(data, ADim) + dimdelta(data, ADim) * (dimsize(data, ADim) - 1)
1972  AUnit = "arb."
1973  endif
1974 
1975  // lens mode can give more detail
1976  if (waveexists(LensMode) && (numpnts(LensMode) >= 1))
1977  switch(LensMode[0])
1978  case 1: // Angular45
1979  ALow = -45/2
1980  AHigh = +45/2
1981  AUnit = "°"
1982  break
1983  case 2: // Angular60
1984  ALow = -60/2
1985  AHigh = +60/2
1986  AUnit = "°"
1987  break
1988  endswitch
1989  endif
1990 
1991  // best option if scales are explicit in separate waves
1992  if (waveexists(ChannelBegin) && waveexists(ChannelEnd) && (numpnts(ChannelBegin) >= 1) && (numpnts(ChannelEnd) >= 1))
1993  ELow = ChannelBegin[0]
1994  EHigh = ChannelEnd[0]
1995  endif
1996  if (waveexists(SliceBegin) && waveexists(SliceEnd) && (numpnts(SliceBegin) >= 1) && (numpnts(SliceEnd) >= 1))
1997  ALow = SliceBegin[0]
1998  AHigh = SliceEnd[0]
1999  endif
2000 
2001  // apply new scales
2002  switch(EDim)
2003  case 0:
2004  setscale /i x ELow, EHigh, EUnit, data
2005  break
2006  case 1:
2007  setscale /i y ELow, EHigh, EUnit, data
2008  break
2009  endswitch
2010  switch(ADim)
2011  case 0:
2012  setscale /i x ALow, AHigh, AUnit, data
2013  break
2014  case 1:
2015  setscale /i y ALow, AHigh, AUnit, data
2016  break
2017  endswitch
2018 
2019  setscale d 0, 0, "arb.", data
2020 
2021  setdatafolder saveDF
2022 end
2023 
2030 function adh5_scale_scan(data)
2031  wave data
2032 
2033  dfref saveDF = GetDataFolderDFR()
2034 
2035  dfref dataDF = GetWavesDataFolderDFR(data)
2036  wave /SDFR=dataDF AcquisitionMode, DetectorMode, EnergyMode
2037 
2038  wave /SDFR=dataDF /z Scan1Active, Scan2Active
2039  wave /SDFR=dataDF /t /z Scan1Positioner1, Scan1Readback1
2040  wave /SDFR=dataDF /t /z Scan1Positioner2, Scan1Readback2
2041  wave /SDFR=dataDF /t /z Scan2Positioner1, Scan2Readback1
2042  wave /SDFR=dataDF /t /z Scan2Positioner2, Scan2Readback2
2043 
2044  // TODO : search the data folder for positioner waves,
2045  // i.e. waves with the PV name corresponding to Scan1Positioner1 in their wave note.
2046  wave /z zscale
2047 
2048  strswitch(GetDimLabel(data, 0, -1))
2049  case "AD_DimN":
2050  setscale /i x zscale[0], zscale[numpnts(zscale)-1], "", data
2051  break
2052  endswitch
2053  strswitch(GetDimLabel(data, 1, -1))
2054  case "AD_DimN":
2055  setscale /i y zscale[0], zscale[numpnts(zscale)-1], "", data
2056  break
2057  endswitch
2058  strswitch(GetDimLabel(data, 2, -1))
2059  case "AD_DimN":
2060  setscale /i z zscale[0], zscale[numpnts(zscale)-1], "", data
2061  break
2062  endswitch
2063 
2064  setdatafolder saveDF
2065 end
string adh5_load_preview(string ANickName, string APathName, string AFileName, variable load_data=defaultValue, variable load_attr=defaultValue)
load a single image from a HDF5 file created by the Area Detector software.
variable kill_progress_panel()
variable display_progress_panel(string title, string message, variable progress_max)
-
string adh5_load_info(string APathName, string AFileName)
load descriptive info from a HDF5 file created by the Area Detector software.
-
variable ad_load_dialog(string APathName)
load area detector data files selected in a file dialog window
+
string adh5_load_info(string APathName, string AFileName)
load descriptive info from a HDF5 file created by the Area Detector software.
+
variable ad_load_dialog(string APathName)
load area detector data files selected in a file dialog window
threadsafe wave ad_profile_x_w(wave dataset, variable q1, variable q2, wave destwave, variable noavg=defaultValue)
1D cut through 2D dataset along X dimension, existing destination wave.
-
static variable read_attribute_info(string datawavename, string source, variable *idest)
sub-function of adh5_loadattr_all.
-
static dfr GetAttrDataFolderDFR(wave data)
find the attributes data folder of an area detector dataset.
-
threadsafe variable adh5_setup_profile(wave image, wave profile, variable dim)
set up a one-dimensional wave for a line profile based on a 2D original wave.
-
threadsafe variable adh5_get_result_waves(wave results, string result_prefix, variable start_index)
copy waves from wave reference wave into current data folder
-
variable adh5_scale_scienta(wave data)
set the energy and angle scales of an area detector dataset from the Scienta analyser.
-
string adh5_test_reduction_func(wave source, funcref reduction_func, string reduction_param, string result_prefix)
wrapper function for testing reduction functions from the command line.
-
variable adh5_loadattr_all(variable fileID, string attributespath)
load an NDAttributes group from an open HDF5 file into the current data folder.
-
variable adh5_scale_scan(wave data)
scales the extra dimensions of an area detector dataset according to the EPICS scan ...
-
string ad_suggest_foldername(string filename, variable ignoredate=defaultValue, string sourcename=defaultValue, variable unique=defaultValue)
generate the name of a data folder based on a file name.
+
static variable read_attribute_info(string datawavename, string source, variable *idest)
sub-function of adh5_loadattr_all.
+
string PearlCleanupName(string name)
+
static dfr GetAttrDataFolderDFR(wave data)
find the attributes data folder of an area detector dataset.
+
threadsafe variable adh5_setup_profile(wave image, wave profile, variable dim)
set up a one-dimensional wave for a line profile based on a 2D original wave.
+
threadsafe variable adh5_get_result_waves(wave results, string result_prefix, variable start_index)
copy waves from wave reference wave into current data folder
+
variable adh5_scale_scienta(wave data)
set the energy and angle scales of an area detector dataset from the Scienta analyser.
+
string adh5_test_reduction_func(wave source, funcref reduction_func, string reduction_param, string result_prefix)
wrapper function for testing reduction functions from the command line.
+
variable adh5_loadattr_all(variable fileID, string attributespath)
load an NDAttributes group from an open HDF5 file into the current data folder.
+
variable adh5_scale_scan(wave data)
scales the extra dimensions of an area detector dataset according to the EPICS scan ...
+
static threadsafe variable reduce_brick_worker(funcref reduction_func)
thread worker for adh5_reduce_brick
+
variable adh5_reduce_brick(wave source, funcref reduction_func, string reduction_param, string result_prefix, variable progress=defaultValue, variable nthreads=defaultValue)
reduce a three-dimensional intensity distribution
+
string ad_suggest_foldername(string filename, variable ignoredate=defaultValue, string sourcename=defaultValue, variable unique=defaultValue)
generate the name of a data folder based on a file name.
threadsafe wave ad_profile_y_w(wave dataset, variable p1, variable p2, wave destwave, variable noavg=defaultValue)
1D cut through 2D dataset along X dimension, existing destination wave.
-
string adh5_load_complete(string ANickName, string APathName, string AFileName, variable load_data=defaultValue, variable load_attr=defaultValue)
import everything from a HDF5 file created by the Area Detector software.
-
variable adh5_load_reduced_detector(variable fileID, string detectorpath, funcref reduction_func, string reduction_param, variable progress=defaultValue, variable nthreads=defaultValue)
load a reduced detector dataset from the open HDF5 file.
-
string adh5_load_reduced(string ANickName, string APathName, string AFileName, funcref reduction_func, string reduction_param, variable load_data=defaultValue, variable load_attr=defaultValue, variable progress=defaultValue)
load and reduce a dataset from a HDF5 file created by the Area Detector software. ...
-
variable adh5_redim(wave data)
redimension a multi-dimensional area detector array loaded from HDF5.
-
threadsafe wave adh5_default_reduction(wave source, string *param)
function prototype for adh5_load_reduced_detector
-
variable adh5_load_detector_slabs(variable fileID, string detectorpath, variable progress=defaultValue)
load the detector dataset from the open HDF5 file.
-
variable adh5_scale(wave data, string source=defaultValue)
set the dimension scales of an area detector dataset.
+
string adh5_load_complete(string ANickName, string APathName, string AFileName, variable load_data=defaultValue, variable load_attr=defaultValue)
import everything from a HDF5 file created by the Area Detector software.
+
variable adh5_load_reduced_detector(variable fileID, string detectorpath, funcref reduction_func, string reduction_param, variable progress=defaultValue, variable nthreads=defaultValue)
load a reduced detector dataset from the open HDF5 file.
+
string adh5_load_reduced(string ANickName, string APathName, string AFileName, funcref reduction_func, string reduction_param, variable load_data=defaultValue, variable load_attr=defaultValue, variable progress=defaultValue)
load and reduce a dataset from a HDF5 file created by the Area Detector software. ...
+
variable adh5_redim(wave data)
redimension a multi-dimensional area detector array loaded from HDF5.
+
threadsafe wave adh5_default_reduction(wave source, string *param)
function prototype for adh5_load_reduced_detector
+
variable adh5_load_detector_slabs(variable fileID, string detectorpath, variable progress=defaultValue)
load the detector dataset from the open HDF5 file.
+
variable adh5_scale(wave data, string source=defaultValue)
set the dimension scales of an area detector dataset.
variable update_progress_panel(variable progress, string message=defaultValue, variable progress_max=defaultValue)
-
variable adh5_load_detector(variable fileID, string detectorpath)
load the detector dataset from the open HDF5 file.
-
static threadsafe wave reduce_slab_image(wave slabdata, wave image, funcref reduction_func, string reduction_param)
-
static variable BeforeFileOpenHook(variable refNum, string fileName, string path, string type, string creator, variable kind)
callback function for drag&drop of HDF5 files into Igor.
-
string adh5_list_reduction_funcs()
get a list of functions which can be used as reduction functions.
-
variable adh5_load_detector_image(variable fileID, string detectorpath, variable dim2start, variable dim2count, variable dim3start, variable dim3count)
load a single image from the detector dataset of the open HDF5 file
-
static threadsafe variable reduce_slab_worker(funcref reduction_func)
+
variable adh5_load_detector(variable fileID, string detectorpath)
load the detector dataset from the open HDF5 file.
+
static threadsafe wave reduce_slab_image(wave slabdata, wave image, funcref reduction_func, string reduction_param)
+
static variable BeforeFileOpenHook(variable refNum, string fileName, string path, string type, string creator, variable kind)
callback function for drag&drop of HDF5 files into Igor.
+
string adh5_list_reduction_funcs()
get a list of functions which can be used as reduction functions.
+
variable adh5_load_detector_image(variable fileID, string detectorpath, variable dim2start, variable dim2count, variable dim3start, variable dim3count)
load a single image from the detector dataset of the open HDF5 file
+
threadsafe wave ad_extract_slab(wave dataset, variable x1, variable x2, variable y1, variable y2, variable z1, variable z2, string destname, variable noavg=defaultValue, variable pscale=defaultValue)
2D cut through 3D dataset, integrate in normal dimension
+
static threadsafe variable reduce_slab_worker(funcref reduction_func)
-

Definition at line 90 of file pearl-arpes.ipf.

+

Definition at line 83 of file pearl-arpes.ipf.

@@ -188,7 +189,7 @@ Licensed under the Apache License, Version 2.0 (the "License");
-Go to the documentation of this file.
1 #pragma rtGlobals=3 // Use modern global access method and strict wave access.
2 #pragma IgorVersion = 6.1
3 #pragma ModuleName = PearlArpes
4 #pragma version = 1.05
5 #include "pearl-area-display" // 2D and 3D data visualization
6 #include "pearl-area-profiles" // data processing for multi-dimensional datasets
7 #include "pearl-area-import" // import data files generated by area detector software
8 #include "pearl-pshell-import"
9 #include "pearl-data-explorer" // preview and import panel for PEARL data
10 #include "pearl-anglescan-process" // angle scan (XPD) processing functions
11 #include "pearl-anglescan-panel" // panel interface to angle scan processing
12 #include "pearl-anglescan-tracker" // live preview of hemispherical angle scan
13 #include "pearl-scienta-preprocess" // pre-processing functions for Scienta detector images
14 #include "pearl-elog"
15 #if exists("pvOpen")
16 #include "pearl-area-live" // live view of area detector
17 #include "pearl-epics" // EPICS access under Igor
18 #include "pearl-arpes-scans" // run ARPES scans under Igor
19 #endif
20 
21 // $Id$
22 //
23 // author: matthias.muntwiler@psi.ch
24 // Copyright (c) 2012-15 Paul Scherrer Institut
25 //
26 // Licensed under the Apache License, Version 2.0 (the "License");
27 // you may not use this file except in compliance with the License.
28 // You may obtain a copy of the License at
29 // http://www.apache.org/licenses/LICENSE-2.0
30 
49 
55 
81 
83 static function AfterCompiledHook()
84 
85  dfref savefolder = GetDataFolderDFR()
86 
87  return 0
88 end
89 
91  execute /p/q/z "DELETEINCLUDE \"pearl-arpes\""
92  execute /p/q/z "COMPILEPROCEDURES "
93 end
variable UnloadPearlArpesPackage()
Definition: pearl-arpes.ipf:90
-
static variable AfterCompiledHook()
initializes package data once when the procedure is first loaded
Definition: pearl-arpes.ipf:83
+Go to the documentation of this file.
1 #pragma rtGlobals=3 // Use modern global access method and strict wave access.
2 #pragma IgorVersion = 6.1
3 #pragma ModuleName = PearlArpes
4 #pragma version = 1.05
5 #include "pearl-area-display" // 2D and 3D data visualization
6 #include "pearl-area-profiles" // data processing for multi-dimensional datasets
7 #include "pearl-area-import" // import data files generated by area detector software
8 #include "pearl-pshell-import"
9 #include "pearl-compat" // compatibility with igor 6
10 #include "pearl-data-explorer" // preview and import panel for PEARL data
11 #include "pearl-anglescan-process" // angle scan (XPD) processing functions
12 #include "pearl-anglescan-panel" // panel interface to angle scan processing
13 #include "pearl-anglescan-tracker" // live preview of hemispherical angle scan
14 #include "pearl-scienta-preprocess" // pre-processing functions for Scienta detector images
15 #include "pearl-elog"
16 #if exists("pvOpen")
17 #include "pearl-area-live" // live view of area detector
18 #include "pearl-epics" // EPICS access under Igor
19 #include "pearl-arpes-scans" // run ARPES scans under Igor
20 #include "pearl-sample-tracker" // live tracking and adjustment of sample position
21 #endif
22 
41 
47 
74 
76 static function AfterCompiledHook()
77 
78  dfref savefolder = GetDataFolderDFR()
79 
80  return 0
81 end
82 
84  execute /p/q/z "DELETEINCLUDE \"pearl-arpes\""
85  execute /p/q/z "COMPILEPROCEDURES "
86 end
variable UnloadPearlArpesPackage()
Definition: pearl-arpes.ipf:83
+
static variable AfterCompiledHook()
initializes package data once when the procedure is first loaded
Definition: pearl-arpes.ipf:76
- + - - + + + +
@@ -106,34 +82,56 @@ $(document).ready(function(){initNavTree('pearl-data-export_8ipf.html','');});
-
pearl-data-export.ipf File Reference
+
pearl-compat.ipf File Reference
-

Go to the source code of this file.

+

compatibility procedures for igor 8 +More...

+ +

Go to the source code of this file.

+ + + + +

+Namespaces

 PearlCompat
 compatibility procedures for igor 8
 
- - + +

Functions

variable export_otf ()
 
string PearlCleanupName (string name)
 
-

Function Documentation

- +

Detailed Description

+

compatibility procedures for igor 8

+

the compatibility procedures ensure that igor experiments created with the PEARL procedures under igor 8 can be opened with earlier igor versions (>= 6.34).

+

the following possible issues are addressed:

+
    +
  • length of object names
  • +
+ +

Definition in file pearl-compat.ipf.

+

Function Documentation

+ +

◆ PearlCleanupName()

+
- + - + +
variable export_otf string PearlCleanupName ()string name)
-

Definition at line 3 of file pearl-data-export.ipf.

+

Definition at line 47 of file pearl-compat.ipf.

@@ -142,10 +140,10 @@ Functions diff --git a/doc/html/pearl-compat_8ipf.js b/doc/html/pearl-compat_8ipf.js new file mode 100644 index 0000000..1cd1c9e --- /dev/null +++ b/doc/html/pearl-compat_8ipf.js @@ -0,0 +1,4 @@ +var pearl_compat_8ipf = +[ + [ "PearlCleanupName", "pearl-compat_8ipf.html#aa1f59acc532c7eee75c83b70ee1feaa9", null ] +]; \ No newline at end of file diff --git a/doc/html/pearl-compat_8ipf_source.html b/doc/html/pearl-compat_8ipf_source.html new file mode 100644 index 0000000..5493ec7 --- /dev/null +++ b/doc/html/pearl-compat_8ipf_source.html @@ -0,0 +1,101 @@ + + + + + + + +PEARL Procedures: pearl-compat.ipf Source File + + + + + + + + + + + + + + +
+
+ + + + + + +
+
PEARL Procedures +  rev-distro-2.0.3-2-g58135e4-dirty +
+
Igor procedures for the analysis of PEARL data
+
+
+ + + + + + + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
pearl-compat.ipf
+
+
+Go to the documentation of this file.
1 #pragma rtGlobals=3 // Use modern global access method and strict wave access.
2 #pragma IgorVersion = 6.1
3 #pragma ModuleName = PearlCompat
4 #pragma version = 1.01
5 
6 // copyright (c) 2019 Paul Scherrer Institut
7 //
8 // Licensed under the Apache License, Version 2.0 (the "License");
9 // you may not use this file except in compliance with the License.
10 // You may obtain a copy of the License at
11 // http:///www.apache.org/licenses/LICENSE-2.0
12 
25 
30 
31 
32 // Compatible CleanupName function
33 //
34 // Igor 8's CleanupName may return long object names (> 31 characters).
35 // This breaks compatibility with earlier Igor versions.
36 // Experiments that include waves, folders, windows etc. with long names
37 // cannot be loaded with an earlier version.
38 //
39 // This is a drop-in replacement function for CleanupName.
40 // In addition to the behaviour of CleanupName,
41 // this replacement ensures that names are limited to 31 characters.
42 //
43 // @param name object name to clean up
44 //
45 // @return (str) clean object name
46 //
47 function /s PearlCleanupName(name)
48  string name
49 
50 #if IgorVersion() >= 8.00
51  // note: this function is not threadsafe
52  return CleanupName(name, 0, 31)
53 #else
54  return CleanupName(name, 0)
55 #endif
56 
57 end
string PearlCleanupName(string name)
+
+
+ + + + diff --git a/doc/html/pearl-data-explorer_8ipf.html b/doc/html/pearl-data-explorer_8ipf.html index ed3f85e..842a2a1 100644 --- a/doc/html/pearl-data-explorer_8ipf.html +++ b/doc/html/pearl-data-explorer_8ipf.html @@ -29,7 +29,7 @@
PEARL Procedures -  rev-distro-2.0.3-0-g0fb0fd9 +  rev-distro-2.0.3-2-g58135e4-dirty
Igor procedures for the analysis of PEARL data
@@ -95,6 +95,7 @@ $(document).ready(function(){initNavTree('pearl-data-explorer_8ipf.html','');});
#include "pearl-area-import"
#include "pearl-area-profiles"
#include "pearl-area-display"
+#include "pearl-compat"
#include "pearl-pshell-import"

Go to the source code of this file.

@@ -283,7 +284,7 @@ Variables
-

Definition at line 820 of file pearl-data-explorer.ipf.

+

Definition at line 821 of file pearl-data-explorer.ipf.

@@ -311,7 +312,7 @@ Variables
-

Definition at line 1748 of file pearl-data-explorer.ipf.

+

Definition at line 1749 of file pearl-data-explorer.ipf.

@@ -339,7 +340,7 @@ Variables
-

Definition at line 1434 of file pearl-data-explorer.ipf.

+

Definition at line 1435 of file pearl-data-explorer.ipf.

@@ -367,7 +368,7 @@ Variables
-

Definition at line 1639 of file pearl-data-explorer.ipf.

+

Definition at line 1640 of file pearl-data-explorer.ipf.

@@ -395,7 +396,7 @@ Variables
-

Definition at line 1613 of file pearl-data-explorer.ipf.

+

Definition at line 1614 of file pearl-data-explorer.ipf.

@@ -423,7 +424,7 @@ Variables
-

Definition at line 1659 of file pearl-data-explorer.ipf.

+

Definition at line 1660 of file pearl-data-explorer.ipf.

@@ -451,7 +452,7 @@ Variables
-

Definition at line 1686 of file pearl-data-explorer.ipf.

+

Definition at line 1687 of file pearl-data-explorer.ipf.

@@ -479,7 +480,7 @@ Variables
-

Definition at line 1500 of file pearl-data-explorer.ipf.

+

Definition at line 1501 of file pearl-data-explorer.ipf.

@@ -507,7 +508,7 @@ Variables
-

Definition at line 1532 of file pearl-data-explorer.ipf.

+

Definition at line 1533 of file pearl-data-explorer.ipf.

@@ -535,7 +536,7 @@ Variables
-

Definition at line 1472 of file pearl-data-explorer.ipf.

+

Definition at line 1473 of file pearl-data-explorer.ipf.

@@ -563,7 +564,7 @@ Variables
-

Definition at line 1486 of file pearl-data-explorer.ipf.

+

Definition at line 1487 of file pearl-data-explorer.ipf.

@@ -591,7 +592,7 @@ Variables
-

Definition at line 1406 of file pearl-data-explorer.ipf.

+

Definition at line 1407 of file pearl-data-explorer.ipf.

@@ -619,7 +620,7 @@ Variables
-

Definition at line 1420 of file pearl-data-explorer.ipf.

+

Definition at line 1421 of file pearl-data-explorer.ipf.

@@ -647,7 +648,7 @@ Variables
-

Definition at line 1599 of file pearl-data-explorer.ipf.

+

Definition at line 1600 of file pearl-data-explorer.ipf.

@@ -675,7 +676,7 @@ Variables
-

Definition at line 1458 of file pearl-data-explorer.ipf.

+

Definition at line 1459 of file pearl-data-explorer.ipf.

@@ -703,7 +704,7 @@ Variables
-

Definition at line 780 of file pearl-data-explorer.ipf.

+

Definition at line 781 of file pearl-data-explorer.ipf.

@@ -741,7 +742,7 @@ Variables
-

Definition at line 937 of file pearl-data-explorer.ipf.

+

Definition at line 938 of file pearl-data-explorer.ipf.

@@ -779,7 +780,7 @@ Variables
-

Definition at line 493 of file pearl-data-explorer.ipf.

+

Definition at line 494 of file pearl-data-explorer.ipf.

@@ -809,7 +810,7 @@ Variables

initialize the global variables of the data explorer.

initializes the global variables and data folder for this procedure file must be called once before the panel is created warning: this function overwrites previous values

-

Definition at line 55 of file pearl-data-explorer.ipf.

+

Definition at line 56 of file pearl-data-explorer.ipf.

@@ -851,7 +852,7 @@ Variables
-

Definition at line 1256 of file pearl-data-explorer.ipf.

+

Definition at line 1257 of file pearl-data-explorer.ipf.

@@ -879,7 +880,7 @@ Variables
-

Definition at line 1713 of file pearl-data-explorer.ipf.

+

Definition at line 1714 of file pearl-data-explorer.ipf.

@@ -907,7 +908,7 @@ Variables
-

Definition at line 1564 of file pearl-data-explorer.ipf.

+

Definition at line 1565 of file pearl-data-explorer.ipf.

@@ -945,7 +946,7 @@ Variables
-

Definition at line 994 of file pearl-data-explorer.ipf.

+

Definition at line 995 of file pearl-data-explorer.ipf.

@@ -983,7 +984,7 @@ Variables
-

Definition at line 1140 of file pearl-data-explorer.ipf.

+

Definition at line 1141 of file pearl-data-explorer.ipf.

@@ -1021,7 +1022,7 @@ Variables
-

Definition at line 1190 of file pearl-data-explorer.ipf.

+

Definition at line 1191 of file pearl-data-explorer.ipf.

@@ -1061,7 +1062,7 @@ Variables

load a matrix (STM) data file

-

Definition at line 1233 of file pearl-data-explorer.ipf.

+

Definition at line 1234 of file pearl-data-explorer.ipf.

@@ -1088,7 +1089,7 @@ Variables
-

Definition at line 116 of file pearl-data-explorer.ipf.

+

Definition at line 117 of file pearl-data-explorer.ipf.

@@ -1126,7 +1127,7 @@ Variables
-

Definition at line 1088 of file pearl-data-explorer.ipf.

+

Definition at line 1089 of file pearl-data-explorer.ipf.

@@ -1154,7 +1155,7 @@ Variables
-

Definition at line 970 of file pearl-data-explorer.ipf.

+

Definition at line 971 of file pearl-data-explorer.ipf.

@@ -1204,7 +1205,7 @@ Variables
-

Definition at line 859 of file pearl-data-explorer.ipf.

+

Definition at line 860 of file pearl-data-explorer.ipf.

@@ -1223,7 +1224,7 @@ Variables
-

Definition at line 44 of file pearl-data-explorer.ipf.

+

Definition at line 45 of file pearl-data-explorer.ipf.

@@ -1262,7 +1263,7 @@ Variables -

Definition at line 161 of file pearl-data-explorer.ipf.

+

Definition at line 162 of file pearl-data-explorer.ipf.

@@ -1281,7 +1282,7 @@ Variables
-

Definition at line 1315 of file pearl-data-explorer.ipf.

+

Definition at line 1316 of file pearl-data-explorer.ipf.

@@ -1337,7 +1338,7 @@ Variables
-

Definition at line 646 of file pearl-data-explorer.ipf.

+

Definition at line 647 of file pearl-data-explorer.ipf.

@@ -1364,7 +1365,7 @@ Variables
-

Definition at line 575 of file pearl-data-explorer.ipf.

+

Definition at line 576 of file pearl-data-explorer.ipf.

@@ -1392,7 +1393,7 @@ Variables
-

Definition at line 532 of file pearl-data-explorer.ipf.

+

Definition at line 533 of file pearl-data-explorer.ipf.

@@ -1420,7 +1421,7 @@ Variables
-

Definition at line 255 of file pearl-data-explorer.ipf.

+

Definition at line 256 of file pearl-data-explorer.ipf.

@@ -1459,7 +1460,7 @@ Variables
Returns
wave reference of the preview image
-

Definition at line 363 of file pearl-data-explorer.ipf.

+

Definition at line 364 of file pearl-data-explorer.ipf.

@@ -1499,7 +1500,7 @@ Variables
Returns
wave reference of the preview trace. empty wave reference if the function failed.
-

Definition at line 414 of file pearl-data-explorer.ipf.

+

Definition at line 415 of file pearl-data-explorer.ipf.

@@ -1539,7 +1540,7 @@ Variables
Returns
wave reference of the preview image. empty wave reference if the function failed.
-

Definition at line 450 of file pearl-data-explorer.ipf.

+

Definition at line 451 of file pearl-data-explorer.ipf.

@@ -1578,7 +1579,7 @@ Variables
Returns
wave reference of the preview image
-

Definition at line 307 of file pearl-data-explorer.ipf.

+

Definition at line 308 of file pearl-data-explorer.ipf.

@@ -1616,7 +1617,7 @@ Variables
-

Definition at line 616 of file pearl-data-explorer.ipf.

+

Definition at line 617 of file pearl-data-explorer.ipf.

@@ -1641,7 +1642,7 @@ Variables

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.

-

Definition at line 1068 of file pearl-data-explorer.ipf.

+

Definition at line 1069 of file pearl-data-explorer.ipf.

@@ -1671,7 +1672,7 @@ Variables
-

Definition at line 1074 of file pearl-data-explorer.ipf.

+

Definition at line 1075 of file pearl-data-explorer.ipf.

@@ -1699,7 +1700,7 @@ Variables
-

Definition at line 1029 of file pearl-data-explorer.ipf.

+

Definition at line 1030 of file pearl-data-explorer.ipf.

@@ -1726,7 +1727,7 @@ Variables
-

Definition at line 96 of file pearl-data-explorer.ipf.

+

Definition at line 97 of file pearl-data-explorer.ipf.

@@ -1764,7 +1765,7 @@ Variables
-

Definition at line 886 of file pearl-data-explorer.ipf.

+

Definition at line 887 of file pearl-data-explorer.ipf.

@@ -1783,7 +1784,7 @@ Variables
-

Definition at line 813 of file pearl-data-explorer.ipf.

+

Definition at line 814 of file pearl-data-explorer.ipf.

@@ -1810,7 +1811,7 @@ Variables
-

Definition at line 212 of file pearl-data-explorer.ipf.

+

Definition at line 213 of file pearl-data-explorer.ipf.

@@ -1840,7 +1841,7 @@ Variables

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.

-

Definition at line 184 of file pearl-data-explorer.ipf.

+

Definition at line 185 of file pearl-data-explorer.ipf.

@@ -1865,7 +1866,7 @@ Variables
-

Definition at line 39 of file pearl-data-explorer.ipf.

+

Definition at line 40 of file pearl-data-explorer.ipf.

@@ -1889,7 +1890,7 @@ Variables
-

Definition at line 41 of file pearl-data-explorer.ipf.

+

Definition at line 42 of file pearl-data-explorer.ipf.

@@ -1913,7 +1914,7 @@ Variables
-

Definition at line 42 of file pearl-data-explorer.ipf.

+

Definition at line 43 of file pearl-data-explorer.ipf.

@@ -1937,7 +1938,7 @@ Variables
-

Definition at line 40 of file pearl-data-explorer.ipf.

+

Definition at line 41 of file pearl-data-explorer.ipf.

@@ -1961,7 +1962,7 @@ Variables
-

Definition at line 36 of file pearl-data-explorer.ipf.

+

Definition at line 37 of file pearl-data-explorer.ipf.

@@ -1985,7 +1986,7 @@ Variables
-

Definition at line 37 of file pearl-data-explorer.ipf.

+

Definition at line 38 of file pearl-data-explorer.ipf.

@@ -1995,7 +1996,7 @@ Variables
-Go to the documentation of this file.
1 #pragma rtGlobals=3 // Use modern global access method and strict wave access.
2 #pragma IgorVersion = 6.1
3 #pragma ModuleName = PearlDataExplorer
4 #pragma version = 1.50
5 #include "pearl-area-import"
6 #include "pearl-area-profiles"
7 #include "pearl-area-display"
8 #include "pearl-pshell-import"
9 #if exists("MFR_OpenResultFile")
10 #include "pearl-matrix-import"
11 #endif
12 
13 // copyright (c) 2013-16 Paul Scherrer Institut
14 //
15 // Licensed under the Apache License, Version 2.0 (the "License");
16 // you may not use this file except in compliance with the License.
17 // You may obtain a copy of the License at
18 // http:///www.apache.org/licenses/LICENSE-2.0
19 
30 
35 
36 static strconstant package_name = "pearl_explorer"
37 static strconstant package_path = "root:packages:pearl_explorer:"
38 
39 static strconstant ks_filematch_adh5 = "*.h5"
40 static strconstant ks_filematch_pshell = "psh*.h5"
41 static strconstant ks_filematch_itx = "*.itx"
42 static strconstant ks_filematch_mtrx = "*_mtrx"
43 
45  init_package()
46  load_prefs()
47  execute /q/z "PearlDataExplorer()"
48 end
49 
55 static function init_package()
56 
57  dfref savefolder = GetDataFolderDFR()
58  SetDataFolder root:
59  newdatafolder /o/s packages
60  newdatafolder /o/s $package_name
61  if (exists("v_InitPanelDone") == 2)
62  SetDataFolder savefolder
63  return 0
64  endif
65 
66  make /o/n=0/t wtFiles
67  make /o/n=0/i wSelectedFiles,wSelectedDatasets
68  make /o/n=0/t wtDatasets
69  make /o/n=0/t wtPositioners,wtDetectors
70  make /o/n=0/i wSelectedPositioners,wSelectedDetectors
71 
72  make /o/n=(1,1) preview_image // preview 2D data
73  make /o/n=0 preview_trace // preview 1D data
74  make /o/n=0/t attr_names, attr_values, attr_filter, attr_filter_summary
75 
76  // persistent strings and variables. persistent = saved in preferences
77  string /g s_filepath = "" // directory path to be listed
78  string /g s_hdf_options = "" // recently used HDF5 load options
79  string /g s_reduction_params = "" // recently used reduction parameters
80  string /g s_preview_pvs = "" // semicolon-separated list of EPICS PVs to display in preview.
81  // the list items can contain wildcards for StringMatch
82  s_preview_pvs = "*OP:CURRENT*;*Stats*Total*;*KEITHLEY*READOUT;*CADC*"
83 
84  // non-persistent strings and variables
85  string /g s_preview_file = "" // file or folder name of the current preview
86  string /g s_preview_source = "" // data source, e.g. EPICS channel name, of the current preview
87  string /g s_profiles_graph = "" // window name of the current preview if the data is two-dimensional
88  string /g s_preview_trace_graph = "" // window name of the current preview if the data is one-dimensional
89  string /g s_file_info = "" // description of selected file
90 
91  variable/g v_InitPanelDone = 1
92 
93  SetDataFolder savefolder
94 end
95 
96 static function save_prefs()
97  // saves persistent package data to the preferences file
98  // the data saved in the file are: data file path, attributes filter
99  dfref saveDF = GetDataFolderDFR()
100 
101  string fullPath = SpecialDirPath("Packages", 0, 0, 0)
102  fullPath += package_name
103  NewPath/O/C/Q tempPackagePrefsPath, fullPath
104  fullPath += ":preferences.pxp"
105 
106  SetDataFolder root:packages
107  SetDataFolder $package_name
108  string objects = "attr_filter;attr_filter_summary;s_filepath;s_hdf_options;s_reduction_params;s_preview_pvs"
109  SaveData /O /Q /J=objects fullPath
110 
111  KillPath/Z tempPackagePrefsPath
112 
113  SetDataFolder saveDF
114 end
115 
116 static function load_prefs()
117  // loads persistent package data from the preferences file
118  // the preferences file is an Igor packed experiment file in a special preferences folder
119  dfref saveDF = GetDataFolderDFR()
120 
121  variable result = -1
122  setdatafolder root:
123  NewDataFolder /O/S packages
124  NewDataFolder /O/S $package_name
125  dfref packageDF = GetDataFolderDFR()
126  string fullPath = SpecialDirPath("Packages", 0, 0, 0)
127  fullPath += package_name
128 
129  GetFileFolderInfo /Q /Z fullPath
130  if (V_Flag == 0) // Disk directory exists?
131  fullPath += ":preferences.pxp"
132  GetFileFolderInfo /Q /Z fullPath
133  if (V_Flag == 0) // Preference file exist?
134  LoadData /O /R /Q fullPath
135  result = 0
136  endif
137  endif
138 
139  if (result == 0)
140  svar /sdfr=packageDF filepath = s_filepath
141  NewPath /O/Z pearl_explorer_filepath, filepath
144  endif
145 
146  SetDataFolder saveDF
147  return result
148 end
149 
161 static function pearl_file_type(filename)
162  string filename
163 
164  if (StringMatch(filename, ks_filematch_pshell))
165  return 1
166  elseif (StringMatch(filename, ks_filematch_adh5))
167  return 2
168  elseif (StringMatch(filename, ks_filematch_itx))
169  return 3
170 #if exists("MFR_OpenResultFile")
171  elseif (StringMatch(filename, ks_filematch_mtrx))
172  return 4
173 #endif
174  else
175  return 0
176  endif
177 end
178 
184 static function update_filelist()
185  dfref saveDF = GetDataFolderDFR()
186 
187  string all_files
188  wave /t wtFiles = $(package_path + "wtFiles")
189  wave wSelectedFiles = $(package_path + "wSelectedFiles")
190  variable nn
191 
192  PathInfo pearl_explorer_filepath
193  if (v_flag == 1)
194  all_files = IndexedFile(pearl_explorer_filepath, -1, "????")
195  nn = ItemsInList(all_files)
196  else
197  all_files = ""
198  nn = 0
199  endif
200 
201  make /n=(nn) /t /free wtAllFiles
202  wtAllFiles = StringFromList(p, all_files)
203  Extract /o /t wtAllFiles, wtFiles, pearl_file_type(wtAllFiles[p])
204  Sort /A /R wtFiles, wtFiles
205 
206  redimension /n=(numpnts(wtFiles)) wSelectedFiles
207  wSelectedFiles = 0
208 
209  setdatafolder saveDF
210 end
211 
212 static function update_datasets()
213  // updates the list of imported datasets.
214  // a dataset means any top-level data folder
215  // which includes a string variable named pearl_explorer_import.
216  dfref saveDF = GetDataFolderDFR()
217 
218  setdatafolder root:
219  dfref rootdf = GetDataFolderDFR()
220  setdatafolder $package_path
221  dfref privatedf = GetDataFolderDFR()
222 
223  wave /t wtDatasets
224  wave wSelectedDatasets
225  variable maxdf = CountObjectsDFR(rootdf, 4)
226  redimension /n=(maxdf) wtDatasets
227 
228  variable idf = 0
229  variable ndf = 0
230  string sdf
231 
232  do
233  sdf = GetIndexedObjNameDFR(rootdf, 4, idf)
234  if (strlen(sdf) >= 1)
235  setdatafolder rootdf
236  setdatafolder $sdf
237  svar /z importer = pearl_explorer_import
238  if (svar_exists(importer))
239  wtDatasets[ndf] = sdf
240  ndf += 1
241  endif
242  else
243  break
244  endif
245  idf += 1
246  while(1)
247 
248  redimension /n=(ndf) wtDatasets, wSelectedDatasets
249  wSelectedDatasets = 0
250  sort wtDatasets, wtDatasets
251 
252  setdatafolder saveDF
253 end
254 
255 static function preview_file(filename)
256  string filename
257 
258  dfref saveDF = GetDataFolderDFR()
259 
260  variable ft = pearl_file_type(filename)
261  switch(ft)
262  case 1:
263  wave /z image = preview_pshell_file(filename)
264  break
265  case 2:
266  wave /z image = preview_hdf_file(filename)
267  break
268  case 3:
269  wave /z image = preview_itx_file(filename)
270  break
271  case 4:
272  wave /z image = preview_mtrx_file(filename)
273  break
274  default:
275  wave /z image = $""
276  endswitch
277 
278  if (WaveExists(image))
279  string graphname = show_preview_graph(image)
280  // preset ELOG panel - if available
281  if (exists("PearlElog#set_panel_attributes") == 6)
282  string cmd
283  sprintf cmd, "PearlElog#set_panel_attributes(\"\", \"File=%s\")", ParseFilePath(0, filename, ":", 1, 0)
284  execute /Q/Z cmd
285  if (strlen(graphname) > 0)
286  sprintf cmd, "PearlElog#set_panel_graphs(\"\", \"%s\")", graphname
287  execute /Q/Z cmd
288  endif
289  endif
290  endif
291 
292  setdatafolder saveDF
293  return 0
294 end
295 
307 static function /wave preview_pshell_file(filename)
308  string filename
309 
310  dfref saveDF = GetDataFolderDFR()
311 
312  setdatafolder $package_path
313  dfref previewDF = GetDataFolderDFR()
314  svar s_preview_file
315  svar s_preview_source
316  svar /z s_file_info
317  if (! svar_exists(s_file_info))
318  string /g s_file_info
319  endif
320 
321  dfref tempDF = NewFreeDataFolder()
322  setdatafolder tempDF
323  string dataname
324  dataname = psh5_load_preview("pearl_explorer_filepath", filename)
325 
326  s_preview_file = filename
327  s_preview_source = ""
328 
329  wave /z data = $dataname
330  if (waveexists(data))
331  duplicate /o data, previewDF:preview_image
332  else
333  print "no data found in file " + filename
334  endif
335 
336  if (strlen(s_preview_file) > 0)
337  s_file_info = psh5_load_info("pearl_explorer_filepath", filename)
338  else
339  s_file_info = ""
340  endif
341 
342  dfref attrDF = tempDF:attr
343  if (DataFolderRefStatus(attrDF))
344  preview_attributes(attrDF)
345  endif
346 
347  setdatafolder saveDF
348  wave /z /sdfr=previewDF preview_image
349  return preview_image
350 end
351 
363 static function /wave preview_hdf_file(filename)
364  string filename
365 
366  dfref saveDF = GetDataFolderDFR()
367  setdatafolder $package_path
368  svar s_preview_file
369  svar s_preview_source
370  adh5_load_preview("preview_image", "pearl_explorer_filepath", filename)
371  s_preview_file = filename
372  s_preview_source = ""
373  wave /z preview_image
374 
375  svar /z s_file_info
376  if (! svar_exists(s_file_info))
377  string /g s_file_info
378  endif
379  if (strlen(s_preview_file) > 0)
380  s_file_info = adh5_load_info("pearl_explorer_filepath", filename)
381  else
382  s_file_info = ""
383  endif
384 
385  if (DataFolderExists("attr"))
386  setdatafolder attr
387  preview_attributes(GetDataFolderDFR())
388  setdatafolder ::
389  endif
390 
391  setdatafolder saveDF
392  return preview_image
393 end
394 
414 static function /wave preview_itx_file(filename)
415  string filename
416 
417  dfref saveDF = GetDataFolderDFR()
418  setdatafolder $package_path
419  svar s_preview_file
420  svar s_preview_source
421  wave preview_image
422 
423  dfref dataDF = newfreedatafolder()
424  setdatafolder dataDF
425  LoadWave /t/p=pearl_explorer_filepath/q filename
426  s_preview_file = s_filename
427  s_preview_source = ""
428 
430  preview_attributes(dataDF, include_datawaves=0)
431 
432  setdatafolder saveDF
433  return preview_image
434 end
435 
450 static function /wave preview_mtrx_file(filename)
451  string filename
452 
453 #if exists("MFR_OpenResultFile")
454  dfref saveDF = GetDataFolderDFR()
455  setdatafolder $package_path
456  variable /g V_MatrixFileReaderOverwrite = 1
457  variable /g V_MatrixFileReaderFolder = 0
458  variable /g V_MatrixFileReaderDouble = 0
459  svar s_preview_file
460  svar s_preview_source
461  string datanames
462  string dataname
463  datanames = mtrx_load_preview("preview", "pearl_explorer_filepath", filename)
464  if (strlen(datanames) > 0)
465  s_preview_file = filename
466 
467  dataname = StringFromList(0, datanames)
468  wave data = $dataname
469  duplicate /o $dataname, preview_image
470  s_preview_source = StringByKey("Dataset", note(data), "=", "\r")
471 
472  svar /z s_file_info
473  if (svar_exists(s_file_info))
474  s_file_info = ""
475  endif
476 
477  variable i
478  variable n = ItemsInList(datanames)
479  string s
480  for (i = 0; i < n; i += 1)
481  s = StringFromList(i, datanames)
482  killwaves /z $s
483  endfor
484  endif
485  wave /z preview_image
486  setdatafolder saveDF
487 #else
488  wave /z preview_image = $""
489 #endif
490  return preview_image
491 end
492 
493 static function extract_preview_image(data, preview)
494  // extracts a preview image from a wave of arbitrary dimension
495  wave data
496  wave preview
497 
498  variable z1, z2
499 
500  // extract image
501  switch (WaveDims(data))
502  case 1:
503  redimension /n=(numpnts(data)) preview
504  preview = data[p]
505  break
506  case 2:
507  redimension /n=(dimsize(data, 0), dimsize(data, 1)) preview
508  preview = data
509  break
510  case 3:
511  redimension /n=(dimsize(data, 0), dimsize(data, 1)) preview
512  z1 = floor(DimSize(data, 2) / 2)
513  z2 = z1
514  wave slab = ad_extract_slab(data, nan, nan, nan, nan, z1, z2, "", pscale=1)
515  preview = slab
516  break
517  case 4:
518  // not implemented
519  endswitch
520 
521  switch (WaveDims(data))
522  case 4:
523  case 3:
524  case 2:
525  setscale /p y dimoffset(data, 1), dimdelta(data, 1), waveunits(data, 1), preview
526  case 1:
527  setscale /p x dimoffset(data, 0), dimdelta(data, 0), waveunits(data, 0), preview
528  setscale d 0, 0, waveunits(data, -1), preview
529  endswitch
530 end
531 
532 static function preview_dataset(datasetname)
533  string datasetname // name of a data folder under root
534 
535  dfref saveDF = GetDataFolderDFR()
536 
537  if (!DataFolderExists("root:" + datasetname))
538  return -1
539  endif
540  setdatafolder root:
541  setdatafolder $datasetname
542  dfref datadf = GetDataFolderDFR()
543  wave /z data
544 
545  setdatafolder $package_path
546  svar s_preview_file
547  svar s_preview_source
548  wave preview_image
549  if (WaveExists(data))
550  s_preview_file = datasetname
551  s_preview_source = ""
552  extract_preview_image(data, preview_image)
553  show_preview_graph(preview_image)
554  else
555  preview_image = nan
556  s_preview_file = datasetname
557  setdatafolder datadf
559  show_preview_graph(preview_image)
560  endif
561 
562  // attributes
563  setdatafolder datadf
564  if (DataFolderExists("attr"))
565  setdatafolder attr
566  preview_attributes(GetDataFolderDFR())
567  else
568  preview_attributes(GetDataFolderDFR(), include_datawaves=0)
569  endif
570 
571  setdatafolder saveDF
572  return 0
573 end
574 
575 static function preview_datafolder()
576  // preview data in the current data folder
577  dfref saveDF = GetDataFolderDFR()
578 
579  setdatafolder $package_path
580  svar s_preview_file
581  svar s_preview_source
582  svar s_preview_pvs
583  wave preview_image
584 
585  setdatafolder saveDF
586 
587  // select a wave to display
588  // consider only double-precision waves, i.e. ignore text and other special waves
589  // filter by matching PV name to s_preview_pvs
590  string d_names = WaveList("*", ";", "DP:1")
591  variable nw = ItemsInList(d_names, ";")
592  variable npv = ItemsInList(s_preview_pvs, ";")
593  variable iw, ipv
594  string wname, wnote, pv_name, pv_match
595  for (iw = 0; iw < nw; iw += 1)
596  wname = StringFromList(iw, d_names, ";")
597  wnote = note($wname)
598  pv_name = StringByKey("PV", wnote, "=", "\r")
599  // find matching data wave by PV name
600  for (ipv = 0; ipv < npv; ipv += 1)
601  pv_match = StringFromList(ipv, s_preview_pvs)
602  if (StringMatch(pv_name, pv_match))
603  wave data = $wname
604  s_preview_source = pv_name
605  extract_preview_image(data, preview_image)
606  preview_setscale_x(data, preview_image)
607  npv = 0
608  nw = 0
609  endif
610  endfor
611  endfor
612 
613  setdatafolder saveDF
614 end
615 
616 static function preview_setscale_x(data, preview)
617  // sets the approximate x scale of OTF data.
618  // requires an Axis1 tag with name of x wave in the wave note.
619  // if any of these conditions is true, the function does not change the scaling:
620  // 1) Axis1 tag or referenced wave is missing.
621  // 2) preview wave is not set to point scaling.
622  // 3) x wave is not monotonic (90% of the steps in the same direction).
623  wave data
624  wave preview
625 
626  if ((DimOffset(preview, 0) == 0) && (DimDelta(preview, 0) == 1))
627  string xname = StringByKey("Axis1", note(data), "=", "\r")
628  wave /z xwave = $xname
629  if (WaveExists(xwave))
630  // check for monotonicity
631  variable monotonic = 0
632  duplicate /free xwave, xdiff
633  differentiate /p xwave /D=xdiff
634  duplicate /free xdiff, xflag
635  xflag = xdiff > 0
636  monotonic = sum(xflag) > numpnts(xwave) * 0.9
637  xflag = xdiff < 0
638  monotonic = monotonic || (sum(xflag) > numpnts(xwave) * 0.9)
639  if (monotonic)
640  setscale /i x xwave[0], xwave[numpnts(xwave)-1], waveunits(xwave, -1), preview
641  endif
642  endif
643  endif
644 end
645 
646 static function preview_attributes(attr_folder, [dest_folder, attr_filter, include_datawaves, include_infowaves])
647  // copies the first elements of attributes in the specified folder to the preview waves
648  // by default, all existing attributes are copied
649  // if a text wave attr_filter exists in the pear_explorer folder, only the attributes referenced therein are copied
650  // to set up a filter, duplicate the attr_names wave of a template dataset, and remove unwanted items
651  dfref attr_folder // data folder which contains the attribute waves
652  dfref dest_folder // destination folder. the output is written to the attr_names and attr_values waves
653  // default = package folder
654  wave /t attr_filter // list of attributes allowed in the output
655  // default = use attr_filter of package folder
656  variable include_datawaves // 1 (default) = include data waves (any numeric wave which has a PV=name note)
657  // 0 = don't include attributes from data waves
658  variable include_infowaves // 1 (default) = include attributes from info waves (IN, ID, IV, IU)
659  // 0 = don't include attributes from info waves
660 
661  dfref saveDF = GetDataFolderDFR()
662  setdatafolder $package_path
663 
664  if (ParamIsDefault(dest_folder))
665  dest_folder = GetDataFolderDFR() // package folder
666  endif
667  if (ParamIsDefault(attr_filter))
668  wave /t /z attr_filter
669  endif
670  if (ParamIsDefault(include_datawaves))
671  include_datawaves = 1
672  endif
673  if (ParamIsDefault(include_infowaves))
674  include_infowaves = 1
675  endif
676 
677  setdatafolder dest_folder
678  wave /t /z attr_names, attr_values
679  if (!WaveExists(attr_names) || !WaveExists(attr_values))
680  make /n=(1) /o /t attr_names, attr_values
681  endif
682  attr_names = ""
683  attr_values = ""
684 
685  setdatafolder attr_folder
686  wave /t /z IN
687  wave /t /z ID
688  wave /t /z IV
689  wave /t /z IU
690 
691  // compile list of attributes
692  variable nattr // destination attributes
693  variable iattr
694  variable ninfo // info wave elements
695  variable iinfo
696  variable nw // attribute waves
697  variable iw
698  string sw
699  string ss
700 
701  if (WaveExists(IN) && include_infowaves)
702  ninfo = numpnts(IN)
703  else
704  ninfo = 0
705  endif
706  if (include_datawaves)
707  string waves = WaveList("*", ";", "")
708  string exceptions = "ID;IN;IU;IV"
709  waves = RemoveFromList(exceptions, waves)
710  nw = ItemsInList(waves, ";")
711  else
712  nw = 0
713  endif
714 
715  if (WaveExists(attr_filter) && (numpnts(attr_filter) >= 1))
716  nattr = numpnts(attr_filter)
717  redimension /n=(nattr) attr_names
718  attr_names = attr_filter
719  else
720  if(ninfo > 0)
721  redimension /n=(ninfo) attr_names
722  attr_names = SelectString(strlen(ID[p]) >= 0, IN[p], ID[p]) // use ID unless empty
723  endif
724 
725  nattr = ninfo + nw
726  iattr = ninfo
727  redimension /n=(nattr) attr_names
728  for (iw = 0; iw < nw; iw +=1 )
729  sw = StringFromList(iw, waves, ";")
730  ss = StringByKey("PV", note($sw), "=", "\r")
731  FindValue /text=sw attr_names
732  if ((v_value < 0) && (strlen(ss) >= 0))
733  attr_names[iattr] = sw
734  iattr += 1
735  endif
736  endfor
737  nattr = iattr
738  endif
739  redimension /n=(nattr) attr_names, attr_values
740  sort attr_names, attr_names
741 
742  // look up attribute values
743  for (iattr = 0; iattr < nattr; iattr += 1)
744  sw = attr_names[iattr]
745  // try info waves
746  if (ninfo > 0)
747  FindValue /text=sw ID
748  if (v_value >= 0)
749  attr_values[iattr] = IV[v_value]
750  endif
751  FindValue /text=sw IN
752  if (v_value >= 0)
753  attr_values[iattr] = IV[v_value]
754  endif
755  endif
756 
757  // override from attribute wave if existent
758  if (nw > 0)
759  switch (WaveType($sw, 1))
760  case 1: // numeric
761  wave /z w = $sw
762  if (WaveExists(w) && (numpnts(w) >= 1))
763  sprintf ss, "%g", w[0]
764  attr_values[iattr] = ss
765  endif
766  break
767  case 2: // text
768  wave /t/z wt = $sw
769  if (WaveExists(wt) && (numpnts(wt) >= 1))
770  attr_values[iattr] = wt[0]
771  endif
772  break
773  endswitch
774  endif
775  endfor
776 
777  setdatafolder saveDF
778 end
779 
780 static function display_dataset(datasetname)
781  // displays the graph of a loaded dataset in its own window
782  string datasetname // name of a data folder under root
783 
784  dfref saveDF = GetDataFolderDFR()
785 
786  if (!DataFolderExists("root:" + datasetname))
787  return -1
788  endif
789  setdatafolder root:
790  setdatafolder $datasetname
791  dfref datadf = GetDataFolderDFR()
792  wave /z data
793  if (!WaveExists(data))
794  wave /z data = data1
795  endif
796 
797  if (WaveExists(data))
798  switch(WaveDims(data))
799  case 2:
800  ad_display_profiles(data)
801  break
802  case 3:
803  ad_display_slice(data)
804  ad_brick_slicer(data)
805  break
806  endswitch
807  endif
808 
809  setdatafolder saveDF
810  return 0
811 end
812 
814  dfref df = GetDataFolderDFR()
815  wave /t /sdfr=df attr_names
816  wave /t /sdfr=df attr_values
817  attributes_notebook(attr_names, attr_values, GetDataFolder(0))
818 end
819 
820 static function attributes_notebook(attr_names, attr_values, title)
821  wave /t attr_names
822  wave /t attr_values
823  string title
824 
825  dfref saveDF = GetDataFolderDFR()
826  setdatafolder $package_path
827  wave /t/z attr_filter, attr_filter_summary
828 
829  string name = CleanupName("nb_" + title[0,28], 0)
830  if (WinType(name) == 5)
831  Notebook $name selection={startOfFile, endOfFile}
832  Notebook $name text=""
833  else
834  NewNotebook /F=1 /K=1 /N=$name as title
835  GetWindow $name wsize
836  v_right = v_left + 260
837  v_bottom = v_top + 360
838  MoveWindow /W=$name v_left, v_top, v_right, v_bottom
839  Notebook $name tabs={2*72}
840  endif
841 
842  // summary
843  if (WaveExists(attr_filter_summary) && (numpnts(attr_filter_summary) >= 1))
844  notebook $name fStyle=1, text="Summary\r\r"
845  notebook $name fStyle=0
846  notebook_add_attributes(name, attr_filter_summary, attr_names, attr_values)
847  notebook $name text="\r"
848  endif
849 
850  // all attributes
851  notebook $name fStyle=1, text="All Attributes\r\r"
852  notebook $name fStyle=0
853  notebook_add_attributes(name, $"", attr_names, attr_values)
854  notebook $name selection={startOfFile,startOfFile}, findText={"",1}
855 
856  setdatafolder saveDF
857 end
858 
859 static function notebook_add_attributes(notebook_name, attr_filter, attr_names, attr_values)
860  string notebook_name
861  wave /t /z attr_filter
862  wave /t attr_names
863  wave /t attr_values
864 
865  variable nw = numpnts(attr_names)
866  variable iw
867  string sw
868  string ss
869 
870  variable do_filter = WaveExists(attr_filter)
871 
872  for (iw = 0; iw < nw; iw += 1)
873  if (do_filter)
874  sw = attr_names[iw]
875  FindValue /text=sw attr_filter
876  else
877  v_value = 0
878  endif
879  if (v_value >= 0)
880  sprintf ss, "%s\t%s\r", attr_names[iw], attr_values[iw]
881  notebook $notebook_name text=ss
882  endif
883  endfor
884 end
885 
886 static function /s show_preview_graph(data, [xdata])
887  // displays a preview of one- or two-dimensional data
888  wave data // data to be displayed. must either one-dimensional or two-dimensional
889  wave xdata // positions on x axis
890 
891  dfref saveDF = GetDataFolderDFR()
892  setdatafolder $package_path
893 
894  svar s_profiles_graph
895  svar s_preview_file
896  svar s_preview_source
897  svar s_preview_trace_graph
898 
899  if ((strlen(s_profiles_graph) > 0) && (WinType(s_profiles_graph) == 1))
900  KillWindow $s_profiles_graph
901  endif
902  if ((strlen(s_preview_trace_graph) > 0) && (WinType(s_preview_trace_graph) == 1))
903  KillWindow $s_preview_trace_graph
904  endif
905 
906  string graphname
907  if (wavedims(data) == 2)
908  s_profiles_graph = ad_display_profiles(data)
909  ModifyGraph /w=$s_profiles_graph /z wbRGB=(48640,56832,60160)
910  graphname = s_profiles_graph
911  elseif (wavedims(data) == 1)
912  duplicate /o data, preview_trace
913  if (!ParamIsDefault(xdata))
914  duplicate /o xdata, preview_trace_x
915  else
916  duplicate /o data, preview_trace_x
917  preview_trace_x = x
918  setscale d 0, 0, WaveUnits(data, 0), preview_trace_x
919  endif
920  s_preview_trace_graph = display_preview_trace(preview_trace_x, preview_trace)
921  ModifyGraph /w=$s_preview_trace_graph wbRGB=(48640,56832,60160)
922  graphname = s_preview_trace_graph
923  else
924  return ""
925  endif
926 
927  string title = "Preview " + s_preview_file
928  if (strlen(s_preview_source) > 0)
929  title = title + " (" + s_preview_source[0,31] + ")"
930  endif
931  dowindow /f/t $graphname, title
932 
933  setdatafolder saveDF
934  return graphname
935 end
936 
937 static function /s display_preview_trace(xtrace, ytrace)
938  wave xtrace
939  wave ytrace
940 
941  display /n=pearl_explorer_1d /k=1 ytrace vs xtrace as "Preview"
942  string graphname = s_name
943  ModifyGraph /w=$graphname rgb[0]=(0,0,0)
944  ModifyGraph /w=$graphname grid=2
945  ModifyGraph /w=$graphname mirror=1
946  ModifyGraph /w=$graphname minor=1
947  ModifyGraph /w=$graphname axThick=0.5
948  ModifyGraph /w=$graphname gridRGB=(52224,52224,52224)
949  ModifyGraph /w=$graphname gridHair=0
950  ModifyGraph /w=$graphname tick=0
951  ModifyGraph /w=$graphname btLen=4
952 
953  // axis labels
954  string labels = note(ytrace)
955  string lab
956  lab = StringByKey("AxisLabelX", labels, "=", "\r")
957  if (!strlen(lab))
958  lab = "X"
959  endif
960  Label /w=$graphname bottom lab + " (\\U)"
961  lab = StringByKey("AxisLabelD", labels, "=", "\r")
962  if (!strlen(lab))
963  lab = "value"
964  endif
965  Label /w=$graphname left lab + " (\\U)"
966 
967  return s_name
968 end
969 
970 static function load_selected_files([options])
971  string options
972 
973  dfref saveDF = GetDataFolderDFR()
974  setdatafolder $package_path
975 
976  wave wSelectedFiles
977  wave/t wtFiles
978  variable nn = numpnts(wSelectedFiles)
979  variable ii
980  for (ii = 0; ii < nn; ii += 1)
981  if (wSelectedFiles[ii])
982  if (ParamIsDefault(options))
983  load_file(wtFiles[ii])
984  else
985  load_file(wtFiles[ii], options=options)
986  endif
987  endif
988  endfor
989 
991  setdatafolder saveDF
992 end
993 
994 static function load_file(filename, [options])
995  string filename
996  string options
997 
998  dfref saveDF = GetDataFolderDFR()
999 
1000  variable ft = pearl_file_type(filename)
1001  switch(ft)
1002  case 1:
1003  if (ParamIsDefault(options))
1004  load_pshell_file(filename)
1005  else
1006  load_pshell_file(filename, options=options)
1007  endif
1008  break
1009  case 2:
1010  if (ParamIsDefault(options))
1011  load_hdf_file(filename)
1012  else
1013  load_hdf_file(filename, options=options)
1014  endif
1015  break
1016  case 3:
1017  load_itx_file(filename)
1018  break
1019  case 4:
1020  load_mtrx_file(filename)
1021  break
1022  default:
1023  break
1024  endswitch
1025 
1026  setdatafolder saveDF
1027 end
1028 
1029 static function prompt_hdf_options(options)
1030  string &options
1031 
1032  string mode = StringByKey("mode", options, ":", ";")
1033  string reduction_func = StringByKey("reduction_func", options, ":", ";")
1034 
1035  string modes = "load_reduced"
1036  string reduction_functions = adh5_list_reduction_funcs()
1037 
1038  if (strlen(mode) == 0)
1039  mode = StringFromList(0, modes, ";")
1040  endif
1041  if (strlen(reduction_func) == 0)
1042  reduction_func = StringFromList(0, reduction_functions, ";")
1043  endif
1044 
1045  prompt mode, "Mode", popup, modes
1046  prompt reduction_func, "Reduction Function", popup, reduction_functions
1047  doprompt "HDF5 Loading Options", mode, reduction_func
1048 
1049  if (v_flag == 0)
1050  options = ReplaceStringByKey("mode", options, mode, ":", ";")
1051  options = ReplaceStringByKey("reduction_func", options, reduction_func, ":", ";")
1052  endif
1053  return v_flag // 0 = OK, 1 = cancel
1054 end
1055 
1068 function prompt_default_process(param)
1069  string &param
1070 
1071  return 0
1072 end
1073 
1074 function prompt_func_params(func_name, func_param)
1075  string func_name
1076  string &func_param
1077 
1078  string prompt_name = "prompt_" + func_name
1079  if (exists(prompt_name) == 6)
1080  funcref prompt_default_process prompt_func = $prompt_name
1081  return prompt_func(func_param)
1082  else
1083  // ignore missing prompt function
1084  return 0
1085  endif
1086 end
1087 
1088 static function /df load_pshell_file(filename, [options])
1089  string filename
1090  string options
1091 
1092  dfref saveDF = GetDataFolderDFR()
1093  string nickname = ad_suggest_foldername(filename)
1094  string loaded_filename = ""
1095 
1096  if (ParamIsDefault(options))
1097  loaded_filename = psh5_load_complete(nickname, "pearl_explorer_filepath", filename)
1098  else
1099  if (strlen(options) == 0)
1100  svar pref_options = $(package_path + "s_hdf_options")
1101  options = pref_options
1102  if (prompt_hdf_options(options) == 0)
1103  // OK
1104  pref_options = options
1105  else
1106  // cancel
1107  options = ""
1108  endif
1109  endif
1110 
1111  string mode = StringByKey("mode", options, ":", ";")
1112 
1113  strswitch(mode)
1114  case "load_reduced":
1115  string reduction_func = StringByKey("reduction_func", options, ":", ";")
1116  svar pref_params = $(package_path + "s_reduction_params")
1117  string reduction_params = pref_params
1118  if (prompt_func_params(reduction_func, reduction_params) == 0)
1119  pref_params = reduction_params
1120  print reduction_func, reduction_params
1121  psh5_load_reduced(nickname, "pearl_explorer_filepath", filename, $reduction_func, reduction_params)
1122  svar s_filepath
1123  loaded_filename = s_filepath
1124  endif
1125  break
1126  endswitch
1127  endif
1128 
1129  dfref dataDF
1130  if (strlen(loaded_filename) > 0)
1131  setdatafolder $("root:" + nickname)
1132  dataDF = GetDataFolderDFR()
1133  string /g pearl_explorer_import = "load_pshell_file"
1134  endif
1135 
1136  setdatafolder saveDF
1137  return dataDF
1138 end
1139 
1140 static function /df load_hdf_file(filename, [options])
1141  string filename
1142  string options
1143 
1144  dfref saveDF = GetDataFolderDFR()
1145  string nickname = ad_suggest_foldername(filename)
1146  string loaded_filename = ""
1147 
1148  if (ParamIsDefault(options))
1149  loaded_filename = adh5_load_complete(nickname, "pearl_explorer_filepath", filename)
1150  else
1151  if (strlen(options) == 0)
1152  svar pref_options = $(package_path + "s_hdf_options")
1153  options = pref_options
1154  if (prompt_hdf_options(options) == 0)
1155  // OK
1156  pref_options = options
1157  else
1158  // cancel
1159  options = ""
1160  endif
1161  endif
1162 
1163  string mode = StringByKey("mode", options, ":", ";")
1164 
1165  strswitch(mode)
1166  case "load_reduced":
1167  string reduction_func = StringByKey("reduction_func", options, ":", ";")
1168  svar pref_params = $(package_path + "s_reduction_params")
1169  string reduction_params = pref_params
1170  if (prompt_func_params(reduction_func, reduction_params) == 0)
1171  pref_params = reduction_params
1172  print reduction_func, reduction_params
1173  loaded_filename = adh5_load_reduced(nickname, "pearl_explorer_filepath", filename, $reduction_func, reduction_params)
1174  endif
1175  break
1176  endswitch
1177  endif
1178 
1179  dfref dataDF
1180  if (strlen(loaded_filename) > 0)
1181  setdatafolder $("root:" + nickname)
1182  dataDF = GetDataFolderDFR()
1183  string /g pearl_explorer_import = "load_hdf_file"
1184  endif
1185 
1186  setdatafolder saveDF
1187  return dataDF
1188 end
1189 
1190 static function /df load_itx_file(filename, [options])
1191  string filename
1192  string options
1193 
1194  dfref saveDF = GetDataFolderDFR()
1195  string nickname = itx_suggest_foldername(filename)
1196 
1197  if (ParamIsDefault(options))
1198  options = ""
1199  endif
1200 
1201  setdatafolder root:
1202  newdatafolder /s/o $("root:" + nickname)
1203  dfref dataDF = GetDataFolderDFR()
1204 
1205  // note: some versions of PEARL data files save data to a new data folder,
1206  // and leave the newly created folder as the current folder.
1207  // the free data folder is used by those files which don't create their own data folder.
1208  // this is the new recommended behaviour
1209 
1210  LoadWave /t/p=pearl_explorer_filepath/q filename
1211  svar waves = s_wavenames
1212  dfref actDF = GetDataFolderDFR()
1213  if (v_flag > 0)
1214  string /g pearl_explorer_import = "load_itx_file"
1215  endif
1216 
1217  if (!DataFolderRefsEqual(actDF, dataDF))
1218  // the file created its own data folder.
1219  // let's kill the pre-allocated folder
1220  setdatafolder dataDF
1221  if (ItemsInList(WaveList("*", ";", ""), ";") == 0)
1222  killdatafolder /z dataDF
1223  endif
1224  endif
1225 
1226  setdatafolder saveDF
1227  return actDF
1228 end
1229 
1233 static function /df load_mtrx_file(filename, [options])
1234  string filename
1235  string options
1236 
1237  dfref saveDF = GetDataFolderDFR()
1238  dfref dataDF = $""
1239 
1240 #if exists("MFR_OpenResultFile")
1241  setdatafolder root:
1242  string datasets = ""
1243  datasets = mtrx_load_file("pearl_explorer_filepath", filename)
1244  if (strlen(datasets) > 0)
1245  string /g pearl_explorer_import = "load_mtrx_file"
1246  string s1 = StringFromList(0, datasets)
1247  wave w1 = $s1
1248  dataDF = GetWavesDataFolderDFR(w1)
1249  endif
1250 #endif
1251 
1252  setdatafolder saveDF
1253  return dataDF
1254 end
1255 
1256 function /s itx_suggest_foldername(filename, [ignoredate,sourcename,unique])
1257  // suggests the name of a data folder based on a file name
1258  // if the file name follows the naming convention source-date-index.extension,
1259  // the function tries to generate the nick name as source_date_index.
1260  // otherwise it's just a cleaned up version of the file name.
1261  string filename // file name, including extension. can also include a folder path (which is ignored)
1262  // the extension is currently ignored, but may be used later to select the parent folder
1263  variable ignoredate // if non-zero, the nick name will not include the date part
1264  // defaults to zero
1265  string sourcename // nick name of the data source
1266  // the function tries to detect the source from the file name
1267  // this option can be used to override auto-detection
1268  // allowed values: sscan, otf
1269  variable unique // if non-zero, the resulting name is made a unique data folder name in the current data folder
1270  // defaults to zero
1271 
1272  if (ParamIsDefault(ignoredate))
1273  ignoredate = 0
1274  endif
1275  if (ParamIsDefault(unique))
1276  unique = 0
1277  endif
1278 
1279  string basename = ParseFilePath(3, filename, ":", 0, 0)
1280  string extension = ParseFilePath(4, filename, ":", 0, 0)
1281  string nickname
1282 
1283  string autosource
1284  if (strsearch(basename, "X03DA_PC", 0, 2) >= 0)
1285  autosource = "sscan"
1286  basename = ReplaceString("_", basename, "-")
1287  ignoredate = 1
1288  elseif (strsearch(basename, "otf", 0, 2) >= 0)
1289  autosource = "otf"
1290  endif
1291  if (ParamIsDefault(sourcename))
1292  sourcename = autosource
1293  endif
1294 
1295  variable nparts = ItemsInList(basename, "-")
1296  if (nparts >= 3)
1297  string datepart = StringFromList(nparts - 2, basename, "-")
1298  string indexpart = StringFromList(nparts - 1, basename, "-")
1299  if (ignoredate)
1300  sprintf nickname, "%s_%s", sourcename, indexpart
1301  else
1302  sprintf nickname, "%s_%s_%s", sourcename, datepart, indexpart
1303  endif
1304  else
1305  nickname = CleanupName(basename, 0)
1306  endif
1307 
1308  if (unique && CheckName(nickname, 11))
1309  nickname = UniqueName(nickname + "_", 11, 0)
1310  endif
1311 
1312  return nickname
1313 end
1314 
1315 Window PearlDataExplorer() : Panel
1316  PauseUpdate; Silent 1 // building window...
1317  NewPanel /K=1 /W=(800,0,1530,444) as "PEARL Data Explorer"
1318  ModifyPanel cbRGB=(48640,56832,60160)
1319 
1320  GroupBox gb_filepath,pos={8,4},size={224,52},title="file system folder"
1321  TitleBox tb_filepath,pos={20,24},size={174,20},frame=2
1322  TitleBox tb_filepath,variable=root:packages:pearl_explorer:s_filepath,fixedSize=1
1323  Button b_browse_filepath,pos={200,24},size={20,20},proc=PearlDataExplorer#bp_browse_filepath,title="..."
1324  Button b_browse_filepath,fColor=(65280,48896,32768)
1325 
1326  GroupBox gb_prefs,pos={240,4},size={58,52},title="prefs",help={"explorer package preferences"}
1327  Button b_save_prefs,pos={252,20},size={32,17},proc=PearlDataExplorer#bp_save_prefs,title="save"
1328  Button b_save_prefs,help={"save preferences of the data explorer package (data file path, attributes filter)"}
1329  Button b_save_prefs,fColor=(65280,48896,32768)
1330  Button b_load_prefs,pos={252,36},size={32,17},proc=PearlDataExplorer#bp_load_prefs,title="load"
1331  Button b_load_prefs,help={"load preferences of the data explorer package"}
1332  Button b_load_prefs,fColor=(65280,48896,32768)
1333 
1334  GroupBox gb_filelist,pos={8,64},size={224,372},title="data files"
1335  ListBox lb_files,pos={20,84},size={200,212},proc=PearlDataExplorer#lbp_filelist
1336  ListBox lb_files,listWave=root:packages:pearl_explorer:wtFiles
1337  ListBox lb_files,selWave=root:packages:pearl_explorer:wSelectedFiles,row= 11,mode= 4
1338  TitleBox tb_file_info,pos={20,300},size={198,78},frame=2,fixedSize=1
1339  TitleBox tb_file_info,variable= root:packages:pearl_explorer:s_file_info
1340 
1341  Button b_update_filelist,pos={20,386},size={60,20},proc=PearlDataExplorer#bp_update_filelist,title="update list"
1342  Button b_update_filelist,fColor=(65280,48896,32768)
1343  CheckBox cb_file_preview,pos={84,390},size={60,20},title="preview"
1344  CheckBox cb_file_preview,help={"enable/disable automatic preview window when selecting a data file"}
1345  CheckBox cb_file_preview,value=1
1346  Button b_file_prev,pos={176,386},size={20,20},proc=PearlDataExplorer#bp_file_prev,title="\\W646"
1347  Button b_file_prev,help={"previous file"}
1348  Button b_file_prev,fColor=(65280,48896,32768)
1349  Button b_file_next,pos={200,386},size={20,20},proc=PearlDataExplorer#bp_file_next,title="\\W649"
1350  Button b_file_next,help={"next file"}
1351  Button b_file_next,fColor=(65280,48896,32768)
1352 
1353  Button b_load_files,pos={20,410},size={76,20},proc=PearlDataExplorer#bp_load_files,title="load complete"
1354  Button b_load_files,help={"load the complete contents from the selected files"}
1355  Button b_load_files,fColor=(65280,48896,32768)
1356  Button b_load_files_opt,pos={100,410},size={76,20},proc=PearlDataExplorer#bp_load_files_opt,title="load reduced"
1357  Button b_load_files_opt,help={"load data from the selected files with options (reduced dimensions)"}
1358  Button b_load_files_opt,fColor=(65280,48896,32768)
1359 
1360  // datasets group
1361  GroupBox gb_datasets,pos={240,64},size={224,372},title="datasets"
1362  ListBox lb_datasets,pos={252,84},size={200,300},proc=PearlDataExplorer#lbp_datasets,help={"list of loaded datasets"}
1363  ListBox lb_datasets,listWave=root:packages:pearl_explorer:wtDatasets
1364  ListBox lb_datasets,selWave=root:packages:pearl_explorer:wSelectedDatasets,mode= 1
1365  ListBox lb_datasets,selRow= -1
1366 
1367  Button b_update_datasets,pos={252,386},size={60,20},proc=PearlDataExplorer#bp_update_datasets,title="update list"
1368  Button b_update_datasets,help={"update the list of datasets"}
1369  Button b_update_datasets,fColor=(65280,48896,32768)
1370  CheckBox cb_dataset_preview,pos={316,390},size={60,20},title="preview"
1371  CheckBox cb_dataset_preview,help={"enable/disable automatic preview window when selecting a dataset"}
1372  CheckBox cb_dataset_preview,value=0
1373  Button b_dataset_prev,pos={408,386},size={20,20},proc=PearlDataExplorer#bp_dataset_prev,title="\\W646"
1374  Button b_dataset_prev,help={"goto previous dataset"}
1375  Button b_dataset_prev,fColor=(65280,48896,32768)
1376  Button b_dataset_next,pos={432,386},size={20,20},proc=PearlDataExplorer#bp_dataset_next,title="\\W649"
1377  Button b_dataset_next,help={"goto next dataset"}
1378  Button b_dataset_next,fColor=(65280,48896,32768)
1379 
1380  Button b_dataset_folder,pos={252,410},size={50,20},proc=PearlDataExplorer#bp_dataset_folder,title="goto DF"
1381  Button b_dataset_folder,help={"set the current data folder of the selected dataset"}
1382  Button b_dataset_folder,fColor=(65280,48896,32768)
1383  Button b_dataset_display,pos={306,410},size={50,20},proc=PearlDataExplorer#bp_dataset_display,title="display"
1384  Button b_dataset_display,help={"display the selected dataset in its own window"}
1385  Button b_dataset_display,fColor=(65280,48896,32768)
1386 
1387  GroupBox gb_preview,pos={472,4},size={250,52},title="preview"
1388  TitleBox tb_preview_file,pos={484,24},size={226,20},frame=2
1389  TitleBox tb_preview_file,variable=root:packages:pearl_explorer:s_preview_file,fixedSize=1
1390 
1391  GroupBox gb_attributes,pos={472,64},size={250,372},title="attributes"
1392  Button b_attr_notebook,pos={484,386},size={60,20},proc=PearlDataExplorer#bp_attr_notebook,title="notebook"
1393  Button b_attr_notebook,help={"show attribute list in a notebook"}
1394  Button b_attr_notebook,fColor=(65280,48896,32768)
1395 
1396  String fldrSav0= GetDataFolder(1)
1397  SetDataFolder root:packages:pearl_explorer:
1398  Edit/W=(484,84,710,384)/HOST=# attr_names,attr_values
1399  ModifyTable format(Point)=1,width(Point)=0,width(attr_names)=103,width(attr_values)=103
1400  ModifyTable statsArea=85
1401  SetDataFolder fldrSav0
1402  RenameWindow #,T0
1403  SetActiveSubwindow ##
1404 EndMacro
1405 
1406 static function bp_load_prefs(ba) : ButtonControl
1407  STRUCT WMButtonAction &ba
1408 
1409  switch( ba.eventCode )
1410  case 2: // mouse up
1411  load_prefs()
1412  break
1413  case -1: // control being killed
1414  break
1415  endswitch
1416 
1417  return 0
1418 End
1419 
1420 static function bp_save_prefs(ba) : ButtonControl
1421  STRUCT WMButtonAction &ba
1422 
1423  switch( ba.eventCode )
1424  case 2: // mouse up
1425  save_prefs()
1426  break
1427  case -1: // control being killed
1428  break
1429  endswitch
1430 
1431  return 0
1432 End
1433 
1434 static function bp_browse_filepath(ba) : ButtonControl
1435  STRUCT WMButtonAction &ba
1436 
1437  dfref saveDF = GetDataFolderDFR()
1438 
1439  switch( ba.eventCode )
1440  case 2: // mouse up
1441  PathInfo /S pearl_explorer_filepath
1442  NewPath /M="select data file folder" /O/Z pearl_explorer_filepath
1443  if (v_flag == 0)
1444  PathInfo /S pearl_explorer_filepath
1445  svar filepath = $(package_path + "s_filepath")
1446  filepath = s_path
1447  update_filelist()
1448  endif
1449  break
1450  case -1: // control being killed
1451  break
1452  endswitch
1453 
1454  setdatafolder saveDF
1455  return 0
1456 End
1457 
1458 static function bp_update_filelist(ba) : ButtonControl
1459  STRUCT WMButtonAction &ba
1460 
1461  switch( ba.eventCode )
1462  case 2: // mouse up
1463  update_filelist()
1464  break
1465  case -1: // control being killed
1466  break
1467  endswitch
1468 
1469  return 0
1470 End
1471 
1472 static function bp_load_files(ba) : ButtonControl
1473  STRUCT WMButtonAction &ba
1474 
1475  switch( ba.eventCode )
1476  case 2: // mouse up
1478  break
1479  case -1: // control being killed
1480  break
1481  endswitch
1482 
1483  return 0
1484 End
1485 
1486 static function bp_load_files_opt(ba) : ButtonControl
1487  STRUCT WMButtonAction &ba
1488 
1489  switch( ba.eventCode )
1490  case 2: // mouse up
1491  load_selected_files(options="")
1492  break
1493  case -1: // control being killed
1494  break
1495  endswitch
1496 
1497  return 0
1498 End
1499 
1500 static function bp_file_next(ba) : ButtonControl
1501  STRUCT WMButtonAction &ba
1502 
1503  dfref saveDF = GetDataFolderDFR()
1504 
1505  switch( ba.eventCode )
1506  case 2: // mouse up
1507  setdatafolder $package_path
1508  wave /t wtFiles
1509  wave wSelectedFiles
1510  FindValue /i=1 wSelectedFiles
1511  v_value += 1
1512  if (v_value >= numpnts(wtFiles))
1513  v_value = min(numpnts(wtFiles) - 1, 0)
1514  endif
1515  wSelectedFiles = p == v_value
1516  if (v_value >= 0)
1517  variable ifile = v_value
1518  ControlInfo /W=PearlDataExplorer cb_file_preview
1519  if (v_value)
1520  preview_file(wtFiles[ifile])
1521  endif
1522  endif
1523  break
1524  case -1: // control being killed
1525  break
1526  endswitch
1527 
1528  setdatafolder saveDF
1529  return 0
1530 End
1531 
1532 static function bp_file_prev(ba) : ButtonControl
1533  STRUCT WMButtonAction &ba
1534 
1535  dfref saveDF = GetDataFolderDFR()
1536 
1537  switch( ba.eventCode )
1538  case 2: // mouse up
1539  setdatafolder $package_path
1540  wave /t wtFiles
1541  wave wSelectedFiles
1542  FindValue /i=1 wSelectedFiles
1543  v_value -= 1
1544  if (v_value < 0)
1545  v_value = numpnts(wtFiles) - 1
1546  endif
1547  wSelectedFiles = p == v_value
1548  if (v_value >= 0)
1549  variable ifile = v_value
1550  ControlInfo /W=PearlDataExplorer cb_file_preview
1551  if (v_value)
1552  preview_file(wtFiles[ifile])
1553  endif
1554  endif
1555  break
1556  case -1: // control being killed
1557  break
1558  endswitch
1559 
1560  setdatafolder saveDF
1561  return 0
1562 End
1563 
1564 static function lbp_filelist(lba) : ListBoxControl
1565  STRUCT WMListboxAction &lba
1566 
1567  Variable row = lba.row
1568  Variable col = lba.col
1569  WAVE/T/Z listWave = lba.listWave
1570  WAVE/Z selWave = lba.selWave
1571 
1572  switch( lba.eventCode )
1573  case -1: // control being killed
1574  break
1575  case 1: // mouse down
1576  if (selWave[row])
1577  ControlInfo /W=PearlDataExplorer cb_file_preview
1578  if (v_value)
1579  preview_file(listWave[row])
1580  endif
1581  endif
1582  break
1583  case 3: // double click
1584  break
1585  case 4: // cell selection
1586  case 5: // cell selection plus shift key
1587  break
1588  case 6: // begin edit
1589  break
1590  case 7: // finish edit
1591  break
1592  case 13: // checkbox clicked (Igor 6.2 or later)
1593  break
1594  endswitch
1595 
1596  return 0
1597 End
1598 
1599 static function bp_update_datasets(ba) : ButtonControl
1600  STRUCT WMButtonAction &ba
1601 
1602  switch( ba.eventCode )
1603  case 2: // mouse up
1604  update_datasets()
1605  break
1606  case -1: // control being killed
1607  break
1608  endswitch
1609 
1610  return 0
1611 End
1612 
1613 static function bp_dataset_folder(ba) : ButtonControl
1614  STRUCT WMButtonAction &ba
1615 
1616  switch( ba.eventCode )
1617  case 2: // mouse up
1618  ControlInfo /W=PearlDataExplorer lb_datasets
1619  if (v_value >= 0)
1620  setdatafolder $package_path
1621  wave /t wtDatasets
1622  string dataset = wtDatasets[v_value]
1623  string cmd
1624  sprintf cmd, "setdatafolder root:%s", PossiblyQuoteName(dataset)
1625  execute /q /z cmd
1626  cmd = "setdatafolder :scan1"
1627  execute /q /z cmd
1628  sprintf cmd, "setdatafolder %s", GetDataFolder(1)
1629  print cmd
1630  endif
1631  break
1632  case -1: // control being killed
1633  break
1634  endswitch
1635 
1636  return 0
1637 End
1638 
1639 static function bp_dataset_display(ba) : ButtonControl
1640  STRUCT WMButtonAction &ba
1641 
1642  switch( ba.eventCode )
1643  case 2: // mouse up
1644  ControlInfo /W=PearlDataExplorer lb_datasets
1645  if (v_value >= 0)
1646  setdatafolder $package_path
1647  wave /t wtDatasets
1648  string dataset = wtDatasets[v_value]
1649  display_dataset(dataset)
1650  endif
1651  break
1652  case -1: // control being killed
1653  break
1654  endswitch
1655 
1656  return 0
1657 End
1658 
1659 static function bp_dataset_next(ba) : ButtonControl
1660  STRUCT WMButtonAction &ba
1661 
1662  switch( ba.eventCode )
1663  case 2: // mouse up
1664  ControlInfo /W=PearlDataExplorer lb_datasets
1665  wave /t wtDatasets = $(s_datafolder + s_value)
1666  v_value += 1
1667  if (v_value >= numpnts(wtDatasets))
1668  v_value = min(0, numpnts(wtDatasets) - 1)
1669  endif
1670  ListBox lb_datasets win=PearlDataExplorer, selRow=v_value
1671  if (v_value >= 0)
1672  variable ids = v_value
1673  ControlInfo /W=PearlDataExplorer cb_dataset_preview
1674  if (v_value)
1675  preview_dataset(wtDatasets[ids])
1676  endif
1677  endif
1678  break
1679  case -1: // control being killed
1680  break
1681  endswitch
1682 
1683  return 0
1684 End
1685 
1686 static function bp_dataset_prev(ba) : ButtonControl
1687  STRUCT WMButtonAction &ba
1688 
1689  switch( ba.eventCode )
1690  case 2: // mouse up
1691  ControlInfo /W=PearlDataExplorer lb_datasets
1692  wave /t wtDatasets = $(s_datafolder + s_value)
1693  v_value -= 1
1694  if (v_value < 0)
1695  v_value = max(-1, numpnts(wtDatasets) - 1)
1696  endif
1697  ListBox lb_datasets win=PearlDataExplorer, selRow=v_value
1698  if (v_value >= 0)
1699  variable ids = v_value
1700  ControlInfo /W=PearlDataExplorer cb_dataset_preview
1701  if (v_value)
1702  preview_dataset(wtDatasets[ids])
1703  endif
1704  endif
1705  break
1706  case -1: // control being killed
1707  break
1708  endswitch
1709 
1710  return 0
1711 End
1712 
1713 static function lbp_datasets(lba) : ListBoxControl
1714  STRUCT WMListboxAction &lba
1715 
1716  Variable row = lba.row
1717  Variable col = lba.col
1718  WAVE/T/Z listWave = lba.listWave
1719  WAVE/Z selWave = lba.selWave
1720 
1721  switch( lba.eventCode )
1722  case -1: // control being killed
1723  break
1724  case 1: // mouse down
1725  if (row >= 0)
1726  ControlInfo /W=PearlDataExplorer cb_dataset_preview
1727  if (v_value)
1728  preview_dataset(listWave[row])
1729  endif
1730  endif
1731  break
1732  case 3: // double click
1733  break
1734  case 4: // cell selection
1735  case 5: // cell selection plus shift key
1736  break
1737  case 6: // begin edit
1738  break
1739  case 7: // finish edit
1740  break
1741  case 13: // checkbox clicked (Igor 6.2 or later)
1742  break
1743  endswitch
1744 
1745  return 0
1746 End
1747 
1748 static function bp_attr_notebook(ba) : ButtonControl
1749  STRUCT WMButtonAction &ba
1750 
1751  dfref saveDF = GetDataFolderDFR()
1752 
1753  switch( ba.eventCode )
1754  case 2: // mouse up
1755  setdatafolder $package_path
1756  svar s_preview_file
1757  wave /t /z attr_names
1758  wave /t /z attr_values
1759  if (WaveExists(attr_names))
1760  attributes_notebook(attr_names, attr_values, s_preview_file)
1761  endif
1762  break
1763  case -1: // control being killed
1764  break
1765  endswitch
1766 
1767  setdatafolder saveDF
1768  return 0
1769 End
static dfr load_mtrx_file(string filename, string options=defaultValue)
load a matrix (STM) data file
-
static const string package_path
-
string adh5_load_preview(string ANickName, string APathName, string AFileName, variable load_data=defaultValue, variable load_attr=defaultValue)
load a single image from a HDF5 file created by the Area Detector software.
-
static variable update_datasets()
-
string psh5_load_reduced(string ANickName, string APathName, string AFileName, funcref reduction_func, string reduction_param, variable progress=defaultValue, variable nthreads=defaultValue)
load and reduce the ScientaImage dataset of the first scan of a PShell data file. ...
-
static variable bp_browse_filepath(WMButtonAction *ba)
-
static variable preview_file(string filename)
-
variable prompt_default_process(string *param)
prototype for prompting for processing function parameters.
-
string adh5_load_info(string APathName, string AFileName)
load descriptive info from a HDF5 file created by the Area Detector software.
-
static variable bp_dataset_prev(WMButtonAction *ba)
-
static string display_preview_trace(wave xtrace, wave ytrace)
-
static variable bp_file_prev(WMButtonAction *ba)
-
variable ad_brick_slicer(wave data)
open a slicer panel for 3D data.
+Go to the documentation of this file.
1 #pragma rtGlobals=3 // Use modern global access method and strict wave access.
2 #pragma IgorVersion = 6.1
3 #pragma ModuleName = PearlDataExplorer
4 #pragma version = 1.50
5 #include "pearl-area-import"
6 #include "pearl-area-profiles"
7 #include "pearl-area-display"
8 #include "pearl-compat"
9 #include "pearl-pshell-import"
10 #if exists("MFR_OpenResultFile")
11 #include "pearl-matrix-import"
12 #endif
13 
14 // copyright (c) 2013-16 Paul Scherrer Institut
15 //
16 // Licensed under the Apache License, Version 2.0 (the "License");
17 // you may not use this file except in compliance with the License.
18 // You may obtain a copy of the License at
19 // http:///www.apache.org/licenses/LICENSE-2.0
20 
31 
36 
37 static strconstant package_name = "pearl_explorer"
38 static strconstant package_path = "root:packages:pearl_explorer:"
39 
40 static strconstant ks_filematch_adh5 = "*.h5"
41 static strconstant ks_filematch_pshell = "psh*.h5"
42 static strconstant ks_filematch_itx = "*.itx"
43 static strconstant ks_filematch_mtrx = "*_mtrx"
44 
46  init_package()
47  load_prefs()
48  execute /q/z "PearlDataExplorer()"
49 end
50 
56 static function init_package()
57 
58  dfref savefolder = GetDataFolderDFR()
59  SetDataFolder root:
60  newdatafolder /o/s packages
61  newdatafolder /o/s $package_name
62  if (exists("v_InitPanelDone") == 2)
63  SetDataFolder savefolder
64  return 0
65  endif
66 
67  make /o/n=0/t wtFiles
68  make /o/n=0/i wSelectedFiles,wSelectedDatasets
69  make /o/n=0/t wtDatasets
70  make /o/n=0/t wtPositioners,wtDetectors
71  make /o/n=0/i wSelectedPositioners,wSelectedDetectors
72 
73  make /o/n=(1,1) preview_image // preview 2D data
74  make /o/n=0 preview_trace // preview 1D data
75  make /o/n=0/t attr_names, attr_values, attr_filter, attr_filter_summary
76 
77  // persistent strings and variables. persistent = saved in preferences
78  string /g s_filepath = "" // directory path to be listed
79  string /g s_hdf_options = "" // recently used HDF5 load options
80  string /g s_reduction_params = "" // recently used reduction parameters
81  string /g s_preview_pvs = "" // semicolon-separated list of EPICS PVs to display in preview.
82  // the list items can contain wildcards for StringMatch
83  s_preview_pvs = "*OP:CURRENT*;*Stats*Total*;*KEITHLEY*READOUT;*CADC*"
84 
85  // non-persistent strings and variables
86  string /g s_preview_file = "" // file or folder name of the current preview
87  string /g s_preview_source = "" // data source, e.g. EPICS channel name, of the current preview
88  string /g s_profiles_graph = "" // window name of the current preview if the data is two-dimensional
89  string /g s_preview_trace_graph = "" // window name of the current preview if the data is one-dimensional
90  string /g s_file_info = "" // description of selected file
91 
92  variable/g v_InitPanelDone = 1
93 
94  SetDataFolder savefolder
95 end
96 
97 static function save_prefs()
98  // saves persistent package data to the preferences file
99  // the data saved in the file are: data file path, attributes filter
100  dfref saveDF = GetDataFolderDFR()
101 
102  string fullPath = SpecialDirPath("Packages", 0, 0, 0)
103  fullPath += package_name
104  NewPath/O/C/Q tempPackagePrefsPath, fullPath
105  fullPath += ":preferences.pxp"
106 
107  SetDataFolder root:packages
108  SetDataFolder $package_name
109  string objects = "attr_filter;attr_filter_summary;s_filepath;s_hdf_options;s_reduction_params;s_preview_pvs"
110  SaveData /O /Q /J=objects fullPath
111 
112  KillPath/Z tempPackagePrefsPath
113 
114  SetDataFolder saveDF
115 end
116 
117 static function load_prefs()
118  // loads persistent package data from the preferences file
119  // the preferences file is an Igor packed experiment file in a special preferences folder
120  dfref saveDF = GetDataFolderDFR()
121 
122  variable result = -1
123  setdatafolder root:
124  NewDataFolder /O/S packages
125  NewDataFolder /O/S $package_name
126  dfref packageDF = GetDataFolderDFR()
127  string fullPath = SpecialDirPath("Packages", 0, 0, 0)
128  fullPath += package_name
129 
130  GetFileFolderInfo /Q /Z fullPath
131  if (V_Flag == 0) // Disk directory exists?
132  fullPath += ":preferences.pxp"
133  GetFileFolderInfo /Q /Z fullPath
134  if (V_Flag == 0) // Preference file exist?
135  LoadData /O /R /Q fullPath
136  result = 0
137  endif
138  endif
139 
140  if (result == 0)
141  svar /sdfr=packageDF filepath = s_filepath
142  NewPath /O/Z pearl_explorer_filepath, filepath
145  endif
146 
147  SetDataFolder saveDF
148  return result
149 end
150 
162 static function pearl_file_type(filename)
163  string filename
164 
165  if (StringMatch(filename, ks_filematch_pshell))
166  return 1
167  elseif (StringMatch(filename, ks_filematch_adh5))
168  return 2
169  elseif (StringMatch(filename, ks_filematch_itx))
170  return 3
171 #if exists("MFR_OpenResultFile")
172  elseif (StringMatch(filename, ks_filematch_mtrx))
173  return 4
174 #endif
175  else
176  return 0
177  endif
178 end
179 
185 static function update_filelist()
186  dfref saveDF = GetDataFolderDFR()
187 
188  string all_files
189  wave /t wtFiles = $(package_path + "wtFiles")
190  wave wSelectedFiles = $(package_path + "wSelectedFiles")
191  variable nn
192 
193  PathInfo pearl_explorer_filepath
194  if (v_flag == 1)
195  all_files = IndexedFile(pearl_explorer_filepath, -1, "????")
196  nn = ItemsInList(all_files)
197  else
198  all_files = ""
199  nn = 0
200  endif
201 
202  make /n=(nn) /t /free wtAllFiles
203  wtAllFiles = StringFromList(p, all_files)
204  Extract /o /t wtAllFiles, wtFiles, pearl_file_type(wtAllFiles[p])
205  Sort /A /R wtFiles, wtFiles
206 
207  redimension /n=(numpnts(wtFiles)) wSelectedFiles
208  wSelectedFiles = 0
209 
210  setdatafolder saveDF
211 end
212 
213 static function update_datasets()
214  // updates the list of imported datasets.
215  // a dataset means any top-level data folder
216  // which includes a string variable named pearl_explorer_import.
217  dfref saveDF = GetDataFolderDFR()
218 
219  setdatafolder root:
220  dfref rootdf = GetDataFolderDFR()
221  setdatafolder $package_path
222  dfref privatedf = GetDataFolderDFR()
223 
224  wave /t wtDatasets
225  wave wSelectedDatasets
226  variable maxdf = CountObjectsDFR(rootdf, 4)
227  redimension /n=(maxdf) wtDatasets
228 
229  variable idf = 0
230  variable ndf = 0
231  string sdf
232 
233  do
234  sdf = GetIndexedObjNameDFR(rootdf, 4, idf)
235  if (strlen(sdf) >= 1)
236  setdatafolder rootdf
237  setdatafolder $sdf
238  svar /z importer = pearl_explorer_import
239  if (svar_exists(importer))
240  wtDatasets[ndf] = sdf
241  ndf += 1
242  endif
243  else
244  break
245  endif
246  idf += 1
247  while(1)
248 
249  redimension /n=(ndf) wtDatasets, wSelectedDatasets
250  wSelectedDatasets = 0
251  sort wtDatasets, wtDatasets
252 
253  setdatafolder saveDF
254 end
255 
256 static function preview_file(filename)
257  string filename
258 
259  dfref saveDF = GetDataFolderDFR()
260 
261  variable ft = pearl_file_type(filename)
262  switch(ft)
263  case 1:
264  wave /z image = preview_pshell_file(filename)
265  break
266  case 2:
267  wave /z image = preview_hdf_file(filename)
268  break
269  case 3:
270  wave /z image = preview_itx_file(filename)
271  break
272  case 4:
273  wave /z image = preview_mtrx_file(filename)
274  break
275  default:
276  wave /z image = $""
277  endswitch
278 
279  if (WaveExists(image))
280  string graphname = show_preview_graph(image)
281  // preset ELOG panel - if available
282  if (exists("PearlElog#set_panel_attributes") == 6)
283  string cmd
284  sprintf cmd, "PearlElog#set_panel_attributes(\"\", \"File=%s\")", ParseFilePath(0, filename, ":", 1, 0)
285  execute /Q/Z cmd
286  if (strlen(graphname) > 0)
287  sprintf cmd, "PearlElog#set_panel_graphs(\"\", \"%s\")", graphname
288  execute /Q/Z cmd
289  endif
290  endif
291  endif
292 
293  setdatafolder saveDF
294  return 0
295 end
296 
308 static function /wave preview_pshell_file(filename)
309  string filename
310 
311  dfref saveDF = GetDataFolderDFR()
312 
313  setdatafolder $package_path
314  dfref previewDF = GetDataFolderDFR()
315  svar s_preview_file
316  svar s_preview_source
317  svar /z s_file_info
318  if (! svar_exists(s_file_info))
319  string /g s_file_info
320  endif
321 
322  dfref tempDF = NewFreeDataFolder()
323  setdatafolder tempDF
324  string dataname
325  dataname = psh5_load_preview("pearl_explorer_filepath", filename)
326 
327  s_preview_file = filename
328  s_preview_source = ""
329 
330  wave /z data = $dataname
331  if (waveexists(data))
332  duplicate /o data, previewDF:preview_image
333  else
334  print "no data found in file " + filename
335  endif
336 
337  if (strlen(s_preview_file) > 0)
338  s_file_info = psh5_load_info("pearl_explorer_filepath", filename)
339  else
340  s_file_info = ""
341  endif
342 
343  dfref attrDF = tempDF:attr
344  if (DataFolderRefStatus(attrDF))
345  preview_attributes(attrDF)
346  endif
347 
348  setdatafolder saveDF
349  wave /z /sdfr=previewDF preview_image
350  return preview_image
351 end
352 
364 static function /wave preview_hdf_file(filename)
365  string filename
366 
367  dfref saveDF = GetDataFolderDFR()
368  setdatafolder $package_path
369  svar s_preview_file
370  svar s_preview_source
371  adh5_load_preview("preview_image", "pearl_explorer_filepath", filename)
372  s_preview_file = filename
373  s_preview_source = ""
374  wave /z preview_image
375 
376  svar /z s_file_info
377  if (! svar_exists(s_file_info))
378  string /g s_file_info
379  endif
380  if (strlen(s_preview_file) > 0)
381  s_file_info = adh5_load_info("pearl_explorer_filepath", filename)
382  else
383  s_file_info = ""
384  endif
385 
386  if (DataFolderExists("attr"))
387  setdatafolder attr
388  preview_attributes(GetDataFolderDFR())
389  setdatafolder ::
390  endif
391 
392  setdatafolder saveDF
393  return preview_image
394 end
395 
415 static function /wave preview_itx_file(filename)
416  string filename
417 
418  dfref saveDF = GetDataFolderDFR()
419  setdatafolder $package_path
420  svar s_preview_file
421  svar s_preview_source
422  wave preview_image
423 
424  dfref dataDF = newfreedatafolder()
425  setdatafolder dataDF
426  LoadWave /t/p=pearl_explorer_filepath/q filename
427  s_preview_file = s_filename
428  s_preview_source = ""
429 
431  preview_attributes(dataDF, include_datawaves=0)
432 
433  setdatafolder saveDF
434  return preview_image
435 end
436 
451 static function /wave preview_mtrx_file(filename)
452  string filename
453 
454 #if exists("MFR_OpenResultFile")
455  dfref saveDF = GetDataFolderDFR()
456  setdatafolder $package_path
457  variable /g V_MatrixFileReaderOverwrite = 1
458  variable /g V_MatrixFileReaderFolder = 0
459  variable /g V_MatrixFileReaderDouble = 0
460  svar s_preview_file
461  svar s_preview_source
462  string datanames
463  string dataname
464  datanames = mtrx_load_preview("preview", "pearl_explorer_filepath", filename)
465  if (strlen(datanames) > 0)
466  s_preview_file = filename
467 
468  dataname = StringFromList(0, datanames)
469  wave data = $dataname
470  duplicate /o $dataname, preview_image
471  s_preview_source = StringByKey("Dataset", note(data), "=", "\r")
472 
473  svar /z s_file_info
474  if (svar_exists(s_file_info))
475  s_file_info = ""
476  endif
477 
478  variable i
479  variable n = ItemsInList(datanames)
480  string s
481  for (i = 0; i < n; i += 1)
482  s = StringFromList(i, datanames)
483  killwaves /z $s
484  endfor
485  endif
486  wave /z preview_image
487  setdatafolder saveDF
488 #else
489  wave /z preview_image = $""
490 #endif
491  return preview_image
492 end
493 
494 static function extract_preview_image(data, preview)
495  // extracts a preview image from a wave of arbitrary dimension
496  wave data
497  wave preview
498 
499  variable z1, z2
500 
501  // extract image
502  switch (WaveDims(data))
503  case 1:
504  redimension /n=(numpnts(data)) preview
505  preview = data[p]
506  break
507  case 2:
508  redimension /n=(dimsize(data, 0), dimsize(data, 1)) preview
509  preview = data
510  break
511  case 3:
512  redimension /n=(dimsize(data, 0), dimsize(data, 1)) preview
513  z1 = floor(DimSize(data, 2) / 2)
514  z2 = z1
515  wave slab = ad_extract_slab(data, nan, nan, nan, nan, z1, z2, "", pscale=1)
516  preview = slab
517  break
518  case 4:
519  // not implemented
520  endswitch
521 
522  switch (WaveDims(data))
523  case 4:
524  case 3:
525  case 2:
526  setscale /p y dimoffset(data, 1), dimdelta(data, 1), waveunits(data, 1), preview
527  case 1:
528  setscale /p x dimoffset(data, 0), dimdelta(data, 0), waveunits(data, 0), preview
529  setscale d 0, 0, waveunits(data, -1), preview
530  endswitch
531 end
532 
533 static function preview_dataset(datasetname)
534  string datasetname // name of a data folder under root
535 
536  dfref saveDF = GetDataFolderDFR()
537 
538  if (!DataFolderExists("root:" + datasetname))
539  return -1
540  endif
541  setdatafolder root:
542  setdatafolder $datasetname
543  dfref datadf = GetDataFolderDFR()
544  wave /z data
545 
546  setdatafolder $package_path
547  svar s_preview_file
548  svar s_preview_source
549  wave preview_image
550  if (WaveExists(data))
551  s_preview_file = datasetname
552  s_preview_source = ""
553  extract_preview_image(data, preview_image)
554  show_preview_graph(preview_image)
555  else
556  preview_image = nan
557  s_preview_file = datasetname
558  setdatafolder datadf
560  show_preview_graph(preview_image)
561  endif
562 
563  // attributes
564  setdatafolder datadf
565  if (DataFolderExists("attr"))
566  setdatafolder attr
567  preview_attributes(GetDataFolderDFR())
568  else
569  preview_attributes(GetDataFolderDFR(), include_datawaves=0)
570  endif
571 
572  setdatafolder saveDF
573  return 0
574 end
575 
576 static function preview_datafolder()
577  // preview data in the current data folder
578  dfref saveDF = GetDataFolderDFR()
579 
580  setdatafolder $package_path
581  svar s_preview_file
582  svar s_preview_source
583  svar s_preview_pvs
584  wave preview_image
585 
586  setdatafolder saveDF
587 
588  // select a wave to display
589  // consider only double-precision waves, i.e. ignore text and other special waves
590  // filter by matching PV name to s_preview_pvs
591  string d_names = WaveList("*", ";", "DP:1")
592  variable nw = ItemsInList(d_names, ";")
593  variable npv = ItemsInList(s_preview_pvs, ";")
594  variable iw, ipv
595  string wname, wnote, pv_name, pv_match
596  for (iw = 0; iw < nw; iw += 1)
597  wname = StringFromList(iw, d_names, ";")
598  wnote = note($wname)
599  pv_name = StringByKey("PV", wnote, "=", "\r")
600  // find matching data wave by PV name
601  for (ipv = 0; ipv < npv; ipv += 1)
602  pv_match = StringFromList(ipv, s_preview_pvs)
603  if (StringMatch(pv_name, pv_match))
604  wave data = $wname
605  s_preview_source = pv_name
606  extract_preview_image(data, preview_image)
607  preview_setscale_x(data, preview_image)
608  npv = 0
609  nw = 0
610  endif
611  endfor
612  endfor
613 
614  setdatafolder saveDF
615 end
616 
617 static function preview_setscale_x(data, preview)
618  // sets the approximate x scale of OTF data.
619  // requires an Axis1 tag with name of x wave in the wave note.
620  // if any of these conditions is true, the function does not change the scaling:
621  // 1) Axis1 tag or referenced wave is missing.
622  // 2) preview wave is not set to point scaling.
623  // 3) x wave is not monotonic (90% of the steps in the same direction).
624  wave data
625  wave preview
626 
627  if ((DimOffset(preview, 0) == 0) && (DimDelta(preview, 0) == 1))
628  string xname = StringByKey("Axis1", note(data), "=", "\r")
629  wave /z xwave = $xname
630  if (WaveExists(xwave))
631  // check for monotonicity
632  variable monotonic = 0
633  duplicate /free xwave, xdiff
634  differentiate /p xwave /D=xdiff
635  duplicate /free xdiff, xflag
636  xflag = xdiff > 0
637  monotonic = sum(xflag) > numpnts(xwave) * 0.9
638  xflag = xdiff < 0
639  monotonic = monotonic || (sum(xflag) > numpnts(xwave) * 0.9)
640  if (monotonic)
641  setscale /i x xwave[0], xwave[numpnts(xwave)-1], waveunits(xwave, -1), preview
642  endif
643  endif
644  endif
645 end
646 
647 static function preview_attributes(attr_folder, [dest_folder, attr_filter, include_datawaves, include_infowaves])
648  // copies the first elements of attributes in the specified folder to the preview waves
649  // by default, all existing attributes are copied
650  // if a text wave attr_filter exists in the pear_explorer folder, only the attributes referenced therein are copied
651  // to set up a filter, duplicate the attr_names wave of a template dataset, and remove unwanted items
652  dfref attr_folder // data folder which contains the attribute waves
653  dfref dest_folder // destination folder. the output is written to the attr_names and attr_values waves
654  // default = package folder
655  wave /t attr_filter // list of attributes allowed in the output
656  // default = use attr_filter of package folder
657  variable include_datawaves // 1 (default) = include data waves (any numeric wave which has a PV=name note)
658  // 0 = don't include attributes from data waves
659  variable include_infowaves // 1 (default) = include attributes from info waves (IN, ID, IV, IU)
660  // 0 = don't include attributes from info waves
661 
662  dfref saveDF = GetDataFolderDFR()
663  setdatafolder $package_path
664 
665  if (ParamIsDefault(dest_folder))
666  dest_folder = GetDataFolderDFR() // package folder
667  endif
668  if (ParamIsDefault(attr_filter))
669  wave /t /z attr_filter
670  endif
671  if (ParamIsDefault(include_datawaves))
672  include_datawaves = 1
673  endif
674  if (ParamIsDefault(include_infowaves))
675  include_infowaves = 1
676  endif
677 
678  setdatafolder dest_folder
679  wave /t /z attr_names, attr_values
680  if (!WaveExists(attr_names) || !WaveExists(attr_values))
681  make /n=(1) /o /t attr_names, attr_values
682  endif
683  attr_names = ""
684  attr_values = ""
685 
686  setdatafolder attr_folder
687  wave /t /z IN
688  wave /t /z ID
689  wave /t /z IV
690  wave /t /z IU
691 
692  // compile list of attributes
693  variable nattr // destination attributes
694  variable iattr
695  variable ninfo // info wave elements
696  variable iinfo
697  variable nw // attribute waves
698  variable iw
699  string sw
700  string ss
701 
702  if (WaveExists(IN) && include_infowaves)
703  ninfo = numpnts(IN)
704  else
705  ninfo = 0
706  endif
707  if (include_datawaves)
708  string waves = WaveList("*", ";", "")
709  string exceptions = "ID;IN;IU;IV"
710  waves = RemoveFromList(exceptions, waves)
711  nw = ItemsInList(waves, ";")
712  else
713  nw = 0
714  endif
715 
716  if (WaveExists(attr_filter) && (numpnts(attr_filter) >= 1))
717  nattr = numpnts(attr_filter)
718  redimension /n=(nattr) attr_names
719  attr_names = attr_filter
720  else
721  if(ninfo > 0)
722  redimension /n=(ninfo) attr_names
723  attr_names = SelectString(strlen(ID[p]) >= 0, IN[p], ID[p]) // use ID unless empty
724  endif
725 
726  nattr = ninfo + nw
727  iattr = ninfo
728  redimension /n=(nattr) attr_names
729  for (iw = 0; iw < nw; iw +=1 )
730  sw = StringFromList(iw, waves, ";")
731  ss = StringByKey("PV", note($sw), "=", "\r")
732  FindValue /text=sw attr_names
733  if ((v_value < 0) && (strlen(ss) >= 0))
734  attr_names[iattr] = sw
735  iattr += 1
736  endif
737  endfor
738  nattr = iattr
739  endif
740  redimension /n=(nattr) attr_names, attr_values
741  sort attr_names, attr_names
742 
743  // look up attribute values
744  for (iattr = 0; iattr < nattr; iattr += 1)
745  sw = attr_names[iattr]
746  // try info waves
747  if (ninfo > 0)
748  FindValue /text=sw ID
749  if (v_value >= 0)
750  attr_values[iattr] = IV[v_value]
751  endif
752  FindValue /text=sw IN
753  if (v_value >= 0)
754  attr_values[iattr] = IV[v_value]
755  endif
756  endif
757 
758  // override from attribute wave if existent
759  if (nw > 0)
760  switch (WaveType($sw, 1))
761  case 1: // numeric
762  wave /z w = $sw
763  if (WaveExists(w) && (numpnts(w) >= 1))
764  sprintf ss, "%g", w[0]
765  attr_values[iattr] = ss
766  endif
767  break
768  case 2: // text
769  wave /t/z wt = $sw
770  if (WaveExists(wt) && (numpnts(wt) >= 1))
771  attr_values[iattr] = wt[0]
772  endif
773  break
774  endswitch
775  endif
776  endfor
777 
778  setdatafolder saveDF
779 end
780 
781 static function display_dataset(datasetname)
782  // displays the graph of a loaded dataset in its own window
783  string datasetname // name of a data folder under root
784 
785  dfref saveDF = GetDataFolderDFR()
786 
787  if (!DataFolderExists("root:" + datasetname))
788  return -1
789  endif
790  setdatafolder root:
791  setdatafolder $datasetname
792  dfref datadf = GetDataFolderDFR()
793  wave /z data
794  if (!WaveExists(data))
795  wave /z data = data1
796  endif
797 
798  if (WaveExists(data))
799  switch(WaveDims(data))
800  case 2:
801  ad_display_profiles(data)
802  break
803  case 3:
804  ad_display_slice(data)
805  ad_brick_slicer(data)
806  break
807  endswitch
808  endif
809 
810  setdatafolder saveDF
811  return 0
812 end
813 
815  dfref df = GetDataFolderDFR()
816  wave /t /sdfr=df attr_names
817  wave /t /sdfr=df attr_values
818  attributes_notebook(attr_names, attr_values, GetDataFolder(0))
819 end
820 
821 static function attributes_notebook(attr_names, attr_values, title)
822  wave /t attr_names
823  wave /t attr_values
824  string title
825 
826  dfref saveDF = GetDataFolderDFR()
827  setdatafolder $package_path
828  wave /t/z attr_filter, attr_filter_summary
829 
830  string name = PearlCleanupName("nb_" + title[0,27])
831  if (WinType(name) == 5)
832  Notebook $name selection={startOfFile, endOfFile}
833  Notebook $name text=""
834  else
835  NewNotebook /F=1 /K=1 /N=$name as title
836  GetWindow $name wsize
837  v_right = v_left + 260
838  v_bottom = v_top + 360
839  MoveWindow /W=$name v_left, v_top, v_right, v_bottom
840  Notebook $name tabs={2*72}
841  endif
842 
843  // summary
844  if (WaveExists(attr_filter_summary) && (numpnts(attr_filter_summary) >= 1))
845  notebook $name fStyle=1, text="Summary\r\r"
846  notebook $name fStyle=0
847  notebook_add_attributes(name, attr_filter_summary, attr_names, attr_values)
848  notebook $name text="\r"
849  endif
850 
851  // all attributes
852  notebook $name fStyle=1, text="All Attributes\r\r"
853  notebook $name fStyle=0
854  notebook_add_attributes(name, $"", attr_names, attr_values)
855  notebook $name selection={startOfFile,startOfFile}, findText={"",1}
856 
857  setdatafolder saveDF
858 end
859 
860 static function notebook_add_attributes(notebook_name, attr_filter, attr_names, attr_values)
861  string notebook_name
862  wave /t /z attr_filter
863  wave /t attr_names
864  wave /t attr_values
865 
866  variable nw = numpnts(attr_names)
867  variable iw
868  string sw
869  string ss
870 
871  variable do_filter = WaveExists(attr_filter)
872 
873  for (iw = 0; iw < nw; iw += 1)
874  if (do_filter)
875  sw = attr_names[iw]
876  FindValue /text=sw attr_filter
877  else
878  v_value = 0
879  endif
880  if (v_value >= 0)
881  sprintf ss, "%s\t%s\r", attr_names[iw], attr_values[iw]
882  notebook $notebook_name text=ss
883  endif
884  endfor
885 end
886 
887 static function /s show_preview_graph(data, [xdata])
888  // displays a preview of one- or two-dimensional data
889  wave data // data to be displayed. must either one-dimensional or two-dimensional
890  wave xdata // positions on x axis
891 
892  dfref saveDF = GetDataFolderDFR()
893  setdatafolder $package_path
894 
895  svar s_profiles_graph
896  svar s_preview_file
897  svar s_preview_source
898  svar s_preview_trace_graph
899 
900  if ((strlen(s_profiles_graph) > 0) && (WinType(s_profiles_graph) == 1))
901  KillWindow $s_profiles_graph
902  endif
903  if ((strlen(s_preview_trace_graph) > 0) && (WinType(s_preview_trace_graph) == 1))
904  KillWindow $s_preview_trace_graph
905  endif
906 
907  string graphname
908  if (wavedims(data) == 2)
909  s_profiles_graph = ad_display_profiles(data)
910  ModifyGraph /w=$s_profiles_graph /z wbRGB=(48640,56832,60160)
911  graphname = s_profiles_graph
912  elseif (wavedims(data) == 1)
913  duplicate /o data, preview_trace
914  if (!ParamIsDefault(xdata))
915  duplicate /o xdata, preview_trace_x
916  else
917  duplicate /o data, preview_trace_x
918  preview_trace_x = x
919  setscale d 0, 0, WaveUnits(data, 0), preview_trace_x
920  endif
921  s_preview_trace_graph = display_preview_trace(preview_trace_x, preview_trace)
922  ModifyGraph /w=$s_preview_trace_graph wbRGB=(48640,56832,60160)
923  graphname = s_preview_trace_graph
924  else
925  return ""
926  endif
927 
928  string title = "Preview " + s_preview_file
929  if (strlen(s_preview_source) > 0)
930  title = title + " (" + s_preview_source[0,31] + ")"
931  endif
932  dowindow /f/t $graphname, title
933 
934  setdatafolder saveDF
935  return graphname
936 end
937 
938 static function /s display_preview_trace(xtrace, ytrace)
939  wave xtrace
940  wave ytrace
941 
942  display /n=pearl_explorer_1d /k=1 ytrace vs xtrace as "Preview"
943  string graphname = s_name
944  ModifyGraph /w=$graphname rgb[0]=(0,0,0)
945  ModifyGraph /w=$graphname grid=2
946  ModifyGraph /w=$graphname mirror=1
947  ModifyGraph /w=$graphname minor=1
948  ModifyGraph /w=$graphname axThick=0.5
949  ModifyGraph /w=$graphname gridRGB=(52224,52224,52224)
950  ModifyGraph /w=$graphname gridHair=0
951  ModifyGraph /w=$graphname tick=0
952  ModifyGraph /w=$graphname btLen=4
953 
954  // axis labels
955  string labels = note(ytrace)
956  string lab
957  lab = StringByKey("AxisLabelX", labels, "=", "\r")
958  if (!strlen(lab))
959  lab = "X"
960  endif
961  Label /w=$graphname bottom lab + " (\\U)"
962  lab = StringByKey("AxisLabelD", labels, "=", "\r")
963  if (!strlen(lab))
964  lab = "value"
965  endif
966  Label /w=$graphname left lab + " (\\U)"
967 
968  return s_name
969 end
970 
971 static function load_selected_files([options])
972  string options
973 
974  dfref saveDF = GetDataFolderDFR()
975  setdatafolder $package_path
976 
977  wave wSelectedFiles
978  wave/t wtFiles
979  variable nn = numpnts(wSelectedFiles)
980  variable ii
981  for (ii = 0; ii < nn; ii += 1)
982  if (wSelectedFiles[ii])
983  if (ParamIsDefault(options))
984  load_file(wtFiles[ii])
985  else
986  load_file(wtFiles[ii], options=options)
987  endif
988  endif
989  endfor
990 
992  setdatafolder saveDF
993 end
994 
995 static function load_file(filename, [options])
996  string filename
997  string options
998 
999  dfref saveDF = GetDataFolderDFR()
1000 
1001  variable ft = pearl_file_type(filename)
1002  switch(ft)
1003  case 1:
1004  if (ParamIsDefault(options))
1005  load_pshell_file(filename)
1006  else
1007  load_pshell_file(filename, options=options)
1008  endif
1009  break
1010  case 2:
1011  if (ParamIsDefault(options))
1012  load_hdf_file(filename)
1013  else
1014  load_hdf_file(filename, options=options)
1015  endif
1016  break
1017  case 3:
1018  load_itx_file(filename)
1019  break
1020  case 4:
1021  load_mtrx_file(filename)
1022  break
1023  default:
1024  break
1025  endswitch
1026 
1027  setdatafolder saveDF
1028 end
1029 
1030 static function prompt_hdf_options(options)
1031  string &options
1032 
1033  string mode = StringByKey("mode", options, ":", ";")
1034  string reduction_func = StringByKey("reduction_func", options, ":", ";")
1035 
1036  string modes = "load_reduced"
1037  string reduction_functions = adh5_list_reduction_funcs()
1038 
1039  if (strlen(mode) == 0)
1040  mode = StringFromList(0, modes, ";")
1041  endif
1042  if (strlen(reduction_func) == 0)
1043  reduction_func = StringFromList(0, reduction_functions, ";")
1044  endif
1045 
1046  prompt mode, "Mode", popup, modes
1047  prompt reduction_func, "Reduction Function", popup, reduction_functions
1048  doprompt "HDF5 Loading Options", mode, reduction_func
1049 
1050  if (v_flag == 0)
1051  options = ReplaceStringByKey("mode", options, mode, ":", ";")
1052  options = ReplaceStringByKey("reduction_func", options, reduction_func, ":", ";")
1053  endif
1054  return v_flag // 0 = OK, 1 = cancel
1055 end
1056 
1069 function prompt_default_process(param)
1070  string &param
1071 
1072  return 0
1073 end
1074 
1075 function prompt_func_params(func_name, func_param)
1076  string func_name
1077  string &func_param
1078 
1079  string prompt_name = "prompt_" + func_name
1080  if (exists(prompt_name) == 6)
1081  funcref prompt_default_process prompt_func = $prompt_name
1082  return prompt_func(func_param)
1083  else
1084  // ignore missing prompt function
1085  return 0
1086  endif
1087 end
1088 
1089 static function /df load_pshell_file(filename, [options])
1090  string filename
1091  string options
1092 
1093  dfref saveDF = GetDataFolderDFR()
1094  string nickname = ad_suggest_foldername(filename)
1095  string loaded_filename = ""
1096 
1097  if (ParamIsDefault(options))
1098  loaded_filename = psh5_load_complete(nickname, "pearl_explorer_filepath", filename)
1099  else
1100  if (strlen(options) == 0)
1101  svar pref_options = $(package_path + "s_hdf_options")
1102  options = pref_options
1103  if (prompt_hdf_options(options) == 0)
1104  // OK
1105  pref_options = options
1106  else
1107  // cancel
1108  options = ""
1109  endif
1110  endif
1111 
1112  string mode = StringByKey("mode", options, ":", ";")
1113 
1114  strswitch(mode)
1115  case "load_reduced":
1116  string reduction_func = StringByKey("reduction_func", options, ":", ";")
1117  svar pref_params = $(package_path + "s_reduction_params")
1118  string reduction_params = pref_params
1119  if (prompt_func_params(reduction_func, reduction_params) == 0)
1120  pref_params = reduction_params
1121  print reduction_func, reduction_params
1122  psh5_load_reduced(nickname, "pearl_explorer_filepath", filename, $reduction_func, reduction_params)
1123  svar s_filepath
1124  loaded_filename = s_filepath
1125  endif
1126  break
1127  endswitch
1128  endif
1129 
1130  dfref dataDF
1131  if (strlen(loaded_filename) > 0)
1132  setdatafolder $("root:" + nickname)
1133  dataDF = GetDataFolderDFR()
1134  string /g pearl_explorer_import = "load_pshell_file"
1135  endif
1136 
1137  setdatafolder saveDF
1138  return dataDF
1139 end
1140 
1141 static function /df load_hdf_file(filename, [options])
1142  string filename
1143  string options
1144 
1145  dfref saveDF = GetDataFolderDFR()
1146  string nickname = ad_suggest_foldername(filename)
1147  string loaded_filename = ""
1148 
1149  if (ParamIsDefault(options))
1150  loaded_filename = adh5_load_complete(nickname, "pearl_explorer_filepath", filename)
1151  else
1152  if (strlen(options) == 0)
1153  svar pref_options = $(package_path + "s_hdf_options")
1154  options = pref_options
1155  if (prompt_hdf_options(options) == 0)
1156  // OK
1157  pref_options = options
1158  else
1159  // cancel
1160  options = ""
1161  endif
1162  endif
1163 
1164  string mode = StringByKey("mode", options, ":", ";")
1165 
1166  strswitch(mode)
1167  case "load_reduced":
1168  string reduction_func = StringByKey("reduction_func", options, ":", ";")
1169  svar pref_params = $(package_path + "s_reduction_params")
1170  string reduction_params = pref_params
1171  if (prompt_func_params(reduction_func, reduction_params) == 0)
1172  pref_params = reduction_params
1173  print reduction_func, reduction_params
1174  loaded_filename = adh5_load_reduced(nickname, "pearl_explorer_filepath", filename, $reduction_func, reduction_params)
1175  endif
1176  break
1177  endswitch
1178  endif
1179 
1180  dfref dataDF
1181  if (strlen(loaded_filename) > 0)
1182  setdatafolder $("root:" + nickname)
1183  dataDF = GetDataFolderDFR()
1184  string /g pearl_explorer_import = "load_hdf_file"
1185  endif
1186 
1187  setdatafolder saveDF
1188  return dataDF
1189 end
1190 
1191 static function /df load_itx_file(filename, [options])
1192  string filename
1193  string options
1194 
1195  dfref saveDF = GetDataFolderDFR()
1196  string nickname = itx_suggest_foldername(filename)
1197 
1198  if (ParamIsDefault(options))
1199  options = ""
1200  endif
1201 
1202  setdatafolder root:
1203  newdatafolder /s/o $("root:" + nickname)
1204  dfref dataDF = GetDataFolderDFR()
1205 
1206  // note: some versions of PEARL data files save data to a new data folder,
1207  // and leave the newly created folder as the current folder.
1208  // the free data folder is used by those files which don't create their own data folder.
1209  // this is the new recommended behaviour
1210 
1211  LoadWave /t/p=pearl_explorer_filepath/q filename
1212  svar waves = s_wavenames
1213  dfref actDF = GetDataFolderDFR()
1214  if (v_flag > 0)
1215  string /g pearl_explorer_import = "load_itx_file"
1216  endif
1217 
1218  if (!DataFolderRefsEqual(actDF, dataDF))
1219  // the file created its own data folder.
1220  // let's kill the pre-allocated folder
1221  setdatafolder dataDF
1222  if (ItemsInList(WaveList("*", ";", ""), ";") == 0)
1223  killdatafolder /z dataDF
1224  endif
1225  endif
1226 
1227  setdatafolder saveDF
1228  return actDF
1229 end
1230 
1234 static function /df load_mtrx_file(filename, [options])
1235  string filename
1236  string options
1237 
1238  dfref saveDF = GetDataFolderDFR()
1239  dfref dataDF = $""
1240 
1241 #if exists("MFR_OpenResultFile")
1242  setdatafolder root:
1243  string datasets = ""
1244  datasets = mtrx_load_file("pearl_explorer_filepath", filename)
1245  if (strlen(datasets) > 0)
1246  string /g pearl_explorer_import = "load_mtrx_file"
1247  string s1 = StringFromList(0, datasets)
1248  wave w1 = $s1
1249  dataDF = GetWavesDataFolderDFR(w1)
1250  endif
1251 #endif
1252 
1253  setdatafolder saveDF
1254  return dataDF
1255 end
1256 
1257 function /s itx_suggest_foldername(filename, [ignoredate,sourcename,unique])
1258  // suggests the name of a data folder based on a file name
1259  // if the file name follows the naming convention source-date-index.extension,
1260  // the function tries to generate the nick name as source_date_index.
1261  // otherwise it's just a cleaned up version of the file name.
1262  string filename // file name, including extension. can also include a folder path (which is ignored)
1263  // the extension is currently ignored, but may be used later to select the parent folder
1264  variable ignoredate // if non-zero, the nick name will not include the date part
1265  // defaults to zero
1266  string sourcename // nick name of the data source
1267  // the function tries to detect the source from the file name
1268  // this option can be used to override auto-detection
1269  // allowed values: sscan, otf
1270  variable unique // if non-zero, the resulting name is made a unique data folder name in the current data folder
1271  // defaults to zero
1272 
1273  if (ParamIsDefault(ignoredate))
1274  ignoredate = 0
1275  endif
1276  if (ParamIsDefault(unique))
1277  unique = 0
1278  endif
1279 
1280  string basename = ParseFilePath(3, filename, ":", 0, 0)
1281  string extension = ParseFilePath(4, filename, ":", 0, 0)
1282  string nickname
1283 
1284  string autosource
1285  if (strsearch(basename, "X03DA_PC", 0, 2) >= 0)
1286  autosource = "sscan"
1287  basename = ReplaceString("_", basename, "-")
1288  ignoredate = 1
1289  elseif (strsearch(basename, "otf", 0, 2) >= 0)
1290  autosource = "otf"
1291  endif
1292  if (ParamIsDefault(sourcename))
1293  sourcename = autosource
1294  endif
1295 
1296  variable nparts = ItemsInList(basename, "-")
1297  if (nparts >= 3)
1298  string datepart = StringFromList(nparts - 2, basename, "-")
1299  string indexpart = StringFromList(nparts - 1, basename, "-")
1300  if (ignoredate)
1301  sprintf nickname, "%s_%s", sourcename, indexpart
1302  else
1303  sprintf nickname, "%s_%s_%s", sourcename, datepart, indexpart
1304  endif
1305  else
1306  nickname = PearlCleanupName(basename)
1307  endif
1308 
1309  if (unique && CheckName(nickname, 11))
1310  nickname = UniqueName(nickname + "_", 11, 0)
1311  endif
1312 
1313  return nickname
1314 end
1315 
1316 Window PearlDataExplorer() : Panel
1317  PauseUpdate; Silent 1 // building window...
1318  NewPanel /K=1 /W=(800,0,1530,444) as "PEARL Data Explorer"
1319  ModifyPanel cbRGB=(48640,56832,60160)
1320 
1321  GroupBox gb_filepath,pos={8,4},size={224,52},title="file system folder"
1322  TitleBox tb_filepath,pos={20,24},size={174,20},frame=2
1323  TitleBox tb_filepath,variable=root:packages:pearl_explorer:s_filepath,fixedSize=1
1324  Button b_browse_filepath,pos={200,24},size={20,20},proc=PearlDataExplorer#bp_browse_filepath,title="..."
1325  Button b_browse_filepath,fColor=(65280,48896,32768)
1326 
1327  GroupBox gb_prefs,pos={240,4},size={58,52},title="prefs",help={"explorer package preferences"}
1328  Button b_save_prefs,pos={252,20},size={32,17},proc=PearlDataExplorer#bp_save_prefs,title="save"
1329  Button b_save_prefs,help={"save preferences of the data explorer package (data file path, attributes filter)"}
1330  Button b_save_prefs,fColor=(65280,48896,32768)
1331  Button b_load_prefs,pos={252,36},size={32,17},proc=PearlDataExplorer#bp_load_prefs,title="load"
1332  Button b_load_prefs,help={"load preferences of the data explorer package"}
1333  Button b_load_prefs,fColor=(65280,48896,32768)
1334 
1335  GroupBox gb_filelist,pos={8,64},size={224,372},title="data files"
1336  ListBox lb_files,pos={20,84},size={200,212},proc=PearlDataExplorer#lbp_filelist
1337  ListBox lb_files,listWave=root:packages:pearl_explorer:wtFiles
1338  ListBox lb_files,selWave=root:packages:pearl_explorer:wSelectedFiles,row= 11,mode= 4
1339  TitleBox tb_file_info,pos={20,300},size={198,78},frame=2,fixedSize=1
1340  TitleBox tb_file_info,variable= root:packages:pearl_explorer:s_file_info
1341 
1342  Button b_update_filelist,pos={20,386},size={60,20},proc=PearlDataExplorer#bp_update_filelist,title="update list"
1343  Button b_update_filelist,fColor=(65280,48896,32768)
1344  CheckBox cb_file_preview,pos={84,390},size={60,20},title="preview"
1345  CheckBox cb_file_preview,help={"enable/disable automatic preview window when selecting a data file"}
1346  CheckBox cb_file_preview,value=1
1347  Button b_file_prev,pos={176,386},size={20,20},proc=PearlDataExplorer#bp_file_prev,title="\\W646"
1348  Button b_file_prev,help={"previous file"}
1349  Button b_file_prev,fColor=(65280,48896,32768)
1350  Button b_file_next,pos={200,386},size={20,20},proc=PearlDataExplorer#bp_file_next,title="\\W649"
1351  Button b_file_next,help={"next file"}
1352  Button b_file_next,fColor=(65280,48896,32768)
1353 
1354  Button b_load_files,pos={20,410},size={76,20},proc=PearlDataExplorer#bp_load_files,title="load complete"
1355  Button b_load_files,help={"load the complete contents from the selected files"}
1356  Button b_load_files,fColor=(65280,48896,32768)
1357  Button b_load_files_opt,pos={100,410},size={76,20},proc=PearlDataExplorer#bp_load_files_opt,title="load reduced"
1358  Button b_load_files_opt,help={"load data from the selected files with options (reduced dimensions)"}
1359  Button b_load_files_opt,fColor=(65280,48896,32768)
1360 
1361  // datasets group
1362  GroupBox gb_datasets,pos={240,64},size={224,372},title="datasets"
1363  ListBox lb_datasets,pos={252,84},size={200,300},proc=PearlDataExplorer#lbp_datasets,help={"list of loaded datasets"}
1364  ListBox lb_datasets,listWave=root:packages:pearl_explorer:wtDatasets
1365  ListBox lb_datasets,selWave=root:packages:pearl_explorer:wSelectedDatasets,mode= 1
1366  ListBox lb_datasets,selRow= -1
1367 
1368  Button b_update_datasets,pos={252,386},size={60,20},proc=PearlDataExplorer#bp_update_datasets,title="update list"
1369  Button b_update_datasets,help={"update the list of datasets"}
1370  Button b_update_datasets,fColor=(65280,48896,32768)
1371  CheckBox cb_dataset_preview,pos={316,390},size={60,20},title="preview"
1372  CheckBox cb_dataset_preview,help={"enable/disable automatic preview window when selecting a dataset"}
1373  CheckBox cb_dataset_preview,value=0
1374  Button b_dataset_prev,pos={408,386},size={20,20},proc=PearlDataExplorer#bp_dataset_prev,title="\\W646"
1375  Button b_dataset_prev,help={"goto previous dataset"}
1376  Button b_dataset_prev,fColor=(65280,48896,32768)
1377  Button b_dataset_next,pos={432,386},size={20,20},proc=PearlDataExplorer#bp_dataset_next,title="\\W649"
1378  Button b_dataset_next,help={"goto next dataset"}
1379  Button b_dataset_next,fColor=(65280,48896,32768)
1380 
1381  Button b_dataset_folder,pos={252,410},size={50,20},proc=PearlDataExplorer#bp_dataset_folder,title="goto DF"
1382  Button b_dataset_folder,help={"set the current data folder of the selected dataset"}
1383  Button b_dataset_folder,fColor=(65280,48896,32768)
1384  Button b_dataset_display,pos={306,410},size={50,20},proc=PearlDataExplorer#bp_dataset_display,title="display"
1385  Button b_dataset_display,help={"display the selected dataset in its own window"}
1386  Button b_dataset_display,fColor=(65280,48896,32768)
1387 
1388  GroupBox gb_preview,pos={472,4},size={250,52},title="preview"
1389  TitleBox tb_preview_file,pos={484,24},size={226,20},frame=2
1390  TitleBox tb_preview_file,variable=root:packages:pearl_explorer:s_preview_file,fixedSize=1
1391 
1392  GroupBox gb_attributes,pos={472,64},size={250,372},title="attributes"
1393  Button b_attr_notebook,pos={484,386},size={60,20},proc=PearlDataExplorer#bp_attr_notebook,title="notebook"
1394  Button b_attr_notebook,help={"show attribute list in a notebook"}
1395  Button b_attr_notebook,fColor=(65280,48896,32768)
1396 
1397  String fldrSav0= GetDataFolder(1)
1398  SetDataFolder root:packages:pearl_explorer:
1399  Edit/W=(484,84,710,384)/HOST=# attr_names,attr_values
1400  ModifyTable format(Point)=1,width(Point)=0,width(attr_names)=103,width(attr_values)=103
1401  ModifyTable statsArea=85
1402  SetDataFolder fldrSav0
1403  RenameWindow #,T0
1404  SetActiveSubwindow ##
1405 EndMacro
1406 
1407 static function bp_load_prefs(ba) : ButtonControl
1408  STRUCT WMButtonAction &ba
1409 
1410  switch( ba.eventCode )
1411  case 2: // mouse up
1412  load_prefs()
1413  break
1414  case -1: // control being killed
1415  break
1416  endswitch
1417 
1418  return 0
1419 End
1420 
1421 static function bp_save_prefs(ba) : ButtonControl
1422  STRUCT WMButtonAction &ba
1423 
1424  switch( ba.eventCode )
1425  case 2: // mouse up
1426  save_prefs()
1427  break
1428  case -1: // control being killed
1429  break
1430  endswitch
1431 
1432  return 0
1433 End
1434 
1435 static function bp_browse_filepath(ba) : ButtonControl
1436  STRUCT WMButtonAction &ba
1437 
1438  dfref saveDF = GetDataFolderDFR()
1439 
1440  switch( ba.eventCode )
1441  case 2: // mouse up
1442  PathInfo /S pearl_explorer_filepath
1443  NewPath /M="select data file folder" /O/Z pearl_explorer_filepath
1444  if (v_flag == 0)
1445  PathInfo /S pearl_explorer_filepath
1446  svar filepath = $(package_path + "s_filepath")
1447  filepath = s_path
1448  update_filelist()
1449  endif
1450  break
1451  case -1: // control being killed
1452  break
1453  endswitch
1454 
1455  setdatafolder saveDF
1456  return 0
1457 End
1458 
1459 static function bp_update_filelist(ba) : ButtonControl
1460  STRUCT WMButtonAction &ba
1461 
1462  switch( ba.eventCode )
1463  case 2: // mouse up
1464  update_filelist()
1465  break
1466  case -1: // control being killed
1467  break
1468  endswitch
1469 
1470  return 0
1471 End
1472 
1473 static function bp_load_files(ba) : ButtonControl
1474  STRUCT WMButtonAction &ba
1475 
1476  switch( ba.eventCode )
1477  case 2: // mouse up
1479  break
1480  case -1: // control being killed
1481  break
1482  endswitch
1483 
1484  return 0
1485 End
1486 
1487 static function bp_load_files_opt(ba) : ButtonControl
1488  STRUCT WMButtonAction &ba
1489 
1490  switch( ba.eventCode )
1491  case 2: // mouse up
1492  load_selected_files(options="")
1493  break
1494  case -1: // control being killed
1495  break
1496  endswitch
1497 
1498  return 0
1499 End
1500 
1501 static function bp_file_next(ba) : ButtonControl
1502  STRUCT WMButtonAction &ba
1503 
1504  dfref saveDF = GetDataFolderDFR()
1505 
1506  switch( ba.eventCode )
1507  case 2: // mouse up
1508  setdatafolder $package_path
1509  wave /t wtFiles
1510  wave wSelectedFiles
1511  FindValue /i=1 wSelectedFiles
1512  v_value += 1
1513  if (v_value >= numpnts(wtFiles))
1514  v_value = min(numpnts(wtFiles) - 1, 0)
1515  endif
1516  wSelectedFiles = p == v_value
1517  if (v_value >= 0)
1518  variable ifile = v_value
1519  ControlInfo /W=PearlDataExplorer cb_file_preview
1520  if (v_value)
1521  preview_file(wtFiles[ifile])
1522  endif
1523  endif
1524  break
1525  case -1: // control being killed
1526  break
1527  endswitch
1528 
1529  setdatafolder saveDF
1530  return 0
1531 End
1532 
1533 static function bp_file_prev(ba) : ButtonControl
1534  STRUCT WMButtonAction &ba
1535 
1536  dfref saveDF = GetDataFolderDFR()
1537 
1538  switch( ba.eventCode )
1539  case 2: // mouse up
1540  setdatafolder $package_path
1541  wave /t wtFiles
1542  wave wSelectedFiles
1543  FindValue /i=1 wSelectedFiles
1544  v_value -= 1
1545  if (v_value < 0)
1546  v_value = numpnts(wtFiles) - 1
1547  endif
1548  wSelectedFiles = p == v_value
1549  if (v_value >= 0)
1550  variable ifile = v_value
1551  ControlInfo /W=PearlDataExplorer cb_file_preview
1552  if (v_value)
1553  preview_file(wtFiles[ifile])
1554  endif
1555  endif
1556  break
1557  case -1: // control being killed
1558  break
1559  endswitch
1560 
1561  setdatafolder saveDF
1562  return 0
1563 End
1564 
1565 static function lbp_filelist(lba) : ListBoxControl
1566  STRUCT WMListboxAction &lba
1567 
1568  Variable row = lba.row
1569  Variable col = lba.col
1570  WAVE/T/Z listWave = lba.listWave
1571  WAVE/Z selWave = lba.selWave
1572 
1573  switch( lba.eventCode )
1574  case -1: // control being killed
1575  break
1576  case 1: // mouse down
1577  if (selWave[row])
1578  ControlInfo /W=PearlDataExplorer cb_file_preview
1579  if (v_value)
1580  preview_file(listWave[row])
1581  endif
1582  endif
1583  break
1584  case 3: // double click
1585  break
1586  case 4: // cell selection
1587  case 5: // cell selection plus shift key
1588  break
1589  case 6: // begin edit
1590  break
1591  case 7: // finish edit
1592  break
1593  case 13: // checkbox clicked (Igor 6.2 or later)
1594  break
1595  endswitch
1596 
1597  return 0
1598 End
1599 
1600 static function bp_update_datasets(ba) : ButtonControl
1601  STRUCT WMButtonAction &ba
1602 
1603  switch( ba.eventCode )
1604  case 2: // mouse up
1605  update_datasets()
1606  break
1607  case -1: // control being killed
1608  break
1609  endswitch
1610 
1611  return 0
1612 End
1613 
1614 static function bp_dataset_folder(ba) : ButtonControl
1615  STRUCT WMButtonAction &ba
1616 
1617  switch( ba.eventCode )
1618  case 2: // mouse up
1619  ControlInfo /W=PearlDataExplorer lb_datasets
1620  if (v_value >= 0)
1621  setdatafolder $package_path
1622  wave /t wtDatasets
1623  string dataset = wtDatasets[v_value]
1624  string cmd
1625  sprintf cmd, "setdatafolder root:%s", PossiblyQuoteName(dataset)
1626  execute /q /z cmd
1627  cmd = "setdatafolder :scan1"
1628  execute /q /z cmd
1629  sprintf cmd, "setdatafolder %s", GetDataFolder(1)
1630  print cmd
1631  endif
1632  break
1633  case -1: // control being killed
1634  break
1635  endswitch
1636 
1637  return 0
1638 End
1639 
1640 static function bp_dataset_display(ba) : ButtonControl
1641  STRUCT WMButtonAction &ba
1642 
1643  switch( ba.eventCode )
1644  case 2: // mouse up
1645  ControlInfo /W=PearlDataExplorer lb_datasets
1646  if (v_value >= 0)
1647  setdatafolder $package_path
1648  wave /t wtDatasets
1649  string dataset = wtDatasets[v_value]
1650  display_dataset(dataset)
1651  endif
1652  break
1653  case -1: // control being killed
1654  break
1655  endswitch
1656 
1657  return 0
1658 End
1659 
1660 static function bp_dataset_next(ba) : ButtonControl
1661  STRUCT WMButtonAction &ba
1662 
1663  switch( ba.eventCode )
1664  case 2: // mouse up
1665  ControlInfo /W=PearlDataExplorer lb_datasets
1666  wave /t wtDatasets = $(s_datafolder + s_value)
1667  v_value += 1
1668  if (v_value >= numpnts(wtDatasets))
1669  v_value = min(0, numpnts(wtDatasets) - 1)
1670  endif
1671  ListBox lb_datasets win=PearlDataExplorer, selRow=v_value
1672  if (v_value >= 0)
1673  variable ids = v_value
1674  ControlInfo /W=PearlDataExplorer cb_dataset_preview
1675  if (v_value)
1676  preview_dataset(wtDatasets[ids])
1677  endif
1678  endif
1679  break
1680  case -1: // control being killed
1681  break
1682  endswitch
1683 
1684  return 0
1685 End
1686 
1687 static function bp_dataset_prev(ba) : ButtonControl
1688  STRUCT WMButtonAction &ba
1689 
1690  switch( ba.eventCode )
1691  case 2: // mouse up
1692  ControlInfo /W=PearlDataExplorer lb_datasets
1693  wave /t wtDatasets = $(s_datafolder + s_value)
1694  v_value -= 1
1695  if (v_value < 0)
1696  v_value = max(-1, numpnts(wtDatasets) - 1)
1697  endif
1698  ListBox lb_datasets win=PearlDataExplorer, selRow=v_value
1699  if (v_value >= 0)
1700  variable ids = v_value
1701  ControlInfo /W=PearlDataExplorer cb_dataset_preview
1702  if (v_value)
1703  preview_dataset(wtDatasets[ids])
1704  endif
1705  endif
1706  break
1707  case -1: // control being killed
1708  break
1709  endswitch
1710 
1711  return 0
1712 End
1713 
1714 static function lbp_datasets(lba) : ListBoxControl
1715  STRUCT WMListboxAction &lba
1716 
1717  Variable row = lba.row
1718  Variable col = lba.col
1719  WAVE/T/Z listWave = lba.listWave
1720  WAVE/Z selWave = lba.selWave
1721 
1722  switch( lba.eventCode )
1723  case -1: // control being killed
1724  break
1725  case 1: // mouse down
1726  if (row >= 0)
1727  ControlInfo /W=PearlDataExplorer cb_dataset_preview
1728  if (v_value)
1729  preview_dataset(listWave[row])
1730  endif
1731  endif
1732  break
1733  case 3: // double click
1734  break
1735  case 4: // cell selection
1736  case 5: // cell selection plus shift key
1737  break
1738  case 6: // begin edit
1739  break
1740  case 7: // finish edit
1741  break
1742  case 13: // checkbox clicked (Igor 6.2 or later)
1743  break
1744  endswitch
1745 
1746  return 0
1747 End
1748 
1749 static function bp_attr_notebook(ba) : ButtonControl
1750  STRUCT WMButtonAction &ba
1751 
1752  dfref saveDF = GetDataFolderDFR()
1753 
1754  switch( ba.eventCode )
1755  case 2: // mouse up
1756  setdatafolder $package_path
1757  svar s_preview_file
1758  wave /t /z attr_names
1759  wave /t /z attr_values
1760  if (WaveExists(attr_names))
1761  attributes_notebook(attr_names, attr_values, s_preview_file)
1762  endif
1763  break
1764  case -1: // control being killed
1765  break
1766  endswitch
1767 
1768  setdatafolder saveDF
1769  return 0
1770 End
static dfr load_mtrx_file(string filename, string options=defaultValue)
load a matrix (STM) data file
+
static const string package_path
+
string adh5_load_preview(string ANickName, string APathName, string AFileName, variable load_data=defaultValue, variable load_attr=defaultValue)
load a single image from a HDF5 file created by the Area Detector software.
+
static variable update_datasets()
+
string psh5_load_reduced(string ANickName, string APathName, string AFileName, funcref reduction_func, string reduction_param, variable progress=defaultValue, variable nthreads=defaultValue)
load and reduce the ScientaImage dataset of the first scan of a PShell data file. ...
+
static variable bp_browse_filepath(WMButtonAction *ba)
+
static variable preview_file(string filename)
+
variable prompt_default_process(string *param)
prototype for prompting for processing function parameters.
+
string adh5_load_info(string APathName, string AFileName)
load descriptive info from a HDF5 file created by the Area Detector software.
+
static variable bp_dataset_prev(WMButtonAction *ba)
+
static string display_preview_trace(wave xtrace, wave ytrace)
+
static variable bp_file_prev(WMButtonAction *ba)
+
variable ad_brick_slicer(wave data)
open a slicer panel for 3D data.
interface for writing ELOG entries with Igor graphs as attachment.
-
static variable lbp_datasets(WMListboxAction *lba)
-
static variable bp_load_files_opt(WMButtonAction *ba)
-
static variable load_selected_files(string options=defaultValue)
-
static variable bp_load_files(WMButtonAction *ba)
-
static variable preview_datafolder()
-
static variable bp_file_next(WMButtonAction *ba)
-
static variable lbp_filelist(WMListboxAction *lba)
-
static variable prompt_hdf_options(string *options)
-
static variable bp_update_datasets(WMButtonAction *ba)
-
static const string ks_filematch_pshell
-
static const string ks_filematch_adh5
-
static wave preview_mtrx_file(string filename)
load the preview of a Matrix STM file.
-
static variable init_package()
initialize the global variables of the data explorer.
-
static wave preview_pshell_file(string filename)
load the preview of a PShell HDF5 file.
-
static variable bp_dataset_folder(WMButtonAction *ba)
-
static variable preview_dataset(string datasetname)
-
static const string package_name
-
static variable update_filelist()
read a list of PEARL files from the file system
-
static dfr load_itx_file(string filename, string options=defaultValue)
-
string psh5_load_preview(string APathName, string AFileName, variable load_data=defaultValue, variable load_attr=defaultValue, string pref_scans=defaultValue, string pref_datasets=defaultValue)
load a preview image from a PShell data file.
-
static variable bp_attr_notebook(WMButtonAction *ba)
-
static variable load_file(string filename, string options=defaultValue)
+
static variable lbp_datasets(WMListboxAction *lba)
+
static variable bp_load_files_opt(WMButtonAction *ba)
+
static variable load_selected_files(string options=defaultValue)
+
string PearlCleanupName(string name)
+
static variable bp_load_files(WMButtonAction *ba)
+
static variable preview_datafolder()
+
static variable bp_file_next(WMButtonAction *ba)
+
static variable lbp_filelist(WMListboxAction *lba)
+
static variable prompt_hdf_options(string *options)
+
static variable bp_update_datasets(WMButtonAction *ba)
+
static const string ks_filematch_pshell
+
static const string ks_filematch_adh5
+
static wave preview_mtrx_file(string filename)
load the preview of a Matrix STM file.
+
static variable init_package()
initialize the global variables of the data explorer.
+
static wave preview_pshell_file(string filename)
load the preview of a PShell HDF5 file.
+
static variable bp_dataset_folder(WMButtonAction *ba)
+
static variable preview_dataset(string datasetname)
+
static const string package_name
+
static variable update_filelist()
read a list of PEARL files from the file system
+
static dfr load_itx_file(string filename, string options=defaultValue)
+
string psh5_load_preview(string APathName, string AFileName, variable load_data=defaultValue, variable load_attr=defaultValue, string pref_scans=defaultValue, string pref_datasets=defaultValue)
load a preview image from a PShell data file.
+
static variable bp_attr_notebook(WMButtonAction *ba)
+
static variable load_file(string filename, string options=defaultValue)
preview and import panel for PEARL data
-
static variable bp_load_prefs(WMButtonAction *ba)
-
static variable preview_setscale_x(wave data, wave preview)
-
static variable bp_save_prefs(WMButtonAction *ba)
-
static dfr load_hdf_file(string filename, string options=defaultValue)
-
string ad_suggest_foldername(string filename, variable ignoredate=defaultValue, string sourcename=defaultValue, variable unique=defaultValue)
generate the name of a data folder based on a file name.
-
static wave preview_hdf_file(string filename)
load the preview of a PEARL HDF5 file.
-
static variable pearl_file_type(string filename)
check whether a file can be imported by this module.
-
static variable bp_dataset_display(WMButtonAction *ba)
-
static const string ks_filematch_itx
-
string adh5_load_complete(string ANickName, string APathName, string AFileName, variable load_data=defaultValue, variable load_attr=defaultValue)
import everything from a HDF5 file created by the Area Detector software.
-
static variable bp_dataset_next(WMButtonAction *ba)
-
static variable extract_preview_image(wave data, wave preview)
-
string psh5_load_info(string APathName, string AFileName)
load descriptive info from a PShell data file.
-
string adh5_load_reduced(string ANickName, string APathName, string AFileName, funcref reduction_func, string reduction_param, variable load_data=defaultValue, variable load_attr=defaultValue, variable progress=defaultValue)
load and reduce a dataset from a HDF5 file created by the Area Detector software. ...
-
string ad_display_profiles(wave image, string filter=defaultValue)
open a new profiles graph window.
-
static variable bp_update_filelist(WMButtonAction *ba)
-
variable pearl_data_explorer()
-
string itx_suggest_foldername(string filename, variable ignoredate=defaultValue, string sourcename=defaultValue, variable unique=defaultValue)
-
string psh5_load_complete(string ANickName, string APathName, string AFileName, variable load_data=defaultValue, variable load_attr=defaultValue)
load everything from a PShell data file.
-
static variable load_prefs()
-
variable prompt_func_params(string func_name, string *func_param)
-
static wave preview_itx_file(string filename)
load the preview of a general ITX file.
-
static variable display_dataset(string datasetname)
-
static dfr load_pshell_file(string filename, string options=defaultValue)
-
static variable save_prefs()
-
variable test_attributes_notebook()
-
static string show_preview_graph(wave data, wave xdata=defaultValue)
+
static variable bp_load_prefs(WMButtonAction *ba)
+
static variable preview_setscale_x(wave data, wave preview)
+
static variable bp_save_prefs(WMButtonAction *ba)
+
static dfr load_hdf_file(string filename, string options=defaultValue)
+
string ad_suggest_foldername(string filename, variable ignoredate=defaultValue, string sourcename=defaultValue, variable unique=defaultValue)
generate the name of a data folder based on a file name.
+
static wave preview_hdf_file(string filename)
load the preview of a PEARL HDF5 file.
+
static variable pearl_file_type(string filename)
check whether a file can be imported by this module.
+
static variable bp_dataset_display(WMButtonAction *ba)
+
static const string ks_filematch_itx
+
string adh5_load_complete(string ANickName, string APathName, string AFileName, variable load_data=defaultValue, variable load_attr=defaultValue)
import everything from a HDF5 file created by the Area Detector software.
+
static variable bp_dataset_next(WMButtonAction *ba)
+
static variable extract_preview_image(wave data, wave preview)
+
string psh5_load_info(string APathName, string AFileName)
load descriptive info from a PShell data file.
+
string adh5_load_reduced(string ANickName, string APathName, string AFileName, funcref reduction_func, string reduction_param, variable load_data=defaultValue, variable load_attr=defaultValue, variable progress=defaultValue)
load and reduce a dataset from a HDF5 file created by the Area Detector software. ...
+
string ad_display_profiles(wave image, string filter=defaultValue)
open a new profiles graph window.
+
static variable bp_update_filelist(WMButtonAction *ba)
+
variable pearl_data_explorer()
+
string itx_suggest_foldername(string filename, variable ignoredate=defaultValue, string sourcename=defaultValue, variable unique=defaultValue)
+
string psh5_load_complete(string ANickName, string APathName, string AFileName, variable load_data=defaultValue, variable load_attr=defaultValue)
load everything from a PShell data file.
+
static variable load_prefs()
+
variable prompt_func_params(string func_name, string *func_param)
+
static wave preview_itx_file(string filename)
load the preview of a general ITX file.
+
static variable display_dataset(string datasetname)
+
static dfr load_pshell_file(string filename, string options=defaultValue)
+
static variable save_prefs()
+
variable test_attributes_notebook()
+
static string show_preview_graph(wave data, wave xdata=defaultValue)
string mtrx_load_preview(string destName, string pathName, string fileName, string traces=defaultValue)
load a preview image from a Matrix data file.
-
string ad_display_slice(wave data)
display three-dimensional data by 2D slice.
-
static const string ks_filematch_mtrx
-
static variable attributes_notebook(wave attr_names, wave attr_values, string title)
+
string ad_display_slice(wave data)
display three-dimensional data by 2D slice.
+
static const string ks_filematch_mtrx
+
static variable attributes_notebook(wave attr_names, wave attr_values, string title)
string mtrx_load_file(string pathName, string fileName, string traces=defaultValue)
load all data from a Matrix data file.
-
static variable preview_attributes(dfref attr_folder, dfref dest_folder=defaultValue, wave attr_filter=defaultValue, variable include_datawaves=defaultValue, variable include_infowaves=defaultValue)
-
string adh5_list_reduction_funcs()
get a list of functions which can be used as reduction functions.
-
static variable notebook_add_attributes(string notebook_name, wave attr_filter, wave attr_names, wave attr_values)
+
static variable preview_attributes(dfref attr_folder, dfref dest_folder=defaultValue, wave attr_filter=defaultValue, variable include_datawaves=defaultValue, variable include_infowaves=defaultValue)
+
string adh5_list_reduction_funcs()
get a list of functions which can be used as reduction functions.
+
static variable notebook_add_attributes(string notebook_name, wave attr_filter, wave attr_names, wave attr_values)
threadsafe wave ad_extract_slab(wave dataset, variable x1, variable x2, variable y1, variable y2, variable z1, variable z2, string destname, variable noavg=defaultValue, variable pscale=defaultValue)
2D cut through 3D dataset, integrate in normal dimension
@@ -164,7 +165,7 @@ $(document).ready(function(){initNavTree('pearl-data-explorer_8ipf_source.html', @@ -652,7 +653,7 @@ Licensed under the Apache License, Version 2.0 (the "License");
-

Definition at line 1384 of file pearl-pshell-import.ipf.

+

Definition at line 1402 of file pearl-pshell-import.ipf.

@@ -681,7 +682,7 @@ Licensed under the Apache License, Version 2.0 (the "License");
-

Definition at line 139 of file pearl-pshell-import.ipf.

+

Definition at line 140 of file pearl-pshell-import.ipf.

@@ -730,7 +731,7 @@ Licensed under the Apache License, Version 2.0 (the "License");
Returns
semicolon-separated list of dataset paths.
Version
since version 1.03 this function returns paths relative to scanpath.
-

Definition at line 439 of file pearl-pshell-import.ipf.

+

Definition at line 440 of file pearl-pshell-import.ipf.

@@ -771,7 +772,7 @@ Licensed under the Apache License, Version 2.0 (the "License");
Returns
semicolon-separated list of datagroup paths.
-

Definition at line 480 of file pearl-pshell-import.ipf.

+

Definition at line 481 of file pearl-pshell-import.ipf.

@@ -801,7 +802,7 @@ Licensed under the Apache License, Version 2.0 (the "License");
Returns
semicolon-separated list of group paths.
-

Definition at line 404 of file pearl-pshell-import.ipf.

+

Definition at line 405 of file pearl-pshell-import.ipf.

@@ -874,7 +875,7 @@ global string s_filepath in new data folder contains the full file path on disk.
global string s_scanpaths in new data folder contains a list of scan groups inside the file.
-

Definition at line 169 of file pearl-pshell-import.ipf.

+

Definition at line 170 of file pearl-pshell-import.ipf.

@@ -940,7 +941,7 @@ global string s_scanpaths in new data folder contains a list of scan groups insi
Returns
name of loaded wave if successful. empty string otherwise.
Version
this function supports regions as of version 1.03.
-

Definition at line 688 of file pearl-pshell-import.ipf.

+

Definition at line 706 of file pearl-pshell-import.ipf.

@@ -996,7 +997,7 @@ global string s_scanpaths in new data folder contains a list of scan groups insi
Returns
0 if successful, non-zero if an error occurred.
-

Definition at line 1073 of file pearl-pshell-import.ipf.

+

Definition at line 1091 of file pearl-pshell-import.ipf.

@@ -1084,7 +1085,7 @@ global string s_scanpaths in new data folder contains a list of scan groups insi
Returns
semicolon-separated list of the loaded dataset ReducedData1, ReducedData2, etc. if successful. auxiliary waves, scan positions, attributes are loaded but not listed in the string. empty string if an error occurred. error messages are printed to the history.
Version
this function supports regions as of version 1.03.
-

Definition at line 2022 of file pearl-pshell-import.ipf.

+

Definition at line 2040 of file pearl-pshell-import.ipf.

@@ -1160,7 +1161,7 @@ global string s_scanpaths in new data folder contains a list of scan groups insi
Returns
name of loaded wave if successful. empty string otherwise.
-

Definition at line 1266 of file pearl-pshell-import.ipf.

+

Definition at line 1284 of file pearl-pshell-import.ipf.

@@ -1219,7 +1220,7 @@ global string s_scanpaths in new data folder contains a list of scan groups insi
Returns
name of loaded wave if successful. empty string otherwise.
-

Definition at line 1130 of file pearl-pshell-import.ipf.

+

Definition at line 1148 of file pearl-pshell-import.ipf.

@@ -1265,7 +1266,7 @@ global string s_scanpaths in new data folder contains a list of scan groups insi
Returns
newline terminated string.
-

Definition at line 2349 of file pearl-pshell-import.ipf.

+

Definition at line 2367 of file pearl-pshell-import.ipf.

@@ -1334,7 +1335,7 @@ global string s_scanpaths in new data folder contains a list of scan groups insi
Returns
name of loaded preview wave.
-

Definition at line 250 of file pearl-pshell-import.ipf.

+

Definition at line 251 of file pearl-pshell-import.ipf.

@@ -1426,7 +1427,7 @@ global string s_filepath in new data folder contains the full file path on disk.
global string s_scanpaths in new data folder contains a list of scan groups inside the file.
-

Definition at line 1893 of file pearl-pshell-import.ipf.

+

Definition at line 1911 of file pearl-pshell-import.ipf.

@@ -1479,7 +1480,7 @@ global string s_scanpaths in new data folder contains a list of scan groups insi
Returns
semicolon-separated list of the loaded waves.
-

Definition at line 553 of file pearl-pshell-import.ipf.

+

Definition at line 554 of file pearl-pshell-import.ipf.

@@ -1542,7 +1543,7 @@ global string s_scanpaths in new data folder contains a list of scan groups insi
Returns
semicolon-separated list of the loaded data waves (excluding attributes).
-

Definition at line 360 of file pearl-pshell-import.ipf.

+

Definition at line 361 of file pearl-pshell-import.ipf.

@@ -1584,7 +1585,7 @@ global string s_scanpaths in new data folder contains a list of scan groups insi
Returns
semicolon-separated list of the loaded waves.
-

Definition at line 513 of file pearl-pshell-import.ipf.

+

Definition at line 514 of file pearl-pshell-import.ipf.

@@ -1630,7 +1631,7 @@ global string s_scanpaths in new data folder contains a list of scan groups insi
Returns
newline terminated string.
-

Definition at line 2396 of file pearl-pshell-import.ipf.

+

Definition at line 2414 of file pearl-pshell-import.ipf.

@@ -1667,6 +1668,9 @@ global string s_scanpaths in new data folder contains a list of scan groups insi
  • Writables (ScanWritables)
  • Readables (ScanReadables)
  • Steps (ScanSteps)
  • +
  • Iterations (ScanIterations) - if present (XPSSpectrum script)
  • +
  • Step Size (ScanStepSize) - if present (XPSSpectrum script)
  • +
  • Step Time (ScanStepTime) - if present (XPSSpectrum script)
  • if they are missing in the file, ScanDimensions and ScanReadables are set to default values assuming the file contains a single spectrum.

    data is loaded into the current data folder.

    @@ -1679,7 +1683,7 @@ global string s_scanpaths in new data folder contains a list of scan groups insi
    Returns
    semicolon-separated list of the loaded waves.
    -

    Definition at line 621 of file pearl-pshell-import.ipf.

    +

    Definition at line 625 of file pearl-pshell-import.ipf.

    @@ -1738,7 +1742,7 @@ global string s_scanpaths in new data folder contains a list of scan groups insi
    Returns
    name of loaded wave if successful. empty string otherwise.
    -

    Definition at line 822 of file pearl-pshell-import.ipf.

    +

    Definition at line 840 of file pearl-pshell-import.ipf.

    @@ -1805,7 +1809,7 @@ global string s_scanpaths in new data folder contains a list of scan groups insi
    Returns
    name of loaded wave if successful. empty string otherwise.
    Warning
    EXPERIMENTAL: this function is under development.
    -

    Definition at line 935 of file pearl-pshell-import.ipf.

    +

    Definition at line 953 of file pearl-pshell-import.ipf.

    @@ -1858,7 +1862,7 @@ global string s_filepath in new data folder contains the full file path on disk.
    global string s_scanpaths in new data folder contains a list of scan groups inside the file.
    -

    Definition at line 109 of file pearl-pshell-import.ipf.

    +

    Definition at line 110 of file pearl-pshell-import.ipf.

    @@ -1908,7 +1912,7 @@ global string s_scanpaths in new data folder contains a list of scan groups insi
    -

    Definition at line 2323 of file pearl-pshell-import.ipf.

    +

    Definition at line 2341 of file pearl-pshell-import.ipf.

    @@ -1936,7 +1940,7 @@ global string s_scanpaths in new data folder contains a list of scan groups insi
    -

    Definition at line 2284 of file pearl-pshell-import.ipf.

    +

    Definition at line 2302 of file pearl-pshell-import.ipf.

    @@ -1984,7 +1988,7 @@ global string s_scanpaths in new data folder contains a list of scan groups insi
    Returns
    selected dataset.
    -

    Definition at line 760 of file pearl-pshell-import.ipf.

    +

    Definition at line 778 of file pearl-pshell-import.ipf.

    @@ -2024,7 +2028,7 @@ global string s_scanpaths in new data folder contains a list of scan groups insi

    convert text wave to list.

    -

    Definition at line 2455 of file pearl-pshell-import.ipf.

    +

    Definition at line 2473 of file pearl-pshell-import.ipf.

    @@ -2070,7 +2074,7 @@ global string s_scanpaths in new data folder contains a list of scan groups insi

    convert numeric wave to list.

    -

    Definition at line 2472 of file pearl-pshell-import.ipf.

    +

    Definition at line 2490 of file pearl-pshell-import.ipf.

    @@ -2089,7 +2093,7 @@ global string s_scanpaths in new data folder contains a list of scan groups insi

    Dimension label for the angle dispersive dimension of multi-dimensional datasets.

    -

    Definition at line 67 of file pearl-pshell-import.ipf.

    +

    Definition at line 68 of file pearl-pshell-import.ipf.

    @@ -2108,7 +2112,7 @@ global string s_scanpaths in new data folder contains a list of scan groups insi

    Dimension label for the data dimension.

    This label may be used to store the parameters for the setscale d operation.

    -

    Definition at line 74 of file pearl-pshell-import.ipf.

    +

    Definition at line 75 of file pearl-pshell-import.ipf.

    @@ -2119,14 +2123,14 @@ global string s_scanpaths in new data folder contains a list of scan groups insi
    - +
    const variable kDetectorSensitivity = 4const variable kDetectorSensitivity = 1

    multiply scienta detector intensity by this value to get actual counts.

    -

    Definition at line 86 of file pearl-pshell-import.ipf.

    +

    Definition at line 87 of file pearl-pshell-import.ipf.

    @@ -2144,7 +2148,7 @@ global string s_scanpaths in new data folder contains a list of scan groups insi

    Dimension label for the energy dispersive dimension of multi-dimensional datasets.

    -

    Definition at line 64 of file pearl-pshell-import.ipf.

    +

    Definition at line 65 of file pearl-pshell-import.ipf.

    @@ -2162,7 +2166,7 @@ global string s_scanpaths in new data folder contains a list of scan groups insi

    List of preferred datasets to load for preview.

    -

    Definition at line 77 of file pearl-pshell-import.ipf.

    +

    Definition at line 78 of file pearl-pshell-import.ipf.

    @@ -2180,7 +2184,7 @@ global string s_scanpaths in new data folder contains a list of scan groups insi

    Dimension label for the scan dimension of multi-dimensional datasets.

    -

    Definition at line 70 of file pearl-pshell-import.ipf.

    +

    Definition at line 71 of file pearl-pshell-import.ipf.

    @@ -2198,7 +2202,7 @@ global string s_scanpaths in new data folder contains a list of scan groups insi

    List of datasets that must be loaded to determine the axis scaling of a Scienta image.

    -

    Definition at line 80 of file pearl-pshell-import.ipf.

    +

    Definition at line 81 of file pearl-pshell-import.ipf.

    @@ -2216,7 +2220,7 @@ global string s_scanpaths in new data folder contains a list of scan groups insi

    List of datasets that should be transposed upon loading.

    -

    Definition at line 83 of file pearl-pshell-import.ipf.

    +

    Definition at line 84 of file pearl-pshell-import.ipf.

    @@ -2226,7 +2230,7 @@ global string s_scanpaths in new data folder contains a list of scan groups insi
    -Go to the documentation of this file.
    1 #pragma rtGlobals=3 // Use modern global access method and strict wave access.
    2 #pragma IgorVersion = 6.36
    3 #pragma ModuleName = PearlPShellImport
    4 #include <HDF5 Browser>
    5 #include "pearl-gui-tools"
    6 #include "pearl-area-import"
    7 
    8 // copyright (c) 2013-18 Paul Scherrer Institut
    9 //
    10 // Licensed under the Apache License, Version 2.0 (the "License");
    11 // you may not use this file except in compliance with the License.
    12 // You may obtain a copy of the License at
    13 // http:///www.apache.org/licenses/LICENSE-2.0
    14 
    57 
    62 
    64 strconstant kEnergyDimLabel = "energy"
    65 
    67 strconstant kAngleDimLabel = "angle"
    68 
    70 strconstant kScanDimLabel = "scan"
    71 
    74 strconstant kDataDimLabel = "data"
    75 
    77 strconstant kPreviewDatasets = "ScientaImage;ScientaSpectrum;ImageAngleDistribution;ImageEnergyDistribution;Counts;SampleCurrent;"
    78 
    80 strconstant kScientaScalingDatasets = "LensMode;ScientaChannelBegin;ScientaChannelEnd;ScientaSliceBegin;ScientaSliceEnd;"
    81 
    83 strconstant kTransposedDatasets = "ScientaImage;"
    84 
    87 
    109 function psh5_open_file(ANickName, APathName, AFileName)
    110  string ANickName
    111  string APathName
    112  string AFileName
    113 
    114  setdatafolder root:
    115  newdatafolder /s /o $("root:" + ANickName)
    116  dfref fileDF = GetDataFolderDFR()
    117 
    118  variable fileID
    119  HDF5OpenFile /P=$APathName /R fileID as AFileName
    120  if (v_flag == 0)
    121  string /g s_filepath
    122  string /g s_scanpaths
    123  s_filepath = s_path + s_filename
    124  s_scanpaths = psh5_list_scans(fileID)
    125  else
    126  fileID = 0
    127  endif
    128 
    129  return fileID
    130 end
    131 
    139 function psh5_close_file(fileID)
    140  variable fileID
    141 
    142  HDF5CloseFile fileID
    143 end
    144 
    169 function /s psh5_load_complete(ANickName, APathName, AFileName, [load_data, load_attr])
    170  string ANickName
    171  string APathName
    172  string AFileName
    173  variable load_data
    174  variable load_attr
    175 
    176  if (ParamIsDefault(load_data))
    177  load_data = 1
    178  endif
    179  if (ParamIsDefault(load_attr))
    180  load_attr = 1
    181  endif
    182 
    183  dfref saveDF = GetDataFolderDFR()
    184 
    185  // performance monitoring
    186  variable timerRefNum
    187  variable /g psh5_perf_secs
    188  timerRefNum = startMSTimer
    189 
    190  variable fileID = psh5_open_file(ANickName, APathName, AFileName)
    191  if (fileID)
    192  dfref fileDF = GetDataFolderDFR()
    193  svar s_filepath
    194  svar s_scanpaths
    195  AFileName = s_filepath
    196  print "loading " + s_filepath + "\r"
    197 
    198  variable ig
    199  variable ng = ItemsInList(s_scanpaths, ";")
    200  string sg
    201  string folder
    202 
    203  for (ig = 0; ig < ng; ig += 1)
    204  sg = StringFromList(ig, s_scanpaths, ";")
    205  folder = ReplaceString("/", sg, "")
    206  folder = ReplaceString(" ", folder, "")
    207  folder = CleanupName(folder, 0)
    208  setdatafolder fileDF
    209  newdatafolder /s /o $folder
    210  psh5_load_scan_complete(fileID, sg, load_data=load_data, load_attr=load_attr)
    211  endfor
    212 
    213  psh5_close_file(fileID)
    214  else
    215  AFileName = ""
    216  endif
    217 
    218  psh5_perf_secs = stopMSTimer(timerRefNum) / 1e6
    219 
    220  setdatafolder saveDF
    221  return AFileName
    222 end
    223 
    250 function /s psh5_load_preview(APathName, AFileName, [load_data, load_attr, pref_scans, pref_datasets])
    251  string APathName
    252  string AFileName
    253  variable load_data
    254  variable load_attr
    255  string pref_scans
    256  string pref_datasets
    257 
    258  if (ParamIsDefault(load_data))
    259  load_data = 1
    260  endif
    261  if (ParamIsDefault(load_attr))
    262  load_attr = 1
    263  endif
    264  if (ParamIsDefault(pref_scans))
    265  pref_scans = "*scan1*;"
    266  endif
    267  if (ParamIsDefault(pref_datasets))
    268  pref_datasets = ""
    269  endif
    270 
    271  dfref saveDF = GetDataFolderDFR()
    272 
    273  variable fileID
    274  string scanpaths = ""
    275  string dataname = ""
    276 
    277  // performance monitoring
    278  variable timerRefNum
    279  variable /g adh5_perf_secs
    280  timerRefNum = startMSTimer
    281 
    282  HDF5OpenFile /P=$APathName /R /Z fileID as AFileName
    283  if (v_flag == 0)
    284  AFileName = s_path + s_filename
    285  dfref fileDF = GetDataFolderDFR()
    286 
    287  scanpaths = psh5_list_scans(fileID)
    288  variable ng = ItemsInList(scanpaths)
    289  variable ig
    290  string sg
    291  variable np = ItemsInList(pref_scans)
    292  variable ip
    293  string sp
    294  variable found = 0
    295  if (ng > 0)
    296  for (ip = 0; ip < np; ip += 1)
    297  for (ig = 0; ig < ng; ig += 1)
    298  sg = StringFromList(ig, scanpaths)
    299  sp = StringFromList(ip, pref_scans)
    300  if (StringMatch(sg, sp))
    301  found = 1
    302  break
    303  endif
    304  endfor
    305  if (found)
    306  break
    307  endif
    308  endfor
    309  if (!found)
    310  ig = 0
    311  endif
    312  sg = StringFromList(ig, scanpaths)
    313 
    314  if (load_attr)
    315  setdatafolder fileDF
    316  newdatafolder /o/s attr
    317  killwaves /a/z
    318  psh5_load_scan_attrs(fileID, sg)
    319  endif
    320 
    321  setdatafolder fileDF
    322  dataname = psh5_load_scan_preview(fileID, sg, set_scale=load_attr, pref_datasets=pref_datasets)
    323  else
    324  print "no scans found in file " + AFileName
    325  endif
    326 
    327  HDF5CloseFile fileID
    328  endif
    329 
    330  if (timerRefNum >= 0)
    331  adh5_perf_secs = stopMSTimer(timerRefNum) / 1e6
    332  endif
    333 
    334  setdatafolder saveDF
    335  return dataname
    336 end
    337 
    360 function /s psh5_load_scan_complete(fileID, scanpath, [load_data, load_attr])
    361  variable fileID
    362  string scanpath
    363  variable load_data
    364  variable load_attr
    365 
    366  if (ParamIsDefault(load_data))
    367  load_data = 1
    368  endif
    369  if (ParamIsDefault(load_attr))
    370  load_attr = 1
    371  endif
    372 
    373  dfref saveDF = GetDataFolderDFR()
    374 
    375  dfref dataDF = GetDataFolderDFR()
    376  string wavenames
    377  string attrnames
    378  psh5_load_scan_meta(fileID, scanpath)
    379  if (load_attr)
    380  newdatafolder /s /o attr
    381  attrnames = psh5_load_scan_attrs(fileID, scanpath)
    382  endif
    383  if (load_data)
    384  setdatafolder dataDF
    385  wavenames = psh5_load_scan_data(fileID, scanpath)
    386  endif
    387  if (load_data && load_attr)
    388  setdatafolder dataDF
    390  endif
    391 
    392  setdatafolder saveDF
    393  return wavenames
    394 end
    395 
    404 function /s psh5_list_scans(fileID)
    405  variable fileID
    406 
    407  HDF5ListGroup /F /TYPE=1 fileID, "/"
    408 
    409  variable ig
    410  variable ng = ItemsInList(S_HDF5ListGroup, ";")
    411  string sg
    412  string scans = ""
    413 
    414  for (ig = 0; ig < ng; ig += 1)
    415  sg = StringFromList(ig, S_HDF5ListGroup, ";")
    416  if (cmpstr(sg[1,4], "scan") == 0)
    417  scans = AddListItem(sg, scans, ";", inf)
    418  endif
    419  endfor
    420 
    421  return scans
    422 end
    423 
    439 function /s psh5_list_scan_datasets(fileID, scanpath, [include_regions])
    440  variable fileID
    441  string scanpath
    442  variable include_regions
    443 
    444  if (ParamIsDefault(include_regions))
    445  include_regions = 0
    446  endif
    447  string result
    448 
    449  HDF5ListGroup /TYPE=2 /Z fileID, scanpath
    450  result = S_HDF5ListGroup
    451 
    452  if (include_regions)
    453  HDF5ListGroup /R /TYPE=2 /Z fileID, scanpath
    454  variable n = ItemsInList(S_HDF5ListGroup)
    455  variable i
    456  string ds
    457  string region_datasets
    458  for (i = 0; i < n; i += 1)
    459  ds = StringFromList(i, S_HDF5ListGroup)
    460  if (StringMatch(ds, "region*/*"))
    461  //region_datasets = psh5_list_scan_datasets(fileID, ReplaceString("//", scanpath + "/" + region, "/"), include_regions=0)
    462  result = AddListItem(ds, result, ";", inf)
    463  endif
    464  endfor
    465  endif
    466 
    467  return result
    468 end
    469 
    480 function /s psh5_list_scan_regions(fileID, scanpath)
    481  variable fileID
    482  string scanpath
    483 
    484  HDF5ListGroup /TYPE=1 /Z fileID, scanpath
    485  variable n = ItemsInList(S_HDF5ListGroup)
    486  variable i
    487  string result = ""
    488  string s
    489  for (i = 0; i < n; i += 1)
    490  s = StringFromList(i, S_HDF5ListGroup)
    491  if (StringMatch(s, "region*"))
    492  result = AddListItem(s, result, ";", inf)
    493  endif
    494  endfor
    495 
    496  return result
    497 end
    498 
    513 function /s psh5_load_scan_data(fileID, scanpath)
    514  variable fileID
    515  string scanpath
    516 
    517  string datasets = psh5_list_scan_datasets(fileID, scanpath, include_regions=1)
    518  variable nds = ItemsInList(datasets)
    519  variable ids
    520  string sds
    521  string sw
    522  string wavenames = ""
    523  for (ids = 0; ids < nds; ids += 1)
    524  sds = StringFromList(ids, datasets)
    525  sw = psh5_load_dataset(fileID, scanpath, sds, set_scale=0)
    526  wavenames = AddListItem(sw, wavenames, ";", inf)
    527  endfor
    528 
    529  return wavenames
    530 end
    531 
    553 function /s psh5_load_scan_attrs(fileID, scanpath, [attr_sets])
    554  variable fileID
    555  string scanpath
    556  variable attr_sets
    557 
    558  if (ParamIsDefault(attr_sets))
    559  attr_sets = 1
    560  endif
    561 
    562  string attr_path = ReplaceString("//", scanpath + "/attrs", "/")
    563  string attr_list = ""
    564  if (attr_sets & 1)
    565  HDF5ListGroup /TYPE=2 /Z fileID, attr_path
    566  if (!v_flag)
    567  attr_list = S_HDF5ListGroup
    568  endif
    569  endif
    570 
    571  variable ids
    572  variable nds
    573  string sds
    574 
    575  if (attr_sets & 2)
    576  nds = ItemsInList(kScientaScalingDatasets, ";")
    577  for (ids = 0; ids < nds; ids += 1)
    578  sds = StringFromList(ids, kScientaScalingDatasets)
    579  if (WhichListItem(sds, attr_list) < 0)
    580  attr_list = AddListItem(sds, attr_list, ";", inf)
    581  endif
    582  endfor
    583  endif
    584 
    585  nds = ItemsInList(attr_list, ";")
    586  string wavenames = ""
    587  for (ids = 0; ids < nds; ids += 1)
    588  sds = StringFromList(ids, attr_list, ";")
    589  HDF5LoadData /O /Q /Z fileID, attr_path + "/" + sds
    590  if (!v_flag)
    591  wavenames = AddListItem(s_wavenames, wavenames, ";", inf)
    592  endif
    593  endfor
    594  wavenames = ReplaceString(";;", wavenames, ";")
    595 
    596  return wavenames
    597 end
    598 
    621 function /s psh5_load_scan_meta(fileID, scanpath)
    622  variable fileID
    623  string scanpath
    624  string wavenames = ""
    625 
    626  HDF5LoadData /O /Q /Z /A="Dimensions" /N=ScanDimensions /TYPE=1 fileID, scanpath
    627  if (!v_flag)
    628  wavenames = AddListItem(s_wavenames, wavenames, ";", inf)
    629  else
    630  make /n=1 /o ScanDimensions
    631  ScanDimensions = 0
    632  wavenames = AddListItem("ScanDimensions", wavenames, ";", inf)
    633  endif
    634  HDF5LoadData /O /Q /Z /A="Readables" /N=ScanReadables /TYPE=1 fileID, scanpath
    635  if (!v_flag)
    636  wavenames = AddListItem(s_wavenames, wavenames, ";", inf)
    637  else
    638  make /n=1 /o /t ScanReadables
    639  ScanReadables[0] = "ScientaSpectrum"
    640  wavenames = AddListItem("ScanReadables", wavenames, ";", inf)
    641  endif
    642  HDF5LoadData /O /Q /Z /A="Writables" /N=ScanWritables /TYPE=1 fileID, scanpath
    643  if (!v_flag)
    644  wavenames = AddListItem(s_wavenames, wavenames, ";", inf)
    645  endif
    646  HDF5LoadData /O /Q /Z /A="Steps" /N=ScanSteps /TYPE=1 fileID, scanpath
    647  if (!v_flag)
    648  wavenames = AddListItem(s_wavenames, wavenames, ";", inf)
    649  endif
    650  wavenames = ReplaceString(";;", wavenames, ";")
    651 
    652  return wavenames
    653 end
    654 
    688 function /s psh5_load_dataset(fileID, scanpath, datasetname, [set_scale])
    689  variable fileID
    690  string scanpath
    691  string datasetname
    692  variable set_scale
    693 
    694  if (ParamIsDefault(set_scale))
    695  set_scale = 1
    696  endif
    697 
    698  dfref base_df = GetDataFolderDFR()
    699 
    700  string datasetpath
    701  datasetpath = scanpath + "/" + datasetname
    702  datasetpath = ReplaceString("//", datasetpath, "/")
    703 
    704  string regionname
    705  string regionpath
    706  if (ItemsInList(datasetname, "/") >= 2)
    707  regionname = StringFromList(0, datasetname, "/")
    708  regionpath = ReplaceString("//", scanpath + "/" + regionname, "/")
    709  datasetname = RemoveListItem(0, datasetname, "/")
    710  NewDataFolder /o/s $regionname
    711  else
    712  regionname = ""
    713  regionpath = scanpath
    714  endif
    715 
    716  STRUCT HDF5DataInfo di // Defined in HDF5 Browser.ipf.
    717  InitHDF5DataInfo(di)
    718  variable err = HDF5DatasetInfo(fileID, datasetpath, 0, di)
    719  if (err != 0)
    720  print "error accessing detector/data"
    721  return ""
    722  endif
    723 
    724  string dataname
    725  if (di.ndims < 2)
    726  HDF5LoadData /O /Q /Z fileID, datasetpath
    727  dataname = StringFromList(0, S_waveNames)
    728  else
    729  dataname = psh5_load_dataset_slabs(fileID, regionpath, datasetname)
    730  endif
    731 
    732  wave /z data = $dataname
    733  if (waveexists(data))
    734  psh5_load_dataset_meta(fileID, regionpath, datasetname, data)
    735  ps_set_dimlabels(data)
    736  if (set_scale)
    737  ps_scale_dataset(data)
    738  endif
    739  else
    740  dataname = ""
    741  endif
    742 
    743  setdatafolder base_df
    744  return dataname
    745 end
    746 
    760 static function /s select_dataset(file_datasets, pref_datasets)
    761  string file_datasets
    762  string pref_datasets
    763 
    764  variable index
    765  variable nds = ItemsInList(file_datasets)
    766  variable ids
    767  string sds = ""
    768  string mds = ""
    769  variable np = ItemsInList(pref_datasets)
    770  variable ip
    771  string sp
    772  variable found = 0
    773  if (nds > 0)
    774  for (ip = 0; ip < np; ip += 1)
    775  for (ids = 0; ids < nds; ids += 1)
    776  sds = StringFromList(ids, file_datasets)
    777  index = ItemsInList(sds, "/") - 1
    778  mds = StringFromList(index, sds, "/")
    779  sp = StringFromList(ip, pref_datasets)
    780  if (StringMatch(mds, sp))
    781  found = 1
    782  break
    783  endif
    784  endfor
    785  if (found)
    786  break
    787  endif
    788  endfor
    789  if (!found)
    790  ids = 0
    791  sds = StringFromList(ids, file_datasets)
    792  endif
    793  endif
    794 
    795  return sds
    796 end
    797 
    822 function /s psh5_load_scan_preview(fileID, scanpath, [set_scale, pref_datasets])
    823  variable fileID
    824  string scanpath
    825  variable set_scale
    826  string pref_datasets
    827 
    828  if (ParamIsDefault(set_scale))
    829  set_scale = 1
    830  endif
    831  if (ParamIsDefault(pref_datasets) || (strlen(pref_datasets) == 0))
    832  pref_datasets = kPreviewDatasets
    833  endif
    834 
    835  dfref saveDF = GetDataFolderDFR()
    836  dfref dataDF = saveDF
    837 
    838  string datasets = psh5_list_scan_datasets(fileID, scanpath, include_regions=1)
    839  string datasetname = select_dataset(datasets, pref_datasets)
    840  string datasetpath
    841  datasetpath = scanpath + "/" + datasetname
    842  datasetpath = ReplaceString("//", datasetpath, "/")
    843 
    844  STRUCT HDF5DataInfo di // Defined in HDF5 Browser.ipf.
    845  InitHDF5DataInfo(di)
    846  variable err = HDF5DatasetInfo(fileID, datasetpath, 0, di)
    847  if (err != 0)
    848  print "error accessing detector/data"
    849  return ""
    850  endif
    851 
    852  string dataname
    853  if (di.ndims < 2)
    854  HDF5LoadData /O /Q /Z fileID, datasetpath
    855  dataname = StringFromList(0, S_waveNames)
    856  wave /z data = $dataname
    857  if (waveexists(data))
    858  ps_set_dimlabels(data)
    859  endif
    860  else
    861  variable dim2start = 0
    862  variable dim2count = 1
    863  variable dim3start = 0
    864  variable dim3count = 1
    865  if (di.ndims >= 3)
    866  dim2start = floor(di.dims[2] / 2)
    867  dim2count = 1
    868  endif
    869  if (di.ndims >= 4)
    870  dim3start = floor(di.dims[3] / 2)
    871  dim3count = 1
    872  endif
    873 
    874  dataname = psh5_load_dataset_slab(fileID, scanpath, datasetname, dim2start, dim2count, dim3start, dim3count)
    875  endif
    876 
    877  wave /z data = $dataname
    878  if (waveexists(data))
    879  if (set_scale)
    880  setdatafolder dataDF
    881  string positioners
    882  string positioner
    883  string positionerpath
    884  positioners = psh5_load_scan_meta(fileID, scanpath)
    885  wave /t /z ScanWritables
    886  if (waveexists(ScanWritables) && (numpnts(ScanWritables) >= 1))
    887  positioner = ScanWritables[0]
    888  if (strlen(positioner) > 0)
    889  positionerpath = scanpath + "/" + positioner
    890  positionerpath = ReplaceString("//", positionerpath, "/")
    891  HDF5LoadData /O /Q /Z fileID, positionerpath
    892  endif
    893  endif
    894 
    895  setdatafolder dataDF
    896  newdatafolder /o/s attr
    897  psh5_load_scan_attrs(fileID, scanpath, attr_sets=2)
    898  setdatafolder dataDF
    899  ps_scale_dataset(data)
    900  endif
    901  else
    902  dataname = ""
    903  endif
    904 
    905  return dataname
    906 end
    907 
    935 function /s psh5_load_scan_section(fileID, scanpath, dim, [set_scale, pref_datasets])
    936  variable fileID
    937  string scanpath
    938  variable dim
    939  variable set_scale
    940  string pref_datasets
    941 
    942  // select first dimension (future argument)
    943  // 0 = first dimension is x axis (energy of scienta image)
    944  dim = 0
    945 
    946  if (ParamIsDefault(set_scale))
    947  set_scale = 1
    948  endif
    949  if (ParamIsDefault(pref_datasets) || (strlen(pref_datasets) == 0))
    950  pref_datasets = kPreviewDatasets
    951  endif
    952 
    953  dfref saveDF = GetDataFolderDFR()
    954  dfref dataDF = saveDF
    955 
    956  string datasets = psh5_list_scan_datasets(fileID, scanpath)
    957  string datasetname = select_dataset(datasets, pref_datasets)
    958  string datasetpath
    959  datasetpath = scanpath + "/" + datasetname
    960  datasetpath = ReplaceString("//", datasetpath, "/")
    961  string dataname = StringFromList(ItemsInList(datasetpath, "/") - 1, datasetpath, "/")
    962  string destname = dataname[0,29] + num2str(dim)
    963 
    964  STRUCT HDF5DataInfo di // Defined in HDF5 Browser.ipf.
    965  InitHDF5DataInfo(di)
    966  variable err = HDF5DatasetInfo(fileID, datasetpath, 0, di)
    967  if (err != 0)
    968  print "error accessing detector/data"
    969  return ""
    970  elseif (di.ndims != 3)
    971  print "error: rank of dataset != 3"
    972  return ""
    973  endif
    974 
    975  variable idx, idy, idz, idt
    976  variable transpose = WhichListItem(dataname, kTransposedDatasets) >= 0
    977  if (transpose)
    978  idx = 1
    979  idy = 0
    980  else
    981  idx = 0
    982  idy = 1
    983  endif
    984  idz = 2
    985  idt = 3
    986 
    987  variable nx, ny, nz
    988  nx = di.dims[idx]
    989  ny = di.dims[idy]
    990  nz = di.dims[idz]
    991 
    992  HDF5MakeHyperslabWave("slab", max(di.ndims, 4))
    993  wave slab
    994  slab[][%Start] = 0
    995  slab[][%Stride] = 1
    996  slab[][%Count] = 1
    997  slab[][%Block] = 1
    998 
    999  if (dim == 0)
    1000  slab[idy][%Start] = floor(ny / 2)
    1001  slab[idx][%Block] = nx
    1002  make /n=(nx,nz) /o $destname
    1003  else
    1004  slab[idx][%Start] = floor(nx / 2)
    1005  slab[idy][%Block] = ny
    1006  make /n=(ny,nz) /o $destname
    1007  endif
    1008  slab[idz][%Block] = nz
    1009  wave data = $destname
    1010  data = 0
    1011 
    1012  HDF5LoadData /O /Q /Z /SLAB=slab /N=slabdata fileID, datasetpath
    1013  if (!v_flag)
    1014  wave slabdata
    1015  if (transpose)
    1016  data += slabdata[0][p][q][0]
    1017  else
    1018  data += slabdata[p][0][q][0]
    1019  endif
    1020  endif
    1021  killwaves /z slab, slabdata
    1022 
    1023  if (set_scale)
    1024  make /n=(1,1,1) /free dummy
    1025  ps_set_dimlabels2(dummy, dataname)
    1026  setdimlabel 0, -1, $GetDimLabel(dummy, dim, -1), data
    1027  setdimlabel 1, -1, $kScanDimLabel, data
    1028 
    1029  setdatafolder dataDF
    1030  string positioners
    1031  string positioner
    1032  string positionerpath
    1033  positioners = psh5_load_scan_meta(fileID, scanpath)
    1034  wave /t /z ScanWritables
    1035  if (waveexists(ScanWritables) && (numpnts(ScanWritables) >= 1))
    1036  positioner = ScanWritables[0]
    1037  if (strlen(positioner) > 0)
    1038  positionerpath = scanpath + "/" + positioner
    1039  positionerpath = ReplaceString("//", positionerpath, "/")
    1040  HDF5LoadData /O /Q /Z fileID, positionerpath
    1041  endif
    1042  endif
    1043 
    1044  setdatafolder dataDF
    1045  newdatafolder /o/s attr
    1046  killwaves /a/z
    1047  psh5_load_scan_attrs(fileID, scanpath, attr_sets=2)
    1048  setdatafolder dataDF
    1049  ps_scale_dataset(data)
    1050  endif
    1051 
    1052  return destname
    1053 end
    1054 
    1073 function psh5_load_dataset_meta(fileID, datapath, datasetname, datawave)
    1074  variable fileID
    1075  string datapath
    1076  string datasetname
    1077  wave datawave
    1078 
    1079  dfref saveDF = GetDataFolderDFR()
    1080  SetDataFolder NewFreeDataFolder()
    1081 
    1082  string datasetpath = datapath + "/" + datasetname
    1083  datasetpath = ReplaceString("//", datasetpath, "/")
    1084  string wnote
    1085 
    1086  HDF5LoadData /O /Q /Z /A="Writable Dimension" /N=WriteDim fileID, datasetpath
    1087  if (!v_flag)
    1088  wave WriteDim
    1089  // scan dimension starts at 1
    1090  sprintf wnote, "ScanDimension=%u", WriteDim[0]
    1091  Note datawave, wnote
    1092  endif
    1093 
    1094  HDF5LoadData /O /Q /Z /A="Writable Index" /N=WriteIndex fileID, datasetpath
    1095  if (!v_flag)
    1096  wave WriteIndex
    1097  sprintf wnote, "WriteableIndex=%u", WriteIndex[0]
    1098  Note datawave, wnote
    1099  endif
    1100 
    1101  HDF5LoadData /O /Q /Z /A="Readable Index" /N=ReadIndex fileID, datasetpath
    1102  if (!v_flag)
    1103  wave ReadIndex
    1104  sprintf wnote, "ReadableIndex=%u", ReadIndex[0]
    1105  Note datawave, wnote
    1106  endif
    1107 
    1108  setdatafolder saveDF
    1109  return 0
    1110 end
    1111 
    1130 function /s psh5_load_dataset_slabs(fileID, datapath, datasetname, [progress])
    1131  variable fileID
    1132  string datapath
    1133  string datasetname
    1134  variable progress
    1135 
    1136  if (ParamIsDefault(progress))
    1137  progress = 1
    1138  endif
    1139 
    1140  variable result = 0
    1141  string datasetpath
    1142  string datawavename
    1143  datasetpath = datapath + "/" + datasetname
    1144  datasetpath = ReplaceString("//", datasetpath, "/")
    1145  datawavename = StringFromList(ItemsInList(datasetpath, "/") - 1, datasetpath, "/")
    1146 
    1147  STRUCT HDF5DataInfo di // Defined in HDF5 Browser.ipf.
    1148  InitHDF5DataInfo(di)
    1149  variable err = HDF5DatasetInfo(fileID, datasetpath, 0, di)
    1150  if (err != 0)
    1151  print "error accessing detector/data"
    1152  return ""
    1153  endif
    1154  if (di.ndims < 2)
    1155  print "error: rank of dataset < 2"
    1156  return ""
    1157  elseif (di.ndims < 3)
    1158  progress = 0
    1159  endif
    1160 
    1161  variable idx, idy, idz, idt, izt
    1162  variable transpose = WhichListItem(datawavename, kTransposedDatasets) >= 0
    1163  if (transpose)
    1164  idx = 1
    1165  idy = 0
    1166  else
    1167  idx = 0
    1168  idy = 1
    1169  endif
    1170  idz = 2
    1171  idt = 3
    1172 
    1173  variable nx, ny, nz, nt, nzt
    1174  nx = di.dims[idx]
    1175  ny = di.dims[idy]
    1176  nz = di.dims[idz]
    1177  nt = di.dims[idt]
    1178  make /n=(nx,ny,nz,nt) /o $datawavename
    1179  wave data = $datawavename
    1180 
    1181  nz = max(nz, 1)
    1182  nt = max(nt, 1)
    1183  nzt = nz * nt
    1184  izt = 0
    1185  if (progress)
    1186  display_progress_panel("HDF5 Import", "Loading data...", nzt)
    1187  endif
    1188 
    1189  // load data image by image
    1190  HDF5MakeHyperslabWave("slab", max(di.ndims, 4))
    1191  wave slab
    1192  slab[][%Start] = 0
    1193  slab[][%Stride] = 1
    1194  slab[][%Count] = 1
    1195  slab[][%Block] = 1
    1196  slab[idx][%Block] = nx
    1197  slab[idy][%Block] = ny
    1198 
    1199  variable iz, it
    1200  for (iz = 0; iz < nz; iz += 1)
    1201  for (it = 0; it < nt; it += 1)
    1202  slab[idz][%Start] = iz
    1203  slab[idt][%Start] = it
    1204  HDF5LoadData /O /Q /Z /SLAB=slab /N=slabdata fileID, datasetpath
    1205  wave slabdata // 2D, 3D, or 4D with singletons
    1206  if (transpose)
    1207  data[][][iz][it] = slabdata[q][p][0][0]
    1208  else
    1209  data[][][iz][it] = slabdata[p][q][0][0]
    1210  endif
    1211 
    1212  // progress window
    1213  izt += 1
    1214  if (progress)
    1215  if (update_progress_panel(izt))
    1216  result = -4 // user abort
    1217  break
    1218  endif
    1219  endif
    1220  endfor
    1221  if (result < 0)
    1222  break
    1223  endif
    1224  endfor
    1225 
    1226  if (progress)
    1227  kill_progress_panel()
    1228  endif
    1229 
    1230  killwaves /z slab, slabdata
    1231  if (!result)
    1232  ps_set_dimlabels(data)
    1233  return datawavename
    1234  else
    1235  killwaves /z data
    1236  return ""
    1237  endif
    1238 end
    1239 
    1266 function /s psh5_load_dataset_slab(fileID, datapath, datasetname, dim2start, dim2count, dim3start, dim3count)
    1267  variable fileID
    1268  string datapath
    1269  string datasetname
    1270  variable dim2start
    1271  variable dim2count
    1272  variable dim3start
    1273  variable dim3count
    1274 
    1275  string datasetpath
    1276  string datawavename
    1277  datasetpath = datapath + "/" + datasetname
    1278  datasetpath = ReplaceString("//", datasetpath, "/")
    1279  datawavename = StringFromList(ItemsInList(datasetpath, "/") - 1, datasetpath, "/")
    1280 
    1281  STRUCT HDF5DataInfo di
    1282  InitHDF5DataInfo(di)
    1283  variable err = HDF5DatasetInfo(fileID, datasetpath, 0, di)
    1284  if (err != 0)
    1285  print "error accessing detector/data"
    1286  return ""
    1287  endif
    1288  if (di.ndims < 2)
    1289  print "error: rank of dataset < 2"
    1290  return ""
    1291  endif
    1292 
    1293  variable idx, idy, idz, idt
    1294  variable transpose = WhichListItem(datawavename, kTransposedDatasets) >= 0
    1295  if (transpose)
    1296  idx = 1
    1297  idy = 0
    1298  else
    1299  idx = 0
    1300  idy = 1
    1301  endif
    1302  idz = 2
    1303  idt = 3
    1304 
    1305  variable nx, ny
    1306  nx = di.dims[idx]
    1307  ny = di.dims[idy]
    1308  make /n=(nx,ny) /o $datawavename
    1309  wave data = $datawavename
    1310  data = 0
    1311 
    1312  HDF5MakeHyperslabWave("slab", max(di.ndims, 4))
    1313  wave slab
    1314  slab[][%Start] = 0
    1315  slab[][%Stride] = 1
    1316  slab[][%Count] = 1
    1317  slab[][%Block] = 1
    1318  slab[idx][%Block] = nx
    1319  slab[idy][%Block] = ny
    1320 
    1321  variable iz, it
    1322  variable navg = 0
    1323  variable dim2end = dim2start + dim2count - 1
    1324  variable dim3end = dim3start + dim3count - 1
    1325  for (iz = dim2start; iz <= dim2end; iz += 1)
    1326  for (it = dim3start; it <= dim3end; it += 1)
    1327  slab[idz][%Start] = iz
    1328  slab[idt][%Start] = it
    1329  HDF5LoadData /O /Q /Z /SLAB=slab /N=slabdata fileID, datasetpath
    1330  if (!v_flag)
    1331  wave slabdata
    1332  if (transpose)
    1333  data += slabdata[q][p][0][0]
    1334  else
    1335  data += slabdata[p][q][0][0]
    1336  endif
    1337  navg += 1
    1338  endif
    1339  endfor
    1340  endfor
    1341  if (navg)
    1342  data /= navg
    1343  endif
    1344 
    1345  killwaves /z slab, slabdata
    1346  ps_set_dimlabels(data)
    1347  return datawavename
    1348 end
    1349 
    1365 function ps_set_dimlabels(data)
    1366  wave data
    1367 
    1368  ps_set_dimlabels2(data, NameOfWave(data))
    1369 end
    1370 
    1384 function ps_set_dimlabels2(data, name)
    1385  wave data
    1386  string name
    1387 
    1388  variable dummy
    1389  try
    1390  // intrinsic dimensions
    1391  strswitch(name)
    1392  case "ScientaImage":
    1393  setdimlabel 0, -1, $kEnergyDimLabel, data
    1394  setdimlabel 1, -1, $kAngleDimLabel, data
    1395  if (WaveDims(data) >= 3)
    1396  setdimlabel 2, -1, $kScanDimLabel, data
    1397  endif
    1398  AbortOnRTE
    1399  break
    1400  case "ImageAngleDistribution":
    1401  case "ScientaAngleDistribution":
    1402  if (WaveDims(data) >= 2)
    1403  setdimlabel 0, -1, $kScanDimLabel, data
    1404  setdimlabel 1, -1, $kAngleDimLabel, data
    1405  else
    1406  setdimlabel 0, -1, $kAngleDimLabel, data
    1407  endif
    1408  AbortOnRTE
    1409  break
    1410  case "ScientaSpectrum":
    1411  case "ImageEnergyDistribution":
    1412  case "ScientaEnergyDistribution":
    1413  if (WaveDims(data) >= 2)
    1414  setdimlabel 0, -1, $kScanDimLabel, data
    1415  setdimlabel 1, -1, $kEnergyDimLabel, data
    1416  else
    1417  setdimlabel 0, -1, $kEnergyDimLabel, data
    1418  endif
    1419  AbortOnRTE
    1420  break
    1421  default:
    1422  if (WaveDims(data) == 1)
    1423  setdimlabel 0, -1, $kScanDimLabel, data
    1424  AbortOnRTE
    1425  else
    1426  return 1
    1427  endif
    1428  endswitch
    1429  catch
    1430  dummy = GetRTError(1)
    1431  return 2
    1432  endtry
    1433  return 0
    1434 end
    1435 
    1441 static function /df find_scan_folder(dataDF)
    1442  dfref dataDF
    1443 
    1444  dfref attrDF = dataDF:attr
    1445  if (!DataFolderRefStatus(attrDF))
    1446  string df = GetDataFolder(1, dataDF) + ":"
    1447  dfref scanDF = $df
    1448  else
    1449  dfref scanDF = dataDF
    1450  endif
    1451  return scanDF
    1452 end
    1453 
    1458 static function /df find_attr_folder(dataDF)
    1459  dfref dataDF
    1460 
    1461  dfref attrDF = dataDF:attr
    1462  if (!DataFolderRefStatus(attrDF))
    1463  string df = GetDataFolder(1, dataDF) + ":"
    1464  dfref scanDF = $df
    1465  dfref attrDF = scanDF:attr
    1466  endif
    1467  return attrDF
    1468 end
    1469 
    1486 function ps_scale_datasets()
    1487  dfref scanDF = GetDataFolderDFR()
    1488  dfref attrDF = find_attr_folder(scanDF)
    1489 
    1490  make /n=3 /free lo, hi
    1491  make /n=3 /t /free ax, un
    1492  wave /t /z /SDFR=scanDF ScanReadables
    1493  if (WaveExists(ScanReadables))
    1494  variable isr
    1495  variable nsr = numpnts(ScanReadables)
    1496  string ssr
    1497  string sdf
    1498  for (isr = 0; isr < nsr; isr += 1)
    1499  setdatafolder scanDF
    1500  ssr = ScanReadables[isr]
    1501  if (ItemsInList(ssr, "/") >= 2)
    1502  sdf = StringFromList(0, ssr, "/")
    1503  ssr = RemoveListItem(0, ssr, "/")
    1504  setdatafolder $sdf
    1505  endif
    1506  wave /z wsr=$ssr
    1507  if (WaveExists(wsr))
    1508  ps_detect_scale(ax, lo, hi, un)
    1509  ps_scale_dataset_2(wsr, ax, lo, hi, un)
    1510  endif
    1511  endfor
    1512  endif
    1513  setdatafolder scanDF
    1514 end
    1515 
    1532 function ps_scale_dataset(data)
    1533  wave data
    1534 
    1535  dfref saveDF = GetDataFolderDFR()
    1536  dfref dataDF = GetWavesDataFolderDFR(data)
    1537 
    1538  setdatafolder dataDF
    1539  make /n=3 /free lo, hi
    1540  make /n=3 /t /free ax, un
    1541  ps_detect_scale(ax, lo, hi, un)
    1542  ps_scale_dataset_2(data, ax, lo, hi, un)
    1543  setdatafolder saveDF
    1544 end
    1545 
    1546 static function /wave find_scale_wave(name, dataDF, scanDF, attrDF)
    1547  string name
    1548  dfref dataDF
    1549  dfref scanDF
    1550  dfref attrDF
    1551 
    1552  wave /SDFR=dataDF /Z w = $name
    1553  if (!WaveExists(w))
    1554  wave /SDFR=scanDF /Z w = $name
    1555  if (!WaveExists(w))
    1556  wave /SDFR=attrDF /Z w = $name
    1557  endif
    1558  endif
    1559  return w
    1560 end
    1561 
    1603 function ps_detect_scale(ax, lo, hi, un)
    1604  wave /t ax
    1605  wave lo
    1606  wave hi
    1607  wave /t un
    1608 
    1609  dfref dataDF = GetDataFolderDFR()
    1610  dfref scanDF = find_scan_folder(dataDF)
    1611  dfref attrDF = find_attr_folder(dataDF)
    1612 
    1613  redimension /n=4 lo, hi, un, ax
    1614  setdimlabel 0, 0, $kEnergyDimLabel, lo, hi, un, ax
    1615  setdimlabel 0, 1, $kAngleDimLabel, lo, hi, un, ax
    1616  setdimlabel 0, 2, $kScanDimLabel, lo, hi, un, ax
    1617  setdimlabel 0, 3, $kDataDimLabel, lo, hi, un, ax
    1618 
    1619  // default values
    1620  lo[%$kEnergyDimLabel] = 0
    1621  hi[%$kEnergyDimLabel] = 1
    1622  un[%$kEnergyDimLabel] = "eV"
    1623  ax[%$kEnergyDimLabel] = "Ekin"
    1624 
    1625  lo[%$kAngleDimLabel] = -1
    1626  hi[%$kAngleDimLabel] = 1
    1627  un[%$kAngleDimLabel] = "arb."
    1628  un[%$kAngleDimLabel] = "slice"
    1629 
    1630  lo[%$kScanDimLabel] = 0
    1631  hi[%$kScanDimLabel] = 1
    1632  un[%$kScanDimLabel] = "arb."
    1633  ax[%$kScanDimLabel] = "scan"
    1634 
    1635  lo[%$kDataDimLabel] = 0
    1636  hi[%$kDataDimLabel] = 0
    1637  un[%$kDataDimLabel] = "arb."
    1638  ax[%$kDataDimLabel] = "value"
    1639 
    1640  wave /SDFR=attrDF /T /Z LensMode
    1641  wave /Z ChannelBegin = find_scale_wave("ScientaChannelBegin", dataDF, scanDF, attrDF)
    1642  wave /Z ChannelEnd = find_scale_wave("ScientaChannelEnd", dataDF, scanDF, attrDF)
    1643  wave /Z SliceBegin = find_scale_wave("ScientaSliceBegin", dataDF, scanDF, attrDF)
    1644  wave /Z SliceEnd = find_scale_wave("ScientaSliceEnd", dataDF, scanDF, attrDF)
    1645 
    1646  // lens mode can give more detail
    1647  if (waveexists(LensMode) && (numpnts(LensMode) >= 1))
    1648  strswitch(LensMode[0])
    1649  case "Angular45":
    1650  lo[%$kAngleDimLabel] = -45/2
    1651  hi[%$kAngleDimLabel] = +45/2
    1652  un[%$kAngleDimLabel] = "°"
    1653  ax[%$kAngleDimLabel] = "angle"
    1654  break
    1655  case "Angular60":
    1656  lo[%$kAngleDimLabel] = -60/2
    1657  hi[%$kAngleDimLabel] = +60/2
    1658  un[%$kAngleDimLabel] = "°"
    1659  ax[%$kAngleDimLabel] = "angle"
    1660  break
    1661  case "Transmission":
    1662  un[%$kAngleDimLabel] = "arb."
    1663  ax[%$kAngleDimLabel] = "offset"
    1664  break
    1665  endswitch
    1666  endif
    1667 
    1668  // best option if scales are explicit in separate waves
    1669  if (waveexists(ChannelBegin) && waveexists(ChannelEnd) && (numpnts(ChannelBegin) >= 1) && (numpnts(ChannelEnd) >= 1))
    1670  lo[%$kEnergyDimLabel] = ChannelBegin[0]
    1671  hi[%$kEnergyDimLabel] = ChannelEnd[0]
    1672  endif
    1673  if (waveexists(SliceBegin) && waveexists(SliceEnd) && (numpnts(SliceBegin) >= 1) && (numpnts(SliceEnd) >= 1))
    1674  lo[%$kAngleDimLabel] = SliceBegin[0]
    1675  hi[%$kAngleDimLabel] = SliceEnd[0]
    1676  endif
    1677 
    1678  wave /z /t /SDFR=scanDF ScanWritables
    1679  if (WaveExists(ScanWritables))
    1680  wave /z /SDFR=scanDF scanner = $ScanWritables[0]
    1681  if (!WaveExists(scanner))
    1682  wave /z /SDFR=attrDF scanner = $ScanWritables[0]
    1683  endif
    1684  if (WaveExists(scanner) && (numpnts(scanner) >= 1))
    1685  lo[%$kScanDimLabel] = scanner[0]
    1686  hi[%$kScanDimLabel] = scanner[numpnts(scanner)-1]
    1687  ax[%$kScanDimLabel] = NameOfWave(scanner)
    1688  strswitch(NameOfWave(scanner))
    1689  case "Eph":
    1690  ax[%$kScanDimLabel] = "photon energy"
    1691  un[%$kScanDimLabel] = "eV"
    1692  break
    1693  case "ManipulatorX":
    1694  case "ManipulatorY":
    1695  case "ManipulatorZ":
    1696  case "FocusYTrans":
    1697  case "FocusZTrans":
    1698  case "RefocusYTrans":
    1699  case "RefocusZTrans":
    1700  case "ExitSlitY":
    1701  un[%$kScanDimLabel] = "mm"
    1702  break
    1703  case "ExitSlit":
    1704  un[%$kScanDimLabel] = "µm"
    1705  break
    1706  case "ManipulatorTheta":
    1707  case "ManipulatorTilt":
    1708  case "ManipulatorPhi":
    1709  un[%$kScanDimLabel] = "°"
    1710  break
    1711  case "FocusXRot":
    1712  case "FocusYRot":
    1713  case "FocusZRot":
    1714  case "RefocusXRot":
    1715  case "RefocusYRot":
    1716  case "RefocusZRot":
    1717  un[%$kScanDimLabel] = "mrad"
    1718  break
    1719  endswitch
    1720  endif
    1721  endif
    1722 end
    1723 
    1763 function ps_scale_dataset_2(data, ax, lo, hi, un)
    1764  wave data
    1765  wave /t ax
    1766  wave lo
    1767  wave hi
    1768  wave /t un
    1769 
    1770  string snote = note(data)
    1771  string sdim
    1772  sdim = GetDimLabel(data, 0, -1)
    1773  if (strlen(sdim))
    1774  setscale /i x lo[%$sdim], hi[%$sdim], un[%$sdim], data
    1775  snote = ReplaceStringByKey("AxisLabelX", snote, ax[%$sdim], "=", "\r")
    1776  endif
    1777 
    1778  sdim = GetDimLabel(data, 1, -1)
    1779  if (strlen(sdim))
    1780  setscale /i y lo[%$sdim], hi[%$sdim], un[%$sdim], data
    1781  snote = ReplaceStringByKey("AxisLabelY", snote, ax[%$sdim], "=", "\r")
    1782  endif
    1783 
    1784  sdim = GetDimLabel(data, 2, -1)
    1785  if (strlen(sdim))
    1786  setscale /i z lo[%$sdim], hi[%$sdim], un[%$sdim], data
    1787  snote = ReplaceStringByKey("AxisLabelZ", snote, ax[%$sdim], "=", "\r")
    1788  endif
    1789 
    1790  string data_unit = un[%$kDataDimLabel]
    1791  string data_label = ax[%$kDataDimLabel]
    1792  string s
    1793  variable def = (cmpstr(data_unit, "arb.") == 0) && (cmpstr(data_label, "value") == 0)
    1794 
    1795  if (def)
    1796  s = StringByKey("AxisLabelD", snote, "=", "\r")
    1797  if (strlen(s) > 0)
    1798  data_label = s
    1799  def = 0
    1800  endif
    1801  s = StringByKey("AxisUnitD", snote, "=", "\r")
    1802  if (strlen(s) > 0)
    1803  data_unit = s
    1804  def = 0
    1805  endif
    1806  endif
    1807 
    1808  if (def)
    1809  strswitch(NameOfWave(data))
    1810  case "ScientaImage":
    1811  case "ImageAngleDistribution":
    1812  case "ScientaAngleDistribution":
    1813  case "ScientaSpectrum":
    1814  case "ImageEnergyDistribution":
    1815  case "ScientaEnergyDistribution":
    1816  data *= kDetectorSensitivity
    1817  data_unit = "counts"
    1818  data_label = "intensity"
    1819  def = 0
    1820  break
    1821  case "SampleCurrent":
    1822  case "RefCurrent":
    1823  case "AuxCurrent":
    1824  data_unit = "A"
    1825  data_label = "current"
    1826  def = 0
    1827  break
    1828  case "MachineCurrent":
    1829  data_unit = "mA"
    1830  data_label = "current"
    1831  def = 0
    1832  break
    1833  endswitch
    1834  endif
    1835 
    1836  setscale d 0, 0, data_unit, data
    1837  snote = ReplaceStringByKey("AxisLabelD", snote, data_label, "=", "\r")
    1838  snote = ReplaceStringByKey("AxisUnitD", snote, data_unit, "=", "\r")
    1839  snote = ReplaceStringByKey("Dataset", snote, NameOfWave(data), "=", "\r")
    1840  note /k data, snote
    1841 end
    1842 
    1893 function /s psh5_load_reduced(ANickName, APathName, AFileName, reduction_func, reduction_param, [progress, nthreads])
    1894  string ANickName
    1895  string APathName
    1896  string AFileName
    1897  funcref adh5_default_reduction reduction_func
    1898  string reduction_param
    1899  variable progress
    1900  variable nthreads
    1901 
    1902  if (ParamIsDefault(progress))
    1903  progress = 1
    1904  endif
    1905  if (ParamIsDefault(nthreads))
    1906  nthreads = -1
    1907  endif
    1908 
    1909  dfref saveDF = GetDataFolderDFR()
    1910 
    1911  // performance monitoring
    1912  variable timerRefNum
    1913  variable /g psh5_perf_secs
    1914  timerRefNum = startMSTimer
    1915 
    1916  variable fileID = psh5_open_file(ANickName, APathName, AFileName)
    1917  string wavenames = ""
    1918  if (fileID)
    1919  dfref fileDF = GetDataFolderDFR()
    1920  svar s_filepath
    1921  svar s_scanpaths
    1922  AFileName = s_filepath
    1923  print "loading " + s_filepath + "\r"
    1924 
    1925  variable ig = 0
    1926  variable ng = ItemsInList(s_scanpaths)
    1927  string scanpath
    1928  string folder
    1929  string positioners
    1930  string positioner
    1931  string positionerpath
    1932 
    1933  scanpath = StringFromList(ig, s_scanpaths)
    1934  folder = ReplaceString("/", scanpath, "")
    1935  folder = ReplaceString(" ", folder, "")
    1936  folder = CleanupName(folder, 0)
    1937  setdatafolder fileDF
    1938  newdatafolder /s /o $folder
    1939  dfref dataDF = GetDataFolderDFR()
    1940  positioners = psh5_load_scan_meta(fileID, scanpath)
    1941  newdatafolder /s /o attr
    1942  killwaves /a/z
    1943  psh5_load_scan_attrs(fileID, scanpath)
    1944  setdatafolder dataDF
    1945  wave /t /z ScanWritables
    1946  if (waveexists(ScanWritables) && (numpnts(ScanWritables) >= 1))
    1947  positioner = ScanWritables[0]
    1948  if (strlen(positioner) > 0)
    1949  positionerpath = scanpath + "/" + positioner
    1950  positionerpath = ReplaceString("//", positionerpath, "/")
    1951  HDF5LoadData /O /Q /Z fileID, positionerpath
    1952  endif
    1953  endif
    1954 
    1955  setdatafolder dataDF
    1956  string datasets = psh5_list_scan_datasets(fileID, scanpath, include_regions=1)
    1957  string dataset = select_dataset(datasets, "ScientaImage")
    1958  wavenames = psh5_load_dataset_reduced(fileID, scanpath, dataset, reduction_func, reduction_param, progress=progress, nthreads=nthreads)
    1959 
    1960  psh5_close_file(fileID)
    1961  endif
    1962 
    1963  if (timerRefNum >= 0)
    1964  psh5_perf_secs = stopMSTimer(timerRefNum) / 1e6
    1965  endif
    1966 
    1967  setdatafolder saveDF
    1968  return wavenames
    1969 end
    1970 
    1971 
    2022 function /s psh5_load_dataset_reduced(fileID, scanpath, datasetname, reduction_func, reduction_param, [progress, nthreads])
    2023  variable fileID
    2024  string scanpath
    2025  string datasetname
    2026  funcref adh5_default_reduction reduction_func
    2027  string reduction_param
    2028  variable progress
    2029  variable nthreads
    2030 
    2031  if (ParamIsDefault(progress))
    2032  progress = 1
    2033  endif
    2034  if (ParamIsDefault(nthreads))
    2035  nthreads = -1
    2036  endif
    2037 
    2038  dfref base_df = GetDataFolderDFR()
    2039  variable result = 0
    2040  string datasetpath
    2041  string datawavename
    2042  string wavenames = ""
    2043 
    2044  datasetpath = scanpath + "/" + datasetname
    2045  datasetpath = ReplaceString("//", datasetpath, "/")
    2046  datawavename = StringFromList(ItemsInList(datasetpath, "/") - 1, datasetpath, "/")
    2047 
    2048  string regionname
    2049  string regionpath
    2050  if (ItemsInList(datasetname, "/") >= 2)
    2051  regionname = StringFromList(0, datasetname, "/")
    2052  regionpath = ReplaceString("//", scanpath + "/" + regionname, "/")
    2053  datasetname = RemoveListItem(0, datasetname, "/")
    2054  NewDataFolder /o/s $regionname
    2055  else
    2056  regionname = ""
    2057  regionpath = scanpath
    2058  endif
    2059 
    2060  STRUCT HDF5DataInfo di // Defined in HDF5 Browser.ipf.
    2061  InitHDF5DataInfo(di)
    2062  variable err = HDF5DatasetInfo(fileID, datasetpath, 0, di)
    2063  if (err != 0)
    2064  print "error accessing detector/data"
    2065  result = -1
    2066  return wavenames
    2067  endif
    2068  if (di.ndims < 2)
    2069  print "error: rank of dataset < 2"
    2070  result = -2
    2071  return wavenames
    2072  elseif (di.ndims < 3)
    2073  progress = 0
    2074  endif
    2075 
    2076  variable idx, idy, idz, idt
    2077  variable transpose = WhichListItem(datawavename, kTransposedDatasets) >= 0
    2078  if (transpose)
    2079  idx = 1
    2080  idy = 0
    2081  else
    2082  idx = 0
    2083  idy = 1
    2084  endif
    2085  idz = 2
    2086  idt = 3
    2087 
    2088  variable nx, ny, nz, nt, nzt
    2089  nx = di.dims[idx]
    2090  ny = di.dims[idy]
    2091  nz = di.dims[idz]
    2092  nt = di.dims[idt]
    2093  // adjust singleton dimensions
    2094  nz = max(nz, 1)
    2095  nt = max(nt, 1)
    2096  nzt = nz * nt
    2097 
    2098  // load data image by image
    2099  HDF5MakeHyperslabWave("slab", max(di.ndims, 4))
    2100  wave slab
    2101  slab[][%Start] = 0
    2102  slab[][%Stride] = 1
    2103  slab[][%Count] = 1
    2104  slab[][%Block] = 1
    2105  slab[idx][%Block] = nx
    2106  slab[idy][%Block] = ny
    2107 
    2108  // set up multi threading
    2109  if (nthreads < 0)
    2110  nthreads = ThreadProcessorCount
    2111  endif
    2112  if (nthreads > 0)
    2113  variable threadGroupID = ThreadGroupCreate(nthreads)
    2114  variable ithread
    2115  for (ithread = 0; ithread < nthreads; ithread += 1)
    2116  ThreadStart threadGroupID, ithread, reduce_slab_worker(reduction_func)
    2117  endfor
    2118  else
    2119  make /n=(nzt) /df /free processing_folders
    2120  endif
    2121 
    2122  if (progress)
    2123  display_progress_panel("HDF5 Import", "Loading data (step 1 of 2)...", nzt)
    2124  endif
    2125 
    2126  // create a template wave with the correct scales and labels
    2127  make /n=(nx,ny) /d /o $datawavename
    2128  wave template = $datawavename
    2129  ps_set_dimlabels2(template, datawavename)
    2130  ps_scale_dataset(template)
    2131 
    2132  variable iz, it, izt
    2133  string dfname
    2134  variable iw, nw
    2135  string sw
    2136  make /n=0 /free /wave result_waves
    2137 
    2138  izt = 0
    2139  for (iz = 0; iz < nz; iz += 1)
    2140  for (it = 0; it < nt; it += 1)
    2141  // load hyperslab
    2142  slab[idz][%Start] = iz
    2143  slab[idt][%Start] = it
    2144  dfname = "processing_" + num2str(izt)
    2145  newdatafolder /s $dfname
    2146  HDF5LoadData /O /Q /Z /SLAB=slab /N=slabdata fileID, datasetpath
    2147 
    2148  // send to processing queue
    2149  duplicate template, image
    2150  variable /g r_index = iz
    2151  variable /g s_index = it
    2152  string /g func_param = reduction_param
    2153 
    2154  if (nthreads > 0)
    2155  WaveClear image
    2156  ThreadGroupPutDF threadGroupID, :
    2157  else
    2158  processing_folders[izt] = GetDataFolderDFR()
    2159  make /n=1/d profile1, profile2
    2160  wave slabdata
    2161  wave /wave reduced_waves = reduce_slab_image(slabdata, image, reduction_func, func_param)
    2162  variable /g func_result = numpnts(reduced_waves)
    2163  adh5_get_result_waves(reduced_waves, "redw_", 0)
    2164  WaveClear slabdata, image, reduced_waves
    2165  setdatafolder ::
    2166  endif
    2167 
    2168  izt += 1
    2169  // progress window
    2170  if (progress)
    2171  if (update_progress_panel(izt))
    2172  print "user abort"
    2173  result = -4
    2174  break
    2175  endif
    2176  endif
    2177  endfor
    2178  endfor
    2179 
    2180  killwaves /z slab, slabdata, template
    2181  if (progress)
    2182  update_progress_panel(0, message="Processing data (step 2 of 2)...")
    2183  endif
    2184 
    2185  dfref dfr
    2186  for (izt = 0; (izt < nzt) && (result == 0); izt += 1)
    2187  if (nthreads > 0)
    2188  do
    2189  if (progress)
    2190  if (update_progress_panel(izt))
    2191  print "user abort"
    2192  result = -4
    2193  break
    2194  endif
    2195  endif
    2196  dfr = ThreadGroupGetDFR(threadGroupID, 1000)
    2197  if (DatafolderRefStatus(dfr) != 0)
    2198  break
    2199  endif
    2200  while (1)
    2201  else
    2202  if (progress)
    2203  if (update_progress_panel(izt))
    2204  print "user abort"
    2205  result = -4
    2206  break
    2207  endif
    2208  endif
    2209  dfr = processing_folders[izt]
    2210  endif
    2211 
    2212  if (result != 0)
    2213  break
    2214  endif
    2215 
    2216  nvar rr = dfr:r_index
    2217  nvar ss = dfr:s_index
    2218  nvar func_result = dfr:func_result
    2219 
    2220  if (func_result < 1)
    2221  print "error during data reduction."
    2222  result = -3
    2223  break
    2224  endif
    2225 
    2226  if (numpnts(result_waves) == 0)
    2227  redimension /n=(func_result) result_waves
    2228  for (iw = 0; iw < func_result; iw += 1)
    2229  sw = "redw_" + num2str(iw)
    2230  wave profile = dfr:$sw
    2231  sw = "ReducedData" + num2str(iw+1)
    2232  make /n=(dimsize(profile, 0), nz, nt) /d /o $sw
    2233  wave data = $sw
    2234  setdimlabel 0, -1, $getdimlabel(profile, 0, -1), data
    2235  setdimlabel 1, -1, $kScanDimLabel, data
    2236  note data, note(profile)
    2237  ps_scale_dataset(data)
    2238  setscale /p x dimoffset(profile, 0), dimdelta(profile, 0), waveunits(profile, 0), data
    2239  setscale d 0, 0, waveunits(profile, -1), data
    2240  result_waves[iw] = data
    2241  endfor
    2242  endif
    2243  for (iw = 0; iw < func_result; iw += 1)
    2244  sw = "redw_" + num2str(iw)
    2245  wave profile = dfr:$sw
    2246  wave data = result_waves[iw]
    2247  data[][rr][ss] = profile[p]
    2248  endfor
    2249  endfor
    2250 
    2251  if (nthreads > 0)
    2252  variable tstatus = ThreadGroupRelease(threadGroupID)
    2253  if (tstatus == -2)
    2254  print "error: thread did not terminate properly."
    2255  result = -5
    2256  endif
    2257  else
    2258  for (izt = 0; izt < nzt; izt += 1)
    2259  KillDataFolder /Z processing_folders[izt]
    2260  endfor
    2261  endif
    2262 
    2263  if (result == 0)
    2264  nw = numpnts(result_waves)
    2265  wavenames = ""
    2266  for (iw = 0; iw < nw; iw += 1)
    2267  wave data = result_waves[iw]
    2268  if (nz == 1)
    2269  redimension /n=(-1, 0, 0) data
    2270  elseif (nt == 1)
    2271  redimension /n=(-1, nz, 0) data
    2272  endif
    2273  wavenames += nameofwave(data) + ";"
    2274  endfor
    2275  endif
    2276  if (progress)
    2277  kill_progress_panel()
    2278  endif
    2279 
    2280  setdatafolder base_df
    2281  return wavenames
    2282 end
    2283 
    2284 threadsafe static function reduce_slab_worker(reduction_func)
    2285  funcref adh5_default_reduction reduction_func
    2286  do
    2287  // wait for job from main thread
    2288  do
    2289  dfref dfr = ThreadGroupGetDFR(0, 1000)
    2290  if (DataFolderRefStatus(dfr) == 0)
    2291  if (GetRTError(2))
    2292  return 0 // no more jobs
    2293  endif
    2294  else
    2295  break
    2296  endif
    2297  while (1)
    2298 
    2299  // get input data
    2300  wave slabdata = dfr:slabdata
    2301  wave image = dfr:image
    2302  svar func_param = dfr:func_param
    2303  nvar rr = dfr:r_index
    2304  nvar ss = dfr:s_index
    2305 
    2306  // do the work
    2307  newdatafolder /s outDF
    2308  variable /g r_index = rr
    2309  variable /g s_index = ss
    2310  wave /wave reduced_waves = reduce_slab_image(slabdata, image, reduction_func, func_param)
    2311  variable /g func_result = numpnts(reduced_waves)
    2312 
    2313  // send output to queue and clean up
    2314  adh5_get_result_waves(reduced_waves, "redw_", 0)
    2315  WaveClear slabdata, image, reduced_waves
    2316  ThreadGroupPutDF 0, :
    2317  KillDataFolder dfr
    2318  while (1)
    2319 
    2320  return 0
    2321 end
    2322 
    2323 threadsafe static function /wave reduce_slab_image(slabdata, image, reduction_func, reduction_param)
    2324  wave slabdata
    2325  wave image
    2326  funcref adh5_default_reduction reduction_func
    2327  string reduction_param
    2328 
    2329  // the multiplication by detector sensitivity assumes that we are loading a ScientaImage.
    2330  image = slabdata[q][p][0][0] * kDetectorSensitivity
    2331 
    2332  return reduction_func(image, reduction_param)
    2333 end
    2334 
    2349 function /s psh5_load_info(APathName, AFileName)
    2350  string APathName
    2351  string AFileName
    2352 
    2353  dfref saveDF = GetDataFolderDFR()
    2354  dfref fileDF = NewFreeDataFolder()
    2355  setdatafolder fileDF
    2356 
    2357  variable fileID
    2358  string filepath
    2359  string scanpaths
    2360  variable nscans
    2361  variable iscan
    2362  string scanpath
    2363  string info = ""
    2364 
    2365  HDF5OpenFile /P=$APathName /R fileID as AFileName
    2366  if (v_flag == 0)
    2367  filepath = s_path + s_filename
    2368  scanpaths = psh5_list_scans(fileID)
    2369  nscans = ItemsInList(scanpaths)
    2370  for (iscan = 0; iscan < nscans; iscan += 1)
    2371  scanpath = StringFromList(iscan, scanpaths)
    2372  info = info + scanpath + "\r"
    2373  info = info + psh5_load_scan_info(fileID, scanpath)
    2374  endfor
    2375  HDF5CloseFile fileID
    2376  endif
    2377 
    2378  setdatafolder saveDF
    2379  return info
    2380 end
    2381 
    2396 function /s psh5_load_scan_info(fileID, scanpath)
    2397  variable fileID
    2398  string scanpath
    2399 
    2400  string info = ""
    2401  string positions = ""
    2402  string positioners = ""
    2403  string readables = ""
    2404  string detectors = ""
    2405  string regions = ""
    2406 
    2407  psh5_load_scan_meta(fileID, scanpath)
    2408 
    2409  wave /z ScanDimensions
    2410  wave /t /z ScanWritables
    2411  wave /t /z ScanReadables
    2412  wave /z ScanSteps
    2413 
    2414  if (WaveExists(ScanSteps) && (numpnts(ScanSteps) >= 1))
    2415  ScanSteps += 1
    2416  positions = "positions = (" + wave2list(ScanSteps, "%u", ",") + ")"
    2417  info = AddListItem(positions, info, "\r", inf)
    2418  endif
    2419  if (WaveExists(ScanWritables) && (numpnts(ScanWritables) >= 1))
    2420  positioners = "positioners = " + twave2list(ScanWritables, ",")
    2421  info = AddListItem(positioners, info, "\r", inf)
    2422  endif
    2423 
    2424  variable i, m, n
    2425  string s
    2426  if (WaveExists(ScanReadables) && (numpnts(ScanReadables) >= 1))
    2427  readables = twave2list(ScanReadables, ",")
    2428  n = ItemsInList(readables, ",")
    2429  for (i = 0; i < n; i += 1)
    2430  s = StringFromList(i, readables, ",")
    2431  m = ItemsInList(s, "/")
    2432  if (m > 1)
    2433  s = StringFromList(m - 1, s, "/")
    2434  endif
    2435  if (WhichListItem(s, detectors, ",") < 0)
    2436  detectors = AddListItem(s, detectors, ",", inf)
    2437  endif
    2438  endfor
    2439  detectors = "detectors = " + detectors
    2440  info = AddListItem(detectors, info, "\r", inf)
    2441  endif
    2442 
    2443  regions = psh5_list_scan_regions(fileID, scanpath)
    2444  if (strlen(regions) > 0)
    2445  regions = "regions = " + regions
    2446  info = AddListItem(regions, info, "\r", inf)
    2447  endif
    2448 
    2449  return info
    2450 end
    2451 
    2455 static function /s twave2list(wt, sep)
    2456  wave /t wt
    2457  string sep
    2458 
    2459  string list = ""
    2460  variable n = numpnts(wt)
    2461  variable i
    2462  for (i = 0; i < n; i += 1)
    2463  list = AddListItem(wt[i], list, sep, inf)
    2464  endfor
    2465 
    2466  return list
    2467 end
    2468 
    2472 static function /s wave2list(w, format, sep)
    2473  wave w
    2474  string format
    2475  string sep
    2476 
    2477  string list = ""
    2478  variable n = numpnts(w)
    2479  variable i
    2480  string s
    2481  for (i = 0; i < n; i += 1)
    2482  sprintf s, format, w[i]
    2483  list = AddListItem(s, list, sep, inf)
    2484  endfor
    2485 
    2486  return list
    2487 end
    const string kEnergyDimLabel
    Dimension label for the energy dispersive dimension of multi-dimensional datasets.
    -
    string psh5_load_scan_preview(variable fileID, string scanpath, variable set_scale=defaultValue, string pref_datasets=defaultValue)
    load a preview dataset from an open PShell HDF5 file.
    -
    string psh5_load_scan_attrs(variable fileID, string scanpath, variable attr_sets=defaultValue)
    load attributes of a PShell scan group.
    -
    const string kTransposedDatasets
    List of datasets that should be transposed upon loading.
    -
    string psh5_load_scan_complete(variable fileID, string scanpath, variable load_data=defaultValue, variable load_attr=defaultValue)
    load all data of a selected scan from a PShell data file.
    -
    const string kScanDimLabel
    Dimension label for the scan dimension of multi-dimensional datasets.
    -
    const string kAngleDimLabel
    Dimension label for the angle dispersive dimension of multi-dimensional datasets. ...
    -
    const string kDataDimLabel
    Dimension label for the data dimension.
    -
    string psh5_load_preview(string APathName, string AFileName, variable load_data=defaultValue, variable load_attr=defaultValue, string pref_scans=defaultValue, string pref_datasets=defaultValue)
    load a preview image from a PShell data file.
    -
    variable psh5_open_file(string ANickName, string APathName, string AFileName)
    open a HDF5 file created by the PShell data acquisition program and prepare the data folder...
    -
    variable ps_scale_datasets()
    set the dimension scales of loaded PShell Scienta datasets according to attributes.
    -
    string psh5_load_scan_meta(variable fileID, string scanpath)
    load metadata of a PShell scan group.
    -
    const string kScientaScalingDatasets
    List of datasets that must be loaded to determine the axis scaling of a Scienta image.
    -
    string psh5_list_scan_datasets(variable fileID, string scanpath, variable include_regions=defaultValue)
    list datasets of a PShell scan group.
    -
    string psh5_load_scan_data(variable fileID, string scanpath)
    load all datasets of a PShell scan group.
    -
    const variable kDetectorSensitivity
    multiply scienta detector intensity by this value to get actual counts.
    -
    string psh5_load_complete(string ANickName, string APathName, string AFileName, variable load_data=defaultValue, variable load_attr=defaultValue)
    load everything from a PShell data file.
    -
    string psh5_list_scans(variable fileID)
    list scan groups of a PShell data file.
    -
    variable psh5_close_file(variable fileID)
    close a HDF5 file opened by psh5_open_file.
    -
    const string kPreviewDatasets
    List of preferred datasets to load for preview.
    +Go to the documentation of this file.
    1 #pragma rtGlobals=3 // Use modern global access method and strict wave access.
    2 #pragma IgorVersion = 6.36
    3 #pragma ModuleName = PearlPShellImport
    4 #include <HDF5 Browser>
    5 #include "pearl-compat"
    6 #include "pearl-gui-tools"
    7 #include "pearl-area-import"
    8 
    9 // copyright (c) 2013-18 Paul Scherrer Institut
    10 //
    11 // Licensed under the Apache License, Version 2.0 (the "License");
    12 // you may not use this file except in compliance with the License.
    13 // You may obtain a copy of the License at
    14 // http:///www.apache.org/licenses/LICENSE-2.0
    15 
    58 
    63 
    65 strconstant kEnergyDimLabel = "energy"
    66 
    68 strconstant kAngleDimLabel = "angle"
    69 
    71 strconstant kScanDimLabel = "scan"
    72 
    75 strconstant kDataDimLabel = "data"
    76 
    78 strconstant kPreviewDatasets = "ScientaImage;ScientaSpectrum;ImageAngleDistribution;ImageEnergyDistribution;Counts;SampleCurrent;"
    79 
    81 strconstant kScientaScalingDatasets = "LensMode;ScientaChannelBegin;ScientaChannelEnd;ScientaSliceBegin;ScientaSliceEnd;"
    82 
    84 strconstant kTransposedDatasets = "ScientaImage;"
    85 
    88 
    110 function psh5_open_file(ANickName, APathName, AFileName)
    111  string ANickName
    112  string APathName
    113  string AFileName
    114 
    115  setdatafolder root:
    116  newdatafolder /s /o $("root:" + ANickName)
    117  dfref fileDF = GetDataFolderDFR()
    118 
    119  variable fileID
    120  HDF5OpenFile /P=$APathName /R fileID as AFileName
    121  if (v_flag == 0)
    122  string /g s_filepath
    123  string /g s_scanpaths
    124  s_filepath = s_path + s_filename
    125  s_scanpaths = psh5_list_scans(fileID)
    126  else
    127  fileID = 0
    128  endif
    129 
    130  return fileID
    131 end
    132 
    140 function psh5_close_file(fileID)
    141  variable fileID
    142 
    143  HDF5CloseFile fileID
    144 end
    145 
    170 function /s psh5_load_complete(ANickName, APathName, AFileName, [load_data, load_attr])
    171  string ANickName
    172  string APathName
    173  string AFileName
    174  variable load_data
    175  variable load_attr
    176 
    177  if (ParamIsDefault(load_data))
    178  load_data = 1
    179  endif
    180  if (ParamIsDefault(load_attr))
    181  load_attr = 1
    182  endif
    183 
    184  dfref saveDF = GetDataFolderDFR()
    185 
    186  // performance monitoring
    187  variable timerRefNum
    188  variable /g psh5_perf_secs
    189  timerRefNum = startMSTimer
    190 
    191  variable fileID = psh5_open_file(ANickName, APathName, AFileName)
    192  if (fileID)
    193  dfref fileDF = GetDataFolderDFR()
    194  svar s_filepath
    195  svar s_scanpaths
    196  AFileName = s_filepath
    197  print "loading " + s_filepath + "\r"
    198 
    199  variable ig
    200  variable ng = ItemsInList(s_scanpaths, ";")
    201  string sg
    202  string folder
    203 
    204  for (ig = 0; ig < ng; ig += 1)
    205  sg = StringFromList(ig, s_scanpaths, ";")
    206  folder = ReplaceString("/", sg, "")
    207  folder = ReplaceString(" ", folder, "")
    208  folder = PearlCleanupName(folder)
    209  setdatafolder fileDF
    210  newdatafolder /s /o $folder
    211  psh5_load_scan_complete(fileID, sg, load_data=load_data, load_attr=load_attr)
    212  endfor
    213 
    214  psh5_close_file(fileID)
    215  else
    216  AFileName = ""
    217  endif
    218 
    219  psh5_perf_secs = stopMSTimer(timerRefNum) / 1e6
    220 
    221  setdatafolder saveDF
    222  return AFileName
    223 end
    224 
    251 function /s psh5_load_preview(APathName, AFileName, [load_data, load_attr, pref_scans, pref_datasets])
    252  string APathName
    253  string AFileName
    254  variable load_data
    255  variable load_attr
    256  string pref_scans
    257  string pref_datasets
    258 
    259  if (ParamIsDefault(load_data))
    260  load_data = 1
    261  endif
    262  if (ParamIsDefault(load_attr))
    263  load_attr = 1
    264  endif
    265  if (ParamIsDefault(pref_scans))
    266  pref_scans = "*scan1*;"
    267  endif
    268  if (ParamIsDefault(pref_datasets))
    269  pref_datasets = ""
    270  endif
    271 
    272  dfref saveDF = GetDataFolderDFR()
    273 
    274  variable fileID
    275  string scanpaths = ""
    276  string dataname = ""
    277 
    278  // performance monitoring
    279  variable timerRefNum
    280  variable /g adh5_perf_secs
    281  timerRefNum = startMSTimer
    282 
    283  HDF5OpenFile /P=$APathName /R /Z fileID as AFileName
    284  if (v_flag == 0)
    285  AFileName = s_path + s_filename
    286  dfref fileDF = GetDataFolderDFR()
    287 
    288  scanpaths = psh5_list_scans(fileID)
    289  variable ng = ItemsInList(scanpaths)
    290  variable ig
    291  string sg
    292  variable np = ItemsInList(pref_scans)
    293  variable ip
    294  string sp
    295  variable found = 0
    296  if (ng > 0)
    297  for (ip = 0; ip < np; ip += 1)
    298  for (ig = 0; ig < ng; ig += 1)
    299  sg = StringFromList(ig, scanpaths)
    300  sp = StringFromList(ip, pref_scans)
    301  if (StringMatch(sg, sp))
    302  found = 1
    303  break
    304  endif
    305  endfor
    306  if (found)
    307  break
    308  endif
    309  endfor
    310  if (!found)
    311  ig = 0
    312  endif
    313  sg = StringFromList(ig, scanpaths)
    314 
    315  if (load_attr)
    316  setdatafolder fileDF
    317  newdatafolder /o/s attr
    318  killwaves /a/z
    319  psh5_load_scan_attrs(fileID, sg)
    320  endif
    321 
    322  setdatafolder fileDF
    323  dataname = psh5_load_scan_preview(fileID, sg, set_scale=load_attr, pref_datasets=pref_datasets)
    324  else
    325  print "no scans found in file " + AFileName
    326  endif
    327 
    328  HDF5CloseFile fileID
    329  endif
    330 
    331  if (timerRefNum >= 0)
    332  adh5_perf_secs = stopMSTimer(timerRefNum) / 1e6
    333  endif
    334 
    335  setdatafolder saveDF
    336  return dataname
    337 end
    338 
    361 function /s psh5_load_scan_complete(fileID, scanpath, [load_data, load_attr])
    362  variable fileID
    363  string scanpath
    364  variable load_data
    365  variable load_attr
    366 
    367  if (ParamIsDefault(load_data))
    368  load_data = 1
    369  endif
    370  if (ParamIsDefault(load_attr))
    371  load_attr = 1
    372  endif
    373 
    374  dfref saveDF = GetDataFolderDFR()
    375 
    376  dfref dataDF = GetDataFolderDFR()
    377  string wavenames
    378  string attrnames
    379  psh5_load_scan_meta(fileID, scanpath)
    380  if (load_attr)
    381  newdatafolder /s /o attr
    382  attrnames = psh5_load_scan_attrs(fileID, scanpath)
    383  endif
    384  if (load_data)
    385  setdatafolder dataDF
    386  wavenames = psh5_load_scan_data(fileID, scanpath)
    387  endif
    388  if (load_data && load_attr)
    389  setdatafolder dataDF
    391  endif
    392 
    393  setdatafolder saveDF
    394  return wavenames
    395 end
    396 
    405 function /s psh5_list_scans(fileID)
    406  variable fileID
    407 
    408  HDF5ListGroup /F /TYPE=1 fileID, "/"
    409 
    410  variable ig
    411  variable ng = ItemsInList(S_HDF5ListGroup, ";")
    412  string sg
    413  string scans = ""
    414 
    415  for (ig = 0; ig < ng; ig += 1)
    416  sg = StringFromList(ig, S_HDF5ListGroup, ";")
    417  if (cmpstr(sg[1,4], "scan") == 0)
    418  scans = AddListItem(sg, scans, ";", inf)
    419  endif
    420  endfor
    421 
    422  return scans
    423 end
    424 
    440 function /s psh5_list_scan_datasets(fileID, scanpath, [include_regions])
    441  variable fileID
    442  string scanpath
    443  variable include_regions
    444 
    445  if (ParamIsDefault(include_regions))
    446  include_regions = 0
    447  endif
    448  string result
    449 
    450  HDF5ListGroup /TYPE=2 /Z fileID, scanpath
    451  result = S_HDF5ListGroup
    452 
    453  if (include_regions)
    454  HDF5ListGroup /R /TYPE=2 /Z fileID, scanpath
    455  variable n = ItemsInList(S_HDF5ListGroup)
    456  variable i
    457  string ds
    458  string region_datasets
    459  for (i = 0; i < n; i += 1)
    460  ds = StringFromList(i, S_HDF5ListGroup)
    461  if (StringMatch(ds, "region*/*"))
    462  //region_datasets = psh5_list_scan_datasets(fileID, ReplaceString("//", scanpath + "/" + region, "/"), include_regions=0)
    463  result = AddListItem(ds, result, ";", inf)
    464  endif
    465  endfor
    466  endif
    467 
    468  return result
    469 end
    470 
    481 function /s psh5_list_scan_regions(fileID, scanpath)
    482  variable fileID
    483  string scanpath
    484 
    485  HDF5ListGroup /TYPE=1 /Z fileID, scanpath
    486  variable n = ItemsInList(S_HDF5ListGroup)
    487  variable i
    488  string result = ""
    489  string s
    490  for (i = 0; i < n; i += 1)
    491  s = StringFromList(i, S_HDF5ListGroup)
    492  if (StringMatch(s, "region*"))
    493  result = AddListItem(s, result, ";", inf)
    494  endif
    495  endfor
    496 
    497  return result
    498 end
    499 
    514 function /s psh5_load_scan_data(fileID, scanpath)
    515  variable fileID
    516  string scanpath
    517 
    518  string datasets = psh5_list_scan_datasets(fileID, scanpath, include_regions=1)
    519  variable nds = ItemsInList(datasets)
    520  variable ids
    521  string sds
    522  string sw
    523  string wavenames = ""
    524  for (ids = 0; ids < nds; ids += 1)
    525  sds = StringFromList(ids, datasets)
    526  sw = psh5_load_dataset(fileID, scanpath, sds, set_scale=0)
    527  wavenames = AddListItem(sw, wavenames, ";", inf)
    528  endfor
    529 
    530  return wavenames
    531 end
    532 
    554 function /s psh5_load_scan_attrs(fileID, scanpath, [attr_sets])
    555  variable fileID
    556  string scanpath
    557  variable attr_sets
    558 
    559  if (ParamIsDefault(attr_sets))
    560  attr_sets = 1
    561  endif
    562 
    563  string attr_path = ReplaceString("//", scanpath + "/attrs", "/")
    564  string attr_list = ""
    565  if (attr_sets & 1)
    566  HDF5ListGroup /TYPE=2 /Z fileID, attr_path
    567  if (!v_flag)
    568  attr_list = S_HDF5ListGroup
    569  endif
    570  endif
    571 
    572  variable ids
    573  variable nds
    574  string sds
    575 
    576  if (attr_sets & 2)
    577  nds = ItemsInList(kScientaScalingDatasets, ";")
    578  for (ids = 0; ids < nds; ids += 1)
    579  sds = StringFromList(ids, kScientaScalingDatasets)
    580  if (WhichListItem(sds, attr_list) < 0)
    581  attr_list = AddListItem(sds, attr_list, ";", inf)
    582  endif
    583  endfor
    584  endif
    585 
    586  nds = ItemsInList(attr_list, ";")
    587  string wavenames = ""
    588  for (ids = 0; ids < nds; ids += 1)
    589  sds = StringFromList(ids, attr_list, ";")
    590  HDF5LoadData /O /Q /Z fileID, attr_path + "/" + sds
    591  if (!v_flag)
    592  wavenames = AddListItem(s_wavenames, wavenames, ";", inf)
    593  endif
    594  endfor
    595  wavenames = ReplaceString(";;", wavenames, ";")
    596 
    597  return wavenames
    598 end
    599 
    625 function /s psh5_load_scan_meta(fileID, scanpath)
    626  variable fileID
    627  string scanpath
    628  string wavenames = ""
    629 
    630  HDF5LoadData /O /Q /Z /A="Dimensions" /N=ScanDimensions /TYPE=1 fileID, scanpath
    631  if (!v_flag)
    632  wavenames = AddListItem(s_wavenames, wavenames, ";", inf)
    633  else
    634  make /n=1 /o ScanDimensions
    635  ScanDimensions = 0
    636  wavenames = AddListItem("ScanDimensions", wavenames, ";", inf)
    637  endif
    638  HDF5LoadData /O /Q /Z /A="Readables" /N=ScanReadables /TYPE=1 fileID, scanpath
    639  if (!v_flag)
    640  wavenames = AddListItem(s_wavenames, wavenames, ";", inf)
    641  else
    642  make /n=1 /o /t ScanReadables
    643  ScanReadables[0] = "ScientaSpectrum"
    644  wavenames = AddListItem("ScanReadables", wavenames, ";", inf)
    645  endif
    646  HDF5LoadData /O /Q /Z /A="Writables" /N=ScanWritables /TYPE=1 fileID, scanpath
    647  if (!v_flag)
    648  wavenames = AddListItem(s_wavenames, wavenames, ";", inf)
    649  endif
    650  HDF5LoadData /O /Q /Z /A="Steps" /N=ScanSteps /TYPE=1 fileID, scanpath
    651  if (!v_flag)
    652  wavenames = AddListItem(s_wavenames, wavenames, ";", inf)
    653  endif
    654  wavenames = ReplaceString(";;", wavenames, ";")
    655 
    656  // additional attributes from XPSSpectrum.py
    657  HDF5LoadData /O /Q /Z /A="Iterations" /N=ScanIterations /TYPE=1 fileID, scanpath
    658  if (!v_flag)
    659  wavenames = AddListItem(s_wavenames, wavenames, ";", inf)
    660  endif
    661  HDF5LoadData /O /Q /Z /A="Step Size" /N=ScanStepSize /TYPE=1 fileID, scanpath
    662  if (!v_flag)
    663  wavenames = AddListItem(s_wavenames, wavenames, ";", inf)
    664  endif
    665  HDF5LoadData /O /Q /Z /A="Step Time" /N=ScanStepTime /TYPE=1 fileID, scanpath
    666  if (!v_flag)
    667  wavenames = AddListItem(s_wavenames, wavenames, ";", inf)
    668  endif
    669 
    670  return wavenames
    671 end
    672 
    706 function /s psh5_load_dataset(fileID, scanpath, datasetname, [set_scale])
    707  variable fileID
    708  string scanpath
    709  string datasetname
    710  variable set_scale
    711 
    712  if (ParamIsDefault(set_scale))
    713  set_scale = 1
    714  endif
    715 
    716  dfref base_df = GetDataFolderDFR()
    717 
    718  string datasetpath
    719  datasetpath = scanpath + "/" + datasetname
    720  datasetpath = ReplaceString("//", datasetpath, "/")
    721 
    722  string regionname
    723  string regionpath
    724  if (ItemsInList(datasetname, "/") >= 2)
    725  regionname = StringFromList(0, datasetname, "/")
    726  regionpath = ReplaceString("//", scanpath + "/" + regionname, "/")
    727  datasetname = RemoveListItem(0, datasetname, "/")
    728  NewDataFolder /o/s $regionname
    729  else
    730  regionname = ""
    731  regionpath = scanpath
    732  endif
    733 
    734  STRUCT HDF5DataInfo di // Defined in HDF5 Browser.ipf.
    735  InitHDF5DataInfo(di)
    736  variable err = HDF5DatasetInfo(fileID, datasetpath, 0, di)
    737  if (err != 0)
    738  print "error accessing detector/data"
    739  return ""
    740  endif
    741 
    742  string dataname
    743  if (di.ndims < 2)
    744  HDF5LoadData /O /Q /Z fileID, datasetpath
    745  dataname = StringFromList(0, S_waveNames)
    746  else
    747  dataname = psh5_load_dataset_slabs(fileID, regionpath, datasetname)
    748  endif
    749 
    750  wave /z data = $dataname
    751  if (waveexists(data))
    752  psh5_load_dataset_meta(fileID, regionpath, datasetname, data)
    753  ps_set_dimlabels(data)
    754  if (set_scale)
    755  ps_scale_dataset(data)
    756  endif
    757  else
    758  dataname = ""
    759  endif
    760 
    761  setdatafolder base_df
    762  return dataname
    763 end
    764 
    778 static function /s select_dataset(file_datasets, pref_datasets)
    779  string file_datasets
    780  string pref_datasets
    781 
    782  variable index
    783  variable nds = ItemsInList(file_datasets)
    784  variable ids
    785  string sds = ""
    786  string mds = ""
    787  variable np = ItemsInList(pref_datasets)
    788  variable ip
    789  string sp
    790  variable found = 0
    791  if (nds > 0)
    792  for (ip = 0; ip < np; ip += 1)
    793  for (ids = 0; ids < nds; ids += 1)
    794  sds = StringFromList(ids, file_datasets)
    795  index = ItemsInList(sds, "/") - 1
    796  mds = StringFromList(index, sds, "/")
    797  sp = StringFromList(ip, pref_datasets)
    798  if (StringMatch(mds, sp))
    799  found = 1
    800  break
    801  endif
    802  endfor
    803  if (found)
    804  break
    805  endif
    806  endfor
    807  if (!found)
    808  ids = 0
    809  sds = StringFromList(ids, file_datasets)
    810  endif
    811  endif
    812 
    813  return sds
    814 end
    815 
    840 function /s psh5_load_scan_preview(fileID, scanpath, [set_scale, pref_datasets])
    841  variable fileID
    842  string scanpath
    843  variable set_scale
    844  string pref_datasets
    845 
    846  if (ParamIsDefault(set_scale))
    847  set_scale = 1
    848  endif
    849  if (ParamIsDefault(pref_datasets) || (strlen(pref_datasets) == 0))
    850  pref_datasets = kPreviewDatasets
    851  endif
    852 
    853  dfref saveDF = GetDataFolderDFR()
    854  dfref dataDF = saveDF
    855 
    856  string datasets = psh5_list_scan_datasets(fileID, scanpath, include_regions=1)
    857  string datasetname = select_dataset(datasets, pref_datasets)
    858  string datasetpath
    859  datasetpath = scanpath + "/" + datasetname
    860  datasetpath = ReplaceString("//", datasetpath, "/")
    861 
    862  STRUCT HDF5DataInfo di // Defined in HDF5 Browser.ipf.
    863  InitHDF5DataInfo(di)
    864  variable err = HDF5DatasetInfo(fileID, datasetpath, 0, di)
    865  if (err != 0)
    866  print "error accessing detector/data"
    867  return ""
    868  endif
    869 
    870  string dataname
    871  if (di.ndims < 2)
    872  HDF5LoadData /O /Q /Z fileID, datasetpath
    873  dataname = StringFromList(0, S_waveNames)
    874  wave /z data = $dataname
    875  if (waveexists(data))
    876  ps_set_dimlabels(data)
    877  endif
    878  else
    879  variable dim2start = 0
    880  variable dim2count = 1
    881  variable dim3start = 0
    882  variable dim3count = 1
    883  if (di.ndims >= 3)
    884  dim2start = floor(di.dims[2] / 2)
    885  dim2count = 1
    886  endif
    887  if (di.ndims >= 4)
    888  dim3start = floor(di.dims[3] / 2)
    889  dim3count = 1
    890  endif
    891 
    892  dataname = psh5_load_dataset_slab(fileID, scanpath, datasetname, dim2start, dim2count, dim3start, dim3count)
    893  endif
    894 
    895  wave /z data = $dataname
    896  if (waveexists(data))
    897  if (set_scale)
    898  setdatafolder dataDF
    899  string positioners
    900  string positioner
    901  string positionerpath
    902  positioners = psh5_load_scan_meta(fileID, scanpath)
    903  wave /t /z ScanWritables
    904  if (waveexists(ScanWritables) && (numpnts(ScanWritables) >= 1))
    905  positioner = ScanWritables[0]
    906  if (strlen(positioner) > 0)
    907  positionerpath = scanpath + "/" + positioner
    908  positionerpath = ReplaceString("//", positionerpath, "/")
    909  HDF5LoadData /O /Q /Z fileID, positionerpath
    910  endif
    911  endif
    912 
    913  setdatafolder dataDF
    914  newdatafolder /o/s attr
    915  psh5_load_scan_attrs(fileID, scanpath, attr_sets=2)
    916  setdatafolder dataDF
    917  ps_scale_dataset(data)
    918  endif
    919  else
    920  dataname = ""
    921  endif
    922 
    923  return dataname
    924 end
    925 
    953 function /s psh5_load_scan_section(fileID, scanpath, dim, [set_scale, pref_datasets])
    954  variable fileID
    955  string scanpath
    956  variable dim
    957  variable set_scale
    958  string pref_datasets
    959 
    960  // select first dimension (future argument)
    961  // 0 = first dimension is x axis (energy of scienta image)
    962  dim = 0
    963 
    964  if (ParamIsDefault(set_scale))
    965  set_scale = 1
    966  endif
    967  if (ParamIsDefault(pref_datasets) || (strlen(pref_datasets) == 0))
    968  pref_datasets = kPreviewDatasets
    969  endif
    970 
    971  dfref saveDF = GetDataFolderDFR()
    972  dfref dataDF = saveDF
    973 
    974  string datasets = psh5_list_scan_datasets(fileID, scanpath)
    975  string datasetname = select_dataset(datasets, pref_datasets)
    976  string datasetpath
    977  datasetpath = scanpath + "/" + datasetname
    978  datasetpath = ReplaceString("//", datasetpath, "/")
    979  string dataname = StringFromList(ItemsInList(datasetpath, "/") - 1, datasetpath, "/")
    980  string destname = dataname[0,29] + num2str(dim)
    981 
    982  STRUCT HDF5DataInfo di // Defined in HDF5 Browser.ipf.
    983  InitHDF5DataInfo(di)
    984  variable err = HDF5DatasetInfo(fileID, datasetpath, 0, di)
    985  if (err != 0)
    986  print "error accessing detector/data"
    987  return ""
    988  elseif (di.ndims != 3)
    989  print "error: rank of dataset != 3"
    990  return ""
    991  endif
    992 
    993  variable idx, idy, idz, idt
    994  variable transpose = WhichListItem(dataname, kTransposedDatasets) >= 0
    995  if (transpose)
    996  idx = 1
    997  idy = 0
    998  else
    999  idx = 0
    1000  idy = 1
    1001  endif
    1002  idz = 2
    1003  idt = 3
    1004 
    1005  variable nx, ny, nz
    1006  nx = di.dims[idx]
    1007  ny = di.dims[idy]
    1008  nz = di.dims[idz]
    1009 
    1010  HDF5MakeHyperslabWave("slab", max(di.ndims, 4))
    1011  wave slab
    1012  slab[][%Start] = 0
    1013  slab[][%Stride] = 1
    1014  slab[][%Count] = 1
    1015  slab[][%Block] = 1
    1016 
    1017  if (dim == 0)
    1018  slab[idy][%Start] = floor(ny / 2)
    1019  slab[idx][%Block] = nx
    1020  make /n=(nx,nz) /o $destname
    1021  else
    1022  slab[idx][%Start] = floor(nx / 2)
    1023  slab[idy][%Block] = ny
    1024  make /n=(ny,nz) /o $destname
    1025  endif
    1026  slab[idz][%Block] = nz
    1027  wave data = $destname
    1028  data = 0
    1029 
    1030  HDF5LoadData /O /Q /Z /SLAB=slab /N=slabdata fileID, datasetpath
    1031  if (!v_flag)
    1032  wave slabdata
    1033  if (transpose)
    1034  data += slabdata[0][p][q][0]
    1035  else
    1036  data += slabdata[p][0][q][0]
    1037  endif
    1038  endif
    1039  killwaves /z slab, slabdata
    1040 
    1041  if (set_scale)
    1042  make /n=(1,1,1) /free dummy
    1043  ps_set_dimlabels2(dummy, dataname)
    1044  setdimlabel 0, -1, $GetDimLabel(dummy, dim, -1), data
    1045  setdimlabel 1, -1, $kScanDimLabel, data
    1046 
    1047  setdatafolder dataDF
    1048  string positioners
    1049  string positioner
    1050  string positionerpath
    1051  positioners = psh5_load_scan_meta(fileID, scanpath)
    1052  wave /t /z ScanWritables
    1053  if (waveexists(ScanWritables) && (numpnts(ScanWritables) >= 1))
    1054  positioner = ScanWritables[0]
    1055  if (strlen(positioner) > 0)
    1056  positionerpath = scanpath + "/" + positioner
    1057  positionerpath = ReplaceString("//", positionerpath, "/")
    1058  HDF5LoadData /O /Q /Z fileID, positionerpath
    1059  endif
    1060  endif
    1061 
    1062  setdatafolder dataDF
    1063  newdatafolder /o/s attr
    1064  killwaves /a/z
    1065  psh5_load_scan_attrs(fileID, scanpath, attr_sets=2)
    1066  setdatafolder dataDF
    1067  ps_scale_dataset(data)
    1068  endif
    1069 
    1070  return destname
    1071 end
    1072 
    1091 function psh5_load_dataset_meta(fileID, datapath, datasetname, datawave)
    1092  variable fileID
    1093  string datapath
    1094  string datasetname
    1095  wave datawave
    1096 
    1097  dfref saveDF = GetDataFolderDFR()
    1098  SetDataFolder NewFreeDataFolder()
    1099 
    1100  string datasetpath = datapath + "/" + datasetname
    1101  datasetpath = ReplaceString("//", datasetpath, "/")
    1102  string wnote
    1103 
    1104  HDF5LoadData /O /Q /Z /A="Writable Dimension" /N=WriteDim fileID, datasetpath
    1105  if (!v_flag)
    1106  wave WriteDim
    1107  // scan dimension starts at 1
    1108  sprintf wnote, "ScanDimension=%u", WriteDim[0]
    1109  Note datawave, wnote
    1110  endif
    1111 
    1112  HDF5LoadData /O /Q /Z /A="Writable Index" /N=WriteIndex fileID, datasetpath
    1113  if (!v_flag)
    1114  wave WriteIndex
    1115  sprintf wnote, "WriteableIndex=%u", WriteIndex[0]
    1116  Note datawave, wnote
    1117  endif
    1118 
    1119  HDF5LoadData /O /Q /Z /A="Readable Index" /N=ReadIndex fileID, datasetpath
    1120  if (!v_flag)
    1121  wave ReadIndex
    1122  sprintf wnote, "ReadableIndex=%u", ReadIndex[0]
    1123  Note datawave, wnote
    1124  endif
    1125 
    1126  setdatafolder saveDF
    1127  return 0
    1128 end
    1129 
    1148 function /s psh5_load_dataset_slabs(fileID, datapath, datasetname, [progress])
    1149  variable fileID
    1150  string datapath
    1151  string datasetname
    1152  variable progress
    1153 
    1154  if (ParamIsDefault(progress))
    1155  progress = 1
    1156  endif
    1157 
    1158  variable result = 0
    1159  string datasetpath
    1160  string datawavename
    1161  datasetpath = datapath + "/" + datasetname
    1162  datasetpath = ReplaceString("//", datasetpath, "/")
    1163  datawavename = StringFromList(ItemsInList(datasetpath, "/") - 1, datasetpath, "/")
    1164 
    1165  STRUCT HDF5DataInfo di // Defined in HDF5 Browser.ipf.
    1166  InitHDF5DataInfo(di)
    1167  variable err = HDF5DatasetInfo(fileID, datasetpath, 0, di)
    1168  if (err != 0)
    1169  print "error accessing detector/data"
    1170  return ""
    1171  endif
    1172  if (di.ndims < 2)
    1173  print "error: rank of dataset < 2"
    1174  return ""
    1175  elseif (di.ndims < 3)
    1176  progress = 0
    1177  endif
    1178 
    1179  variable idx, idy, idz, idt, izt
    1180  variable transpose = WhichListItem(datawavename, kTransposedDatasets) >= 0
    1181  if (transpose)
    1182  idx = 1
    1183  idy = 0
    1184  else
    1185  idx = 0
    1186  idy = 1
    1187  endif
    1188  idz = 2
    1189  idt = 3
    1190 
    1191  variable nx, ny, nz, nt, nzt
    1192  nx = di.dims[idx]
    1193  ny = di.dims[idy]
    1194  nz = di.dims[idz]
    1195  nt = di.dims[idt]
    1196  make /n=(nx,ny,nz,nt) /o $datawavename
    1197  wave data = $datawavename
    1198 
    1199  nz = max(nz, 1)
    1200  nt = max(nt, 1)
    1201  nzt = nz * nt
    1202  izt = 0
    1203  if (progress)
    1204  display_progress_panel("HDF5 Import", "Loading data...", nzt)
    1205  endif
    1206 
    1207  // load data image by image
    1208  HDF5MakeHyperslabWave("slab", max(di.ndims, 4))
    1209  wave slab
    1210  slab[][%Start] = 0
    1211  slab[][%Stride] = 1
    1212  slab[][%Count] = 1
    1213  slab[][%Block] = 1
    1214  slab[idx][%Block] = nx
    1215  slab[idy][%Block] = ny
    1216 
    1217  variable iz, it
    1218  for (iz = 0; iz < nz; iz += 1)
    1219  for (it = 0; it < nt; it += 1)
    1220  slab[idz][%Start] = iz
    1221  slab[idt][%Start] = it
    1222  HDF5LoadData /O /Q /Z /SLAB=slab /N=slabdata fileID, datasetpath
    1223  wave slabdata // 2D, 3D, or 4D with singletons
    1224  if (transpose)
    1225  data[][][iz][it] = slabdata[q][p][0][0]
    1226  else
    1227  data[][][iz][it] = slabdata[p][q][0][0]
    1228  endif
    1229 
    1230  // progress window
    1231  izt += 1
    1232  if (progress)
    1233  if (update_progress_panel(izt))
    1234  result = -4 // user abort
    1235  break
    1236  endif
    1237  endif
    1238  endfor
    1239  if (result < 0)
    1240  break
    1241  endif
    1242  endfor
    1243 
    1244  if (progress)
    1245  kill_progress_panel()
    1246  endif
    1247 
    1248  killwaves /z slab, slabdata
    1249  if (!result)
    1250  ps_set_dimlabels(data)
    1251  return datawavename
    1252  else
    1253  killwaves /z data
    1254  return ""
    1255  endif
    1256 end
    1257 
    1284 function /s psh5_load_dataset_slab(fileID, datapath, datasetname, dim2start, dim2count, dim3start, dim3count)
    1285  variable fileID
    1286  string datapath
    1287  string datasetname
    1288  variable dim2start
    1289  variable dim2count
    1290  variable dim3start
    1291  variable dim3count
    1292 
    1293  string datasetpath
    1294  string datawavename
    1295  datasetpath = datapath + "/" + datasetname
    1296  datasetpath = ReplaceString("//", datasetpath, "/")
    1297  datawavename = StringFromList(ItemsInList(datasetpath, "/") - 1, datasetpath, "/")
    1298 
    1299  STRUCT HDF5DataInfo di
    1300  InitHDF5DataInfo(di)
    1301  variable err = HDF5DatasetInfo(fileID, datasetpath, 0, di)
    1302  if (err != 0)
    1303  print "error accessing detector/data"
    1304  return ""
    1305  endif
    1306  if (di.ndims < 2)
    1307  print "error: rank of dataset < 2"
    1308  return ""
    1309  endif
    1310 
    1311  variable idx, idy, idz, idt
    1312  variable transpose = WhichListItem(datawavename, kTransposedDatasets) >= 0
    1313  if (transpose)
    1314  idx = 1
    1315  idy = 0
    1316  else
    1317  idx = 0
    1318  idy = 1
    1319  endif
    1320  idz = 2
    1321  idt = 3
    1322 
    1323  variable nx, ny
    1324  nx = di.dims[idx]
    1325  ny = di.dims[idy]
    1326  make /n=(nx,ny) /o $datawavename
    1327  wave data = $datawavename
    1328  data = 0
    1329 
    1330  HDF5MakeHyperslabWave("slab", max(di.ndims, 4))
    1331  wave slab
    1332  slab[][%Start] = 0
    1333  slab[][%Stride] = 1
    1334  slab[][%Count] = 1
    1335  slab[][%Block] = 1
    1336  slab[idx][%Block] = nx
    1337  slab[idy][%Block] = ny
    1338 
    1339  variable iz, it
    1340  variable navg = 0
    1341  variable dim2end = dim2start + dim2count - 1
    1342  variable dim3end = dim3start + dim3count - 1
    1343  for (iz = dim2start; iz <= dim2end; iz += 1)
    1344  for (it = dim3start; it <= dim3end; it += 1)
    1345  slab[idz][%Start] = iz
    1346  slab[idt][%Start] = it
    1347  HDF5LoadData /O /Q /Z /SLAB=slab /N=slabdata fileID, datasetpath
    1348  if (!v_flag)
    1349  wave slabdata
    1350  if (transpose)
    1351  data += slabdata[q][p][0][0]
    1352  else
    1353  data += slabdata[p][q][0][0]
    1354  endif
    1355  navg += 1
    1356  endif
    1357  endfor
    1358  endfor
    1359  if (navg)
    1360  data /= navg
    1361  endif
    1362 
    1363  killwaves /z slab, slabdata
    1364  ps_set_dimlabels(data)
    1365  return datawavename
    1366 end
    1367 
    1383 function ps_set_dimlabels(data)
    1384  wave data
    1385 
    1386  ps_set_dimlabels2(data, NameOfWave(data))
    1387 end
    1388 
    1402 function ps_set_dimlabels2(data, name)
    1403  wave data
    1404  string name
    1405 
    1406  variable dummy
    1407  try
    1408  // intrinsic dimensions
    1409  strswitch(name)
    1410  case "ScientaImage":
    1411  setdimlabel 0, -1, $kEnergyDimLabel, data
    1412  setdimlabel 1, -1, $kAngleDimLabel, data
    1413  if (WaveDims(data) >= 3)
    1414  setdimlabel 2, -1, $kScanDimLabel, data
    1415  endif
    1416  AbortOnRTE
    1417  break
    1418  case "ImageAngleDistribution":
    1419  case "ScientaAngleDistribution":
    1420  if (WaveDims(data) >= 2)
    1421  setdimlabel 0, -1, $kScanDimLabel, data
    1422  setdimlabel 1, -1, $kAngleDimLabel, data
    1423  else
    1424  setdimlabel 0, -1, $kAngleDimLabel, data
    1425  endif
    1426  AbortOnRTE
    1427  break
    1428  case "ScientaSpectrum":
    1429  case "ImageEnergyDistribution":
    1430  case "ScientaEnergyDistribution":
    1431  if (WaveDims(data) >= 2)
    1432  setdimlabel 0, -1, $kScanDimLabel, data
    1433  setdimlabel 1, -1, $kEnergyDimLabel, data
    1434  else
    1435  setdimlabel 0, -1, $kEnergyDimLabel, data
    1436  endif
    1437  AbortOnRTE
    1438  break
    1439  default:
    1440  if (WaveDims(data) == 1)
    1441  setdimlabel 0, -1, $kScanDimLabel, data
    1442  AbortOnRTE
    1443  else
    1444  return 1
    1445  endif
    1446  endswitch
    1447  catch
    1448  dummy = GetRTError(1)
    1449  return 2
    1450  endtry
    1451  return 0
    1452 end
    1453 
    1459 static function /df find_scan_folder(dataDF)
    1460  dfref dataDF
    1461 
    1462  dfref attrDF = dataDF:attr
    1463  if (!DataFolderRefStatus(attrDF))
    1464  string df = GetDataFolder(1, dataDF) + ":"
    1465  dfref scanDF = $df
    1466  else
    1467  dfref scanDF = dataDF
    1468  endif
    1469  return scanDF
    1470 end
    1471 
    1476 static function /df find_attr_folder(dataDF)
    1477  dfref dataDF
    1478 
    1479  dfref attrDF = dataDF:attr
    1480  if (!DataFolderRefStatus(attrDF))
    1481  string df = GetDataFolder(1, dataDF) + ":"
    1482  dfref scanDF = $df
    1483  dfref attrDF = scanDF:attr
    1484  endif
    1485  return attrDF
    1486 end
    1487 
    1504 function ps_scale_datasets()
    1505  dfref scanDF = GetDataFolderDFR()
    1506  dfref attrDF = find_attr_folder(scanDF)
    1507 
    1508  make /n=3 /free lo, hi
    1509  make /n=3 /t /free ax, un
    1510  wave /t /z /SDFR=scanDF ScanReadables
    1511  if (WaveExists(ScanReadables))
    1512  variable isr
    1513  variable nsr = numpnts(ScanReadables)
    1514  string ssr
    1515  string sdf
    1516  for (isr = 0; isr < nsr; isr += 1)
    1517  setdatafolder scanDF
    1518  ssr = ScanReadables[isr]
    1519  if (ItemsInList(ssr, "/") >= 2)
    1520  sdf = StringFromList(0, ssr, "/")
    1521  ssr = RemoveListItem(0, ssr, "/")
    1522  setdatafolder $sdf
    1523  endif
    1524  wave /z wsr=$ssr
    1525  if (WaveExists(wsr))
    1526  ps_detect_scale(ax, lo, hi, un)
    1527  ps_scale_dataset_2(wsr, ax, lo, hi, un)
    1528  endif
    1529  endfor
    1530  endif
    1531  setdatafolder scanDF
    1532 end
    1533 
    1550 function ps_scale_dataset(data)
    1551  wave data
    1552 
    1553  dfref saveDF = GetDataFolderDFR()
    1554  dfref dataDF = GetWavesDataFolderDFR(data)
    1555 
    1556  setdatafolder dataDF
    1557  make /n=3 /free lo, hi
    1558  make /n=3 /t /free ax, un
    1559  ps_detect_scale(ax, lo, hi, un)
    1560  ps_scale_dataset_2(data, ax, lo, hi, un)
    1561  setdatafolder saveDF
    1562 end
    1563 
    1564 static function /wave find_scale_wave(name, dataDF, scanDF, attrDF)
    1565  string name
    1566  dfref dataDF
    1567  dfref scanDF
    1568  dfref attrDF
    1569 
    1570  wave /SDFR=dataDF /Z w = $name
    1571  if (!WaveExists(w))
    1572  wave /SDFR=scanDF /Z w = $name
    1573  if (!WaveExists(w))
    1574  wave /SDFR=attrDF /Z w = $name
    1575  endif
    1576  endif
    1577  return w
    1578 end
    1579 
    1621 function ps_detect_scale(ax, lo, hi, un)
    1622  wave /t ax
    1623  wave lo
    1624  wave hi
    1625  wave /t un
    1626 
    1627  dfref dataDF = GetDataFolderDFR()
    1628  dfref scanDF = find_scan_folder(dataDF)
    1629  dfref attrDF = find_attr_folder(dataDF)
    1630 
    1631  redimension /n=4 lo, hi, un, ax
    1632  setdimlabel 0, 0, $kEnergyDimLabel, lo, hi, un, ax
    1633  setdimlabel 0, 1, $kAngleDimLabel, lo, hi, un, ax
    1634  setdimlabel 0, 2, $kScanDimLabel, lo, hi, un, ax
    1635  setdimlabel 0, 3, $kDataDimLabel, lo, hi, un, ax
    1636 
    1637  // default values
    1638  lo[%$kEnergyDimLabel] = 0
    1639  hi[%$kEnergyDimLabel] = 1
    1640  un[%$kEnergyDimLabel] = "eV"
    1641  ax[%$kEnergyDimLabel] = "Ekin"
    1642 
    1643  lo[%$kAngleDimLabel] = -1
    1644  hi[%$kAngleDimLabel] = 1
    1645  un[%$kAngleDimLabel] = "arb."
    1646  un[%$kAngleDimLabel] = "slice"
    1647 
    1648  lo[%$kScanDimLabel] = 0
    1649  hi[%$kScanDimLabel] = 1
    1650  un[%$kScanDimLabel] = "arb."
    1651  ax[%$kScanDimLabel] = "scan"
    1652 
    1653  lo[%$kDataDimLabel] = 0
    1654  hi[%$kDataDimLabel] = 0
    1655  un[%$kDataDimLabel] = "arb."
    1656  ax[%$kDataDimLabel] = "value"
    1657 
    1658  wave /SDFR=attrDF /T /Z LensMode
    1659  wave /Z ChannelBegin = find_scale_wave("ScientaChannelBegin", dataDF, scanDF, attrDF)
    1660  wave /Z ChannelEnd = find_scale_wave("ScientaChannelEnd", dataDF, scanDF, attrDF)
    1661  wave /Z SliceBegin = find_scale_wave("ScientaSliceBegin", dataDF, scanDF, attrDF)
    1662  wave /Z SliceEnd = find_scale_wave("ScientaSliceEnd", dataDF, scanDF, attrDF)
    1663 
    1664  // lens mode can give more detail
    1665  if (waveexists(LensMode) && (numpnts(LensMode) >= 1))
    1666  strswitch(LensMode[0])
    1667  case "Angular45":
    1668  lo[%$kAngleDimLabel] = -45/2
    1669  hi[%$kAngleDimLabel] = +45/2
    1670  un[%$kAngleDimLabel] = "°"
    1671  ax[%$kAngleDimLabel] = "angle"
    1672  break
    1673  case "Angular60":
    1674  lo[%$kAngleDimLabel] = -60/2
    1675  hi[%$kAngleDimLabel] = +60/2
    1676  un[%$kAngleDimLabel] = "°"
    1677  ax[%$kAngleDimLabel] = "angle"
    1678  break
    1679  case "Transmission":
    1680  un[%$kAngleDimLabel] = "arb."
    1681  ax[%$kAngleDimLabel] = "offset"
    1682  break
    1683  endswitch
    1684  endif
    1685 
    1686  // best option if scales are explicit in separate waves
    1687  if (waveexists(ChannelBegin) && waveexists(ChannelEnd) && (numpnts(ChannelBegin) >= 1) && (numpnts(ChannelEnd) >= 1))
    1688  lo[%$kEnergyDimLabel] = ChannelBegin[0]
    1689  hi[%$kEnergyDimLabel] = ChannelEnd[0]
    1690  endif
    1691  if (waveexists(SliceBegin) && waveexists(SliceEnd) && (numpnts(SliceBegin) >= 1) && (numpnts(SliceEnd) >= 1))
    1692  lo[%$kAngleDimLabel] = SliceBegin[0]
    1693  hi[%$kAngleDimLabel] = SliceEnd[0]
    1694  endif
    1695 
    1696  wave /z /t /SDFR=scanDF ScanWritables
    1697  if (WaveExists(ScanWritables))
    1698  wave /z /SDFR=scanDF scanner = $ScanWritables[0]
    1699  if (!WaveExists(scanner))
    1700  wave /z /SDFR=attrDF scanner = $ScanWritables[0]
    1701  endif
    1702  if (WaveExists(scanner) && (numpnts(scanner) >= 1))
    1703  lo[%$kScanDimLabel] = scanner[0]
    1704  hi[%$kScanDimLabel] = scanner[numpnts(scanner)-1]
    1705  ax[%$kScanDimLabel] = NameOfWave(scanner)
    1706  strswitch(NameOfWave(scanner))
    1707  case "Eph":
    1708  ax[%$kScanDimLabel] = "photon energy"
    1709  un[%$kScanDimLabel] = "eV"
    1710  break
    1711  case "ManipulatorX":
    1712  case "ManipulatorY":
    1713  case "ManipulatorZ":
    1714  case "FocusYTrans":
    1715  case "FocusZTrans":
    1716  case "RefocusYTrans":
    1717  case "RefocusZTrans":
    1718  case "ExitSlitY":
    1719  un[%$kScanDimLabel] = "mm"
    1720  break
    1721  case "ExitSlit":
    1722  un[%$kScanDimLabel] = "µm"
    1723  break
    1724  case "ManipulatorTheta":
    1725  case "ManipulatorTilt":
    1726  case "ManipulatorPhi":
    1727  un[%$kScanDimLabel] = "°"
    1728  break
    1729  case "FocusXRot":
    1730  case "FocusYRot":
    1731  case "FocusZRot":
    1732  case "RefocusXRot":
    1733  case "RefocusYRot":
    1734  case "RefocusZRot":
    1735  un[%$kScanDimLabel] = "mrad"
    1736  break
    1737  endswitch
    1738  endif
    1739  endif
    1740 end
    1741 
    1781 function ps_scale_dataset_2(data, ax, lo, hi, un)
    1782  wave data
    1783  wave /t ax
    1784  wave lo
    1785  wave hi
    1786  wave /t un
    1787 
    1788  string snote = note(data)
    1789  string sdim
    1790  sdim = GetDimLabel(data, 0, -1)
    1791  if (strlen(sdim))
    1792  setscale /i x lo[%$sdim], hi[%$sdim], un[%$sdim], data
    1793  snote = ReplaceStringByKey("AxisLabelX", snote, ax[%$sdim], "=", "\r")
    1794  endif
    1795 
    1796  sdim = GetDimLabel(data, 1, -1)
    1797  if (strlen(sdim))
    1798  setscale /i y lo[%$sdim], hi[%$sdim], un[%$sdim], data
    1799  snote = ReplaceStringByKey("AxisLabelY", snote, ax[%$sdim], "=", "\r")
    1800  endif
    1801 
    1802  sdim = GetDimLabel(data, 2, -1)
    1803  if (strlen(sdim))
    1804  setscale /i z lo[%$sdim], hi[%$sdim], un[%$sdim], data
    1805  snote = ReplaceStringByKey("AxisLabelZ", snote, ax[%$sdim], "=", "\r")
    1806  endif
    1807 
    1808  string data_unit = un[%$kDataDimLabel]
    1809  string data_label = ax[%$kDataDimLabel]
    1810  string s
    1811  variable def = (cmpstr(data_unit, "arb.") == 0) && (cmpstr(data_label, "value") == 0)
    1812 
    1813  if (def)
    1814  s = StringByKey("AxisLabelD", snote, "=", "\r")
    1815  if (strlen(s) > 0)
    1816  data_label = s
    1817  def = 0
    1818  endif
    1819  s = StringByKey("AxisUnitD", snote, "=", "\r")
    1820  if (strlen(s) > 0)
    1821  data_unit = s
    1822  def = 0
    1823  endif
    1824  endif
    1825 
    1826  if (def)
    1827  strswitch(NameOfWave(data))
    1828  case "ScientaImage":
    1829  case "ImageAngleDistribution":
    1830  case "ScientaAngleDistribution":
    1831  case "ScientaSpectrum":
    1832  case "ImageEnergyDistribution":
    1833  case "ScientaEnergyDistribution":
    1834  data *= kDetectorSensitivity
    1835  data_unit = "counts"
    1836  data_label = "intensity"
    1837  def = 0
    1838  break
    1839  case "SampleCurrent":
    1840  case "RefCurrent":
    1841  case "AuxCurrent":
    1842  data_unit = "A"
    1843  data_label = "current"
    1844  def = 0
    1845  break
    1846  case "MachineCurrent":
    1847  data_unit = "mA"
    1848  data_label = "current"
    1849  def = 0
    1850  break
    1851  endswitch
    1852  endif
    1853 
    1854  setscale d 0, 0, data_unit, data
    1855  snote = ReplaceStringByKey("AxisLabelD", snote, data_label, "=", "\r")
    1856  snote = ReplaceStringByKey("AxisUnitD", snote, data_unit, "=", "\r")
    1857  snote = ReplaceStringByKey("Dataset", snote, NameOfWave(data), "=", "\r")
    1858  note /k data, snote
    1859 end
    1860 
    1911 function /s psh5_load_reduced(ANickName, APathName, AFileName, reduction_func, reduction_param, [progress, nthreads])
    1912  string ANickName
    1913  string APathName
    1914  string AFileName
    1915  funcref adh5_default_reduction reduction_func
    1916  string reduction_param
    1917  variable progress
    1918  variable nthreads
    1919 
    1920  if (ParamIsDefault(progress))
    1921  progress = 1
    1922  endif
    1923  if (ParamIsDefault(nthreads))
    1924  nthreads = -1
    1925  endif
    1926 
    1927  dfref saveDF = GetDataFolderDFR()
    1928 
    1929  // performance monitoring
    1930  variable timerRefNum
    1931  variable /g psh5_perf_secs
    1932  timerRefNum = startMSTimer
    1933 
    1934  variable fileID = psh5_open_file(ANickName, APathName, AFileName)
    1935  string wavenames = ""
    1936  if (fileID)
    1937  dfref fileDF = GetDataFolderDFR()
    1938  svar s_filepath
    1939  svar s_scanpaths
    1940  AFileName = s_filepath
    1941  print "loading " + s_filepath + "\r"
    1942 
    1943  variable ig = 0
    1944  variable ng = ItemsInList(s_scanpaths)
    1945  string scanpath
    1946  string folder
    1947  string positioners
    1948  string positioner
    1949  string positionerpath
    1950 
    1951  scanpath = StringFromList(ig, s_scanpaths)
    1952  folder = ReplaceString("/", scanpath, "")
    1953  folder = ReplaceString(" ", folder, "")
    1954  folder = PearlCleanupName(folder)
    1955  setdatafolder fileDF
    1956  newdatafolder /s /o $folder
    1957  dfref dataDF = GetDataFolderDFR()
    1958  positioners = psh5_load_scan_meta(fileID, scanpath)
    1959  newdatafolder /s /o attr
    1960  killwaves /a/z
    1961  psh5_load_scan_attrs(fileID, scanpath)
    1962  setdatafolder dataDF
    1963  wave /t /z ScanWritables
    1964  if (waveexists(ScanWritables) && (numpnts(ScanWritables) >= 1))
    1965  positioner = ScanWritables[0]
    1966  if (strlen(positioner) > 0)
    1967  positionerpath = scanpath + "/" + positioner
    1968  positionerpath = ReplaceString("//", positionerpath, "/")
    1969  HDF5LoadData /O /Q /Z fileID, positionerpath
    1970  endif
    1971  endif
    1972 
    1973  setdatafolder dataDF
    1974  string datasets = psh5_list_scan_datasets(fileID, scanpath, include_regions=1)
    1975  string dataset = select_dataset(datasets, "ScientaImage")
    1976  wavenames = psh5_load_dataset_reduced(fileID, scanpath, dataset, reduction_func, reduction_param, progress=progress, nthreads=nthreads)
    1977 
    1978  psh5_close_file(fileID)
    1979  endif
    1980 
    1981  if (timerRefNum >= 0)
    1982  psh5_perf_secs = stopMSTimer(timerRefNum) / 1e6
    1983  endif
    1984 
    1985  setdatafolder saveDF
    1986  return wavenames
    1987 end
    1988 
    1989 
    2040 function /s psh5_load_dataset_reduced(fileID, scanpath, datasetname, reduction_func, reduction_param, [progress, nthreads])
    2041  variable fileID
    2042  string scanpath
    2043  string datasetname
    2044  funcref adh5_default_reduction reduction_func
    2045  string reduction_param
    2046  variable progress
    2047  variable nthreads
    2048 
    2049  if (ParamIsDefault(progress))
    2050  progress = 1
    2051  endif
    2052  if (ParamIsDefault(nthreads))
    2053  nthreads = -1
    2054  endif
    2055 
    2056  dfref base_df = GetDataFolderDFR()
    2057  variable result = 0
    2058  string datasetpath
    2059  string datawavename
    2060  string wavenames = ""
    2061 
    2062  datasetpath = scanpath + "/" + datasetname
    2063  datasetpath = ReplaceString("//", datasetpath, "/")
    2064  datawavename = StringFromList(ItemsInList(datasetpath, "/") - 1, datasetpath, "/")
    2065 
    2066  string regionname
    2067  string regionpath
    2068  if (ItemsInList(datasetname, "/") >= 2)
    2069  regionname = StringFromList(0, datasetname, "/")
    2070  regionpath = ReplaceString("//", scanpath + "/" + regionname, "/")
    2071  datasetname = RemoveListItem(0, datasetname, "/")
    2072  NewDataFolder /o/s $regionname
    2073  else
    2074  regionname = ""
    2075  regionpath = scanpath
    2076  endif
    2077 
    2078  STRUCT HDF5DataInfo di // Defined in HDF5 Browser.ipf.
    2079  InitHDF5DataInfo(di)
    2080  variable err = HDF5DatasetInfo(fileID, datasetpath, 0, di)
    2081  if (err != 0)
    2082  print "error accessing detector/data"
    2083  result = -1
    2084  return wavenames
    2085  endif
    2086  if (di.ndims < 2)
    2087  print "error: rank of dataset < 2"
    2088  result = -2
    2089  return wavenames
    2090  elseif (di.ndims < 3)
    2091  progress = 0
    2092  endif
    2093 
    2094  variable idx, idy, idz, idt
    2095  variable transpose = WhichListItem(datawavename, kTransposedDatasets) >= 0
    2096  if (transpose)
    2097  idx = 1
    2098  idy = 0
    2099  else
    2100  idx = 0
    2101  idy = 1
    2102  endif
    2103  idz = 2
    2104  idt = 3
    2105 
    2106  variable nx, ny, nz, nt, nzt
    2107  nx = di.dims[idx]
    2108  ny = di.dims[idy]
    2109  nz = di.dims[idz]
    2110  nt = di.dims[idt]
    2111  // adjust singleton dimensions
    2112  nz = max(nz, 1)
    2113  nt = max(nt, 1)
    2114  nzt = nz * nt
    2115 
    2116  // load data image by image
    2117  HDF5MakeHyperslabWave("slab", max(di.ndims, 4))
    2118  wave slab
    2119  slab[][%Start] = 0
    2120  slab[][%Stride] = 1
    2121  slab[][%Count] = 1
    2122  slab[][%Block] = 1
    2123  slab[idx][%Block] = nx
    2124  slab[idy][%Block] = ny
    2125 
    2126  // set up multi threading
    2127  if (nthreads < 0)
    2128  nthreads = ThreadProcessorCount
    2129  endif
    2130  if (nthreads > 0)
    2131  variable threadGroupID = ThreadGroupCreate(nthreads)
    2132  variable ithread
    2133  for (ithread = 0; ithread < nthreads; ithread += 1)
    2134  ThreadStart threadGroupID, ithread, reduce_slab_worker(reduction_func)
    2135  endfor
    2136  else
    2137  make /n=(nzt) /df /free processing_folders
    2138  endif
    2139 
    2140  if (progress)
    2141  display_progress_panel("HDF5 Import", "Loading data (step 1 of 2)...", nzt)
    2142  endif
    2143 
    2144  // create a template wave with the correct scales and labels
    2145  make /n=(nx,ny) /d /o $datawavename
    2146  wave template = $datawavename
    2147  ps_set_dimlabels2(template, datawavename)
    2148  ps_scale_dataset(template)
    2149 
    2150  variable iz, it, izt
    2151  string dfname
    2152  variable iw, nw
    2153  string sw
    2154  make /n=0 /free /wave result_waves
    2155 
    2156  izt = 0
    2157  for (iz = 0; iz < nz; iz += 1)
    2158  for (it = 0; it < nt; it += 1)
    2159  // load hyperslab
    2160  slab[idz][%Start] = iz
    2161  slab[idt][%Start] = it
    2162  dfname = "processing_" + num2str(izt)
    2163  newdatafolder /s $dfname
    2164  HDF5LoadData /O /Q /Z /SLAB=slab /N=slabdata fileID, datasetpath
    2165 
    2166  // send to processing queue
    2167  duplicate template, image
    2168  variable /g r_index = iz
    2169  variable /g s_index = it
    2170  string /g func_param = reduction_param
    2171 
    2172  if (nthreads > 0)
    2173  WaveClear image
    2174  ThreadGroupPutDF threadGroupID, :
    2175  else
    2176  processing_folders[izt] = GetDataFolderDFR()
    2177  make /n=1/d profile1, profile2
    2178  wave slabdata
    2179  wave /wave reduced_waves = reduce_slab_image(slabdata, image, reduction_func, func_param)
    2180  variable /g func_result = numpnts(reduced_waves)
    2181  adh5_get_result_waves(reduced_waves, "redw_", 0)
    2182  WaveClear slabdata, image, reduced_waves
    2183  setdatafolder ::
    2184  endif
    2185 
    2186  izt += 1
    2187  // progress window
    2188  if (progress)
    2189  if (update_progress_panel(izt))
    2190  print "user abort"
    2191  result = -4
    2192  break
    2193  endif
    2194  endif
    2195  endfor
    2196  endfor
    2197 
    2198  killwaves /z slab, slabdata, template
    2199  if (progress)
    2200  update_progress_panel(0, message="Processing data (step 2 of 2)...")
    2201  endif
    2202 
    2203  dfref dfr
    2204  for (izt = 0; (izt < nzt) && (result == 0); izt += 1)
    2205  if (nthreads > 0)
    2206  do
    2207  if (progress)
    2208  if (update_progress_panel(izt))
    2209  print "user abort"
    2210  result = -4
    2211  break
    2212  endif
    2213  endif
    2214  dfr = ThreadGroupGetDFR(threadGroupID, 1000)
    2215  if (DatafolderRefStatus(dfr) != 0)
    2216  break
    2217  endif
    2218  while (1)
    2219  else
    2220  if (progress)
    2221  if (update_progress_panel(izt))
    2222  print "user abort"
    2223  result = -4
    2224  break
    2225  endif
    2226  endif
    2227  dfr = processing_folders[izt]
    2228  endif
    2229 
    2230  if (result != 0)
    2231  break
    2232  endif
    2233 
    2234  nvar rr = dfr:r_index
    2235  nvar ss = dfr:s_index
    2236  nvar func_result = dfr:func_result
    2237 
    2238  if (func_result < 1)
    2239  print "error during data reduction."
    2240  result = -3
    2241  break
    2242  endif
    2243 
    2244  if (numpnts(result_waves) == 0)
    2245  redimension /n=(func_result) result_waves
    2246  for (iw = 0; iw < func_result; iw += 1)
    2247  sw = "redw_" + num2str(iw)
    2248  wave profile = dfr:$sw
    2249  sw = "ReducedData" + num2str(iw+1)
    2250  make /n=(dimsize(profile, 0), nz, nt) /d /o $sw
    2251  wave data = $sw
    2252  setdimlabel 0, -1, $getdimlabel(profile, 0, -1), data
    2253  setdimlabel 1, -1, $kScanDimLabel, data
    2254  note data, note(profile)
    2255  ps_scale_dataset(data)
    2256  setscale /p x dimoffset(profile, 0), dimdelta(profile, 0), waveunits(profile, 0), data
    2257  setscale d 0, 0, waveunits(profile, -1), data
    2258  result_waves[iw] = data
    2259  endfor
    2260  endif
    2261  for (iw = 0; iw < func_result; iw += 1)
    2262  sw = "redw_" + num2str(iw)
    2263  wave profile = dfr:$sw
    2264  wave data = result_waves[iw]
    2265  data[][rr][ss] = profile[p]
    2266  endfor
    2267  endfor
    2268 
    2269  if (nthreads > 0)
    2270  variable tstatus = ThreadGroupRelease(threadGroupID)
    2271  if (tstatus == -2)
    2272  print "error: thread did not terminate properly."
    2273  result = -5
    2274  endif
    2275  else
    2276  for (izt = 0; izt < nzt; izt += 1)
    2277  KillDataFolder /Z processing_folders[izt]
    2278  endfor
    2279  endif
    2280 
    2281  if (result == 0)
    2282  nw = numpnts(result_waves)
    2283  wavenames = ""
    2284  for (iw = 0; iw < nw; iw += 1)
    2285  wave data = result_waves[iw]
    2286  if (nz == 1)
    2287  redimension /n=(-1, 0, 0) data
    2288  elseif (nt == 1)
    2289  redimension /n=(-1, nz, 0) data
    2290  endif
    2291  wavenames += nameofwave(data) + ";"
    2292  endfor
    2293  endif
    2294  if (progress)
    2295  kill_progress_panel()
    2296  endif
    2297 
    2298  setdatafolder base_df
    2299  return wavenames
    2300 end
    2301 
    2302 threadsafe static function reduce_slab_worker(reduction_func)
    2303  funcref adh5_default_reduction reduction_func
    2304  do
    2305  // wait for job from main thread
    2306  do
    2307  dfref dfr = ThreadGroupGetDFR(0, 1000)
    2308  if (DataFolderRefStatus(dfr) == 0)
    2309  if (GetRTError(2))
    2310  return 0 // no more jobs
    2311  endif
    2312  else
    2313  break
    2314  endif
    2315  while (1)
    2316 
    2317  // get input data
    2318  wave slabdata = dfr:slabdata
    2319  wave image = dfr:image
    2320  svar func_param = dfr:func_param
    2321  nvar rr = dfr:r_index
    2322  nvar ss = dfr:s_index
    2323 
    2324  // do the work
    2325  newdatafolder /s outDF
    2326  variable /g r_index = rr
    2327  variable /g s_index = ss
    2328  wave /wave reduced_waves = reduce_slab_image(slabdata, image, reduction_func, func_param)
    2329  variable /g func_result = numpnts(reduced_waves)
    2330 
    2331  // send output to queue and clean up
    2332  adh5_get_result_waves(reduced_waves, "redw_", 0)
    2333  WaveClear slabdata, image, reduced_waves
    2334  ThreadGroupPutDF 0, :
    2335  KillDataFolder dfr
    2336  while (1)
    2337 
    2338  return 0
    2339 end
    2340 
    2341 threadsafe static function /wave reduce_slab_image(slabdata, image, reduction_func, reduction_param)
    2342  wave slabdata
    2343  wave image
    2344  funcref adh5_default_reduction reduction_func
    2345  string reduction_param
    2346 
    2347  // the multiplication by detector sensitivity assumes that we are loading a ScientaImage.
    2348  image = slabdata[q][p][0][0] * kDetectorSensitivity
    2349 
    2350  return reduction_func(image, reduction_param)
    2351 end
    2352 
    2367 function /s psh5_load_info(APathName, AFileName)
    2368  string APathName
    2369  string AFileName
    2370 
    2371  dfref saveDF = GetDataFolderDFR()
    2372  dfref fileDF = NewFreeDataFolder()
    2373  setdatafolder fileDF
    2374 
    2375  variable fileID
    2376  string filepath
    2377  string scanpaths
    2378  variable nscans
    2379  variable iscan
    2380  string scanpath
    2381  string info = ""
    2382 
    2383  HDF5OpenFile /P=$APathName /R fileID as AFileName
    2384  if (v_flag == 0)
    2385  filepath = s_path + s_filename
    2386  scanpaths = psh5_list_scans(fileID)
    2387  nscans = ItemsInList(scanpaths)
    2388  for (iscan = 0; iscan < nscans; iscan += 1)
    2389  scanpath = StringFromList(iscan, scanpaths)
    2390  info = info + scanpath + "\r"
    2391  info = info + psh5_load_scan_info(fileID, scanpath)
    2392  endfor
    2393  HDF5CloseFile fileID
    2394  endif
    2395 
    2396  setdatafolder saveDF
    2397  return info
    2398 end
    2399 
    2414 function /s psh5_load_scan_info(fileID, scanpath)
    2415  variable fileID
    2416  string scanpath
    2417 
    2418  string info = ""
    2419  string positions = ""
    2420  string positioners = ""
    2421  string readables = ""
    2422  string detectors = ""
    2423  string regions = ""
    2424 
    2425  psh5_load_scan_meta(fileID, scanpath)
    2426 
    2427  wave /z ScanDimensions
    2428  wave /t /z ScanWritables
    2429  wave /t /z ScanReadables
    2430  wave /z ScanSteps
    2431 
    2432  if (WaveExists(ScanSteps) && (numpnts(ScanSteps) >= 1))
    2433  ScanSteps += 1
    2434  positions = "positions = (" + wave2list(ScanSteps, "%u", ",") + ")"
    2435  info = AddListItem(positions, info, "\r", inf)
    2436  endif
    2437  if (WaveExists(ScanWritables) && (numpnts(ScanWritables) >= 1))
    2438  positioners = "positioners = " + twave2list(ScanWritables, ",")
    2439  info = AddListItem(positioners, info, "\r", inf)
    2440  endif
    2441 
    2442  variable i, m, n
    2443  string s
    2444  if (WaveExists(ScanReadables) && (numpnts(ScanReadables) >= 1))
    2445  readables = twave2list(ScanReadables, ",")
    2446  n = ItemsInList(readables, ",")
    2447  for (i = 0; i < n; i += 1)
    2448  s = StringFromList(i, readables, ",")
    2449  m = ItemsInList(s, "/")
    2450  if (m > 1)
    2451  s = StringFromList(m - 1, s, "/")
    2452  endif
    2453  if (WhichListItem(s, detectors, ",") < 0)
    2454  detectors = AddListItem(s, detectors, ",", inf)
    2455  endif
    2456  endfor
    2457  detectors = "detectors = " + detectors
    2458  info = AddListItem(detectors, info, "\r", inf)
    2459  endif
    2460 
    2461  regions = psh5_list_scan_regions(fileID, scanpath)
    2462  if (strlen(regions) > 0)
    2463  regions = "regions = " + regions
    2464  info = AddListItem(regions, info, "\r", inf)
    2465  endif
    2466 
    2467  return info
    2468 end
    2469 
    2473 static function /s twave2list(wt, sep)
    2474  wave /t wt
    2475  string sep
    2476 
    2477  string list = ""
    2478  variable n = numpnts(wt)
    2479  variable i
    2480  for (i = 0; i < n; i += 1)
    2481  list = AddListItem(wt[i], list, sep, inf)
    2482  endfor
    2483 
    2484  return list
    2485 end
    2486 
    2490 static function /s wave2list(w, format, sep)
    2491  wave w
    2492  string format
    2493  string sep
    2494 
    2495  string list = ""
    2496  variable n = numpnts(w)
    2497  variable i
    2498  string s
    2499  for (i = 0; i < n; i += 1)
    2500  sprintf s, format, w[i]
    2501  list = AddListItem(s, list, sep, inf)
    2502  endfor
    2503 
    2504  return list
    2505 end
    const string kEnergyDimLabel
    Dimension label for the energy dispersive dimension of multi-dimensional datasets.
    +
    string psh5_load_scan_preview(variable fileID, string scanpath, variable set_scale=defaultValue, string pref_datasets=defaultValue)
    load a preview dataset from an open PShell HDF5 file.
    +
    string psh5_load_scan_attrs(variable fileID, string scanpath, variable attr_sets=defaultValue)
    load attributes of a PShell scan group.
    +
    const string kTransposedDatasets
    List of datasets that should be transposed upon loading.
    +
    string psh5_load_scan_complete(variable fileID, string scanpath, variable load_data=defaultValue, variable load_attr=defaultValue)
    load all data of a selected scan from a PShell data file.
    +
    const string kScanDimLabel
    Dimension label for the scan dimension of multi-dimensional datasets.
    +
    string PearlCleanupName(string name)
    +
    const string kAngleDimLabel
    Dimension label for the angle dispersive dimension of multi-dimensional datasets. ...
    +
    const string kDataDimLabel
    Dimension label for the data dimension.
    +
    string psh5_load_preview(string APathName, string AFileName, variable load_data=defaultValue, variable load_attr=defaultValue, string pref_scans=defaultValue, string pref_datasets=defaultValue)
    load a preview image from a PShell data file.
    +
    variable psh5_open_file(string ANickName, string APathName, string AFileName)
    open a HDF5 file created by the PShell data acquisition program and prepare the data folder...
    +
    variable ps_scale_datasets()
    set the dimension scales of loaded PShell Scienta datasets according to attributes.
    +
    string psh5_load_scan_meta(variable fileID, string scanpath)
    load metadata of a PShell scan group.
    +
    const string kScientaScalingDatasets
    List of datasets that must be loaded to determine the axis scaling of a Scienta image.
    +
    string psh5_list_scan_datasets(variable fileID, string scanpath, variable include_regions=defaultValue)
    list datasets of a PShell scan group.
    +
    string psh5_load_scan_data(variable fileID, string scanpath)
    load all datasets of a PShell scan group.
    +
    const variable kDetectorSensitivity
    multiply scienta detector intensity by this value to get actual counts.
    +
    string psh5_load_complete(string ANickName, string APathName, string AFileName, variable load_data=defaultValue, variable load_attr=defaultValue)
    load everything from a PShell data file.
    +
    string psh5_list_scans(variable fileID)
    list scan groups of a PShell data file.
    +
    variable psh5_close_file(variable fileID)
    close a HDF5 file opened by psh5_open_file.
    +
    const string kPreviewDatasets
    List of preferred datasets to load for preview.