PEARL Procedures  rev-distro-1.4.0-0-g80a01f2
Igor procedures for the analysis of PEARL data
pearl-pshell-import.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.36
3 #pragma ModuleName = PearlPShellImport
4 #pragma version = 1.03
5 #include <HDF5 Browser>
6 #include "pearl-gui-tools"
7 #include "pearl-area-import"
8 
9 // copyright (c) 2013-16 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 
50 
55 
57 const string kEnergyDimLabel = "energy";
58 
60 const string kAngleDimLabel = "angle";
61 
63 const string kScanDimLabel = "scan";
64 
67 const string kDataDimLabel = "data";
68 
70 const string kPreviewDatasets = "ScientaImage;ScientaSpectrum;ImageAngleDistribution;ImageEnergyDistribution;Counts;SampleCurrent;";
71 
73 const string kScientaScalingDatasets = "LensMode;ScientaChannelBegin;ScientaChannelEnd;ScientaSliceBegin;ScientaSliceEnd;";
74 
76 const string kTransposedDatasets = "ScientaImage;";
77 
99 variable psh5_open_file(string ANickName, string APathName, string AFileName){
100  string ANickName
101  string APathName
102  string AFileName
103 
104  setdatafolder root:
105  newdatafolder /s /o $("root:" + ANickName)
106  dfref fileDF = GetDataFolderDFR()
107 
108  variable fileID
109  HDF5OpenFile /P=$APathName /R fileID as AFileName
110  if (v_flag == 0)
111  string /g s_filepath
112  string /g s_scanpaths
113  s_filepath = s_path + s_filename
114  s_scanpaths = psh5_list_scans(fileID)
115  else
116  fileID = 0
117  endif
118 
119  return fileID
120 };
121 
129 variable psh5_close_file(variable fileID){
130  variable fileID
131 
132  HDF5CloseFile fileID
133 };
134 
159 string psh5_load_complete(string ANickName, string APathName, string AFileName, variable load_data = defaultValue, variable load_attr = defaultValue){
160  string ANickName
161  string APathName
162  string AFileName
163  variable load_data
164  variable load_attr
165 
166  if (ParamIsDefault(load_data))
167  load_data = 1
168  endif
169  if (ParamIsDefault(load_attr))
170  load_attr = 1
171  endif
172 
173  dfref saveDF = GetDataFolderDFR()
174 
175  // performance monitoring
176  variable timerRefNum
177  variable /g psh5_perf_secs
178  timerRefNum = startMSTimer
179 
180  variable fileID = psh5_open_file(ANickName, APathName, AFileName)
181  if (fileID)
182  dfref fileDF = GetDataFolderDFR()
183  svar s_filepath
184  svar s_scanpaths
185  AFileName = s_filepath
186  print "loading " + s_filepath + "\r"
187 
188  variable ig
189  variable ng = ItemsInList(s_scanpaths, ";")
190  string sg
191  string folder
192 
193  for (ig = 0; ig < ng; ig += 1)
194  sg = StringFromList(ig, s_scanpaths, ";")
195  folder = ReplaceString("/", sg, "")
196  folder = ReplaceString(" ", folder, "")
197  folder = CleanupName(folder, 0)
198  setdatafolder fileDF
199  newdatafolder /s /o $folder
200  psh5_load_scan_complete(fileID, sg, load_data=load_data, load_attr=load_attr)
201  endfor
202 
203  psh5_close_file(fileID)
204  else
205  AFileName = ""
206  endif
207 
208  psh5_perf_secs = stopMSTimer(timerRefNum) / 1e6
209 
210  setdatafolder saveDF
211  return AFileName
212 };
213 
245 string psh5_load_preview(string ANickName, string APathName, string AFileName, variable load_data = defaultValue, variable load_attr = defaultValue, string pref_scans = defaultValue, string pref_datasets = defaultValue){
246  string ANickName
247  string APathName
248  string AFileName
249  variable load_data
250  variable load_attr
251  string pref_scans
252  string pref_datasets
253 
254  if (ParamIsDefault(load_data))
255  load_data = 1
256  endif
257  if (ParamIsDefault(load_attr))
258  load_attr = 1
259  endif
260  if (ParamIsDefault(pref_scans))
261  pref_scans = "*scan1*;"
262  endif
263  if (ParamIsDefault(pref_datasets))
264  pref_datasets = ""
265  endif
266 
267  dfref saveDF = GetDataFolderDFR()
268  setdatafolder root:
269  newdatafolder /o/s pearl_area
270  newdatafolder /o/s preview
271 
272  variable fileID
273  string scanpaths = ""
274  string dataname = ""
275 
276  // performance monitoring
277  variable timerRefNum
278  variable /g adh5_perf_secs
279  timerRefNum = startMSTimer
280 
281  HDF5OpenFile /P=$APathName /R /Z fileID as AFileName
282  if (v_flag == 0)
283  AFileName = s_path + s_filename
284  dfref fileDF = GetDataFolderDFR()
285 
286  scanpaths = psh5_list_scans(fileID)
287  variable ng = ItemsInList(scanpaths)
288  variable ig
289  string sg
290  variable np = ItemsInList(pref_scans)
291  variable ip
292  string sp
293  variable found = 0
294  if (ng > 0)
295  for (ip = 0; ip < np; ip += 1)
296  for (ig = 0; ig < ng; ig += 1)
297  sg = StringFromList(ig, scanpaths)
298  sp = StringFromList(ip, pref_scans)
299  if (StringMatch(sg, sp))
300  found = 1
301  break
302  endif
303  endfor
304  if (found)
305  break
306  endif
307  endfor
308  if (!found)
309  ig = 0
310  endif
311  sg = StringFromList(ig, scanpaths)
312 
313  if (load_attr)
314  setdatafolder fileDF
315  newdatafolder /o/s attr
316  killwaves /a/z
317  psh5_load_scan_attrs(fileID, sg)
318  endif
319 
320  setdatafolder fileDF
321  dataname = psh5_load_scan_preview(fileID, sg, set_scale=load_attr, pref_datasets=pref_datasets)
322 
323  wave /z data = $dataname
324  string destpath = GetDataFolder(1, saveDF) + ANickName
325  if (waveexists(data))
326  duplicate /o data, $destpath
327  wave /z data = $destpath
328  else
329  print "no data found in file " + AFileName
330  endif
331 
332  else
333  print "no scans found in file " + AFileName
334  endif
335 
336  HDF5CloseFile fileID
337  endif
338 
339  if (timerRefNum >= 0)
340  adh5_perf_secs = stopMSTimer(timerRefNum) / 1e6
341  endif
342 
343  setdatafolder saveDF
344  return dataname
345 };
346 
369 string psh5_load_scan_complete(variable fileID, string scanpath, variable load_data = defaultValue, variable load_attr = defaultValue){
370  variable fileID
371  string scanpath
372  variable load_data
373  variable load_attr
374 
375  if (ParamIsDefault(load_data))
376  load_data = 1
377  endif
378  if (ParamIsDefault(load_attr))
379  load_attr = 1
380  endif
381 
382  dfref saveDF = GetDataFolderDFR()
383 
384  dfref dataDF = GetDataFolderDFR()
385  string wavenames
386  string attrnames
387  psh5_load_scan_meta(fileID, scanpath)
388  if (load_attr)
389  newdatafolder /s /o attr
390  attrnames = psh5_load_scan_attrs(fileID, scanpath)
391  endif
392  if (load_data)
393  setdatafolder dataDF
394  wavenames = psh5_load_scan_data(fileID, scanpath)
395  endif
396  if (load_data && load_attr)
397  setdatafolder dataDF
399  endif
400 
401  setdatafolder saveDF
402  return wavenames
403 };
404 
413 string psh5_list_scans(variable fileID){
414  variable fileID
415 
416  HDF5ListGroup /F /TYPE=1 fileID, "/"
417 
418  variable ig
419  variable ng = ItemsInList(S_HDF5ListGroup, ";")
420  string sg
421  string scans = ""
422 
423  for (ig = 0; ig < ng; ig += 1)
424  sg = StringFromList(ig, S_HDF5ListGroup, ";")
425  if (cmpstr(sg[1,4], "scan") == 0)
426  scans = AddListItem(sg, scans, ";", inf)
427  endif
428  endfor
429 
430  return scans
431 };
432 
448 string psh5_list_scan_datasets(variable fileID, string scanpath, variable include_regions = defaultValue){
449  variable fileID
450  string scanpath
451  variable include_regions
452 
453  if (ParamIsDefault(include_regions))
454  include_regions = 0
455  endif
456  string result
457 
458  HDF5ListGroup /TYPE=2 /Z fileID, scanpath
459  result = S_HDF5ListGroup
460 
461  if (include_regions)
462  HDF5ListGroup /R /TYPE=2 /Z fileID, scanpath
463  variable n = ItemsInList(S_HDF5ListGroup)
464  variable i
465  string ds
466  string region_datasets
467  for (i = 0; i < n; i += 1)
468  ds = StringFromList(i, S_HDF5ListGroup)
469  if (StringMatch(ds, "region*/*"))
470  //region_datasets = psh5_list_scan_datasets(fileID, ReplaceString("//", scanpath + "/" + region, "/"), include_regions=0)
471  result = AddListItem(ds, result, ";", inf)
472  endif
473  endfor
474  endif
475 
476  return result
477 };
478 
489 string psh5_list_scan_regions(variable fileID, string scanpath){
490  variable fileID
491  string scanpath
492 
493  HDF5ListGroup /TYPE=1 /Z fileID, scanpath
494  variable n = ItemsInList(S_HDF5ListGroup)
495  variable i
496  string result = ""
497  string s
498  for (i = 0; i < n; i += 1)
499  s = StringFromList(i, S_HDF5ListGroup)
500  if (StringMatch(s, "region*"))
501  result = AddListItem(s, result, ";", inf)
502  endif
503  endfor
504 
505  return result
506 };
507 
522 string psh5_load_scan_data(variable fileID, string scanpath){
523  variable fileID
524  string scanpath
525 
526  string datasets = psh5_list_scan_datasets(fileID, scanpath, include_regions=1)
527  variable nds = ItemsInList(datasets)
528  variable ids
529  string sds
530  string sw
531  string wavenames = ""
532  for (ids = 0; ids < nds; ids += 1)
533  sds = StringFromList(ids, datasets)
534  sw = psh5_load_dataset(fileID, scanpath, sds, set_scale=0)
535  wavenames = AddListItem(sw, wavenames, ";", inf)
536  endfor
537 
538  return wavenames
539 };
540 
562 string psh5_load_scan_attrs(variable fileID, string scanpath, variable attr_sets = defaultValue){
563  variable fileID
564  string scanpath
565  variable attr_sets
566 
567  if (ParamIsDefault(attr_sets))
568  attr_sets = 1
569  endif
570 
571  string attr_path = ReplaceString("//", scanpath + "/attrs", "/")
572  string attr_list = ""
573  if (attr_sets & 1)
574  HDF5ListGroup /TYPE=2 /Z fileID, attr_path
575  if (!v_flag)
576  attr_list = S_HDF5ListGroup
577  endif
578  endif
579 
580  variable ids
581  variable nds
582  string sds
583 
584  if (attr_sets & 2)
585  nds = ItemsInList(kScientaScalingDatasets, ";")
586  for (ids = 0; ids < nds; ids += 1)
587  sds = StringFromList(ids, kScientaScalingDatasets)
588  if (WhichListItem(sds, attr_list) < 0)
589  attr_list = AddListItem(sds, attr_list, ";", inf)
590  endif
591  endfor
592  endif
593 
594  nds = ItemsInList(attr_list, ";")
595  string wavenames = ""
596  for (ids = 0; ids < nds; ids += 1)
597  sds = StringFromList(ids, attr_list, ";")
598  HDF5LoadData /O /Q /Z fileID, attr_path + "/" + sds
599  if (!v_flag)
600  wavenames = AddListItem(s_wavenames, wavenames, ";", inf)
601  endif
602  endfor
603  wavenames = ReplaceString(";;", wavenames, ";")
604 
605  return wavenames
606 };
607 
630 string psh5_load_scan_meta(variable fileID, string scanpath){
631  variable fileID
632  string scanpath
633  string wavenames = ""
634 
635  HDF5LoadData /O /Q /Z /A="Dimensions" /N=ScanDimensions /TYPE=1 fileID, scanpath
636  if (!v_flag)
637  wavenames = AddListItem(s_wavenames, wavenames, ";", inf)
638  else
639  make /n=1 /o ScanDimensions
640  ScanDimensions = 0
641  wavenames = AddListItem("ScanDimensions", wavenames, ";", inf)
642  endif
643  HDF5LoadData /O /Q /Z /A="Readables" /N=ScanReadables /TYPE=1 fileID, scanpath
644  if (!v_flag)
645  wavenames = AddListItem(s_wavenames, wavenames, ";", inf)
646  else
647  make /n=1 /o /t ScanReadables
648  ScanReadables[0] = "ScientaSpectrum"
649  wavenames = AddListItem("ScanReadables", wavenames, ";", inf)
650  endif
651  HDF5LoadData /O /Q /Z /A="Writables" /N=ScanWritables /TYPE=1 fileID, scanpath
652  if (!v_flag)
653  wavenames = AddListItem(s_wavenames, wavenames, ";", inf)
654  endif
655  HDF5LoadData /O /Q /Z /A="Steps" /N=ScanSteps /TYPE=1 fileID, scanpath
656  if (!v_flag)
657  wavenames = AddListItem(s_wavenames, wavenames, ";", inf)
658  endif
659  wavenames = ReplaceString(";;", wavenames, ";")
660 
661  return wavenames
662 };
663 
697 string psh5_load_dataset(variable fileID, string scanpath, string datasetname, variable set_scale = defaultValue){
698  variable fileID
699  string scanpath
700  string datasetname
701  variable set_scale
702 
703  if (ParamIsDefault(set_scale))
704  set_scale = 1
705  endif
706 
707  dfref base_df = GetDataFolderDFR()
708 
709  string datasetpath
710  datasetpath = scanpath + "/" + datasetname
711  datasetpath = ReplaceString("//", datasetpath, "/")
712 
713  string regionname
714  string regionpath
715  if (ItemsInList(datasetname, "/") >= 2)
716  regionname = StringFromList(0, datasetname, "/")
717  regionpath = ReplaceString("//", scanpath + "/" + regionname, "/")
718  datasetname = RemoveListItem(0, datasetname, "/")
719  NewDataFolder /o/s $regionname
720  else
721  regionname = ""
722  regionpath = scanpath
723  endif
724 
725  STRUCT HDF5DataInfo di// Defined in HDF5 Browser.ipf.
726  InitHDF5DataInfo(di)
727  variable err = HDF5DatasetInfo(fileID, datasetpath, 0, di)
728  if (err != 0)
729  print "error accessing detector/data"
730  return ""
731  endif
732 
733  string dataname
734  if (di.ndims < 2)
735  HDF5LoadData /O /Q /Z fileID, datasetpath
736  dataname = StringFromList(0, S_waveNames)
737  else
738  dataname = psh5_load_dataset_slabs(fileID, regionpath, datasetname)
739  endif
740 
741  wave /z data = $dataname
742  if (waveexists(data))
743  psh5_load_dataset_meta(fileID, regionpath, datasetname, data)
744  ps_set_dimlabels(data)
745  if (set_scale)
746  ps_scale_dataset(data)
747  endif
748  else
749  dataname = ""
750  endif
751 
752  setdatafolder base_df
753  return dataname
754 };
755 
769 static string select_dataset(string file_datasets, string pref_datasets){
770  string file_datasets
771  string pref_datasets
772 
773  variable index
774  variable nds = ItemsInList(file_datasets)
775  variable ids
776  string sds = ""
777  string mds = ""
778  variable np = ItemsInList(pref_datasets)
779  variable ip
780  string sp
781  variable found = 0
782  if (nds > 0)
783  for (ip = 0; ip < np; ip += 1)
784  for (ids = 0; ids < nds; ids += 1)
785  sds = StringFromList(ids, file_datasets)
786  index = ItemsInList(sds, "/") - 1
787  mds = StringFromList(index, sds, "/")
788  sp = StringFromList(ip, pref_datasets)
789  if (StringMatch(mds, sp))
790  found = 1
791  break
792  endif
793  endfor
794  if (found)
795  break
796  endif
797  endfor
798  if (!found)
799  ids = 0
800  sds = StringFromList(ids, file_datasets)
801  endif
802  endif
803 
804  return sds
805 };
806 
831 string psh5_load_scan_preview(variable fileID, string scanpath, variable set_scale = defaultValue, string pref_datasets = defaultValue){
832  variable fileID
833  string scanpath
834  variable set_scale
835  string pref_datasets
836 
837  if (ParamIsDefault(set_scale))
838  set_scale = 1
839  endif
840  if (ParamIsDefault(pref_datasets) || (strlen(pref_datasets) == 0))
841  pref_datasets = kPreviewDatasets
842  endif
843 
844  dfref saveDF = GetDataFolderDFR()
845  dfref dataDF = saveDF
846 
847  string datasets = psh5_list_scan_datasets(fileID, scanpath, include_regions=1)
848  string datasetname = select_dataset(datasets, pref_datasets)
849  string datasetpath
850  datasetpath = scanpath + "/" + datasetname
851  datasetpath = ReplaceString("//", datasetpath, "/")
852 
853  STRUCT HDF5DataInfo di// Defined in HDF5 Browser.ipf.
854  InitHDF5DataInfo(di)
855  variable err = HDF5DatasetInfo(fileID, datasetpath, 0, di)
856  if (err != 0)
857  print "error accessing detector/data"
858  return ""
859  endif
860 
861  string dataname
862  if (di.ndims < 2)
863  HDF5LoadData /O /Q /Z fileID, datasetpath
864  dataname = StringFromList(0, S_waveNames)
865  wave /z data = $dataname
866  if (waveexists(data))
867  ps_set_dimlabels(data)
868  endif
869  else
870  variable dim2start = 0
871  variable dim2count = 1
872  variable dim3start = 0
873  variable dim3count = 1
874  if (di.ndims >= 3)
875  dim2start = floor(di.dims[2] / 2)
876  dim2count = 1
877  endif
878  if (di.ndims >= 4)
879  dim3start = floor(di.dims[3] / 2)
880  dim3count = 1
881  endif
882 
883  dataname = psh5_load_dataset_slab(fileID, scanpath, datasetname, dim2start, dim2count, dim3start, dim3count)
884  endif
885 
886  wave /z data = $dataname
887  if (waveexists(data))
888  if (set_scale)
889  setdatafolder dataDF
890  string positioners
891  string positioner
892  string positionerpath
893  positioners = psh5_load_scan_meta(fileID, scanpath)
894  wave /t /z ScanWritables
895  if (waveexists(ScanWritables) && (numpnts(ScanWritables) >= 1))
896  positioner = ScanWritables[0]
897  if (strlen(positioner) > 0)
898  positionerpath = scanpath + "/" + positioner
899  positionerpath = ReplaceString("//", positionerpath, "/")
900  HDF5LoadData /O /Q /Z fileID, positionerpath
901  endif
902  endif
903 
904  setdatafolder dataDF
905  newdatafolder /o/s attr
906  killwaves /a/z
907  psh5_load_scan_attrs(fileID, scanpath, attr_sets=2)
908  setdatafolder dataDF
909  ps_scale_dataset(data)
910  endif
911  else
912  dataname = ""
913  endif
914 
915  return dataname
916 };
917 
945 string psh5_load_scan_section(variable fileID, string scanpath, variable dim, variable set_scale = defaultValue, string pref_datasets = defaultValue){
946  variable fileID
947  string scanpath
948  variable dim
949  variable set_scale
950  string pref_datasets
951 
952  // select first dimension (future argument)
953  // 0 = first dimension is x axis (energy of scienta image)
954  dim = 0
955 
956  if (ParamIsDefault(set_scale))
957  set_scale = 1
958  endif
959  if (ParamIsDefault(pref_datasets) || (strlen(pref_datasets) == 0))
960  pref_datasets = kPreviewDatasets
961  endif
962 
963  dfref saveDF = GetDataFolderDFR()
964  dfref dataDF = saveDF
965 
966  string datasets = psh5_list_scan_datasets(fileID, scanpath)
967  string datasetname = select_dataset(datasets, pref_datasets)
968  string datasetpath
969  datasetpath = scanpath + "/" + datasetname
970  datasetpath = ReplaceString("//", datasetpath, "/")
971  string dataname = StringFromList(ItemsInList(datasetpath, "/") - 1, datasetpath, "/")
972  string destname = dataname[0,29] + num2str(dim)
973 
974  STRUCT HDF5DataInfo di// Defined in HDF5 Browser.ipf.
975  InitHDF5DataInfo(di)
976  variable err = HDF5DatasetInfo(fileID, datasetpath, 0, di)
977  if (err != 0)
978  print "error accessing detector/data"
979  return ""
980  else if (di.ndims != 3)
981  print "error: rank of dataset != 3"
982  return ""
983  endif
984 
985  variable idx, idy, idz, idt
986  variable transpose = WhichListItem(dataname, kTransposedDatasets) >= 0
987  if (transpose)
988  idx = 1
989  idy = 0
990  else
991  idx = 0
992  idy = 1
993  endif
994  idz = 2
995  idt = 3
996 
997  variable nx, ny, nz
998  nx = di.dims[idx]
999  ny = di.dims[idy]
1000  nz = di.dims[idz]
1001 
1002  HDF5MakeHyperslabWave(GetDataFolder(1) + "slab", max(di.ndims, 4))
1003  wave slab
1004  slab[][%Start] = 0
1005  slab[][%Stride] = 1
1006  slab[][%Count] = 1
1007  slab[][%Block] = 1
1008 
1009  if (dim == 0)
1010  slab[idy][%Start] = floor(ny / 2)
1011  slab[idx][%Block] = nx
1012  make /n=(nx,nz) /o $destname
1013  else
1014  slab[idx][%Start] = floor(nx / 2)
1015  slab[idy][%Block] = ny
1016  make /n=(ny,nz) /o $destname
1017  endif
1018  slab[idz][%Block] = nz
1019  wave data = $destname
1020  data = 0
1021 
1022  HDF5LoadData /O /Q /Z /SLAB=slab /N=slabdata fileID, datasetpath
1023  if (!v_flag)
1024  wave slabdata
1025  if (transpose)
1026  data += slabdata[0][p][q][0]
1027  else
1028  data += slabdata[p][0][q][0]
1029  endif
1030  endif
1031  killwaves /z slab, slabdata
1032 
1033  if (set_scale)
1034  make /n=(1,1,1) /free dummy
1035  ps_set_dimlabels2(dummy, dataname)
1036  setdimlabel 0, -1, $GetDimLabel(dummy, dim, -1), data
1037  setdimlabel 1, -1, $kScanDimLabel, data
1038 
1039  setdatafolder dataDF
1040  string positioners
1041  string positioner
1042  string positionerpath
1043  positioners = psh5_load_scan_meta(fileID, scanpath)
1044  wave /t /z ScanWritables
1045  if (waveexists(ScanWritables) && (numpnts(ScanWritables) >= 1))
1046  positioner = ScanWritables[0]
1047  if (strlen(positioner) > 0)
1048  positionerpath = scanpath + "/" + positioner
1049  positionerpath = ReplaceString("//", positionerpath, "/")
1050  HDF5LoadData /O /Q /Z fileID, positionerpath
1051  endif
1052  endif
1053 
1054  setdatafolder dataDF
1055  newdatafolder /o/s attr
1056  killwaves /a/z
1057  psh5_load_scan_attrs(fileID, scanpath, attr_sets=2)
1058  setdatafolder dataDF
1059  ps_scale_dataset(data)
1060  endif
1061 
1062  return destname
1063 };
1064 
1083 variable psh5_load_dataset_meta(variable fileID, string datapath, string datasetname, wave datawave){
1084  variable fileID
1085  string datapath
1086  string datasetname
1087  wave datawave
1088 
1089  dfref saveDF = GetDataFolderDFR()
1090  SetDataFolder NewFreeDataFolder()
1091 
1092  string datasetpath = datapath + "/" + datasetname
1093  datasetpath = ReplaceString("//", datasetpath, "/")
1094  string wnote
1095 
1096  HDF5LoadData /O /Q /Z /A="Writable Dimension" /N=WriteDim fileID, datasetpath
1097  if (!v_flag)
1098  wave WriteDim
1099  // scan dimension starts at 1
1100  sprintf wnote, "ScanDimension=%u", WriteDim[0]
1101  Note datawave, wnote
1102  endif
1103 
1104  HDF5LoadData /O /Q /Z /A="Writable Index" /N=WriteIndex fileID, datasetpath
1105  if (!v_flag)
1106  wave WriteIndex
1107  sprintf wnote, "WriteableIndex=%u", WriteIndex[0]
1108  Note datawave, wnote
1109  endif
1110 
1111  HDF5LoadData /O /Q /Z /A="Readable Index" /N=ReadIndex fileID, datasetpath
1112  if (!v_flag)
1113  wave ReadIndex
1114  sprintf wnote, "ReadableIndex=%u", ReadIndex[0]
1115  Note datawave, wnote
1116  endif
1117 
1118  setdatafolder saveDF
1119  return 0
1120 };
1121 
1140 string psh5_load_dataset_slabs(variable fileID, string datapath, string datasetname, variable progress = defaultValue){
1141  variable fileID
1142  string datapath
1143  string datasetname
1144  variable progress
1145 
1146  if (ParamIsDefault(progress))
1147  progress = 1
1148  endif
1149 
1150  variable result = 0
1151  string datasetpath
1152  string datawavename
1153  datasetpath = datapath + "/" + datasetname
1154  datasetpath = ReplaceString("//", datasetpath, "/")
1155  datawavename = StringFromList(ItemsInList(datasetpath, "/") - 1, datasetpath, "/")
1156 
1157  STRUCT HDF5DataInfo di// Defined in HDF5 Browser.ipf.
1158  InitHDF5DataInfo(di)
1159  variable err = HDF5DatasetInfo(fileID, datasetpath, 0, di)
1160  if (err != 0)
1161  print "error accessing detector/data"
1162  return ""
1163  endif
1164  if (di.ndims < 2)
1165  print "error: rank of dataset < 2"
1166  return ""
1167  else if (di.ndims < 3)
1168  progress = 0
1169  endif
1170 
1171  variable idx, idy, idz, idt, izt
1172  variable transpose = WhichListItem(datawavename, kTransposedDatasets) >= 0
1173  if (transpose)
1174  idx = 1
1175  idy = 0
1176  else
1177  idx = 0
1178  idy = 1
1179  endif
1180  idz = 2
1181  idt = 3
1182 
1183  variable nx, ny, nz, nt, nzt
1184  nx = di.dims[idx]
1185  ny = di.dims[idy]
1186  nz = di.dims[idz]
1187  nt = di.dims[idt]
1188  make /n=(nx,ny,nz,nt) /o $datawavename
1189  wave data = $datawavename
1190 
1191  nz = max(nz, 1)
1192  nt = max(nt, 1)
1193  nzt = nz * nt
1194  izt = 0
1195  if (progress)
1196  display_progress_panel("HDF5 Import", "Loading data...", nzt)
1197  endif
1198 
1199  // load data image by image
1200  HDF5MakeHyperslabWave(GetDataFolder(1) + "slab", max(di.ndims, 4))
1201  wave slab
1202  slab[][%Start] = 0
1203  slab[][%Stride] = 1
1204  slab[][%Count] = 1
1205  slab[][%Block] = 1
1206  slab[idx][%Block] = nx
1207  slab[idy][%Block] = ny
1208 
1209  variable iz, it
1210  for (iz = 0; iz < nz; iz += 1)
1211  for (it = 0; it < nt; it += 1)
1212  slab[idz][%Start] = iz
1213  slab[idt][%Start] = it
1214  HDF5LoadData /O /Q /Z /SLAB=slab /N=slabdata fileID, datasetpath
1215  wave slabdata// 2D, 3D, or 4D with singletons
1216  if (transpose)
1217  data[][][iz][it] = slabdata[q][p][0][0]
1218  else
1219  data[][][iz][it] = slabdata[p][q][0][0]
1220  endif
1221 
1222  // progress window
1223  izt += 1
1224  if (progress)
1225  if (update_progress_panel(izt))
1226  result = -4// user abort
1227  break
1228  endif
1229  endif
1230  endfor
1231  if (result < 0)
1232  break
1233  endif
1234  endfor
1235 
1236  if (progress)
1238  endif
1239 
1240  killwaves /z slab, slabdata
1241  if (!result)
1242  ps_set_dimlabels(data)
1243  return datawavename
1244  else
1245  killwaves /z data
1246  return ""
1247  endif
1248 };
1249 
1276 string psh5_load_dataset_slab(variable fileID, string datapath, string datasetname, variable dim2start, variable dim2count, variable dim3start, variable dim3count){
1277  variable fileID
1278  string datapath
1279  string datasetname
1280  variable dim2start
1281  variable dim2count
1282  variable dim3start
1283  variable dim3count
1284 
1285  string datasetpath
1286  string datawavename
1287  datasetpath = datapath + "/" + datasetname
1288  datasetpath = ReplaceString("//", datasetpath, "/")
1289  datawavename = StringFromList(ItemsInList(datasetpath, "/") - 1, datasetpath, "/")
1290 
1291  STRUCT HDF5DataInfo di
1292  InitHDF5DataInfo(di)
1293  variable err = HDF5DatasetInfo(fileID, datasetpath, 0, di)
1294  if (err != 0)
1295  print "error accessing detector/data"
1296  return ""
1297  endif
1298  if (di.ndims < 2)
1299  print "error: rank of dataset < 2"
1300  return ""
1301  endif
1302 
1303  variable idx, idy, idz, idt
1304  variable transpose = WhichListItem(datawavename, kTransposedDatasets) >= 0
1305  if (transpose)
1306  idx = 1
1307  idy = 0
1308  else
1309  idx = 0
1310  idy = 1
1311  endif
1312  idz = 2
1313  idt = 3
1314 
1315  variable nx, ny
1316  nx = di.dims[idx]
1317  ny = di.dims[idy]
1318  make /n=(nx,ny) /o $datawavename
1319  wave data = $datawavename
1320  data = 0
1321 
1322  HDF5MakeHyperslabWave(GetDataFolder(1) + "slab", max(di.ndims, 4))
1323  wave slab
1324  slab[][%Start] = 0
1325  slab[][%Stride] = 1
1326  slab[][%Count] = 1
1327  slab[][%Block] = 1
1328  slab[idx][%Block] = nx
1329  slab[idy][%Block] = ny
1330 
1331  variable iz, it
1332  variable navg = 0
1333  variable dim2end = dim2start + dim2count - 1
1334  variable dim3end = dim3start + dim3count - 1
1335  for (iz = dim2start; iz <= dim2end; iz += 1)
1336  for (it = dim3start; it <= dim3end; it += 1)
1337  slab[idz][%Start] = iz
1338  slab[idt][%Start] = it
1339  HDF5LoadData /O /Q /Z /SLAB=slab /N=slabdata fileID, datasetpath
1340  if (!v_flag)
1341  wave slabdata
1342  if (transpose)
1343  data += slabdata[q][p][0][0]
1344  else
1345  data += slabdata[p][q][0][0]
1346  endif
1347  navg += 1
1348  endif
1349  endfor
1350  endfor
1351  if (navg)
1352  data /= navg
1353  endif
1354 
1355  killwaves /z slab, slabdata
1356  ps_set_dimlabels(data)
1357  return datawavename
1358 };
1359 
1375 variable ps_set_dimlabels(wave data){
1376  wave data
1377 
1378  ps_set_dimlabels2(data, NameOfWave(data))
1379 };
1380 
1394 variable ps_set_dimlabels2(wave data, string name){
1395  wave data
1396  string name
1397 
1398  variable dummy
1399  try
1400  // intrinsic dimensions
1401  strswitch(name)
1402  case "ScientaImage":
1403  setdimlabel 0, -1, $kEnergyDimLabel, data
1404  setdimlabel 1, -1, $kAngleDimLabel, data
1405  if (WaveDims(data) >= 3)
1406  setdimlabel 2, -1, $kScanDimLabel, data
1407  endif
1408  AbortOnRTE
1409  break
1410  case "ImageAngleDistribution":
1411  case "ScientaAngleDistribution":
1412  if (WaveDims(data) >= 2)
1413  setdimlabel 0, -1, $kScanDimLabel, data
1414  setdimlabel 1, -1, $kAngleDimLabel, data
1415  else
1416  setdimlabel 0, -1, $kAngleDimLabel, data
1417  endif
1418  AbortOnRTE
1419  break
1420  case "ScientaSpectrum":
1421  case "ImageEnergyDistribution":
1422  case "ScientaEnergyDistribution":
1423  if (WaveDims(data) >= 2)
1424  setdimlabel 0, -1, $kScanDimLabel, data
1425  setdimlabel 1, -1, $kEnergyDimLabel, data
1426  else
1427  setdimlabel 0, -1, $kEnergyDimLabel, data
1428  endif
1429  AbortOnRTE
1430  break
1431  default:
1432  if (WaveDims(data) == 1)
1433  setdimlabel 0, -1, $kScanDimLabel, data
1434  AbortOnRTE
1435  else
1436  return 1
1437  endif
1438  endswitch
1439  catch
1440  dummy = GetRTError(1)
1441  return 2
1442  endtry
1443  return 0
1444 };
1445 
1451 static dfr find_scan_folder(dfref dataDF){
1452  dfref dataDF
1453 
1454  dfref attrDF = dataDF:attr
1455  if (!DataFolderRefStatus(attrDF))
1456  string df = GetDataFolder(1, dataDF) + ":"
1457  dfref scanDF = $df
1458  else
1459  dfref scanDF = dataDF
1460  endif
1461  return scanDF
1462 };
1463 
1468 static dfr find_attr_folder(dfref dataDF){
1469  dfref dataDF
1470 
1471  dfref attrDF = dataDF:attr
1472  if (!DataFolderRefStatus(attrDF))
1473  string df = GetDataFolder(1, dataDF) + ":"
1474  dfref scanDF = $df
1475  dfref attrDF = scanDF:attr
1476  endif
1477  return attrDF
1478 };
1479 
1497  dfref scanDF = GetDataFolderDFR()
1498  dfref attrDF = find_attr_folder(scanDF)
1499 
1500  make /n=3 /free lo, hi
1501  make /n=3 /t /free ax, un
1502  wave /t /z /SDFR=scanDF ScanReadables
1503  if (WaveExists(ScanReadables))
1504  variable isr
1505  variable nsr = numpnts(ScanReadables)
1506  string ssr
1507  string sdf
1508  for (isr = 0; isr < nsr; isr += 1)
1509  setdatafolder scanDF
1510  ssr = ScanReadables[isr]
1511  if (ItemsInList(ssr, "/") >= 2)
1512  sdf = StringFromList(0, ssr, "/")
1513  ssr = RemoveListItem(0, ssr, "/")
1514  setdatafolder $sdf
1515  endif
1516  wave /z wsr=$ssr
1517  if (WaveExists(wsr))
1518  ps_detect_scale(ax, lo, hi, un)
1519  ps_scale_dataset_2(wsr, ax, lo, hi, un)
1520  endif
1521  endfor
1522  endif
1523  setdatafolder scanDF
1524 };
1525 
1542 variable ps_scale_dataset(wave data){
1543  wave data
1544 
1545  dfref saveDF = GetDataFolderDFR()
1546  dfref dataDF = GetWavesDataFolderDFR(data)
1547 
1548  setdatafolder dataDF
1549  make /n=3 /free lo, hi
1550  make /n=3 /t /free ax, un
1551  ps_detect_scale(ax, lo, hi, un)
1552  ps_scale_dataset_2(data, ax, lo, hi, un)
1553  setdatafolder saveDF
1554 };
1555 
1556 static wave find_scale_wave(string name, dfref dataDF, dfref scanDF, dfref attrDF){
1557  string name
1558  dfref dataDF
1559  dfref scanDF
1560  dfref attrDF
1561 
1562  wave /SDFR=dataDF /Z w = $name
1563  if (!WaveExists(w))
1564  wave /SDFR=scanDF /Z w = $name
1565  if (!WaveExists(w))
1566  wave /SDFR=attrDF /Z w = $name
1567  endif
1568  endif
1569  return w
1570 };
1571 
1613 variable ps_detect_scale(wave ax, wave lo, wave hi, wave un){
1614  wave /t ax
1615  wave lo
1616  wave hi
1617  wave /t un
1618 
1619  dfref dataDF = GetDataFolderDFR()
1620  dfref scanDF = find_scan_folder(dataDF)
1621  dfref attrDF = find_attr_folder(dataDF)
1622 
1623  redimension /n=4 lo, hi, un, ax
1624  setdimlabel 0, 0, $kEnergyDimLabel, lo, hi, un, ax
1625  setdimlabel 0, 1, $kAngleDimLabel, lo, hi, un, ax
1626  setdimlabel 0, 2, $kScanDimLabel, lo, hi, un, ax
1627  setdimlabel 0, 3, $kDataDimLabel, lo, hi, un, ax
1628 
1629  // default values
1630  lo[%$kEnergyDimLabel] = 0
1631  hi[%$kEnergyDimLabel] = 1
1632  un[%$kEnergyDimLabel] = "eV"
1633  ax[%$kEnergyDimLabel] = "Ekin"
1634 
1635  lo[%$kAngleDimLabel] = -1
1636  hi[%$kAngleDimLabel] = 1
1637  un[%$kAngleDimLabel] = "arb."
1638  un[%$kAngleDimLabel] = "slice"
1639 
1640  lo[%$kScanDimLabel] = 0
1641  hi[%$kScanDimLabel] = 1
1642  un[%$kScanDimLabel] = "arb."
1643  ax[%$kScanDimLabel] = "scan"
1644 
1645  lo[%$kDataDimLabel] = 0
1646  hi[%$kDataDimLabel] = 0
1647  un[%$kDataDimLabel] = "arb."
1648  ax[%$kDataDimLabel] = "value"
1649 
1650  wave /SDFR=attrDF /T /Z LensMode
1651  wave /Z ChannelBegin = find_scale_wave("ScientaChannelBegin", dataDF, scanDF, attrDF)
1652  wave /Z ChannelEnd = find_scale_wave("ScientaChannelEnd", dataDF, scanDF, attrDF)
1653  wave /Z SliceBegin = find_scale_wave("ScientaSliceBegin", dataDF, scanDF, attrDF)
1654  wave /Z SliceEnd = find_scale_wave("ScientaSliceEnd", dataDF, scanDF, attrDF)
1655 
1656  // lens mode can give more detail
1657  if (waveexists(LensMode) && (numpnts(LensMode) >= 1))
1658  strswitch(LensMode[0])
1659  case "Angular45":
1660  lo[%$kAngleDimLabel] = -45/2
1661  hi[%$kAngleDimLabel] = +45/2
1662  un[%$kAngleDimLabel] = ""
1663  ax[%$kAngleDimLabel] = "angle"
1664  break
1665  case "Angular60":
1666  lo[%$kAngleDimLabel] = -60/2
1667  hi[%$kAngleDimLabel] = +60/2
1668  un[%$kAngleDimLabel] = ""
1669  ax[%$kAngleDimLabel] = "angle"
1670  break
1671  case "Transmission":
1672  un[%$kAngleDimLabel] = "arb."
1673  ax[%$kAngleDimLabel] = "offset"
1674  break
1675  endswitch
1676  endif
1677 
1678  // best option if scales are explicit in separate waves
1679  if (waveexists(ChannelBegin) && waveexists(ChannelEnd) && (numpnts(ChannelBegin) >= 1) && (numpnts(ChannelEnd) >= 1))
1680  lo[%$kEnergyDimLabel] = ChannelBegin[0]
1681  hi[%$kEnergyDimLabel] = ChannelEnd[0]
1682  endif
1683  if (waveexists(SliceBegin) && waveexists(SliceEnd) && (numpnts(SliceBegin) >= 1) && (numpnts(SliceEnd) >= 1))
1684  lo[%$kAngleDimLabel] = SliceBegin[0]
1685  hi[%$kAngleDimLabel] = SliceEnd[0]
1686  endif
1687 
1688  wave /z /t /SDFR=scanDF ScanWritables
1689  if (WaveExists(ScanWritables))
1690  wave /z /SDFR=scanDF scanner = $ScanWritables[0]
1691  if (!WaveExists(scanner))
1692  wave /z /SDFR=attrDF scanner = $ScanWritables[0]
1693  endif
1694  if (WaveExists(scanner) && (numpnts(scanner) >= 1))
1695  lo[%$kScanDimLabel] = scanner[0]
1696  hi[%$kScanDimLabel] = scanner[numpnts(scanner)-1]
1697  ax[%$kScanDimLabel] = NameOfWave(scanner)
1698  strswitch(NameOfWave(scanner))
1699  case "Eph":
1700  ax[%$kScanDimLabel] = "photon energy"
1701  un[%$kScanDimLabel] = "eV"
1702  break
1703  case "ManipulatorX":
1704  case "ManipulatorY":
1705  case "ManipulatorZ":
1706  case "FocusYTrans":
1707  case "FocusZTrans":
1708  case "RefocusYTrans":
1709  case "RefocusZTrans":
1710  case "ExitSlitY":
1711  un[%$kScanDimLabel] = "mm"
1712  break
1713  case "ExitSlit":
1714  un[%$kScanDimLabel] = "m"
1715  break
1716  case "ManipulatorTheta":
1717  case "ManipulatorTilt":
1718  case "ManipulatorPhi":
1719  un[%$kScanDimLabel] = ""
1720  break
1721  case "FocusXRot":
1722  case "FocusYRot":
1723  case "FocusZRot":
1724  case "RefocusXRot":
1725  case "RefocusYRot":
1726  case "RefocusZRot":
1727  un[%$kScanDimLabel] = "mrad"
1728  break
1729  endswitch
1730  endif
1731  endif
1732 };
1733 
1767 variable ps_scale_dataset_2(wave data, wave ax, wave lo, wave hi, wave un){
1768  wave data
1769  wave /t ax
1770  wave lo
1771  wave hi
1772  wave /t un
1773 
1774  string sdim
1775  sdim = GetDimLabel(data, 0, -1)
1776  if (strlen(sdim))
1777  setscale /i x lo[%$sdim], hi[%$sdim], un[%$sdim], data
1778  Note data, "AxisLabelX=" + ax[%$sdim]
1779  endif
1780 
1781  sdim = GetDimLabel(data, 1, -1)
1782  if (strlen(sdim))
1783  setscale /i y lo[%$sdim], hi[%$sdim], un[%$sdim], data
1784  Note data, "AxisLabelY=" + ax[%$sdim]
1785  endif
1786 
1787  sdim = GetDimLabel(data, 2, -1)
1788  if (strlen(sdim))
1789  setscale /i z lo[%$sdim], hi[%$sdim], un[%$sdim], data
1790  Note data, "AxisLabelZ=" + ax[%$sdim]
1791  endif
1792 
1793  string data_unit = un[%$kDataDimLabel]
1794  string data_label = ax[%$kDataDimLabel]
1795  if (cmpstr(data_unit, "arb.") == 0)
1796  strswitch(NameOfWave(data))
1797  case "SampleCurrent":
1798  case "RefCurrent":
1799  case "AuxCurrent":
1800  data_unit = "A"
1801  data_label = "current"
1802  break
1803  case "MachineCurrent":
1804  data_unit = "mA"
1805  data_label = "current"
1806  break
1807  endswitch
1808  endif
1809  setscale d 0, 0, data_unit, data
1810  Note data, "AxisLabelD=" + data_label
1811  Note data, "Dataset=" + NameOfWave(data)
1812 };
1813 
1853 string psh5_load_reduced(string ANickName, string APathName, string AFileName, funcref reduction_func, string reduction_param, variable progress = defaultValue){
1854  string ANickName
1855  string APathName
1856  string AFileName
1857  funcref adh5_default_reduction reduction_func
1858  string reduction_param
1859  variable progress
1860 
1861  if (ParamIsDefault(progress))
1862  progress = 1
1863  endif
1864 
1865  dfref saveDF = GetDataFolderDFR()
1866 
1867  // performance monitoring
1868  variable timerRefNum
1869  variable /g psh5_perf_secs
1870  timerRefNum = startMSTimer
1871 
1872  variable fileID = psh5_open_file(ANickName, APathName, AFileName)
1873  string wavenames = ""
1874  if (fileID)
1875  dfref fileDF = GetDataFolderDFR()
1876  svar s_filepath
1877  svar s_scanpaths
1878  AFileName = s_filepath
1879  print "loading " + s_filepath + "\r"
1880 
1881  variable ig = 0
1882  variable ng = ItemsInList(s_scanpaths)
1883  string scanpath
1884  string folder
1885  string positioners
1886  string positioner
1887  string positionerpath
1888 
1889  scanpath = StringFromList(ig, s_scanpaths)
1890  folder = ReplaceString("/", scanpath, "")
1891  folder = ReplaceString(" ", folder, "")
1892  folder = CleanupName(folder, 0)
1893  setdatafolder fileDF
1894  newdatafolder /s /o $folder
1895  dfref dataDF = GetDataFolderDFR()
1896  positioners = psh5_load_scan_meta(fileID, scanpath)
1897  newdatafolder /s /o attr
1898  killwaves /a/z
1899  psh5_load_scan_attrs(fileID, scanpath)
1900  setdatafolder dataDF
1901  wave /t /z ScanWritables
1902  if (waveexists(ScanWritables) && (numpnts(ScanWritables) >= 1))
1903  positioner = ScanWritables[0]
1904  if (strlen(positioner) > 0)
1905  positionerpath = scanpath + "/" + positioner
1906  positionerpath = ReplaceString("//", positionerpath, "/")
1907  HDF5LoadData /O /Q /Z fileID, positionerpath
1908  endif
1909  endif
1910 
1911  setdatafolder dataDF
1912  string datasets = psh5_list_scan_datasets(fileID, scanpath, include_regions=1)
1913  string dataset = select_dataset(datasets, "ScientaImage")
1914  wavenames = psh5_load_dataset_reduced(fileID, scanpath, dataset, reduction_func, reduction_param, progress=progress)
1915 
1916  psh5_close_file(fileID)
1917  endif
1918 
1919  if (timerRefNum >= 0)
1920  psh5_perf_secs = stopMSTimer(timerRefNum) / 1e6
1921  endif
1922 
1923  setdatafolder saveDF
1924  return wavenames
1925 };
1926 
1927 
1976 string psh5_load_dataset_reduced(variable fileID, string scanpath, string datasetname, funcref reduction_func, string reduction_param, variable progress = defaultValue, variable nthreads = defaultValue){
1977  variable fileID
1978  string scanpath
1979  string datasetname
1980  funcref adh5_default_reduction reduction_func
1981  string reduction_param
1982  variable progress
1983  variable nthreads
1984 
1985  if (ParamIsDefault(progress))
1986  progress = 1
1987  endif
1988  if (ParamIsDefault(nthreads))
1989  nthreads = -1
1990  endif
1991 
1992  dfref base_df = GetDataFolderDFR()
1993  variable result = 0
1994  string datasetpath
1995  string datawavename
1996  string wavenames = ""
1997 
1998  datasetpath = scanpath + "/" + datasetname
1999  datasetpath = ReplaceString("//", datasetpath, "/")
2000  datawavename = StringFromList(ItemsInList(datasetpath, "/") - 1, datasetpath, "/")
2001 
2002  string regionname
2003  string regionpath
2004  if (ItemsInList(datasetname, "/") >= 2)
2005  regionname = StringFromList(0, datasetname, "/")
2006  regionpath = ReplaceString("//", scanpath + "/" + regionname, "/")
2007  datasetname = RemoveListItem(0, datasetname, "/")
2008  NewDataFolder /o/s $regionname
2009  else
2010  regionname = ""
2011  regionpath = scanpath
2012  endif
2013 
2014  STRUCT HDF5DataInfo di// Defined in HDF5 Browser.ipf.
2015  InitHDF5DataInfo(di)
2016  variable err = HDF5DatasetInfo(fileID, datasetpath, 0, di)
2017  if (err != 0)
2018  print "error accessing detector/data"
2019  result = -1
2020  return wavenames
2021  endif
2022  if (di.ndims < 2)
2023  print "error: rank of dataset < 2"
2024  result = -2
2025  return wavenames
2026  else if (di.ndims < 3)
2027  progress = 0
2028  endif
2029 
2030  variable idx, idy, idz, idt
2031  variable transpose = WhichListItem(datawavename, kTransposedDatasets) >= 0
2032  if (transpose)
2033  idx = 1
2034  idy = 0
2035  else
2036  idx = 0
2037  idy = 1
2038  endif
2039  idz = 2
2040  idt = 3
2041 
2042  variable nx, ny, nz, nt, nzt
2043  nx = di.dims[idx]
2044  ny = di.dims[idy]
2045  nz = di.dims[idz]
2046  nt = di.dims[idt]
2047  // adjust singleton dimensions
2048  nz = max(nz, 1)
2049  nt = max(nt, 1)
2050  nzt = nz * nt
2051 
2052  // load data image by image
2053  HDF5MakeHyperslabWave(GetDataFolder(1) + "slab", max(di.ndims, 4))
2054  wave slab
2055  slab[][%Start] = 0
2056  slab[][%Stride] = 1
2057  slab[][%Count] = 1
2058  slab[][%Block] = 1
2059  slab[idx][%Block] = nx
2060  slab[idy][%Block] = ny
2061 
2062  // set up multi threading
2063  if (nthreads < 0)
2064  nthreads = ThreadProcessorCount
2065  endif
2066  if (nthreads > 0)
2067  variable threadGroupID = ThreadGroupCreate(nthreads)
2068  variable ithread
2069  for (ithread = 0; ithread < nthreads; ithread += 1)
2070  ThreadStart threadGroupID, ithread, reduce_slab_worker(reduction_func)
2071  endfor
2072  else
2073  make /n=(nzt) /df /free processing_folders
2074  endif
2075 
2076  if (progress)
2077  display_progress_panel("HDF5 Import", "Loading data (step 1 of 2)...", nzt)
2078  endif
2079 
2080  make /n=(nx,ny) /d /o image_template
2081  setdimlabel 0, -1, $kEnergyDimLabel, image_template
2082  setdimlabel 1, -1, $kAngleDimLabel, image_template
2083  ps_scale_dataset(image_template)
2084 
2085  variable iz, it, izt
2086  string dfname
2087  izt = 0
2088  for (iz = 0; iz < nz; iz += 1)
2089  for (it = 0; it < nt; it += 1)
2090  // load hyperslab
2091  slab[idz][%Start] = iz
2092  slab[idt][%Start] = it
2093  dfname = "processing_" + num2str(izt)
2094  newdatafolder /s $dfname
2095  HDF5LoadData /O /Q /Z /SLAB=slab /N=slabdata fileID, datasetpath
2096 
2097  // send to processing queue
2098  duplicate image_template, image
2099  variable /g r_index = iz
2100  variable /g s_index = it
2101  string /g func_param = reduction_param
2102 
2103  if (nthreads > 0)
2104  WaveClear image
2105  ThreadGroupPutDF threadGroupID, :
2106  else
2107  processing_folders[izt] = GetDataFolderDFR()
2108  make /n=1/d profile1, profile2
2109  wave slabdata
2110  variable /g func_result
2111  func_result = reduce_slab_image(slabdata, image, profile1, profile2, reduction_func, func_param)
2112  WaveClear slabdata, image, profile1, profile2
2113  setdatafolder ::
2114  endif
2115 
2116  izt += 1
2117  // progress window
2118  if (progress)
2119  if (update_progress_panel(izt))
2120  print "user abort"
2121  result = -4
2122  break
2123  endif
2124  endif
2125  endfor
2126  endfor
2127 
2128  killwaves /z slab, slabdata, image_template
2129  if (progress)
2130  update_progress_panel(0, message="Processing data (step 2 of 2)...")
2131  endif
2132 
2133  dfref dfr
2134  for (izt = 0; (izt < nzt) && (result == 0); izt += 1)
2135  if (nthreads > 0)
2136  do
2137  dfr = ThreadGroupGetDFR(threadGroupID, 1000)
2138  if (DatafolderRefStatus(dfr) != 0)
2139  break
2140  endif
2141  if (progress)
2142  if (update_progress_panel(izt))
2143  print "user abort"
2144  result = -4
2145  break
2146  endif
2147  endif
2148  while (1)
2149  else
2150  dfr = processing_folders[izt]
2151  if (progress)
2152  if (update_progress_panel(izt))
2153  print "user abort"
2154  result = -4
2155  break
2156  endif
2157  endif
2158  endif
2159 
2160  if (result != 0)
2161  break
2162  endif
2163 
2164  nvar rr = dfr:r_index
2165  nvar ss = dfr:s_index
2166  nvar func_result = dfr:func_result
2167  wave profile1 = dfr:profile1
2168  wave profile2 = dfr:profile2
2169 
2170  if (func_result == 0)
2171  if (izt == 0)
2172  make /n=(dimsize(profile1, 0), nz, nt) /d /o ReducedData1
2173  make /n=(dimsize(profile2, 0), nz, nt) /d /o ReducedData2
2174  setdimlabel 0, -1, $getdimlabel(profile1, 0, -1), ReducedData1
2175  setdimlabel 0, -1, $getdimlabel(profile2, 0, -1), ReducedData2
2176  setdimlabel 1, -1, $kScanDimLabel, ReducedData1
2177  setdimlabel 1, -1, $kScanDimLabel, ReducedData2
2178  setscale /p x dimoffset(profile1, 0), dimdelta(profile1, 0), waveunits(profile1, 0), ReducedData1
2179  setscale /p x dimoffset(profile2, 0), dimdelta(profile2, 0), waveunits(profile2, 0), ReducedData2
2180  setscale d 0, 0, waveunits(profile1, -1), ReducedData1
2181  setscale d 0, 0, waveunits(profile2, -1), ReducedData2
2182  endif
2183  ReducedData1[][rr][ss] = profile1[p]
2184  ReducedData2[][rr][ss] = profile2[p]
2185  else
2186  print "error during data reduction."
2187  result = -3
2188  break
2189  endif
2190  endfor
2191 
2192  if (nthreads > 0)
2193  variable tstatus = ThreadGroupRelease(threadGroupID)
2194  if (tstatus == -2)
2195  print "error: thread did not terminate properly."
2196  result = -5
2197  endif
2198  else
2199  for (izt = 0; izt < nzt; izt += 1)
2200  KillDataFolder /Z processing_folders[izt]
2201  endfor
2202  endif
2203 
2204  if (result == 0)
2205  if (nz == 1)
2206  redimension /n=(-1, 0, 0) ReducedData1
2207  redimension /n=(-1, 0, 0) ReducedData2
2208  else if (nt == 1)
2209  redimension /n=(-1, nz, 0) ReducedData1
2210  redimension /n=(-1, nz, 0) ReducedData2
2211  endif
2212  wavenames = "ReducedData1;ReducedData2;"
2213  ps_scale_dataset(ReducedData1)
2214  ps_scale_dataset(ReducedData2)
2215  endif
2216  if (progress)
2218  endif
2219 
2220  setdatafolder base_df
2221  return wavenames
2222 };
2223 
2224 threadsafe static variable reduce_slab_worker(funcref reduction_func){
2225  funcref adh5_default_reduction reduction_func
2226  do
2227  // wait for job from main thread
2228  do
2229  dfref dfr = ThreadGroupGetDFR(0, 1000)
2230  if (DataFolderRefStatus(dfr) == 0)
2231  if (GetRTError(2))
2232  return 0// no more jobs
2233  endif
2234  else
2235  break
2236  endif
2237  while (1)
2238 
2239  // get input data
2240  wave slabdata = dfr:slabdata
2241  wave image = dfr:image
2242  svar func_param = dfr:func_param
2243  nvar rr = dfr:r_index
2244  nvar ss = dfr:s_index
2245 
2246  // do the work
2247  newdatafolder /s outDF
2248  make /n=1/d profile1, profile2
2249  variable /g r_index = rr
2250  variable /g s_index = ss
2251  variable /g func_result
2252  func_result = reduce_slab_image(slabdata, image, profile1, profile2, reduction_func, func_param)
2253 
2254  // send output to queue and clean up
2255  WaveClear slabdata, image, profile1, profile2
2256  ThreadGroupPutDF 0, :
2257  KillDataFolder dfr
2258  while (1)
2259 
2260  return 0
2261 };
2262 
2263 threadsafe static variable reduce_slab_image(wave slabdata, wave image, wave profile1, wave profile2, funcref reduction_func, string reduction_param){
2264  wave slabdata
2265  wave image
2266  wave profile1
2267  wave profile2
2268  funcref adh5_default_reduction reduction_func
2269  string reduction_param
2270 
2271  image = slabdata[q][p][0][0]
2272 
2273  return reduction_func(image, profile1, profile2, reduction_param)
2274 };
2275 
2290 string psh5_load_info(string APathName, string AFileName){
2291  string APathName
2292  string AFileName
2293 
2294  dfref saveDF = GetDataFolderDFR()
2295  dfref fileDF = NewFreeDataFolder()
2296  setdatafolder fileDF
2297 
2298  variable fileID
2299  string filepath
2300  string scanpaths
2301  variable nscans
2302  variable iscan
2303  string scanpath
2304  string info = ""
2305 
2306  HDF5OpenFile /P=$APathName /R fileID as AFileName
2307  if (v_flag == 0)
2308  filepath = s_path + s_filename
2309  scanpaths = psh5_list_scans(fileID)
2310  nscans = ItemsInList(scanpaths)
2311  for (iscan = 0; iscan < nscans; iscan += 1)
2312  scanpath = StringFromList(iscan, scanpaths)
2313  info = info + scanpath + "\r"
2314  info = info + psh5_load_scan_info(fileID, scanpath)
2315  endfor
2316  HDF5CloseFile fileID
2317  endif
2318 
2319  setdatafolder saveDF
2320  return info
2321 };
2322 
2336 string psh5_load_scan_info(variable fileID, string scanpath){
2337  variable fileID
2338  string scanpath
2339 
2340  string info = ""
2341  string positions = ""
2342  string positioners = ""
2343  string detectors = ""
2344 
2345  psh5_load_scan_meta(fileID, scanpath)
2346  wave /z ScanDimensions
2347  wave /t /z ScanWritables
2348  wave /t /z ScanReadables
2349  wave /z ScanSteps
2350 
2351  if (WaveExists(ScanSteps) && (numpnts(ScanSteps) >= 1))
2352  ScanSteps += 1
2353  positions = "positions = (" + wave2list(ScanSteps, "%u", ",") + ")"
2354  info = AddListItem(positions, info, "\r", inf)
2355  endif
2356  if (WaveExists(ScanWritables) && (numpnts(ScanWritables) >= 1))
2357  positioners = "positioners = " + twave2list(ScanWritables, ",")
2358  info = AddListItem(positioners, info, "\r", inf)
2359  endif
2360  if (WaveExists(ScanReadables) && (numpnts(ScanReadables) >= 1))
2361  detectors = "detectors = " + twave2list(ScanReadables, ",")
2362  info = AddListItem(detectors, info, "\r", inf)
2363  endif
2364 
2365  return info
2366 };
2367 
2371 static string twave2list(wave wt, string sep){
2372  wave /t wt
2373  string sep
2374 
2375  string list = ""
2376  variable n = numpnts(wt)
2377  variable i
2378  for (i = 0; i < n; i += 1)
2379  list = AddListItem(wt[i], list, sep, inf)
2380  endfor
2381 
2382  return list
2383 };
2384 
2388 static string wave2list(wave w, string format, string sep){
2389  wave w
2390  string format
2391  string sep
2392 
2393  string list = ""
2394  variable n = numpnts(w)
2395  variable i
2396  string s
2397  for (i = 0; i < n; i += 1)
2398  sprintf s, format, w[i]
2399  list = AddListItem(s, list, sep, inf)
2400  endfor
2401 
2402  return list
2403 };
2404 
string psh5_list_scan_regions(variable fileID, string scanpath)
list regions of a PShell scan group.
const string kEnergyDimLabel
Dimension label for the energy dispersive dimension of multi-dimensional datasets.
string psh5_load_reduced(string ANickName, string APathName, string AFileName, funcref reduction_func, string reduction_param, variable progress=defaultValue)
load and reduce the ScientaImage dataset of the first scan of a PShell data file. ...
string psh5_load_dataset_reduced(variable fileID, string scanpath, string datasetname, funcref reduction_func, string reduction_param, variable progress=defaultValue, variable nthreads=defaultValue)
load a reduced dataset from the open PShell HDF5 file.
variable kill_progress_panel()
variable display_progress_panel(string title, string message, variable progress_max)
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.
static threadsafe variable reduce_slab_worker(funcref reduction_func)
variable ps_set_dimlabels2(wave data, string name)
set dimension labels according to the axis type
const string kScanDimLabel
Dimension label for the scan dimension of multi-dimensional datasets.
string psh5_load_dataset(variable fileID, string scanpath, string datasetname, variable set_scale=defaultValue)
load a dataset from an open PShell HDF5 file.
variable ps_set_dimlabels(wave data)
set dimension labels according to the axis type
string psh5_load_preview(string ANickName, 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 dfr find_scan_folder(dfref dataDF)
find the scan folder
const string kAngleDimLabel
Dimension label for the angle dispersive dimension of multi-dimensional datasets. ...
static string twave2list(wave wt, string sep)
convert text wave to list.
variable ps_scale_dataset_2(wave data, wave ax, wave lo, wave hi, wave un)
set the dimension scales of a dataset.
static string wave2list(wave w, string format, string sep)
convert numeric wave to list.
static threadsafe variable reduce_slab_image(wave slabdata, wave image, wave profile1, wave profile2, funcref reduction_func, string reduction_param)
static string select_dataset(string file_datasets, string pref_datasets)
select the preferred dataset from a list of available datasets.
const string kDataDimLabel
Dimension label for the data dimension.
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...
string psh5_load_dataset_slabs(variable fileID, string datapath, string datasetname, variable progress=defaultValue)
load a dataset slab-wise from the open PShell HDF5 file.
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.
threadsafe variable adh5_default_reduction(wave source, wave dest1, wave dest2, string *param)
function prototype for adh5_load_reduced_detector
const string kScientaScalingDatasets
List of datasets that must be loaded to determine the axis scaling of a Scienta image.
string psh5_load_scan_section(variable fileID, string scanpath, variable dim, variable set_scale=defaultValue, string pref_datasets=defaultValue)
load a longitudinal section of a scan from an open PShell HDF5 file.
string psh5_list_scan_datasets(variable fileID, string scanpath, variable include_regions=defaultValue)
list datasets of a PShell scan group.
string psh5_load_info(string APathName, string AFileName)
load descriptive info from a PShell data file.
string psh5_load_dataset_slab(variable fileID, string datapath, string datasetname, variable dim2start, variable dim2count, variable dim3start, variable dim3count)
load a single image from the open PShell data file.
string psh5_load_scan_data(variable fileID, string scanpath)
load all datasets of a PShell scan group.
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 dfr find_attr_folder(dfref dataDF)
find the attributes data folder
static wave find_scale_wave(string name, dfref dataDF, dfref scanDF, dfref attrDF)
variable update_progress_panel(variable progress, string message=defaultValue, variable progress_max=defaultValue)
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.
variable ps_detect_scale(wave ax, wave lo, wave hi, wave un)
detect the dimension scales from attributes.
variable psh5_load_dataset_meta(variable fileID, string datapath, string datasetname, wave datawave)
load metadata of a PShell dataset.
const string kPreviewDatasets
List of preferred datasets to load for preview.
variable ps_scale_dataset(wave data)
set the dimension scales of a loaded PShell Scienta dataset according to attributes.
string psh5_load_scan_info(variable fileID, string scanpath)
load descriptive info from a PShell scan.