PEARL Procedures  rev-distro-3.0.0-0-gfa24916-dirty
Igor procedures for the analysis of PEARL data
pearl-pshell-import.ipf
Go to the documentation of this file.
1 #pragma TextEncoding = "UTF-8"
2 #pragma rtGlobals=3 // Use modern global access method and strict wave access.
3 #pragma IgorVersion = 8.00
4 #pragma ModuleName = PearlPShellImport
5 #pragma version = 2.1
6 #if IgorVersion() < 9.00
7 #include <HDF5 Browser>
8 #endif
9 #include "pearl-compat"
10 #include "pearl-gui-tools"
11 #include "pearl-area-import"
12 
13 // copyright (c) 2013-22 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 
43 
48 
50 strconstant kEnergyDimLabel = "energy"
51 
53 strconstant kAngleDimLabel = "angle"
54 
56 strconstant kScanDimLabel = "scan"
57 
60 strconstant kDataDimLabel = "data"
61 
63 strconstant kPreviewDatasets = "ImageEnergyDistribution;ScientaSpectrum;ScientaImage;Counts;SampleCurrent;"
64 
66 strconstant kScientaScalingDatasets = "LensMode;ScientaChannelBegin;ScientaChannelEnd;ScientaSliceBegin;ScientaSliceEnd;Eph;"
67 
69 strconstant kEssentialDiagnostics = "ManipulatorX;ManipulatorY;ManipulatorZ;ManipulatorTheta;ManipulatorTilt;ManipulatorPhi;MonoEnergy;"
70 
72 strconstant kTransposedDatasets = "ScientaImage;"
73 
74 constant kDSCPositioners = 0x0001
75 constant kDSCDetectors = 0x0002
76 constant kDSCScientaScaling = 0x0004
77 constant kDSCPreview = 0x0008
78 constant kDSCEssentialDiags = 0x0010
79 constant kDSCAttrs = 0x0020
80 constant kDSCDiags = 0x0040
81 constant kDSCSnaps = 0x0080
82 constant kDSCMeta = 0x0100
83 constant kDSCMonitors = 0x0200
84 constant kDSCRegions = 0x0400
85 constant kDSCOther = 0x8000
86 constant kDSCAll = 0xffff
87 
88 
89 // ====== main import functions ======
90 
158 function /df psh5_load(path_name, file_name, scans, regions, datasets, [classes, max_rank, reduction_func, reduction_params, dest_df])
159  string path_name
160  string file_name
161  string scans
162  string regions
163  string datasets
164  variable classes
165  variable max_rank
166  string reduction_func
167  string reduction_params
168  dfref dest_df
169 
170  dfref save_df = GetDataFolderDFR()
171  variable timerRefNum = startMSTimer
172 
173  if (ParamIsDefault(classes) || (classes == 0))
175  endif
176  variable essential_classes = kDSCPositioners | kDSCScientaScaling | kDSCEssentialDiags
177 
178  if (ParamIsDefault(dest_df) || !DataFolderRefStatus(dest_df))
179  dest_df = psh5_open_file(path_name, file_name)
180  else
181  dest_df = psh5_open_file(path_name, file_name, dest_df=dest_df)
182  endif
183  if (ParamIsDefault(reduction_func))
184  reduction_func = ""
185  endif
186  if (ParamIsDefault(reduction_params))
187  reduction_params = ""
188  endif
189 
190  if (DataFolderRefStatus(dest_df))
191  setdatafolder dest_df
192  psh5_load_general_group(dest_df)
193 
194  // datasets contained in file
195  svar /sdfr=dest_df file_datasets = s_datasets
196 
197  // datasets contained in file up to allowed rank
198  string ranked_datasets = ""
199  if (ParamIsDefault(max_rank))
200  ranked_datasets = file_datasets
201  else
202  svar /sdfr=dest_df file_ranks = s_datasets_ranks
203  ranked_datasets = psh5_filter_datasets_rank(file_datasets, file_ranks, 0, max_rank)
204  endif
205 
206  string matching_datasets = ""
207  string matching_essentials = ""
208  string scan_datasets = ""
209  string region_datasets = ""
210  string free_datasets = ""
211  string selected_datasets = ""
212  string essential_datasets = ""
213 
214  variable i_item
215  variable n_items
216  string item
217 
218  // select datasets belonging to selected scans
219  n_items = ItemsInList(scans, ";")
220  for (i_item = 0; i_item < n_items; i_item += 1)
221  item = StringFromList(i_item, scans, ";")
222  if (cmpstr(item[0,3], "scan") == 0)
223  item = "/" + item
224  endif
225  item = ReplaceString("//", item + "/*", "/")
226  matching_datasets = psh5_match_datasets(ranked_datasets, item)
227  scan_datasets = scan_datasets + matching_datasets
228  endfor
229 
230  // select datasets belonging to selected regions
231  n_items = ItemsInList(regions, ";")
232  for (i_item = 0; i_item < n_items; i_item += 1)
233  item = StringFromList(i_item, regions, ";")
234  if (cmpstr(item[0,3], "scan") == 0)
235  item = "/" + item
236  endif
237  item = ReplaceString("//", item + "/*", "/")
238  matching_datasets = psh5_match_datasets(ranked_datasets, item)
239  region_datasets = region_datasets + matching_datasets
240  endfor
241 
242  // free select datasets
243  n_items = ItemsInList(datasets, ";")
244  for (i_item = 0; i_item < n_items; i_item += 1)
245  item = StringFromList(i_item, datasets, ";")
246  if (cmpstr(item[0,3], "scan") == 0)
247  item = "/" + item
248  endif
249  matching_datasets = psh5_match_datasets(ranked_datasets, item)
250  free_datasets = free_datasets + matching_datasets
251  endfor
252 
253  selected_datasets = scan_datasets + region_datasets + free_datasets
254 
255  string filtered_datasets = ""
256  string diag_datasets = ""
257  string selected_scans = psh5_extract_scan_paths(selected_datasets)
258  variable i_scan
259  variable n_scans = ItemsInList(selected_scans)
260  string scan
261  string selected_regions = psh5_extract_region_paths(selected_datasets)
262  variable i_region
263  variable n_regions = ItemsInList(selected_regions)
264  string region
265  string positioners
266  string detectors
267 
268  // datasets directly under one of the selected regions
269  region_datasets = ""
270  for (i_region = 0; i_region < n_regions; i_region += 1)
271  region = StringFromList(i_region, selected_regions, ";")
272  region_datasets = region_datasets + GrepList(file_datasets, "(?i)^" + region + "[[:alpha:]]+$")
273  endfor
274 
275  // filter selected datasets by class and add essential dependencies
276  // each scan may have specific positioners and detectors
277  for (i_scan = 0; i_scan < n_scans; i_scan += 1)
278  scan = StringFromList(i_scan, selected_scans, ";")
279 
280  // potentially interesting diagnostics of current scan and selected regions
281  diag_datasets = psh5_match_datasets(file_datasets, scan + "*")
282  diag_datasets = psh5_match_dataset_classes(diag_datasets, kDSCAttrs | kDSCDiags | kDSCSnaps)
283  diag_datasets = diag_datasets + GrepList(file_datasets, "(?i)^" + scan + "[[:alpha:]]+$")
284  diag_datasets = diag_datasets + psh5_match_datasets(region_datasets, scan + "*")
285 
286  // explicit positioners and detectors set by pshell
287  setdatafolder dest_df
288  dfref scan_df = psh5_create_folders(scan)
289  setdatafolder scan_df
290  psh5_load_scan_meta(dest_df, scan)
291  wave /t /z ScanWritables
292  wave /t /z ScanReadables
293  if (WaveExists(ScanWritables))
294  positioners = twave2list(ScanWritables, ";")
295  else
296  positioners = ""
297  endif
298  if (WaveExists(ScanReadables))
299  detectors = twave2list(ScanReadables, ";")
300  else
301  detectors = ""
302  endif
303 
304  // filtering by classes
305  matching_datasets = psh5_match_dataset_classes(selected_datasets, classes, positioners=positioners, detectors=detectors)
306 
307  // add essential diags
308  if (strlen(matching_datasets) > 1)
309  essential_datasets = psh5_match_dataset_classes(diag_datasets, essential_classes, positioners=positioners, detectors=detectors)
310  endif
311 
312  // scaling datasets before detectors because data reduction needs the scales
313  filtered_datasets = essential_datasets + filtered_datasets + matching_datasets
314  endfor
315 
316  // load the datasets
317  setdatafolder dest_df
318  string /g s_loaded_datasets = ""
319  s_loaded_datasets = psh5_load_datasets(dest_df, filtered_datasets, reduction_func=reduction_func, reduction_params=reduction_params)
320 
321  // apply scaling by scan
322  for (i_scan = 0; i_scan < n_scans; i_scan += 1)
323  scan = StringFromList(i_scan, selected_scans, ";")
325  endfor
326 
327  psh5_close_file(dest_df)
328 
329  // performance reporting
330  if (timerRefNum >= 0)
331  setdatafolder dest_df
332  variable /g psh5_perf_secs
333  psh5_perf_secs = stopMSTimer(timerRefNum) / 1e6
334  endif
335  endif
336 
337  setdatafolder save_df
338  return dest_df
339 end
340 
345 function /df psh5_preview(path_name, file_name, [dest_df, preview_datasets])
346  string path_name
347  string file_name
348  dfref dest_df
349  string preview_datasets
350 
351  dfref save_df = GetDataFolderDFR()
352 
353  if (ParamIsDefault(dest_df))
354  dest_df = psh5_open_file(path_name, file_name)
355  else
356  dest_df = psh5_open_file(path_name, file_name, dest_df=dest_df)
357  endif
358  if (ParamIsDefault(preview_datasets))
359  preview_datasets = kPreviewDatasets
360  endif
361  variable essential_classes = kDSCPositioners | kDSCScientaScaling
362 
363  if (DataFolderRefStatus(dest_df))
364  setdatafolder dest_df
365  psh5_load_general_group(dest_df)
366 
367  // select dataset based on preference
368  svar /sdfr=dest_df file_datasets = s_datasets
369  svar /sdfr=dest_df file_datasets_ranks = s_datasets_ranks
370  string selected_datasets = ""
371  string essential_datasets = ""
372  string scan_datasets = ""
373  string filtered_datasets = ""
374 
375  variable nds = ItemsInList(preview_datasets, ";")
376  variable ids
377  string ds
378  for (ids = 0; ids < nds; ids += 1)
379  ds = StringFromList(ids, preview_datasets, ";")
380  selected_datasets = psh5_filter_datasets_rank(file_datasets, file_datasets_ranks, 1, 2)
381  selected_datasets = psh5_match_datasets(selected_datasets, "/scan*" + ds)
382  if (strlen(selected_datasets) > 1)
383  selected_datasets = StringFromList(0, selected_datasets, ";")
384  break
385  endif
386  endfor
387 
388  // add essential dependencies
389  if (strlen(selected_datasets) > 1)
390  string selected_scans = psh5_extract_scan_paths(selected_datasets)
391  string scan
392  string positioners
393 
394  scan = StringFromList(0, selected_scans, ";")
395  scan_datasets = psh5_match_datasets(file_datasets, scan + "*")
396 
397  psh5_load_scan_meta(dest_df, scan)
398  wave /t /z ScanWritables
399  if (WaveExists(ScanWritables))
400  positioners = twave2list(ScanWritables, ";")
401  else
402  positioners = ""
403  endif
404 
405  essential_datasets = psh5_match_dataset_classes(scan_datasets, essential_classes, positioners=positioners)
406  filtered_datasets = essential_datasets + selected_datasets
407 
408  // load the datasets
409  psh5_load_datasets(dest_df, filtered_datasets, create_folders=0)
410  ps_scale_datasets(dest_df)
411  string /g s_preview_dataset = StringFromList(0, selected_datasets, ";")
412  string /g s_preview_wave = StringFromList(ItemsInList(s_preview_dataset, "/") - 1, s_preview_dataset, "/")
413  endif
414 
415  psh5_close_file(dest_df)
416  endif
417 
418  setdatafolder save_df
419  return dest_df
420 end
421 
450 function /df psh5_open_file(path_name, file_name, [dest_df])
451  string path_name
452  string file_name
453  dfref dest_df
454 
455  dfref save_df = GetDataFolderDFR()
456 
457  variable fid
458  HDF5OpenFile /P=$path_name /R fid as file_name
459  if (v_flag == 0)
460  if (!ParamIsDefault(dest_df))
461  setdatafolder dest_df
462  else
463  string dest_name = ad_suggest_foldername(s_filename, sourcename="psh")
464  setdatafolder root:
465  newdatafolder /s /o $("root:" + dest_name)
466  endif
467  dfref file_df = GetDataFolderDFR()
468 
469  variable /g file_id = fid
470  string /g s_filepath
471  string /g s_scanpaths
472  string /g s_datasets
473  string datatypes
474  string ranks
475  string dimensions
476  s_filepath = s_path + s_filename
477  s_scanpaths = psh5_list_scans(file_id)
478  s_datasets = psh5_list_all_datasets(file_id)
479  [datatypes, ranks, dimensions] = psh5_list_dataset_info(file_id, s_datasets)
480  string /g s_datasets_datatypes = datatypes
481  string /g s_datasets_ranks = ranks
482  string /g s_datasets_dimensions = dimensions
483  else
484  dfref file_df = $""
485  endif
486 
487  setdatafolder save_df
488  return file_df
489 end
490 
509 function psh5_close_file(file_df)
510  dfref file_df
511 
512  if (DataFolderRefStatus(file_df))
513  nvar /sdfr=file_df /z file_id
514  if (nvar_Exists(file_id))
515  HDF5CloseFile /z file_id
516  file_id = 0
517  KillVariables /z file_id
518  else
519  dfref parent_df = $(GetDataFolder(1, file_df) + ":")
520  if (DataFolderRefStatus(parent_df))
521  psh5_close_file(parent_df)
522  endif
523  endif
524  endif
525 end
526 
527 // === datasets and paths ===
528 
532 static function /s twave2list(wt, sep)
533  wave /t wt
534  string sep
535 
536  string list = ""
537  variable n = numpnts(wt)
538  variable i
539  for (i = 0; i < n; i += 1)
540  list = AddListItem(wt[i], list, sep, inf)
541  endfor
542 
543  return list
544 end
545 
549 static function /s wave2list(w, format, sep)
550  wave w
551  string format
552  string sep
553 
554  string list = ""
555  variable n = numpnts(w)
556  variable i
557  string s
558  for (i = 0; i < n; i += 1)
559  sprintf s, format, w[i]
560  list = AddListItem(s, list, sep, inf)
561  endfor
562 
563  return list
564 end
565 
574 function /s psh5_list_scans(file_id)
575  variable file_id
576 
577  HDF5ListGroup /F /TYPE=1 file_id, "/"
578 
579  variable ig
580  variable ng = ItemsInList(S_HDF5ListGroup, ";")
581  string sg
582  string scans = ""
583 
584  for (ig = 0; ig < ng; ig += 1)
585  sg = StringFromList(ig, S_HDF5ListGroup, ";")
586  if (cmpstr(sg[1,4], "scan") == 0)
587  scans = AddListItem(sg, scans, ";", inf)
588  endif
589  endfor
590 
591  return scans
592 end
593 
605 function /s psh5_list_all_datasets(file_id)
606  variable file_id
607 
608  HDF5ListGroup /F /R /TYPE=2 /Z file_id, "/"
609  if (!v_flag)
610  return S_HDF5ListGroup
611  else
612  return ""
613  endif
614 end
615 
631 function [string datatypes, string ranks, string dimensions] psh5_list_dataset_info(variable file_id, string datasets)
632  variable nds = ItemsInList(datasets, ";")
633  variable ids
634  string sds
635  STRUCT HDF5DataInfo di
636  InitHDF5DataInfo(di)
637  variable err
638  variable idim
639  string sdims
640  datatypes = ""
641  ranks = ""
642  dimensions = ""
643 
644  for (ids = 0; ids < nds; ids += 1)
645  sds = StringFromList(ids, datasets, ";")
646  err = HDF5DatasetInfo(file_id, sds, 0, di)
647  if (err == 0)
648  switch (di.datatype_class)
649  case H5T_INTEGER:
650  datatypes = AddListItem("i", datatypes, ";", ids)
651  break
652  case H5T_FLOAT:
653  datatypes = AddListItem("f", datatypes, ";", ids)
654  break
655  case H5T_STRING:
656  datatypes = AddListItem("s", datatypes, ";", ids)
657  break
658  default:
659  datatypes = AddListItem("?", datatypes, ";", ids)
660  break
661  endswitch
662 
663  ranks = AddListItem(num2str(di.ndims), ranks, ";", ids)
664 
665  sdims = ""
666  for (idim = 0; idim < di.ndims; idim += 1)
667  sdims = AddListItem(num2str(di.dims[idim]), sdims, ",", idim)
668  endfor
669  if (strlen(sdims) > 1)
670  sdims = sdims[0, strlen(sdims)-2]
671  endif
672  dimensions = AddListItem(sdims, dimensions, ";", ids)
673  endif
674  endfor
675 end
676 
692 function /s psh5_match_datasets(datasets, match)
693  string datasets
694  string match
695 
696  string result = ""
697 
698  string spaceless_datasets = ReplaceString(" ", datasets, "")
699  string spaceless_match = ReplaceString(" ", match, "")
700 
701  string sep = ";"
702  variable seplen = strlen(sep)
703  variable nds = ItemsInList(spaceless_datasets, sep)
704  variable ids
705  string ds
706  variable offset = 0
707 
708  for (ids = 0; ids < nds; ids += 1)
709  ds = StringFromList(0, spaceless_datasets, sep, offset)
710  offset += strlen(ds) + seplen
711  if (StringMatch(ds, spaceless_match))
712  ds = StringFromList(ids, datasets, sep, 0)
713  result = AddListItem(ds, result, sep, inf)
714  endif
715  endfor
716 
717  return result
718 end
719 
728 function /s psh5_filter_datasets_rank(datasets, ranks, min_rank, max_rank)
729  string datasets
730  string ranks
731  variable min_rank
732  variable max_rank
733 
734  string result = ""
735  string sep = ";"
736  variable seplen = strlen(sep)
737  variable nds = ItemsInList(datasets, sep)
738  variable ids
739  string ds
740  variable offset = 0
741  variable rank
742 
743  for (ids = 0; ids < nds; ids += 1)
744  ds = StringFromList(0, datasets, sep, offset)
745  offset += strlen(ds) + seplen
746  rank = str2num(StringFromList(ids, ranks, sep))
747  if ((rank >= min_rank) && (rank <= max_rank))
748  result = AddListItem(ds, result, sep, inf)
749  endif
750  endfor
751 
752  return result
753 end
754 
764 static function /s unique_strings(list)
765  string list
766 
767  string result = ""
768 
769  string sep = ";"
770  variable seplen = strlen(sep)
771  variable nn = ItemsInList(list, sep)
772  variable ii
773  string item
774  variable offset = 0
775 
776  make /n=(nn) /t /free wt_in
777  for (ii = 0; ii < nn; ii += 1)
778  item = StringFromList(0, list, sep, offset)
779  offset += strlen(item) + seplen
780  wt_in[ii] = item
781  endfor
782 
783  FindDuplicates /Z /FREE /RT=wt_out wt_in
784 
785  return twave2list(wt_out, ";")
786 end
787 
803 function /s psh5_extract_scan_paths(datasets)
804  string datasets
805 
806  string result = ""
807  string sep = ";"
808  variable seplen = strlen(sep)
809  variable nds = ItemsInList(datasets, sep)
810  variable ids
811  string ds
812  string scan
813  string item
814  variable offset = 0
815 
816  for (ids = 0; ids < nds; ids += 1)
817  ds = StringFromList(0, datasets, sep, offset)
818  offset += strlen(ds) + seplen
819  if (cmpstr(ds[0], "/") != 0)
820  ds = "/" + ds
821  endif
822 
823  scan = StringFromList(1, ds, "/")
824  if (StringMatch(scan, "scan*"))
825  item = "/" + scan + "/"
826  else
827  item = ""
828  endif
829 
830  if ((strlen(item) > 0) && (WhichListItem(item, result, ";", 0, 0) < 0))
831  result = AddListItem(item, result, ";", inf)
832  endif
833  endfor
834 
835  return result
836 end
837 
853 function /s psh5_extract_region_paths(datasets)
854  string datasets
855 
856  string result = ""
857  string sep = ";"
858  variable seplen = strlen(sep)
859  variable nds = ItemsInList(datasets, sep)
860  variable ids
861  string ds
862  string scan
863  string region
864  string item
865  variable offset = 0
866 
867  for (ids = 0; ids < nds; ids += 1)
868  ds = StringFromList(0, datasets, sep, offset)
869  offset += strlen(ds) + seplen
870  if (cmpstr(ds[0], "/") != 0)
871  ds = "/" + ds
872  endif
873 
874  scan = StringFromList(1, ds, "/")
875  region = StringFromList(2, ds, "/")
876  if (StringMatch(scan, "scan*") && StringMatch(region, "region*"))
877  item = "/" + scan + "/" + region + "/"
878  else
879  item = ""
880  endif
881 
882  if ((strlen(item) > 0) && (WhichListItem(item, result, ";", 0, 0) < 0))
883  result = AddListItem(item, result, ";", inf)
884  endif
885  endfor
886 
887  return result
888 end
889 
899 function /s psh5_match_dataset_classes(datasets, classes, [positioners, detectors])
900  string datasets
901  variable classes
902  string positioners
903  string detectors
904 
905  if (ParamIsDefault(positioners))
906  positioners = ""
907  endif
908  if (ParamIsDefault(detectors) || (strlen(detectors) == 0))
909  detectors = kPreviewDatasets
910  endif
911 
912  string result = ""
913  string sep = ";"
914  variable seplen = strlen(sep)
915  variable nds = ItemsInList(datasets, sep)
916  variable ids
917  variable offset = 0
918  string ds
919  variable nparts
920  string ds_parent
921  string ds_name
922  string ds_scan_rel
923  variable ds_class
924 
925  for (ids = 0; ids < nds; ids += 1)
926  ds = StringFromList(0, datasets, sep, offset)
927  offset += strlen(ds) + seplen
928  nparts = ItemsInList(ds, "/")
929  ds_parent = StringFromList(nparts - 2, ds, "/")
930  ds_name = StringFromList(nparts - 1, ds, "/")
931  if (cmpstr(ds[0,4], "/scan") == 0)
932  ds_scan_rel = RemoveListItem(0, ds[1, strlen(ds) - 1], "/")
933  else
934  ds_scan_rel = ds
935  endif
936  ds_class = 0
937 
938  if (strlen(ds_parent) > 0)
939  ds_class = ds_class | (cmpstr(ds_parent, "attr") == 0 ? kDSCAttrs : 0)
940  ds_class = ds_class | (cmpstr(ds_parent, "attrs") == 0 ? kDSCAttrs : 0)
941  ds_class = ds_class | (cmpstr(ds_parent, "diags") == 0 ? kDSCDiags : 0)
942  ds_class = ds_class | (cmpstr(ds_parent, "snaps") == 0 ? kDSCSnaps : 0)
943  ds_class = ds_class | (cmpstr(ds_parent, "meta") == 0 ? kDSCMeta : 0)
944  ds_class = ds_class | (cmpstr(ds_parent, "monitors") == 0 ? kDSCMonitors : 0)
945  ds_class = ds_class | (cmpstr(ds_parent[0,5], "region") == 0 ? kDSCRegions : 0)
946  endif
947 
948  if (strlen(ds_name) > 0)
949  ds_class = ds_class | (WhichListItem(ds_scan_rel, positioners, sep, 0, 0) >= 0 ? kDSCPositioners : 0)
950  ds_class = ds_class | (WhichListItem(ds_scan_rel, detectors, sep, 0, 0) >= 0 ? kDSCDetectors : 0)
951  ds_class = ds_class | (WhichListItem(ds_name, kPreviewDatasets, sep, 0, 0) >= 0 ? kDSCPreview : 0)
952  ds_class = ds_class | (WhichListItem(ds_name, kScientaScalingDatasets, sep, 0, 0) >= 0 ? kDSCScientaScaling : 0)
953  ds_class = ds_class | (WhichListItem(ds_name, kEssentialDiagnostics, sep, 0, 0) >= 0 ? kDSCEssentialDiags : 0)
954  endif
955 
956  if (ds_class == 0)
957  ds_class = kDSCOther
958  endif
959 
960  if (ds_class & classes)
961  result = AddListItem(ds, result, sep, inf)
962  endif
963  endfor
964 
965  return result
966 end
967 
990 function /df psh5_create_folders(datasetpath)
991  string datasetpath
992 
993  if (cmpstr(datasetpath[0], "/") == 0)
994  datasetpath = datasetpath[1, strlen(datasetpath)-1]
995  endif
996  if (cmpstr(datasetpath[strlen(datasetpath)-1], "/") == 0)
997  datasetpath += "dummy"
998  endif
999 
1000  variable nfolders = ItemsInList(datasetpath, "/") - 1
1001  variable ifolder
1002  string folder
1003  string inc_path = "/"
1004 
1005  for (ifolder = 0; ifolder < nfolders; ifolder += 1)
1006  folder = StringFromList(ifolder, datasetpath, "/")
1007  folder = ps_fix_folder_name(folder)
1008  NewDataFolder /o/s $folder
1009  inc_path += folder
1010  inc_path += "/"
1011  string /g s_hdf5_group = inc_path
1012  endfor
1013 
1014  return GetDataFolderDFR()
1015 end
1016 
1034 function /df psh5_dataset_to_folder(parent_df, datasetpath)
1035  dfref parent_df
1036  string datasetpath
1037 
1038  if (cmpstr(datasetpath[0], "/") == 0)
1039  datasetpath = datasetpath[1, strlen(datasetpath)-1]
1040  endif
1041  if (cmpstr(datasetpath[strlen(datasetpath)-1], "/") == 0)
1042  datasetpath += "dummy"
1043  endif
1044 
1045  variable nfolders = ItemsInList(datasetpath, "/") - 1
1046  variable ifolder
1047  string folder
1048  string inc_path = ""
1049 
1050  for (ifolder = 0; ifolder < nfolders; ifolder += 1)
1051  folder = StringFromList(ifolder, datasetpath, "/")
1052  folder = ps_fix_folder_name(folder)
1053  if (ifolder)
1054  inc_path += ":"
1055  endif
1056  inc_path += folder
1057  endfor
1058 
1059  dfref out_df = parent_df:$inc_path
1060  return out_df
1061 end
1062 
1065 function /s ps_fix_folder_name(group_name)
1066  string group_name
1067  string folder_name
1068 
1069  folder_name = ReplaceString(" ", group_name, "")
1070  if (cmpstr(folder_name, "attrs") == 0)
1071  folder_name = "attr"
1072  endif
1073  folder_name = PearlCleanupName(folder_name)
1074 
1075  return folder_name
1076 end
1077 
1078 // ====== import functions ======
1079 
1098 function /s psh5_load_datasets(file_df, datasets, [create_folders, reduction_func, reduction_params])
1099  dfref file_df
1100  string datasets
1101  variable create_folders
1102  string reduction_func
1103  string reduction_params
1104 
1105  if (!DataFolderRefStatus(file_df))
1106  dfref file_df = GetDataFolderDFR()
1107  endif
1108  if (ParamIsDefault(create_folders))
1109  create_folders = 1
1110  endif
1111  if (ParamIsDefault(reduction_func))
1112  reduction_func = ""
1113  endif
1114  if (ParamIsDefault(reduction_params))
1115  reduction_params = ""
1116  endif
1117 
1118  dfref save_df = GetdataFolderDFR()
1119 
1120  datasets = unique_strings(datasets)
1121  variable nds = ItemsInList(datasets, ";")
1122  variable ids
1123  string ds
1124  string loaded_datasets = ""
1125  string loaded_waves = ""
1126 
1127  for (ids = 0; ids < nds; ids += 1)
1128  SetDataFolder file_df
1129  ds = StringFromList(ids, datasets, ";")
1130  loaded_waves = psh5_load_dataset(file_df, ds, create_folders=create_folders, reduction_func=reduction_func, reduction_params=reduction_params)
1131  if (strlen(loaded_waves) > 1)
1132  loaded_datasets = loaded_datasets + ds + ";"
1133  endif
1134  endfor
1135 
1136  setdatafolder save_df
1137  return loaded_datasets
1138 end
1139 
1176 function /s psh5_load_dataset(file_df, datasetpath, [create_folders, reduction_func, reduction_params])
1177  dfref file_df
1178  string datasetpath
1179  variable create_folders
1180  string reduction_func
1181  string reduction_params
1182 
1183  dfref base_df = GetDataFolderDFR()
1184  if (!DataFolderRefStatus(file_df))
1185  dfref file_df = GetDataFolderDFR()
1186  endif
1187  nvar /sdfr=file_df file_id
1188 
1189  if (ParamIsDefault(create_folders))
1190  create_folders = 1
1191  endif
1192  if (create_folders)
1193  psh5_create_folders(datasetpath)
1194  endif
1195  if (ParamIsDefault(reduction_func))
1196  reduction_func = ""
1197  endif
1198  if (ParamIsDefault(reduction_params))
1199  reduction_params = ""
1200  endif
1201 
1202  STRUCT HDF5DataInfo di // Defined in HDF5 Browser.ipf.
1203  InitHDF5DataInfo(di)
1204  variable err = HDF5DatasetInfo(file_id, datasetpath, 0, di)
1205  if (err != 0)
1206  // error accessing data
1207  return ""
1208  endif
1209 
1210  variable numeric = 0
1211  variable compound = 0
1212 
1213  switch (di.datatype_class)
1214  case H5T_INTEGER:
1215  case H5T_FLOAT:
1216  numeric = 1
1217  break
1218  case H5T_STRING:
1219  numeric = 0
1220  break
1221  case H5T_COMPOUND:
1222  compound = 1
1223  break
1224  case H5T_TIME:
1225  case H5T_BITFIELD:
1226  case H5T_OPAQUE:
1227  case H5T_REFERENCE:
1228  case H5T_ENUM:
1229  case H5T_VLEN:
1230  case H5T_ARRAY:
1231  default:
1232  // unsupported data type
1233  return ""
1234  endswitch
1235 
1236  string wave_names = ""
1237  if (di.ndims <= 2)
1238  string datasetname = StringFromList(ItemsInList(datasetpath, "/") - 1, datasetpath, "/")
1239  variable transpose = WhichListItem(datasetname, kTransposedDatasets) >= 0
1240  HDF5LoadData /O /Q /Z /TRAN=(transpose) file_id, datasetpath
1241  wave_names = S_waveNames
1242  elseif (numeric)
1243  if (exists(reduction_func) == 6)
1244  wave_names = psh5_load_dataset_reduced(file_df, datasetpath, $reduction_func, reduction_params, create_folders=0)
1245  else
1246  wave_names = psh5_load_dataset_slabs(file_df, datasetpath, create_folders=0)
1247  endif
1248  endif
1249 
1250  variable nw = ItemsInList(wave_names, ";")
1251  variable iw
1252  string sw
1253  string loaded_waves = ""
1254  for (iw = 0; iw < nw; iw += 1)
1255  sw = StringFromList(iw, wave_names)
1256  wave /z w = $sw
1257  if (WaveExists(w))
1258  loaded_waves = loaded_waves + sw + ";"
1259  ps_set_dimlabels(w)
1260  psh5_load_dataset_meta(file_df, datasetpath, w)
1261  endif
1262  endfor
1263 
1264  setdatafolder base_df
1265  return loaded_waves
1266 end
1267 
1289 function /s psh5_load_dataset_slabs(file_df, datasetpath, [create_folders, progress])
1290  dfref file_df
1291  string datasetpath
1292  variable create_folders
1293  variable progress
1294 
1295  if (ParamIsDefault(create_folders))
1296  create_folders = 1
1297  endif
1298  if (ParamIsDefault(progress))
1299  progress = 1
1300  endif
1301 
1302  if (!DataFolderRefStatus(file_df))
1303  dfref file_df = GetDataFolderDFR()
1304  endif
1305  nvar /sdfr=file_df file_id
1306 
1307  variable result = 0
1308  string datawavename = StringFromList(ItemsInList(datasetpath, "/") - 1, datasetpath, "/")
1309 
1310  if (create_folders)
1311  psh5_create_folders(datasetpath)
1312  endif
1313 
1314  STRUCT HDF5DataInfo di // Defined in HDF5 Browser.ipf.
1315  InitHDF5DataInfo(di)
1316  variable err = HDF5DatasetInfo(file_id, datasetpath, 0, di)
1317  if (err != 0)
1318  print "error accessing dataset", datasetpath
1319  return ""
1320  endif
1321  if (di.ndims < 2)
1322  print "error: rank of dataset < 2", datasetpath
1323  return ""
1324  elseif (di.ndims < 3)
1325  progress = 0
1326  endif
1327  if ((di.datatype_class != H5T_INTEGER) && (di.datatype_class != H5T_FLOAT))
1328  print "error: unsupported datatype", datasetpath
1329  return ""
1330  endif
1331 
1332  variable idx, idy, idz, idt, izt
1333  variable transpose = WhichListItem(datawavename, kTransposedDatasets) >= 0
1334  if (transpose)
1335  idx = 1
1336  idy = 0
1337  else
1338  idx = 0
1339  idy = 1
1340  endif
1341  idz = 2
1342  idt = 3
1343 
1344  variable nx, ny, nz, nt, nzt
1345  nx = di.dims[idx]
1346  ny = di.dims[idy]
1347  nz = di.dims[idz]
1348  nt = di.dims[idt]
1349  make /n=(nx,ny,nz,nt) /o $datawavename
1350  wave data = $datawavename
1351 
1352  nz = max(nz, 1)
1353  nt = max(nt, 1)
1354  nzt = nz * nt
1355  izt = 0
1356  if (progress)
1357  display_progress_panel("HDF5 Import", "Loading " + datasetpath + "...", nzt)
1358  endif
1359 
1360  // load data image by image
1361  HDF5MakeHyperslabWave("slab", max(di.ndims, 4))
1362  wave slab
1363  slab[][%Start] = 0
1364  slab[][%Stride] = 1
1365  slab[][%Count] = 1
1366  slab[][%Block] = 1
1367  slab[idx][%Block] = nx
1368  slab[idy][%Block] = ny
1369 
1370  variable iz, it
1371  for (iz = 0; iz < nz; iz += 1)
1372  for (it = 0; it < nt; it += 1)
1373  slab[idz][%Start] = iz
1374  slab[idt][%Start] = it
1375  HDF5LoadData /O /Q /Z /SLAB=slab /N=slabdata file_id, datasetpath
1376  wave slabdata // 2D, 3D, or 4D with singletons
1377  if (transpose)
1378  data[][][iz][it] = slabdata[q][p][0][0]
1379  else
1380  data[][][iz][it] = slabdata[p][q][0][0]
1381  endif
1382 
1383  // progress window
1384  izt += 1
1385  if (progress)
1386  if (update_progress_panel(izt))
1387  result = -4 // user abort
1388  break
1389  endif
1390  endif
1391  endfor
1392  if (result < 0)
1393  break
1394  endif
1395  endfor
1396 
1397  if (progress)
1399  endif
1400 
1401  killwaves /z slab, slabdata
1402  if (!result)
1403  ps_set_dimlabels(data)
1404  return NameOfWave(data) + ";"
1405  else
1406  killwaves /z data
1407  return ""
1408  endif
1409 end
1410 
1411 // ====== data reduction ======
1412 
1472 function /s psh5_load_dataset_reduced(file_df, datasetpath, reduction_func, reduction_params, [create_folders, progress, nthreads])
1473  dfref file_df
1474  string datasetpath
1475  funcref adh5_default_reduction reduction_func
1476  string reduction_params
1477  variable create_folders
1478  variable progress
1479  variable nthreads
1480 
1481  if (ParamIsDefault(create_folders))
1482  create_folders = 1
1483  endif
1484  if (ParamIsDefault(progress))
1485  progress = 1
1486  endif
1487  if (ParamIsDefault(nthreads))
1488  nthreads = -1
1489  endif
1490 
1491  dfref base_df = GetDataFolderDFR()
1492  if (!DataFolderRefStatus(file_df))
1493  dfref file_df = GetDataFolderDFR()
1494  endif
1495  nvar /sdfr=file_df file_id
1496 
1497  variable result = 0
1498  string datawavename = StringFromList(ItemsInList(datasetpath, "/") - 1, datasetpath, "/")
1499  string wavenames = ""
1500 
1501  if (create_folders)
1502  psh5_create_folders(datasetpath)
1503  endif
1504 
1505  STRUCT HDF5DataInfo di // Defined in HDF5 Browser.ipf.
1506  InitHDF5DataInfo(di)
1507  variable err = HDF5DatasetInfo(file_id, datasetpath, 0, di)
1508  if (err != 0)
1509  print "error accessing detector/data"
1510  result = -1
1511  return wavenames
1512  endif
1513  if (di.ndims < 2)
1514  print "error: rank of dataset < 2"
1515  result = -2
1516  return wavenames
1517  elseif (di.ndims < 3)
1518  progress = 0
1519  endif
1520 
1521  variable idx, idy, idz, idt
1522  variable transpose = WhichListItem(datawavename, kTransposedDatasets) >= 0
1523  if (transpose)
1524  idx = 1
1525  idy = 0
1526  else
1527  idx = 0
1528  idy = 1
1529  endif
1530  idz = 2
1531  idt = 3
1532 
1533  variable nx, ny, nz, nt, nzt
1534  nx = di.dims[idx]
1535  ny = di.dims[idy]
1536  nz = di.dims[idz]
1537  nt = di.dims[idt]
1538  // adjust singleton dimensions
1539  nz = max(nz, 1)
1540  nt = max(nt, 1)
1541  nzt = nz * nt
1542 
1543  // load data image by image
1544  HDF5MakeHyperslabWave("slab", max(di.ndims, 4))
1545  wave slab
1546  slab[][%Start] = 0
1547  slab[][%Stride] = 1
1548  slab[][%Count] = 1
1549  slab[][%Block] = 1
1550  slab[idx][%Block] = nx
1551  slab[idy][%Block] = ny
1552 
1553  // set up multi threading
1554  if (nthreads < 0)
1555  nthreads = ThreadProcessorCount
1556  endif
1557  if (nthreads > 0)
1558  variable threadGroupID = ThreadGroupCreate(nthreads)
1559  variable ithread
1560  for (ithread = 0; ithread < nthreads; ithread += 1)
1561  ThreadStart threadGroupID, ithread, reduce_slab_worker(reduction_func)
1562  endfor
1563  else
1564  make /n=(nzt) /df /free processing_folders
1565  endif
1566 
1567  if (progress)
1568  display_progress_panel("PShell Import", "Reducing " + datasetpath + "...", nzt)
1569  endif
1570 
1571  // create a template wave with the correct scales and labels
1572  make /n=(nx,ny) /d /o $datawavename
1573  wave template = $datawavename
1574  ps_set_dimlabels2(template, datawavename)
1575  ps_scale_dataset(template)
1576 
1577  variable iz, it, izt
1578  variable n_sent = 0
1579  variable n_recvd = 0
1580  variable tmo = 0
1581  string dfname
1582  dfref dfr
1583  variable iw, nw
1584  string sw
1585  make /n=0 /free /wave result_waves
1586 
1587  iz = 0
1588  it = 0
1589 
1590  do
1591  // fill the processing queue up to a maximum number of folders
1592  if (n_sent < max(1, nthreads) * 10 + n_recvd)
1593  if (iz < nz)
1594  if (it < nt)
1595  // load a slab into a temporary folder
1596  slab[idz][%Start] = iz
1597  slab[idt][%Start] = it
1598  dfname = "processing_" + num2str(n_sent)
1599  NewDataFolder /s $dfname
1600  HDF5LoadData /O /Q /Z /SLAB=slab /N=slabdata file_id, datasetpath
1601 
1602  duplicate template, image
1603  variable /g r_index = iz
1604  variable /g s_index = it
1605  string /g func_param = reduction_params
1606 
1607  if (nthreads > 0)
1608  // send to thread group
1609  WaveClear image
1610  ThreadGroupPutDF threadGroupID, :
1611  else
1612  // process immediately in single-thread mode
1613  processing_folders[n_sent] = GetDataFolderDFR()
1614  make /n=1/d profile1, profile2
1615  wave slabdata
1616  wave /wave reduced_waves = reduce_slab_image(slabdata, image, reduction_func, func_param)
1617  variable /g func_result = numpnts(reduced_waves)
1618  adh5_get_result_waves(reduced_waves, "redw_", 0)
1619  WaveClear slabdata, image, reduced_waves
1620  setdatafolder ::
1621  endif
1622 
1623  iz += 1
1624  n_sent += 1
1625  tmo = 0
1626  else
1627  iz += 1
1628  it = 0
1629  endif
1630  endif
1631  else
1632  // throttle the loop if processing is slow
1633  tmo = min(100, tmo + 10)
1634  endif
1635 
1636  // receive a slab from the processing queue
1637  if (n_recvd < nzt)
1638  if (nthreads > 0)
1639  dfr = ThreadGroupGetDFR(threadGroupID, tmo)
1640  else
1641  dfr = processing_folders[n_recvd]
1642  processing_folders[n_recvd] = $""
1643  endif
1644 
1645  if (DatafolderRefStatus(dfr) != 0)
1646  // access results folder
1647  nvar rr = dfr:r_index
1648  nvar ss = dfr:s_index
1649  nvar func_result = dfr:func_result
1650 
1651  if (func_result < 1)
1652  print "error during data reduction."
1653  result = -3
1654  break
1655  endif
1656 
1657  // initialize result waves just once
1658  if (numpnts(result_waves) == 0)
1659  redimension /n=(func_result) result_waves
1660  for (iw = 0; iw < func_result; iw += 1)
1661  sw = "redw_" + num2str(iw)
1662  wave profile = dfr:$sw
1663  sw = "ReducedData" + num2str(iw+1)
1664  make /n=(dimsize(profile, 0), nz, nt) /d /o $sw
1665  wave data = $sw
1666  setdimlabel 0, -1, $getdimlabel(profile, 0, -1), data
1667  setdimlabel 1, -1, $kScanDimLabel, data
1668  note data, note(profile)
1669  ps_scale_dataset(data)
1670  setscale /p x dimoffset(profile, 0), dimdelta(profile, 0), waveunits(profile, 0), data
1671  setscale d 0, 0, waveunits(profile, -1), data
1672  result_waves[iw] = data
1673  endfor
1674  endif
1675 
1676  // copy results
1677  for (iw = 0; iw < func_result; iw += 1)
1678  sw = "redw_" + num2str(iw)
1679  wave profile = dfr:$sw
1680  wave data = result_waves[iw]
1681  data[][rr][ss] = profile[p]
1682  endfor
1683 
1684  n_recvd += 1
1685  KillDataFolder /Z dfr
1686  endif
1687  else
1688  // processing complete
1689  break
1690  endif
1691 
1692  // update progress window
1693  if (progress)
1694  if (update_progress_panel(n_recvd))
1695  print "user abort"
1696  result = -4
1697  break
1698  endif
1699  endif
1700  while ((n_recvd < nzt) && (result == 0))
1701 
1702  // clean up
1703  killwaves /z slab, slabdata, template
1704 
1705  if (nthreads > 0)
1706  variable tstatus = ThreadGroupRelease(threadGroupID)
1707  if (tstatus == -2)
1708  print "error: thread did not terminate properly."
1709  result = -5
1710  endif
1711  endif
1712 
1713  // finalize results
1714  nw = numpnts(result_waves)
1715  wavenames = ""
1716  for (iw = 0; iw < nw; iw += 1)
1717  wave /z data = result_waves[iw]
1718  if (WaveExists(data))
1719  if (nz == 1)
1720  redimension /n=(-1, 0, 0) data
1721  elseif (nt == 1)
1722  redimension /n=(-1, nz, 0) data
1723  endif
1724  wavenames += nameofwave(data) + ";"
1725  endif
1726  endfor
1727 
1728  if (progress)
1730  endif
1731 
1732  setdatafolder base_df
1733  return wavenames
1734 end
1735 
1736 
1737 threadsafe static function reduce_slab_worker(reduction_func)
1738  funcref adh5_default_reduction reduction_func
1739  do
1740  // wait for job from main thread
1741  do
1742  dfref dfr = ThreadGroupGetDFR(0, 1000)
1743  if (DataFolderRefStatus(dfr) == 0)
1744  if (GetRTError(2))
1745  return 0 // no more jobs
1746  endif
1747  else
1748  break
1749  endif
1750  while (1)
1751 
1752  // get input data
1753  wave slabdata = dfr:slabdata
1754  wave image = dfr:image
1755  svar func_param = dfr:func_param
1756  nvar rr = dfr:r_index
1757  nvar ss = dfr:s_index
1758 
1759  // do the work
1760  newdatafolder /s out_df
1761  variable /g r_index = rr
1762  variable /g s_index = ss
1763  wave /wave reduced_waves = reduce_slab_image(slabdata, image, reduction_func, func_param)
1764  variable /g func_result = numpnts(reduced_waves)
1765 
1766  // send output to queue and clean up
1767  adh5_get_result_waves(reduced_waves, "redw_", 0)
1768  WaveClear slabdata, image, reduced_waves
1769  ThreadGroupPutDF 0, :
1770  KillDataFolder dfr
1771  while (1)
1772 
1773  return 0
1774 end
1775 
1776 threadsafe static function /wave reduce_slab_image(slabdata, image, reduction_func, reduction_params)
1777  wave slabdata
1778  wave image
1779  funcref adh5_default_reduction reduction_func
1780  string reduction_params
1781 
1782  image = slabdata[q][p][0][0]
1783 
1784  return reduction_func(image, reduction_params)
1785 end
1786 
1787 // ====== meta and auxiliary data ======
1788 
1803 function /s psh5_load_general_group(file_df)
1804  dfref file_df
1805 
1806  if (!DataFolderRefStatus(file_df))
1807  dfref file_df = GetDataFolderDFR()
1808  endif
1809  nvar /sdfr=file_df file_id
1810 
1811  string obj_names = "authors;pgroup;proposal;proposer;sample;"
1812  variable nn = ItemsInList(obj_names, ";")
1813  variable ii
1814  string name
1815 
1816  for (ii = 0; ii < nn; ii += 1)
1817  name = StringFromList(ii, obj_names, ";")
1818  psh_load_general_string(file_df, name)
1819  endfor
1820 
1821  return obj_names
1822 end
1823 
1838 function /s psh_load_general_string(file_df, name)
1839  dfref file_df
1840  string name
1841 
1842  if (!DataFolderRefStatus(file_df))
1843  dfref file_df = GetDataFolderDFR()
1844  endif
1845  nvar /sdfr=file_df file_id
1846 
1847  string path = "/general/" + name
1848  HDF5LoadData /O /Q /Z /N=wt_load_general /TYPE=1 file_id, path
1849  string values = ""
1850  if (!v_flag)
1851  wave /t wt_load_general
1852  variable nn = numpnts(wt_load_general)
1853  variable ii
1854  for (ii = 0; ii < nn; ii += 1)
1855  values = AddListItem(wt_load_general[ii], values, ",", inf)
1856  endfor
1857  killwaves /z wt_load_general
1858  if (strlen(values) >= 1)
1859  values = values[0,strlen(values)-2]
1860  endif
1861  endif
1862  string /g $name = values
1863  return values
1864 end
1865 
1887 function psh5_load_dataset_meta(file_df, datasetpath, datawave)
1888  dfref file_df
1889  string datasetpath
1890  wave datawave
1891 
1892  if (!DataFolderRefStatus(file_df))
1893  dfref file_df = GetDataFolderDFR()
1894  endif
1895  nvar /sdfr=file_df file_id
1896 
1897  dfref save_df = GetDataFolderDFR()
1898  SetDataFolder NewFreeDataFolder()
1899 
1900  string wnote
1901 
1902  HDF5LoadData /O /Q /Z /A="Writable Dimension" /N=WriteDim file_id, datasetpath
1903  if (!v_flag)
1904  wave WriteDim
1905  // scan dimension starts at 1
1906  sprintf wnote, "ScanDimension=%u", WriteDim[0]
1907  Note datawave, wnote
1908  endif
1909 
1910  HDF5LoadData /O /Q /Z /A="Writable Index" /N=WriteIndex file_id, datasetpath
1911  if (!v_flag)
1912  wave WriteIndex
1913  sprintf wnote, "WriteableIndex=%u", WriteIndex[0]
1914  Note datawave, wnote
1915  endif
1916 
1917  HDF5LoadData /O /Q /Z /A="Readable Index" /N=ReadIndex file_id, datasetpath
1918  if (!v_flag)
1919  wave ReadIndex
1920  sprintf wnote, "ReadableIndex=%u", ReadIndex[0]
1921  Note datawave, wnote
1922  endif
1923 
1924  setdatafolder save_df
1925  return 0
1926 end
1927 
1954 function /s psh5_load_scan_meta(file_df, scanpath)
1955  // todo: convert to variables/strings
1956  dfref file_df
1957  string scanpath
1958  string wavenames = ""
1959 
1960  if (!DataFolderRefStatus(file_df))
1961  dfref file_df = GetDataFolderDFR()
1962  endif
1963  nvar /sdfr=file_df file_id
1964 
1965  HDF5LoadData /O /Q /Z /A="Dimensions" /N=ScanDimensions /TYPE=1 file_id, scanpath
1966  if (!v_flag)
1967  wavenames = AddListItem(s_wavenames, wavenames, ";", inf)
1968  else
1969  make /n=1 /o ScanDimensions
1970  ScanDimensions = 0
1971  wavenames = AddListItem("ScanDimensions", wavenames, ";", inf)
1972  endif
1973  HDF5LoadData /O /Q /Z /A="Readables" /N=ScanReadables /TYPE=1 file_id, scanpath
1974  if (!v_flag)
1975  wavenames = AddListItem(s_wavenames, wavenames, ";", inf)
1976  else
1977  make /n=1 /o /t ScanReadables
1978  ScanReadables[0] = "ScientaSpectrum"
1979  wavenames = AddListItem("ScanReadables", wavenames, ";", inf)
1980  endif
1981  HDF5LoadData /O /Q /Z /A="Writables" /N=ScanWritables /TYPE=1 file_id, scanpath
1982  if (!v_flag)
1983  wavenames = AddListItem(s_wavenames, wavenames, ";", inf)
1984  else
1985  // OTF script
1986  HDF5LoadData /O /Q /Z /A="PlotDomain" /N=ScanWritables /TYPE=1 file_id, scanpath
1987  if (!v_flag)
1988  wavenames = AddListItem(s_wavenames, wavenames, ";", inf)
1989  endif
1990  endif
1991  HDF5LoadData /O /Q /Z /A="Steps" /N=ScanSteps /TYPE=1 file_id, scanpath
1992  if (!v_flag)
1993  wavenames = AddListItem(s_wavenames, wavenames, ";", inf)
1994  endif
1995  wavenames = ReplaceString(";;", wavenames, ";")
1996 
1997  // additional attributes from XPSSpectrum.py
1998  HDF5LoadData /O /Q /Z /A="Iterations" /N=ScanIterations /TYPE=1 file_id, scanpath
1999  if (!v_flag)
2000  wavenames = AddListItem(s_wavenames, wavenames, ";", inf)
2001  endif
2002  HDF5LoadData /O /Q /Z /A="Step Size" /N=ScanStepSize /TYPE=1 file_id, scanpath
2003  if (!v_flag)
2004  wavenames = AddListItem(s_wavenames, wavenames, ";", inf)
2005  endif
2006  HDF5LoadData /O /Q /Z /A="Step Time" /N=ScanStepTime /TYPE=1 file_id, scanpath
2007  if (!v_flag)
2008  wavenames = AddListItem(s_wavenames, wavenames, ";", inf)
2009  endif
2010 
2011  return wavenames
2012 end
2013 
2014 // ====== dimension scaling ======
2015 
2031 function ps_set_dimlabels(data)
2032  wave data
2033 
2034  ps_set_dimlabels2(data, NameOfWave(data))
2035 end
2036 
2050 function ps_set_dimlabels2(data, name)
2051  wave data
2052  string name
2053 
2054  variable dummy
2055  try
2056  // intrinsic dimensions
2057  strswitch(name)
2058  case "ScientaImage":
2059  setdimlabel 0, -1, $kEnergyDimLabel, data
2060  setdimlabel 1, -1, $kAngleDimLabel, data
2061  if (WaveDims(data) >= 3)
2062  setdimlabel 2, -1, $kScanDimLabel, data
2063  endif
2064  AbortOnRTE
2065  break
2066  case "ImageAngleDistribution":
2067  case "ScientaAngleDistribution":
2068  if (WaveDims(data) >= 2)
2069  setdimlabel 0, -1, $kScanDimLabel, data
2070  setdimlabel 1, -1, $kAngleDimLabel, data
2071  else
2072  setdimlabel 0, -1, $kAngleDimLabel, data
2073  endif
2074  AbortOnRTE
2075  break
2076  case "ScientaSpectrum":
2077  case "ImageEnergyDistribution":
2078  case "ScientaEnergyDistribution":
2079  if (WaveDims(data) >= 2)
2080  setdimlabel 0, -1, $kScanDimLabel, data
2081  setdimlabel 1, -1, $kEnergyDimLabel, data
2082  else
2083  setdimlabel 0, -1, $kEnergyDimLabel, data
2084  endif
2085  AbortOnRTE
2086  break
2087  default:
2088  if (WaveDims(data) == 1)
2089  setdimlabel 0, -1, $kScanDimLabel, data
2090  AbortOnRTE
2091  else
2092  return 1
2093  endif
2094  endswitch
2095  catch
2096  dummy = GetRTError(1)
2097  return 2
2098  endtry
2099  return 0
2100 end
2101 
2111 function /df ps_find_scan_folder(data_df)
2112  dfref data_df
2113 
2114  wave /z /t /sdfr=data_df ScanWritables=::ScanWritables
2115  if (WaveExists(ScanWritables))
2116  string sdf = GetDataFolder(1, data_df)
2117  dfref parent_df = $(sdf + ":")
2118  return parent_df
2119  else
2120  return data_df
2121  endif
2122 end
2123 
2134 function /df ps_find_attr_folder(scan_df)
2135  dfref scan_df
2136 
2137  dfref diags_df = data_df:diags
2138  dfref attrs_df = scan_df:attrs
2139  dfref attr_df = scan_df:attr
2140  if (DataFolderRefStatus(diags_df))
2141  return diags_df
2142  elseif (DataFolderRefStatus(attrs_df))
2143  return attrs_df
2144  elseif (DataFolderRefStatus(attr_df))
2145  return attr_df
2146  else
2147  return $""
2148  endif
2149 end
2150 
2161 function /wave ps_find_scale_wave(name, df1, df2, df3)
2162  string name
2163  dfref df1
2164  dfref df2
2165  dfref df3
2166 
2167  variable idf
2168  variable ndf=3
2169  make /n=(ndf) /df /free dfs
2170  dfs[0] = {df1, df2, df3}
2171  for (idf = 0; idf < ndf; idf += 1)
2172  if (DataFolderRefStatus(dfs[idf]))
2173  wave /SDFR=dfs[idf] /Z w = $name
2174  if (WaveExists(w))
2175  return w
2176  endif
2177  endif
2178  endfor
2179 
2180  return $""
2181 end
2182 
2225 function ps_detect_scale(data_df, ax, lo, hi, un)
2226  dfref data_df
2227  wave /t ax
2228  wave lo
2229  wave hi
2230  wave /t un
2231 
2232  dfref scan_df = ps_find_scan_folder(data_df)
2233  dfref attr_df = ps_find_attr_folder(scan_df)
2234 
2235  redimension /n=4 lo, hi, un, ax
2236  setdimlabel 0, 0, $kEnergyDimLabel, lo, hi, un, ax
2237  setdimlabel 0, 1, $kAngleDimLabel, lo, hi, un, ax
2238  setdimlabel 0, 2, $kScanDimLabel, lo, hi, un, ax
2239  setdimlabel 0, 3, $kDataDimLabel, lo, hi, un, ax
2240 
2241  // default values
2242  lo[%$kEnergyDimLabel] = 0
2243  hi[%$kEnergyDimLabel] = 1
2244  un[%$kEnergyDimLabel] = "eV"
2245  ax[%$kEnergyDimLabel] = "Ekin"
2246 
2247  lo[%$kAngleDimLabel] = -1
2248  hi[%$kAngleDimLabel] = 1
2249  un[%$kAngleDimLabel] = "arb."
2250  un[%$kAngleDimLabel] = "slice"
2251 
2252  lo[%$kScanDimLabel] = 0
2253  hi[%$kScanDimLabel] = 1
2254  un[%$kScanDimLabel] = "arb."
2255  ax[%$kScanDimLabel] = "scan"
2256 
2257  lo[%$kDataDimLabel] = 0
2258  hi[%$kDataDimLabel] = 0
2259  un[%$kDataDimLabel] = "arb."
2260  ax[%$kDataDimLabel] = "value"
2261 
2262  wave /T /Z LensMode = ps_find_scale_wave("LensMode", data_df, scan_df, attr_df)
2263  wave /Z ChannelBegin = ps_find_scale_wave("ScientaChannelBegin", data_df, scan_df, attr_df)
2264  wave /Z ChannelEnd = ps_find_scale_wave("ScientaChannelEnd", data_df, scan_df, attr_df)
2265  wave /Z SliceBegin = ps_find_scale_wave("ScientaSliceBegin", data_df, scan_df, attr_df)
2266  wave /Z SliceEnd = ps_find_scale_wave("ScientaSliceEnd", data_df, scan_df, attr_df)
2267  wave /Z ScientaChannels = ps_find_scale_wave("ScientaChannels", data_df, scan_df, attr_df)
2268 
2269  // lens mode can give more detail
2270  if (waveexists(LensMode) && (numpnts(LensMode) >= 1))
2271  strswitch(LensMode[0])
2272  case "Angular45":
2273  lo[%$kAngleDimLabel] = -45/2
2274  hi[%$kAngleDimLabel] = +45/2
2275  un[%$kAngleDimLabel] = "°"
2276  ax[%$kAngleDimLabel] = "angle"
2277  break
2278  case "Angular60":
2279  lo[%$kAngleDimLabel] = -60/2
2280  hi[%$kAngleDimLabel] = +60/2
2281  un[%$kAngleDimLabel] = "°"
2282  ax[%$kAngleDimLabel] = "angle"
2283  break
2284  case "Transmission":
2285  un[%$kAngleDimLabel] = "arb."
2286  ax[%$kAngleDimLabel] = "offset"
2287  break
2288  endswitch
2289  endif
2290 
2291  // best option if scales are explicit in separate waves
2292  if (waveexists(ChannelBegin) && waveexists(ChannelEnd) && (numpnts(ChannelBegin) >= 1) && (numpnts(ChannelEnd) >= 1))
2293  lo[%$kEnergyDimLabel] = ChannelBegin[0]
2294  hi[%$kEnergyDimLabel] = ChannelEnd[0]
2295  elseif (waveexists(ScientaChannels) && (numpnts(ScientaChannels) >= 1))
2296  lo[%$kEnergyDimLabel] = ScientaChannels[0]
2297  hi[%$kEnergyDimLabel] = ScientaChannels[numpnts(ScientaChannels)-1]
2298  endif
2299  if (waveexists(SliceBegin) && waveexists(SliceEnd) && (numpnts(SliceBegin) >= 1) && (numpnts(SliceEnd) >= 1))
2300  lo[%$kAngleDimLabel] = SliceBegin[0]
2301  hi[%$kAngleDimLabel] = SliceEnd[0]
2302  endif
2303 
2304  wave /z /t /SDFR=scan_df ScanWritables
2305  if (WaveExists(ScanWritables))
2306  wave /z /SDFR=scan_df scanner = $ScanWritables[0]
2307  if (!WaveExists(scanner))
2308  wave /z /SDFR=attr_df scanner = $ScanWritables[0]
2309  endif
2310  if (WaveExists(scanner) && (numpnts(scanner) >= 1))
2311  lo[%$kScanDimLabel] = scanner[0]
2312  hi[%$kScanDimLabel] = scanner[numpnts(scanner)-1]
2313  ax[%$kScanDimLabel] = NameOfWave(scanner)
2314  strswitch(NameOfWave(scanner))
2315  case "Eph":
2316  ax[%$kScanDimLabel] = "photon energy"
2317  un[%$kScanDimLabel] = "eV"
2318  break
2319  case "ManipulatorX":
2320  case "ManipulatorY":
2321  case "ManipulatorZ":
2322  case "FocusYTrans":
2323  case "FocusZTrans":
2324  case "RefocusYTrans":
2325  case "RefocusZTrans":
2326  case "ExitSlitY":
2327  un[%$kScanDimLabel] = "mm"
2328  break
2329  case "ExitSlit":
2330  un[%$kScanDimLabel] = "µm"
2331  break
2332  case "ManipulatorTheta":
2333  case "ManipulatorTilt":
2334  case "ManipulatorPhi":
2335  un[%$kScanDimLabel] = "°"
2336  break
2337  case "FocusXRot":
2338  case "FocusYRot":
2339  case "FocusZRot":
2340  case "RefocusXRot":
2341  case "RefocusYRot":
2342  case "RefocusZRot":
2343  un[%$kScanDimLabel] = "mrad"
2344  break
2345  endswitch
2346  endif
2347  endif
2348 end
2349 
2389 function ps_scale_dataset_2(data, ax, lo, hi, un)
2390  wave data
2391  wave /t ax
2392  wave lo
2393  wave hi
2394  wave /t un
2395 
2396  string snote = note(data)
2397  string sdim
2398  sdim = GetDimLabel(data, 0, -1)
2399  if (strlen(sdim))
2400  setscale /i x lo[%$sdim], hi[%$sdim], un[%$sdim], data
2401  snote = ReplaceStringByKey("AxisLabelX", snote, ax[%$sdim], "=", "\r")
2402  endif
2403 
2404  sdim = GetDimLabel(data, 1, -1)
2405  if (strlen(sdim))
2406  setscale /i y lo[%$sdim], hi[%$sdim], un[%$sdim], data
2407  snote = ReplaceStringByKey("AxisLabelY", snote, ax[%$sdim], "=", "\r")
2408  endif
2409 
2410  sdim = GetDimLabel(data, 2, -1)
2411  if (strlen(sdim))
2412  setscale /i z lo[%$sdim], hi[%$sdim], un[%$sdim], data
2413  snote = ReplaceStringByKey("AxisLabelZ", snote, ax[%$sdim], "=", "\r")
2414  endif
2415 
2416  string data_unit = un[%$kDataDimLabel]
2417  string data_label = ax[%$kDataDimLabel]
2418  string s
2419  variable def = (cmpstr(data_unit, "arb.") == 0) && (cmpstr(data_label, "value") == 0)
2420 
2421  if (def)
2422  s = StringByKey("AxisLabelD", snote, "=", "\r")
2423  if (strlen(s) > 0)
2424  data_label = s
2425  def = 0
2426  endif
2427  s = StringByKey("AxisUnitD", snote, "=", "\r")
2428  if (strlen(s) > 0)
2429  data_unit = s
2430  def = 0
2431  endif
2432  endif
2433 
2434  if (def)
2435  strswitch(NameOfWave(data))
2436  case "ScientaImage":
2437  case "ImageAngleDistribution":
2438  case "ScientaAngleDistribution":
2439  case "ScientaSpectrum":
2440  case "ImageEnergyDistribution":
2441  case "ScientaEnergyDistribution":
2442  data_unit = "arb."
2443  data_label = "intensity"
2444  def = 0
2445  break
2446  case "SampleCurrent":
2447  case "RefCurrent":
2448  case "AuxCurrent":
2449  data_unit = "A"
2450  data_label = "current"
2451  def = 0
2452  break
2453  case "MachineCurrent":
2454  data_unit = "mA"
2455  data_label = "current"
2456  def = 0
2457  break
2458  endswitch
2459  endif
2460 
2461  setscale d 0, 0, data_unit, data
2462  snote = ReplaceStringByKey("AxisLabelD", snote, data_label, "=", "\r")
2463  snote = ReplaceStringByKey("AxisUnitD", snote, data_unit, "=", "\r")
2464  snote = ReplaceStringByKey("Dataset", snote, NameOfWave(data), "=", "\r")
2465  note /k data, snote
2466 end
2467 
2483 function ps_scale_datasets(scan_df)
2484  dfref scan_df
2485 
2486  make /n=3 /free lo, hi
2487  make /n=3 /t /free ax, un
2488  wave /t /z /SDFR=scan_df ScanReadables
2489  if (WaveExists(ScanReadables))
2490  variable isr
2491  variable nsr = numpnts(ScanReadables)
2492  variable nel
2493  string ssr
2494  string sds
2495  for (isr = 0; isr < nsr; isr += 1)
2496  ssr = ScanReadables[isr]
2497  dfref data_df = psh5_dataset_to_folder(scan_df, ssr)
2498  if (!DataFolderRefStatus(data_df))
2499  dfref data_df = scan_df
2500  endif
2501  nel = ItemsInList(ssr, "/")
2502  sds = StringFromList(nel - 1, ssr, "/")
2503  wave /z /sdfr=data_df wsr=$sds
2504  if (WaveExists(wsr))
2505  ps_detect_scale(data_df, ax, lo, hi, un)
2506  ps_scale_dataset_2(wsr, ax, lo, hi, un)
2507  endif
2508  endfor
2509  endif
2510 end
2511 
2528 function ps_scale_dataset(data)
2529  wave data
2530 
2531  dfref save_df = GetDataFolderDFR()
2532  dfref data_df = GetWavesDataFolderDFR(data)
2533 
2534  setdatafolder data_df
2535  make /n=3 /free lo, hi
2536  make /n=3 /t /free ax, un
2537  ps_detect_scale(data_df, ax, lo, hi, un)
2538  ps_scale_dataset_2(data, ax, lo, hi, un)
2539  setdatafolder save_df
2540 end
2541 
2542 
2543 // ====== miscellaneous functions ======
2544 
2554 function /s kill_matching_waves(dfr, pattern, recurse, [killed])
2555  DFREF dfr
2556  string pattern
2557  variable recurse
2558  string killed
2559 
2560  if (ParamIsDefault(killed))
2561  killed = ""
2562  endif
2563 
2564  string s
2565  string r
2566  variable index = 0
2567  do
2568  Wave/Z w = WaveRefIndexedDFR(dfr, index)
2569  if (!WaveExists(w))
2570  break
2571  endif
2572 
2573  s = NameOfWave(w)
2574  if (stringmatch(s, pattern))
2575  killwaves /z w
2576  killed = AddListItem(s, killed, ";", Inf)
2577  endif
2578 
2579  index += 1
2580  while(1)
2581 
2582  if (recurse)
2583  Variable numChildDataFolders = CountObjectsDFR(dfr, 4)
2584  Variable i
2585  for(i=0; i<numChildDataFolders; i+=1)
2586  String childDFName = GetIndexedObjNameDFR(dfr, 4, i)
2587  DFREF childDFR = dfr:$childDFName
2588  killed = kill_matching_waves(childDFR, pattern, 1, killed=killed)
2589  endfor
2590  endif
2591 
2592  return killed
2593 End
psh5_load_dataset
string psh5_load_dataset(dfref file_df, string datasetpath, variable create_folders=defaultValue, string reduction_func=defaultValue, string reduction_params=defaultValue)
load a dataset from an open PShell HDF5 file.
Definition: pearl-pshell-import.ipf:1176
ps_fix_folder_name
string ps_fix_folder_name(string group_name)
convert HDF5 group name to data folder name and fix compatibility issues
Definition: pearl-pshell-import.ipf:1065
reduce_slab_worker
static threadsafe variable reduce_slab_worker(funcref reduction_func)
Definition: pearl-pshell-import.ipf:1737
psh5_filter_datasets_rank
string psh5_filter_datasets_rank(string datasets, string ranks, variable min_rank, variable max_rank)
filter datasets by rank
Definition: pearl-pshell-import.ipf:728
ps_find_scale_wave
wave ps_find_scale_wave(string name, dfref df1, dfref df2, dfref df3)
find a wave in scan and attr data folders
Definition: pearl-pshell-import.ipf:2161
kDSCEssentialDiags
const variable kDSCEssentialDiags
Definition: pearl-pshell-import.ipf:78
psh5_create_folders
dfr psh5_create_folders(string datasetpath)
create all data folders along a dataset path
Definition: pearl-pshell-import.ipf:990
ps_set_dimlabels
variable ps_set_dimlabels(wave data)
set dimension labels according to the axis type
Definition: pearl-pshell-import.ipf:2031
ps_set_dimlabels2
variable ps_set_dimlabels2(wave data, string name)
set dimension labels according to the axis type
Definition: pearl-pshell-import.ipf:2050
psh5_load_general_group
string psh5_load_general_group(dfref file_df)
load organizational metadata from the general group.
Definition: pearl-pshell-import.ipf:1803
psh_load_general_string
string psh_load_general_string(dfref file_df, string name)
load a string from the general group.
Definition: pearl-pshell-import.ipf:1838
kill_progress_panel
variable kill_progress_panel()
Definition: pearl-gui-tools.ipf:51
psh5_load_dataset_slabs
string psh5_load_dataset_slabs(dfref file_df, string datasetpath, variable create_folders=defaultValue, variable progress=defaultValue)
load a dataset slab-wise from the open PShell HDF5 file.
Definition: pearl-pshell-import.ipf:1289
display_progress_panel
variable display_progress_panel(string title, string message, variable progress_max)
Definition: pearl-gui-tools.ipf:19
update_progress_panel
variable update_progress_panel(variable progress, string message=defaultValue, variable progress_max=defaultValue)
Definition: pearl-gui-tools.ipf:33
kScientaScalingDatasets
const string kScientaScalingDatasets
List of datasets that must be loaded to determine the axis scaling of a Scienta image.
Definition: pearl-pshell-import.ipf:66
kDSCMonitors
const variable kDSCMonitors
Definition: pearl-pshell-import.ipf:83
psh5_load_dataset_reduced
string psh5_load_dataset_reduced(dfref file_df, string datasetpath, funcref reduction_func, string reduction_params, variable create_folders=defaultValue, variable progress=defaultValue, variable nthreads=defaultValue)
load a dataset with reduced dimensionality
Definition: pearl-pshell-import.ipf:1472
kDSCRegions
const variable kDSCRegions
Definition: pearl-pshell-import.ipf:84
kDSCPositioners
const variable kDSCPositioners
Definition: pearl-pshell-import.ipf:74
adh5_get_result_waves
threadsafe variable adh5_get_result_waves(wave results, string result_prefix, variable start_index)
copy waves from wave reference wave into current data folder
Definition: pearl-area-import.ipf:1463
kDSCPreview
const variable kDSCPreview
Definition: pearl-pshell-import.ipf:77
psh5_load_scan_meta
string psh5_load_scan_meta(dfref file_df, string scanpath)
load metadata of a PShell scan group.
Definition: pearl-pshell-import.ipf:1954
twave2list
static string twave2list(wave wt, string sep)
convert text wave to list.
Definition: pearl-pshell-import.ipf:532
kDSCScientaScaling
const variable kDSCScientaScaling
Definition: pearl-pshell-import.ipf:76
psh5_load_dataset_meta
variable psh5_load_dataset_meta(dfref file_df, string datasetpath, wave datawave)
load metadata of a PShell dataset.
Definition: pearl-pshell-import.ipf:1887
ps_scale_dataset
variable ps_scale_dataset(wave data)
set the dimension scales of a loaded PShell Scienta dataset according to attributes.
Definition: pearl-pshell-import.ipf:2528
psh5_extract_region_paths
string psh5_extract_region_paths(string datasets)
trim dataset paths to the scan/region part
Definition: pearl-pshell-import.ipf:853
kAngleDimLabel
const string kAngleDimLabel
Dimension label for the angle dispersive dimension of multi-dimensional datasets.
Definition: pearl-pshell-import.ipf:53
ps_scale_dataset_2
variable ps_scale_dataset_2(wave data, wave ax, wave lo, wave hi, wave un)
set the dimension scales of a dataset.
Definition: pearl-pshell-import.ipf:2389
kTransposedDatasets
const string kTransposedDatasets
List of datasets that must be transposed upon loading.
Definition: pearl-pshell-import.ipf:72
kDSCSnaps
const variable kDSCSnaps
Definition: pearl-pshell-import.ipf:81
psh5_dataset_to_folder
dfr psh5_dataset_to_folder(dfref parent_df, string datasetpath)
map dataset path to datafolder path
Definition: pearl-pshell-import.ipf:1034
ad_suggest_foldername
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.
Definition: pearl-area-import.ipf:110
kDSCMeta
const variable kDSCMeta
Definition: pearl-pshell-import.ipf:82
kDSCDiags
const variable kDSCDiags
Definition: pearl-pshell-import.ipf:80
kPreviewDatasets
const string kPreviewDatasets
List of preferred datasets to load for preview.
Definition: pearl-pshell-import.ipf:63
kDSCOther
const variable kDSCOther
Definition: pearl-pshell-import.ipf:85
ps_find_attr_folder
dfr ps_find_attr_folder(dfref scan_df)
find the attributes data folder
Definition: pearl-pshell-import.ipf:2134
kDSCAttrs
const variable kDSCAttrs
Definition: pearl-pshell-import.ipf:79
psh5_list_all_datasets
string psh5_list_all_datasets(variable file_id)
list all datasets in a file
Definition: pearl-pshell-import.ipf:605
psh5_load_datasets
string psh5_load_datasets(dfref file_df, string datasets, variable create_folders=defaultValue, string reduction_func=defaultValue, string reduction_params=defaultValue)
load multiple datasets from open file
Definition: pearl-pshell-import.ipf:1098
kEssentialDiagnostics
const string kEssentialDiagnostics
List of diagnostic datasets that are normally loaded with a scan.
Definition: pearl-pshell-import.ipf:69
kDataDimLabel
const string kDataDimLabel
Dimension label for the data dimension.
Definition: pearl-pshell-import.ipf:60
wave2list
static string wave2list(wave w, string format, string sep)
convert numeric wave to list.
Definition: pearl-pshell-import.ipf:549
adh5_default_reduction
threadsafe wave adh5_default_reduction(wave source, string *param)
function prototype for adh5_load_reduced_detector
Definition: pearl-area-import.ipf:1115
kDSCDetectors
const variable kDSCDetectors
Definition: pearl-pshell-import.ipf:75
psh5_preview
dfr psh5_preview(string path_name, string file_name, dfref dest_df=defaultValue, string preview_datasets=defaultValue)
load preview
Definition: pearl-pshell-import.ipf:345
psh5_close_file
variable psh5_close_file(dfref file_df)
close a HDF5 file opened by psh5_open_file.
Definition: pearl-pshell-import.ipf:509
psh5_list_scans
string psh5_list_scans(variable file_id)
list scan groups of a PShell data file.
Definition: pearl-pshell-import.ipf:574
kill_matching_waves
string kill_matching_waves(dfref dfr, string pattern, variable recurse, string killed=defaultValue)
kill any waves matching a pattern in the experiment
Definition: pearl-pshell-import.ipf:2554
PearlCleanupName
string PearlCleanupName(string name)
Definition: pearl-compat.ipf:48
unique_strings
static string unique_strings(string list)
remove duplicate items from list
Definition: pearl-pshell-import.ipf:764
ps_scale_datasets
variable ps_scale_datasets(dfref scan_df)
set the dimension scales of loaded PShell Scienta datasets according to attributes.
Definition: pearl-pshell-import.ipf:2483
psh5_load
dfr psh5_load(string path_name, string file_name, string scans, string regions, string datasets, variable classes=defaultValue, variable max_rank=defaultValue, string reduction_func=defaultValue, string reduction_params=defaultValue, dfref dest_df=defaultValue)
main data loading function
Definition: pearl-pshell-import.ipf:158
kScanDimLabel
const string kScanDimLabel
Dimension label for the scan dimension of multi-dimensional datasets.
Definition: pearl-pshell-import.ipf:56
psh5_match_dataset_classes
string psh5_match_dataset_classes(string datasets, variable classes, string positioners=defaultValue, string detectors=defaultValue)
filter a list of datasets by classification
Definition: pearl-pshell-import.ipf:899
ps_detect_scale
variable ps_detect_scale(dfref data_df, wave ax, wave lo, wave hi, wave un)
detect the dimension scales from attributes.
Definition: pearl-pshell-import.ipf:2225
psh5_list_dataset_info
variable[string datatypes, string ranks, string dimensions] psh5_list_dataset_info(string variable, string file_id, variable string, sds datasets)
list data types and dimensions of datasets
Definition: pearl-pshell-import.ipf:631
kEnergyDimLabel
const string kEnergyDimLabel
Dimension label for the energy dispersive dimension of multi-dimensional datasets.
Definition: pearl-pshell-import.ipf:50
psh5_extract_scan_paths
string psh5_extract_scan_paths(string datasets)
trim dataset paths to the scan part
Definition: pearl-pshell-import.ipf:803
psh5_open_file
dfr psh5_open_file(string path_name, string file_name, dfref dest_df=defaultValue)
open a HDF5 file created by the PShell data acquisition program and prepare the data folder.
Definition: pearl-pshell-import.ipf:450
reduce_slab_image
static threadsafe wave reduce_slab_image(wave slabdata, wave image, funcref reduction_func, string reduction_params)
Definition: pearl-pshell-import.ipf:1776
ps_find_scan_folder
dfr ps_find_scan_folder(dfref data_df)
find the scan folder of current data
Definition: pearl-pshell-import.ipf:2111
kDSCAll
const variable kDSCAll
Definition: pearl-pshell-import.ipf:86