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