PEARL Procedures  rev-distro-1.6.0-0-gcf1399e-dirty
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 
79 const variable kDetectorSensitivity = 4;
80 
102 variable psh5_open_file(string ANickName, string APathName, string AFileName){
103  string ANickName
104  string APathName
105  string AFileName
106 
107  setdatafolder root:
108  newdatafolder /s /o $("root:" + ANickName)
109  dfref fileDF = GetDataFolderDFR()
110 
111  variable fileID
112  HDF5OpenFile /P=$APathName /R fileID as AFileName
113  if (v_flag == 0)
114  string /g s_filepath
115  string /g s_scanpaths
116  s_filepath = s_path + s_filename
117  s_scanpaths = psh5_list_scans(fileID)
118  else
119  fileID = 0
120  endif
121 
122  return fileID
123 };
124 
132 variable psh5_close_file(variable fileID){
133  variable fileID
134 
135  HDF5CloseFile fileID
136 };
137 
162 string psh5_load_complete(string ANickName, string APathName, string AFileName, variable load_data = defaultValue, variable load_attr = defaultValue){
163  string ANickName
164  string APathName
165  string AFileName
166  variable load_data
167  variable load_attr
168 
169  if (ParamIsDefault(load_data))
170  load_data = 1
171  endif
172  if (ParamIsDefault(load_attr))
173  load_attr = 1
174  endif
175 
176  dfref saveDF = GetDataFolderDFR()
177 
178  // performance monitoring
179  variable timerRefNum
180  variable /g psh5_perf_secs
181  timerRefNum = startMSTimer
182 
183  variable fileID = psh5_open_file(ANickName, APathName, AFileName)
184  if (fileID)
185  dfref fileDF = GetDataFolderDFR()
186  svar s_filepath
187  svar s_scanpaths
188  AFileName = s_filepath
189  print "loading " + s_filepath + "\r"
190 
191  variable ig
192  variable ng = ItemsInList(s_scanpaths, ";")
193  string sg
194  string folder
195 
196  for (ig = 0; ig < ng; ig += 1)
197  sg = StringFromList(ig, s_scanpaths, ";")
198  folder = ReplaceString("/", sg, "")
199  folder = ReplaceString(" ", folder, "")
200  folder = CleanupName(folder, 0)
201  setdatafolder fileDF
202  newdatafolder /s /o $folder
203  psh5_load_scan_complete(fileID, sg, load_data=load_data, load_attr=load_attr)
204  endfor
205 
206  psh5_close_file(fileID)
207  else
208  AFileName = ""
209  endif
210 
211  psh5_perf_secs = stopMSTimer(timerRefNum) / 1e6
212 
213  setdatafolder saveDF
214  return AFileName
215 };
216 
243 string psh5_load_preview(string APathName, string AFileName, variable load_data = defaultValue, variable load_attr = defaultValue, string pref_scans = defaultValue, string pref_datasets = defaultValue){
244  string APathName
245  string AFileName
246  variable load_data
247  variable load_attr
248  string pref_scans
249  string pref_datasets
250 
251  if (ParamIsDefault(load_data))
252  load_data = 1
253  endif
254  if (ParamIsDefault(load_attr))
255  load_attr = 1
256  endif
257  if (ParamIsDefault(pref_scans))
258  pref_scans = "*scan1*;"
259  endif
260  if (ParamIsDefault(pref_datasets))
261  pref_datasets = ""
262  endif
263 
264  dfref saveDF = GetDataFolderDFR()
265 
266  variable fileID
267  string scanpaths = ""
268  string dataname = ""
269 
270  // performance monitoring
271  variable timerRefNum
272  variable /g adh5_perf_secs
273  timerRefNum = startMSTimer
274 
275  HDF5OpenFile /P=$APathName /R /Z fileID as AFileName
276  if (v_flag == 0)
277  AFileName = s_path + s_filename
278  dfref fileDF = GetDataFolderDFR()
279 
280  scanpaths = psh5_list_scans(fileID)
281  variable ng = ItemsInList(scanpaths)
282  variable ig
283  string sg
284  variable np = ItemsInList(pref_scans)
285  variable ip
286  string sp
287  variable found = 0
288  if (ng > 0)
289  for (ip = 0; ip < np; ip += 1)
290  for (ig = 0; ig < ng; ig += 1)
291  sg = StringFromList(ig, scanpaths)
292  sp = StringFromList(ip, pref_scans)
293  if (StringMatch(sg, sp))
294  found = 1
295  break
296  endif
297  endfor
298  if (found)
299  break
300  endif
301  endfor
302  if (!found)
303  ig = 0
304  endif
305  sg = StringFromList(ig, scanpaths)
306 
307  if (load_attr)
308  setdatafolder fileDF
309  newdatafolder /o/s attr
310  killwaves /a/z
311  psh5_load_scan_attrs(fileID, sg)
312  endif
313 
314  setdatafolder fileDF
315  dataname = psh5_load_scan_preview(fileID, sg, set_scale=load_attr, pref_datasets=pref_datasets)
316  else
317  print "no scans found in file " + AFileName
318  endif
319 
320  HDF5CloseFile fileID
321  endif
322 
323  if (timerRefNum >= 0)
324  adh5_perf_secs = stopMSTimer(timerRefNum) / 1e6
325  endif
326 
327  setdatafolder saveDF
328  return dataname
329 };
330 
353 string psh5_load_scan_complete(variable fileID, string scanpath, variable load_data = defaultValue, variable load_attr = defaultValue){
354  variable fileID
355  string scanpath
356  variable load_data
357  variable load_attr
358 
359  if (ParamIsDefault(load_data))
360  load_data = 1
361  endif
362  if (ParamIsDefault(load_attr))
363  load_attr = 1
364  endif
365 
366  dfref saveDF = GetDataFolderDFR()
367 
368  dfref dataDF = GetDataFolderDFR()
369  string wavenames
370  string attrnames
371  psh5_load_scan_meta(fileID, scanpath)
372  if (load_attr)
373  newdatafolder /s /o attr
374  attrnames = psh5_load_scan_attrs(fileID, scanpath)
375  endif
376  if (load_data)
377  setdatafolder dataDF
378  wavenames = psh5_load_scan_data(fileID, scanpath)
379  endif
380  if (load_data && load_attr)
381  setdatafolder dataDF
383  endif
384 
385  setdatafolder saveDF
386  return wavenames
387 };
388 
397 string psh5_list_scans(variable fileID){
398  variable fileID
399 
400  HDF5ListGroup /F /TYPE=1 fileID, "/"
401 
402  variable ig
403  variable ng = ItemsInList(S_HDF5ListGroup, ";")
404  string sg
405  string scans = ""
406 
407  for (ig = 0; ig < ng; ig += 1)
408  sg = StringFromList(ig, S_HDF5ListGroup, ";")
409  if (cmpstr(sg[1,4], "scan") == 0)
410  scans = AddListItem(sg, scans, ";", inf)
411  endif
412  endfor
413 
414  return scans
415 };
416 
432 string psh5_list_scan_datasets(variable fileID, string scanpath, variable include_regions = defaultValue){
433  variable fileID
434  string scanpath
435  variable include_regions
436 
437  if (ParamIsDefault(include_regions))
438  include_regions = 0
439  endif
440  string result
441 
442  HDF5ListGroup /TYPE=2 /Z fileID, scanpath
443  result = S_HDF5ListGroup
444 
445  if (include_regions)
446  HDF5ListGroup /R /TYPE=2 /Z fileID, scanpath
447  variable n = ItemsInList(S_HDF5ListGroup)
448  variable i
449  string ds
450  string region_datasets
451  for (i = 0; i < n; i += 1)
452  ds = StringFromList(i, S_HDF5ListGroup)
453  if (StringMatch(ds, "region*/*"))
454  //region_datasets = psh5_list_scan_datasets(fileID, ReplaceString("//", scanpath + "/" + region, "/"), include_regions=0)
455  result = AddListItem(ds, result, ";", inf)
456  endif
457  endfor
458  endif
459 
460  return result
461 };
462 
473 string psh5_list_scan_regions(variable fileID, string scanpath){
474  variable fileID
475  string scanpath
476 
477  HDF5ListGroup /TYPE=1 /Z fileID, scanpath
478  variable n = ItemsInList(S_HDF5ListGroup)
479  variable i
480  string result = ""
481  string s
482  for (i = 0; i < n; i += 1)
483  s = StringFromList(i, S_HDF5ListGroup)
484  if (StringMatch(s, "region*"))
485  result = AddListItem(s, result, ";", inf)
486  endif
487  endfor
488 
489  return result
490 };
491 
506 string psh5_load_scan_data(variable fileID, string scanpath){
507  variable fileID
508  string scanpath
509 
510  string datasets = psh5_list_scan_datasets(fileID, scanpath, include_regions=1)
511  variable nds = ItemsInList(datasets)
512  variable ids
513  string sds
514  string sw
515  string wavenames = ""
516  for (ids = 0; ids < nds; ids += 1)
517  sds = StringFromList(ids, datasets)
518  sw = psh5_load_dataset(fileID, scanpath, sds, set_scale=0)
519  wavenames = AddListItem(sw, wavenames, ";", inf)
520  endfor
521 
522  return wavenames
523 };
524 
546 string psh5_load_scan_attrs(variable fileID, string scanpath, variable attr_sets = defaultValue){
547  variable fileID
548  string scanpath
549  variable attr_sets
550 
551  if (ParamIsDefault(attr_sets))
552  attr_sets = 1
553  endif
554 
555  string attr_path = ReplaceString("//", scanpath + "/attrs", "/")
556  string attr_list = ""
557  if (attr_sets & 1)
558  HDF5ListGroup /TYPE=2 /Z fileID, attr_path
559  if (!v_flag)
560  attr_list = S_HDF5ListGroup
561  endif
562  endif
563 
564  variable ids
565  variable nds
566  string sds
567 
568  if (attr_sets & 2)
569  nds = ItemsInList(kScientaScalingDatasets, ";")
570  for (ids = 0; ids < nds; ids += 1)
571  sds = StringFromList(ids, kScientaScalingDatasets)
572  if (WhichListItem(sds, attr_list) < 0)
573  attr_list = AddListItem(sds, attr_list, ";", inf)
574  endif
575  endfor
576  endif
577 
578  nds = ItemsInList(attr_list, ";")
579  string wavenames = ""
580  for (ids = 0; ids < nds; ids += 1)
581  sds = StringFromList(ids, attr_list, ";")
582  HDF5LoadData /O /Q /Z fileID, attr_path + "/" + sds
583  if (!v_flag)
584  wavenames = AddListItem(s_wavenames, wavenames, ";", inf)
585  endif
586  endfor
587  wavenames = ReplaceString(";;", wavenames, ";")
588 
589  return wavenames
590 };
591 
614 string psh5_load_scan_meta(variable fileID, string scanpath){
615  variable fileID
616  string scanpath
617  string wavenames = ""
618 
619  HDF5LoadData /O /Q /Z /A="Dimensions" /N=ScanDimensions /TYPE=1 fileID, scanpath
620  if (!v_flag)
621  wavenames = AddListItem(s_wavenames, wavenames, ";", inf)
622  else
623  make /n=1 /o ScanDimensions
624  ScanDimensions = 0
625  wavenames = AddListItem("ScanDimensions", wavenames, ";", inf)
626  endif
627  HDF5LoadData /O /Q /Z /A="Readables" /N=ScanReadables /TYPE=1 fileID, scanpath
628  if (!v_flag)
629  wavenames = AddListItem(s_wavenames, wavenames, ";", inf)
630  else
631  make /n=1 /o /t ScanReadables
632  ScanReadables[0] = "ScientaSpectrum"
633  wavenames = AddListItem("ScanReadables", wavenames, ";", inf)
634  endif
635  HDF5LoadData /O /Q /Z /A="Writables" /N=ScanWritables /TYPE=1 fileID, scanpath
636  if (!v_flag)
637  wavenames = AddListItem(s_wavenames, wavenames, ";", inf)
638  endif
639  HDF5LoadData /O /Q /Z /A="Steps" /N=ScanSteps /TYPE=1 fileID, scanpath
640  if (!v_flag)
641  wavenames = AddListItem(s_wavenames, wavenames, ";", inf)
642  endif
643  wavenames = ReplaceString(";;", wavenames, ";")
644 
645  return wavenames
646 };
647 
681 string psh5_load_dataset(variable fileID, string scanpath, string datasetname, variable set_scale = defaultValue){
682  variable fileID
683  string scanpath
684  string datasetname
685  variable set_scale
686 
687  if (ParamIsDefault(set_scale))
688  set_scale = 1
689  endif
690 
691  dfref base_df = GetDataFolderDFR()
692 
693  string datasetpath
694  datasetpath = scanpath + "/" + datasetname
695  datasetpath = ReplaceString("//", datasetpath, "/")
696 
697  string regionname
698  string regionpath
699  if (ItemsInList(datasetname, "/") >= 2)
700  regionname = StringFromList(0, datasetname, "/")
701  regionpath = ReplaceString("//", scanpath + "/" + regionname, "/")
702  datasetname = RemoveListItem(0, datasetname, "/")
703  NewDataFolder /o/s $regionname
704  else
705  regionname = ""
706  regionpath = scanpath
707  endif
708 
709  STRUCT HDF5DataInfo di// Defined in HDF5 Browser.ipf.
710  InitHDF5DataInfo(di)
711  variable err = HDF5DatasetInfo(fileID, datasetpath, 0, di)
712  if (err != 0)
713  print "error accessing detector/data"
714  return ""
715  endif
716 
717  string dataname
718  if (di.ndims < 2)
719  HDF5LoadData /O /Q /Z fileID, datasetpath
720  dataname = StringFromList(0, S_waveNames)
721  else
722  dataname = psh5_load_dataset_slabs(fileID, regionpath, datasetname)
723  endif
724 
725  wave /z data = $dataname
726  if (waveexists(data))
727  psh5_load_dataset_meta(fileID, regionpath, datasetname, data)
728  ps_set_dimlabels(data)
729  if (set_scale)
730  ps_scale_dataset(data)
731  endif
732  else
733  dataname = ""
734  endif
735 
736  setdatafolder base_df
737  return dataname
738 };
739 
753 static string select_dataset(string file_datasets, string pref_datasets){
754  string file_datasets
755  string pref_datasets
756 
757  variable index
758  variable nds = ItemsInList(file_datasets)
759  variable ids
760  string sds = ""
761  string mds = ""
762  variable np = ItemsInList(pref_datasets)
763  variable ip
764  string sp
765  variable found = 0
766  if (nds > 0)
767  for (ip = 0; ip < np; ip += 1)
768  for (ids = 0; ids < nds; ids += 1)
769  sds = StringFromList(ids, file_datasets)
770  index = ItemsInList(sds, "/") - 1
771  mds = StringFromList(index, sds, "/")
772  sp = StringFromList(ip, pref_datasets)
773  if (StringMatch(mds, sp))
774  found = 1
775  break
776  endif
777  endfor
778  if (found)
779  break
780  endif
781  endfor
782  if (!found)
783  ids = 0
784  sds = StringFromList(ids, file_datasets)
785  endif
786  endif
787 
788  return sds
789 };
790 
815 string psh5_load_scan_preview(variable fileID, string scanpath, variable set_scale = defaultValue, string pref_datasets = defaultValue){
816  variable fileID
817  string scanpath
818  variable set_scale
819  string pref_datasets
820 
821  if (ParamIsDefault(set_scale))
822  set_scale = 1
823  endif
824  if (ParamIsDefault(pref_datasets) || (strlen(pref_datasets) == 0))
825  pref_datasets = kPreviewDatasets
826  endif
827 
828  dfref saveDF = GetDataFolderDFR()
829  dfref dataDF = saveDF
830 
831  string datasets = psh5_list_scan_datasets(fileID, scanpath, include_regions=1)
832  string datasetname = select_dataset(datasets, pref_datasets)
833  string datasetpath
834  datasetpath = scanpath + "/" + datasetname
835  datasetpath = ReplaceString("//", datasetpath, "/")
836 
837  STRUCT HDF5DataInfo di// Defined in HDF5 Browser.ipf.
838  InitHDF5DataInfo(di)
839  variable err = HDF5DatasetInfo(fileID, datasetpath, 0, di)
840  if (err != 0)
841  print "error accessing detector/data"
842  return ""
843  endif
844 
845  string dataname
846  if (di.ndims < 2)
847  HDF5LoadData /O /Q /Z fileID, datasetpath
848  dataname = StringFromList(0, S_waveNames)
849  wave /z data = $dataname
850  if (waveexists(data))
851  ps_set_dimlabels(data)
852  endif
853  else
854  variable dim2start = 0
855  variable dim2count = 1
856  variable dim3start = 0
857  variable dim3count = 1
858  if (di.ndims >= 3)
859  dim2start = floor(di.dims[2] / 2)
860  dim2count = 1
861  endif
862  if (di.ndims >= 4)
863  dim3start = floor(di.dims[3] / 2)
864  dim3count = 1
865  endif
866 
867  dataname = psh5_load_dataset_slab(fileID, scanpath, datasetname, dim2start, dim2count, dim3start, dim3count)
868  endif
869 
870  wave /z data = $dataname
871  if (waveexists(data))
872  if (set_scale)
873  setdatafolder dataDF
874  string positioners
875  string positioner
876  string positionerpath
877  positioners = psh5_load_scan_meta(fileID, scanpath)
878  wave /t /z ScanWritables
879  if (waveexists(ScanWritables) && (numpnts(ScanWritables) >= 1))
880  positioner = ScanWritables[0]
881  if (strlen(positioner) > 0)
882  positionerpath = scanpath + "/" + positioner
883  positionerpath = ReplaceString("//", positionerpath, "/")
884  HDF5LoadData /O /Q /Z fileID, positionerpath
885  endif
886  endif
887 
888  setdatafolder dataDF
889  newdatafolder /o/s attr
890  psh5_load_scan_attrs(fileID, scanpath, attr_sets=2)
891  setdatafolder dataDF
892  ps_scale_dataset(data)
893  endif
894  else
895  dataname = ""
896  endif
897 
898  return dataname
899 };
900 
928 string psh5_load_scan_section(variable fileID, string scanpath, variable dim, variable set_scale = defaultValue, string pref_datasets = defaultValue){
929  variable fileID
930  string scanpath
931  variable dim
932  variable set_scale
933  string pref_datasets
934 
935  // select first dimension (future argument)
936  // 0 = first dimension is x axis (energy of scienta image)
937  dim = 0
938 
939  if (ParamIsDefault(set_scale))
940  set_scale = 1
941  endif
942  if (ParamIsDefault(pref_datasets) || (strlen(pref_datasets) == 0))
943  pref_datasets = kPreviewDatasets
944  endif
945 
946  dfref saveDF = GetDataFolderDFR()
947  dfref dataDF = saveDF
948 
949  string datasets = psh5_list_scan_datasets(fileID, scanpath)
950  string datasetname = select_dataset(datasets, pref_datasets)
951  string datasetpath
952  datasetpath = scanpath + "/" + datasetname
953  datasetpath = ReplaceString("//", datasetpath, "/")
954  string dataname = StringFromList(ItemsInList(datasetpath, "/") - 1, datasetpath, "/")
955  string destname = dataname[0,29] + num2str(dim)
956 
957  STRUCT HDF5DataInfo di// Defined in HDF5 Browser.ipf.
958  InitHDF5DataInfo(di)
959  variable err = HDF5DatasetInfo(fileID, datasetpath, 0, di)
960  if (err != 0)
961  print "error accessing detector/data"
962  return ""
963  else if (di.ndims != 3)
964  print "error: rank of dataset != 3"
965  return ""
966  endif
967 
968  variable idx, idy, idz, idt
969  variable transpose = WhichListItem(dataname, kTransposedDatasets) >= 0
970  if (transpose)
971  idx = 1
972  idy = 0
973  else
974  idx = 0
975  idy = 1
976  endif
977  idz = 2
978  idt = 3
979 
980  variable nx, ny, nz
981  nx = di.dims[idx]
982  ny = di.dims[idy]
983  nz = di.dims[idz]
984 
985  HDF5MakeHyperslabWave("slab", max(di.ndims, 4))
986  wave slab
987  slab[][%Start] = 0
988  slab[][%Stride] = 1
989  slab[][%Count] = 1
990  slab[][%Block] = 1
991 
992  if (dim == 0)
993  slab[idy][%Start] = floor(ny / 2)
994  slab[idx][%Block] = nx
995  make /n=(nx,nz) /o $destname
996  else
997  slab[idx][%Start] = floor(nx / 2)
998  slab[idy][%Block] = ny
999  make /n=(ny,nz) /o $destname
1000  endif
1001  slab[idz][%Block] = nz
1002  wave data = $destname
1003  data = 0
1004 
1005  HDF5LoadData /O /Q /Z /SLAB=slab /N=slabdata fileID, datasetpath
1006  if (!v_flag)
1007  wave slabdata
1008  if (transpose)
1009  data += slabdata[0][p][q][0]
1010  else
1011  data += slabdata[p][0][q][0]
1012  endif
1013  endif
1014  killwaves /z slab, slabdata
1015 
1016  if (set_scale)
1017  make /n=(1,1,1) /free dummy
1018  ps_set_dimlabels2(dummy, dataname)
1019  setdimlabel 0, -1, $GetDimLabel(dummy, dim, -1), data
1020  setdimlabel 1, -1, $kScanDimLabel, data
1021 
1022  setdatafolder dataDF
1023  string positioners
1024  string positioner
1025  string positionerpath
1026  positioners = psh5_load_scan_meta(fileID, scanpath)
1027  wave /t /z ScanWritables
1028  if (waveexists(ScanWritables) && (numpnts(ScanWritables) >= 1))
1029  positioner = ScanWritables[0]
1030  if (strlen(positioner) > 0)
1031  positionerpath = scanpath + "/" + positioner
1032  positionerpath = ReplaceString("//", positionerpath, "/")
1033  HDF5LoadData /O /Q /Z fileID, positionerpath
1034  endif
1035  endif
1036 
1037  setdatafolder dataDF
1038  newdatafolder /o/s attr
1039  killwaves /a/z
1040  psh5_load_scan_attrs(fileID, scanpath, attr_sets=2)
1041  setdatafolder dataDF
1042  ps_scale_dataset(data)
1043  endif
1044 
1045  return destname
1046 };
1047 
1066 variable psh5_load_dataset_meta(variable fileID, string datapath, string datasetname, wave datawave){
1067  variable fileID
1068  string datapath
1069  string datasetname
1070  wave datawave
1071 
1072  dfref saveDF = GetDataFolderDFR()
1073  SetDataFolder NewFreeDataFolder()
1074 
1075  string datasetpath = datapath + "/" + datasetname
1076  datasetpath = ReplaceString("//", datasetpath, "/")
1077  string wnote
1078 
1079  HDF5LoadData /O /Q /Z /A="Writable Dimension" /N=WriteDim fileID, datasetpath
1080  if (!v_flag)
1081  wave WriteDim
1082  // scan dimension starts at 1
1083  sprintf wnote, "ScanDimension=%u", WriteDim[0]
1084  Note datawave, wnote
1085  endif
1086 
1087  HDF5LoadData /O /Q /Z /A="Writable Index" /N=WriteIndex fileID, datasetpath
1088  if (!v_flag)
1089  wave WriteIndex
1090  sprintf wnote, "WriteableIndex=%u", WriteIndex[0]
1091  Note datawave, wnote
1092  endif
1093 
1094  HDF5LoadData /O /Q /Z /A="Readable Index" /N=ReadIndex fileID, datasetpath
1095  if (!v_flag)
1096  wave ReadIndex
1097  sprintf wnote, "ReadableIndex=%u", ReadIndex[0]
1098  Note datawave, wnote
1099  endif
1100 
1101  setdatafolder saveDF
1102  return 0
1103 };
1104 
1123 string psh5_load_dataset_slabs(variable fileID, string datapath, string datasetname, variable progress = defaultValue){
1124  variable fileID
1125  string datapath
1126  string datasetname
1127  variable progress
1128 
1129  if (ParamIsDefault(progress))
1130  progress = 1
1131  endif
1132 
1133  variable result = 0
1134  string datasetpath
1135  string datawavename
1136  datasetpath = datapath + "/" + datasetname
1137  datasetpath = ReplaceString("//", datasetpath, "/")
1138  datawavename = StringFromList(ItemsInList(datasetpath, "/") - 1, datasetpath, "/")
1139 
1140  STRUCT HDF5DataInfo di// Defined in HDF5 Browser.ipf.
1141  InitHDF5DataInfo(di)
1142  variable err = HDF5DatasetInfo(fileID, datasetpath, 0, di)
1143  if (err != 0)
1144  print "error accessing detector/data"
1145  return ""
1146  endif
1147  if (di.ndims < 2)
1148  print "error: rank of dataset < 2"
1149  return ""
1150  else if (di.ndims < 3)
1151  progress = 0
1152  endif
1153 
1154  variable idx, idy, idz, idt, izt
1155  variable transpose = WhichListItem(datawavename, kTransposedDatasets) >= 0
1156  if (transpose)
1157  idx = 1
1158  idy = 0
1159  else
1160  idx = 0
1161  idy = 1
1162  endif
1163  idz = 2
1164  idt = 3
1165 
1166  variable nx, ny, nz, nt, nzt
1167  nx = di.dims[idx]
1168  ny = di.dims[idy]
1169  nz = di.dims[idz]
1170  nt = di.dims[idt]
1171  make /n=(nx,ny,nz,nt) /o $datawavename
1172  wave data = $datawavename
1173 
1174  nz = max(nz, 1)
1175  nt = max(nt, 1)
1176  nzt = nz * nt
1177  izt = 0
1178  if (progress)
1179  display_progress_panel("HDF5 Import", "Loading data...", nzt)
1180  endif
1181 
1182  // load data image by image
1183  HDF5MakeHyperslabWave("slab", max(di.ndims, 4))
1184  wave slab
1185  slab[][%Start] = 0
1186  slab[][%Stride] = 1
1187  slab[][%Count] = 1
1188  slab[][%Block] = 1
1189  slab[idx][%Block] = nx
1190  slab[idy][%Block] = ny
1191 
1192  variable iz, it
1193  for (iz = 0; iz < nz; iz += 1)
1194  for (it = 0; it < nt; it += 1)
1195  slab[idz][%Start] = iz
1196  slab[idt][%Start] = it
1197  HDF5LoadData /O /Q /Z /SLAB=slab /N=slabdata fileID, datasetpath
1198  wave slabdata// 2D, 3D, or 4D with singletons
1199  if (transpose)
1200  data[][][iz][it] = slabdata[q][p][0][0]
1201  else
1202  data[][][iz][it] = slabdata[p][q][0][0]
1203  endif
1204 
1205  // progress window
1206  izt += 1
1207  if (progress)
1208  if (update_progress_panel(izt))
1209  result = -4// user abort
1210  break
1211  endif
1212  endif
1213  endfor
1214  if (result < 0)
1215  break
1216  endif
1217  endfor
1218 
1219  if (progress)
1221  endif
1222 
1223  killwaves /z slab, slabdata
1224  if (!result)
1225  ps_set_dimlabels(data)
1226  return datawavename
1227  else
1228  killwaves /z data
1229  return ""
1230  endif
1231 };
1232 
1259 string psh5_load_dataset_slab(variable fileID, string datapath, string datasetname, variable dim2start, variable dim2count, variable dim3start, variable dim3count){
1260  variable fileID
1261  string datapath
1262  string datasetname
1263  variable dim2start
1264  variable dim2count
1265  variable dim3start
1266  variable dim3count
1267 
1268  string datasetpath
1269  string datawavename
1270  datasetpath = datapath + "/" + datasetname
1271  datasetpath = ReplaceString("//", datasetpath, "/")
1272  datawavename = StringFromList(ItemsInList(datasetpath, "/") - 1, datasetpath, "/")
1273 
1274  STRUCT HDF5DataInfo di
1275  InitHDF5DataInfo(di)
1276  variable err = HDF5DatasetInfo(fileID, datasetpath, 0, di)
1277  if (err != 0)
1278  print "error accessing detector/data"
1279  return ""
1280  endif
1281  if (di.ndims < 2)
1282  print "error: rank of dataset < 2"
1283  return ""
1284  endif
1285 
1286  variable idx, idy, idz, idt
1287  variable transpose = WhichListItem(datawavename, kTransposedDatasets) >= 0
1288  if (transpose)
1289  idx = 1
1290  idy = 0
1291  else
1292  idx = 0
1293  idy = 1
1294  endif
1295  idz = 2
1296  idt = 3
1297 
1298  variable nx, ny
1299  nx = di.dims[idx]
1300  ny = di.dims[idy]
1301  make /n=(nx,ny) /o $datawavename
1302  wave data = $datawavename
1303  data = 0
1304 
1305  HDF5MakeHyperslabWave("slab", max(di.ndims, 4))
1306  wave slab
1307  slab[][%Start] = 0
1308  slab[][%Stride] = 1
1309  slab[][%Count] = 1
1310  slab[][%Block] = 1
1311  slab[idx][%Block] = nx
1312  slab[idy][%Block] = ny
1313 
1314  variable iz, it
1315  variable navg = 0
1316  variable dim2end = dim2start + dim2count - 1
1317  variable dim3end = dim3start + dim3count - 1
1318  for (iz = dim2start; iz <= dim2end; iz += 1)
1319  for (it = dim3start; it <= dim3end; it += 1)
1320  slab[idz][%Start] = iz
1321  slab[idt][%Start] = it
1322  HDF5LoadData /O /Q /Z /SLAB=slab /N=slabdata fileID, datasetpath
1323  if (!v_flag)
1324  wave slabdata
1325  if (transpose)
1326  data += slabdata[q][p][0][0]
1327  else
1328  data += slabdata[p][q][0][0]
1329  endif
1330  navg += 1
1331  endif
1332  endfor
1333  endfor
1334  if (navg)
1335  data /= navg
1336  endif
1337 
1338  killwaves /z slab, slabdata
1339  ps_set_dimlabels(data)
1340  return datawavename
1341 };
1342 
1358 variable ps_set_dimlabels(wave data){
1359  wave data
1360 
1361  ps_set_dimlabels2(data, NameOfWave(data))
1362 };
1363 
1377 variable ps_set_dimlabels2(wave data, string name){
1378  wave data
1379  string name
1380 
1381  variable dummy
1382  try
1383  // intrinsic dimensions
1384  strswitch(name)
1385  case "ScientaImage":
1386  setdimlabel 0, -1, $kEnergyDimLabel, data
1387  setdimlabel 1, -1, $kAngleDimLabel, data
1388  if (WaveDims(data) >= 3)
1389  setdimlabel 2, -1, $kScanDimLabel, data
1390  endif
1391  AbortOnRTE
1392  break
1393  case "ImageAngleDistribution":
1394  case "ScientaAngleDistribution":
1395  if (WaveDims(data) >= 2)
1396  setdimlabel 0, -1, $kScanDimLabel, data
1397  setdimlabel 1, -1, $kAngleDimLabel, data
1398  else
1399  setdimlabel 0, -1, $kAngleDimLabel, data
1400  endif
1401  AbortOnRTE
1402  break
1403  case "ScientaSpectrum":
1404  case "ImageEnergyDistribution":
1405  case "ScientaEnergyDistribution":
1406  if (WaveDims(data) >= 2)
1407  setdimlabel 0, -1, $kScanDimLabel, data
1408  setdimlabel 1, -1, $kEnergyDimLabel, data
1409  else
1410  setdimlabel 0, -1, $kEnergyDimLabel, data
1411  endif
1412  AbortOnRTE
1413  break
1414  default:
1415  if (WaveDims(data) == 1)
1416  setdimlabel 0, -1, $kScanDimLabel, data
1417  AbortOnRTE
1418  else
1419  return 1
1420  endif
1421  endswitch
1422  catch
1423  dummy = GetRTError(1)
1424  return 2
1425  endtry
1426  return 0
1427 };
1428 
1434 static dfr find_scan_folder(dfref dataDF){
1435  dfref dataDF
1436 
1437  dfref attrDF = dataDF:attr
1438  if (!DataFolderRefStatus(attrDF))
1439  string df = GetDataFolder(1, dataDF) + ":"
1440  dfref scanDF = $df
1441  else
1442  dfref scanDF = dataDF
1443  endif
1444  return scanDF
1445 };
1446 
1451 static dfr find_attr_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  dfref attrDF = scanDF:attr
1459  endif
1460  return attrDF
1461 };
1462 
1480  dfref scanDF = GetDataFolderDFR()
1481  dfref attrDF = find_attr_folder(scanDF)
1482 
1483  make /n=3 /free lo, hi
1484  make /n=3 /t /free ax, un
1485  wave /t /z /SDFR=scanDF ScanReadables
1486  if (WaveExists(ScanReadables))
1487  variable isr
1488  variable nsr = numpnts(ScanReadables)
1489  string ssr
1490  string sdf
1491  for (isr = 0; isr < nsr; isr += 1)
1492  setdatafolder scanDF
1493  ssr = ScanReadables[isr]
1494  if (ItemsInList(ssr, "/") >= 2)
1495  sdf = StringFromList(0, ssr, "/")
1496  ssr = RemoveListItem(0, ssr, "/")
1497  setdatafolder $sdf
1498  endif
1499  wave /z wsr=$ssr
1500  if (WaveExists(wsr))
1501  ps_detect_scale(ax, lo, hi, un)
1502  ps_scale_dataset_2(wsr, ax, lo, hi, un)
1503  endif
1504  endfor
1505  endif
1506  setdatafolder scanDF
1507 };
1508 
1525 variable ps_scale_dataset(wave data){
1526  wave data
1527 
1528  dfref saveDF = GetDataFolderDFR()
1529  dfref dataDF = GetWavesDataFolderDFR(data)
1530 
1531  setdatafolder dataDF
1532  make /n=3 /free lo, hi
1533  make /n=3 /t /free ax, un
1534  ps_detect_scale(ax, lo, hi, un)
1535  ps_scale_dataset_2(data, ax, lo, hi, un)
1536  setdatafolder saveDF
1537 };
1538 
1539 static wave find_scale_wave(string name, dfref dataDF, dfref scanDF, dfref attrDF){
1540  string name
1541  dfref dataDF
1542  dfref scanDF
1543  dfref attrDF
1544 
1545  wave /SDFR=dataDF /Z w = $name
1546  if (!WaveExists(w))
1547  wave /SDFR=scanDF /Z w = $name
1548  if (!WaveExists(w))
1549  wave /SDFR=attrDF /Z w = $name
1550  endif
1551  endif
1552  return w
1553 };
1554 
1596 variable ps_detect_scale(wave ax, wave lo, wave hi, wave un){
1597  wave /t ax
1598  wave lo
1599  wave hi
1600  wave /t un
1601 
1602  dfref dataDF = GetDataFolderDFR()
1603  dfref scanDF = find_scan_folder(dataDF)
1604  dfref attrDF = find_attr_folder(dataDF)
1605 
1606  redimension /n=4 lo, hi, un, ax
1607  setdimlabel 0, 0, $kEnergyDimLabel, lo, hi, un, ax
1608  setdimlabel 0, 1, $kAngleDimLabel, lo, hi, un, ax
1609  setdimlabel 0, 2, $kScanDimLabel, lo, hi, un, ax
1610  setdimlabel 0, 3, $kDataDimLabel, lo, hi, un, ax
1611 
1612  // default values
1613  lo[%$kEnergyDimLabel] = 0
1614  hi[%$kEnergyDimLabel] = 1
1615  un[%$kEnergyDimLabel] = "eV"
1616  ax[%$kEnergyDimLabel] = "Ekin"
1617 
1618  lo[%$kAngleDimLabel] = -1
1619  hi[%$kAngleDimLabel] = 1
1620  un[%$kAngleDimLabel] = "arb."
1621  un[%$kAngleDimLabel] = "slice"
1622 
1623  lo[%$kScanDimLabel] = 0
1624  hi[%$kScanDimLabel] = 1
1625  un[%$kScanDimLabel] = "arb."
1626  ax[%$kScanDimLabel] = "scan"
1627 
1628  lo[%$kDataDimLabel] = 0
1629  hi[%$kDataDimLabel] = 0
1630  un[%$kDataDimLabel] = "arb."
1631  ax[%$kDataDimLabel] = "value"
1632 
1633  wave /SDFR=attrDF /T /Z LensMode
1634  wave /Z ChannelBegin = find_scale_wave("ScientaChannelBegin", dataDF, scanDF, attrDF)
1635  wave /Z ChannelEnd = find_scale_wave("ScientaChannelEnd", dataDF, scanDF, attrDF)
1636  wave /Z SliceBegin = find_scale_wave("ScientaSliceBegin", dataDF, scanDF, attrDF)
1637  wave /Z SliceEnd = find_scale_wave("ScientaSliceEnd", dataDF, scanDF, attrDF)
1638 
1639  // lens mode can give more detail
1640  if (waveexists(LensMode) && (numpnts(LensMode) >= 1))
1641  strswitch(LensMode[0])
1642  case "Angular45":
1643  lo[%$kAngleDimLabel] = -45/2
1644  hi[%$kAngleDimLabel] = +45/2
1645  un[%$kAngleDimLabel] = ""
1646  ax[%$kAngleDimLabel] = "angle"
1647  break
1648  case "Angular60":
1649  lo[%$kAngleDimLabel] = -60/2
1650  hi[%$kAngleDimLabel] = +60/2
1651  un[%$kAngleDimLabel] = ""
1652  ax[%$kAngleDimLabel] = "angle"
1653  break
1654  case "Transmission":
1655  un[%$kAngleDimLabel] = "arb."
1656  ax[%$kAngleDimLabel] = "offset"
1657  break
1658  endswitch
1659  endif
1660 
1661  // best option if scales are explicit in separate waves
1662  if (waveexists(ChannelBegin) && waveexists(ChannelEnd) && (numpnts(ChannelBegin) >= 1) && (numpnts(ChannelEnd) >= 1))
1663  lo[%$kEnergyDimLabel] = ChannelBegin[0]
1664  hi[%$kEnergyDimLabel] = ChannelEnd[0]
1665  endif
1666  if (waveexists(SliceBegin) && waveexists(SliceEnd) && (numpnts(SliceBegin) >= 1) && (numpnts(SliceEnd) >= 1))
1667  lo[%$kAngleDimLabel] = SliceBegin[0]
1668  hi[%$kAngleDimLabel] = SliceEnd[0]
1669  endif
1670 
1671  wave /z /t /SDFR=scanDF ScanWritables
1672  if (WaveExists(ScanWritables))
1673  wave /z /SDFR=scanDF scanner = $ScanWritables[0]
1674  if (!WaveExists(scanner))
1675  wave /z /SDFR=attrDF scanner = $ScanWritables[0]
1676  endif
1677  if (WaveExists(scanner) && (numpnts(scanner) >= 1))
1678  lo[%$kScanDimLabel] = scanner[0]
1679  hi[%$kScanDimLabel] = scanner[numpnts(scanner)-1]
1680  ax[%$kScanDimLabel] = NameOfWave(scanner)
1681  strswitch(NameOfWave(scanner))
1682  case "Eph":
1683  ax[%$kScanDimLabel] = "photon energy"
1684  un[%$kScanDimLabel] = "eV"
1685  break
1686  case "ManipulatorX":
1687  case "ManipulatorY":
1688  case "ManipulatorZ":
1689  case "FocusYTrans":
1690  case "FocusZTrans":
1691  case "RefocusYTrans":
1692  case "RefocusZTrans":
1693  case "ExitSlitY":
1694  un[%$kScanDimLabel] = "mm"
1695  break
1696  case "ExitSlit":
1697  un[%$kScanDimLabel] = "m"
1698  break
1699  case "ManipulatorTheta":
1700  case "ManipulatorTilt":
1701  case "ManipulatorPhi":
1702  un[%$kScanDimLabel] = ""
1703  break
1704  case "FocusXRot":
1705  case "FocusYRot":
1706  case "FocusZRot":
1707  case "RefocusXRot":
1708  case "RefocusYRot":
1709  case "RefocusZRot":
1710  un[%$kScanDimLabel] = "mrad"
1711  break
1712  endswitch
1713  endif
1714  endif
1715 };
1716 
1750 variable ps_scale_dataset_2(wave data, wave ax, wave lo, wave hi, wave un){
1751  wave data
1752  wave /t ax
1753  wave lo
1754  wave hi
1755  wave /t un
1756 
1757  string sdim
1758  sdim = GetDimLabel(data, 0, -1)
1759  if (strlen(sdim))
1760  setscale /i x lo[%$sdim], hi[%$sdim], un[%$sdim], data
1761  Note data, "AxisLabelX=" + ax[%$sdim]
1762  endif
1763 
1764  sdim = GetDimLabel(data, 1, -1)
1765  if (strlen(sdim))
1766  setscale /i y lo[%$sdim], hi[%$sdim], un[%$sdim], data
1767  Note data, "AxisLabelY=" + ax[%$sdim]
1768  endif
1769 
1770  sdim = GetDimLabel(data, 2, -1)
1771  if (strlen(sdim))
1772  setscale /i z lo[%$sdim], hi[%$sdim], un[%$sdim], data
1773  Note data, "AxisLabelZ=" + ax[%$sdim]
1774  endif
1775 
1776  string data_unit = un[%$kDataDimLabel]
1777  string data_label = ax[%$kDataDimLabel]
1778  if (cmpstr(data_unit, "arb.") == 0)
1779  strswitch(NameOfWave(data))
1780  case "ScientaImage":
1781  case "ImageAngleDistribution":
1782  case "ScientaAngleDistribution":
1783  case "ScientaSpectrum":
1784  case "ImageEnergyDistribution":
1785  case "ScientaEnergyDistribution":
1786  data *= kDetectorSensitivity
1787  data_unit = "counts"
1788  data_label = "intensity"
1789  break
1790  case "SampleCurrent":
1791  case "RefCurrent":
1792  case "AuxCurrent":
1793  data_unit = "A"
1794  data_label = "current"
1795  break
1796  case "MachineCurrent":
1797  data_unit = "mA"
1798  data_label = "current"
1799  break
1800  endswitch
1801  endif
1802  setscale d 0, 0, data_unit, data
1803  Note data, "AxisLabelD=" + data_label
1804  Note data, "Dataset=" + NameOfWave(data)
1805 };
1806 
1846 string psh5_load_reduced(string ANickName, string APathName, string AFileName, funcref reduction_func, string reduction_param, variable progress = defaultValue){
1847  string ANickName
1848  string APathName
1849  string AFileName
1850  funcref adh5_default_reduction reduction_func
1851  string reduction_param
1852  variable progress
1853 
1854  if (ParamIsDefault(progress))
1855  progress = 1
1856  endif
1857 
1858  dfref saveDF = GetDataFolderDFR()
1859 
1860  // performance monitoring
1861  variable timerRefNum
1862  variable /g psh5_perf_secs
1863  timerRefNum = startMSTimer
1864 
1865  variable fileID = psh5_open_file(ANickName, APathName, AFileName)
1866  string wavenames = ""
1867  if (fileID)
1868  dfref fileDF = GetDataFolderDFR()
1869  svar s_filepath
1870  svar s_scanpaths
1871  AFileName = s_filepath
1872  print "loading " + s_filepath + "\r"
1873 
1874  variable ig = 0
1875  variable ng = ItemsInList(s_scanpaths)
1876  string scanpath
1877  string folder
1878  string positioners
1879  string positioner
1880  string positionerpath
1881 
1882  scanpath = StringFromList(ig, s_scanpaths)
1883  folder = ReplaceString("/", scanpath, "")
1884  folder = ReplaceString(" ", folder, "")
1885  folder = CleanupName(folder, 0)
1886  setdatafolder fileDF
1887  newdatafolder /s /o $folder
1888  dfref dataDF = GetDataFolderDFR()
1889  positioners = psh5_load_scan_meta(fileID, scanpath)
1890  newdatafolder /s /o attr
1891  killwaves /a/z
1892  psh5_load_scan_attrs(fileID, scanpath)
1893  setdatafolder dataDF
1894  wave /t /z ScanWritables
1895  if (waveexists(ScanWritables) && (numpnts(ScanWritables) >= 1))
1896  positioner = ScanWritables[0]
1897  if (strlen(positioner) > 0)
1898  positionerpath = scanpath + "/" + positioner
1899  positionerpath = ReplaceString("//", positionerpath, "/")
1900  HDF5LoadData /O /Q /Z fileID, positionerpath
1901  endif
1902  endif
1903 
1904  setdatafolder dataDF
1905  string datasets = psh5_list_scan_datasets(fileID, scanpath, include_regions=1)
1906  string dataset = select_dataset(datasets, "ScientaImage")
1907  wavenames = psh5_load_dataset_reduced(fileID, scanpath, dataset, reduction_func, reduction_param, progress=progress)
1908 
1909  psh5_close_file(fileID)
1910  endif
1911 
1912  if (timerRefNum >= 0)
1913  psh5_perf_secs = stopMSTimer(timerRefNum) / 1e6
1914  endif
1915 
1916  setdatafolder saveDF
1917  return wavenames
1918 };
1919 
1920 
1970 string psh5_load_dataset_reduced(variable fileID, string scanpath, string datasetname, funcref reduction_func, string reduction_param, variable progress = defaultValue, variable nthreads = defaultValue){
1971  variable fileID
1972  string scanpath
1973  string datasetname
1974  funcref adh5_default_reduction reduction_func
1975  string reduction_param
1976  variable progress
1977  variable nthreads
1978 
1979  if (ParamIsDefault(progress))
1980  progress = 1
1981  endif
1982  if (ParamIsDefault(nthreads))
1983  nthreads = -1
1984  endif
1985 
1986  dfref base_df = GetDataFolderDFR()
1987  variable result = 0
1988  string datasetpath
1989  string datawavename
1990  string wavenames = ""
1991 
1992  datasetpath = scanpath + "/" + datasetname
1993  datasetpath = ReplaceString("//", datasetpath, "/")
1994  datawavename = StringFromList(ItemsInList(datasetpath, "/") - 1, datasetpath, "/")
1995 
1996  string regionname
1997  string regionpath
1998  if (ItemsInList(datasetname, "/") >= 2)
1999  regionname = StringFromList(0, datasetname, "/")
2000  regionpath = ReplaceString("//", scanpath + "/" + regionname, "/")
2001  datasetname = RemoveListItem(0, datasetname, "/")
2002  NewDataFolder /o/s $regionname
2003  else
2004  regionname = ""
2005  regionpath = scanpath
2006  endif
2007 
2008  STRUCT HDF5DataInfo di// Defined in HDF5 Browser.ipf.
2009  InitHDF5DataInfo(di)
2010  variable err = HDF5DatasetInfo(fileID, datasetpath, 0, di)
2011  if (err != 0)
2012  print "error accessing detector/data"
2013  result = -1
2014  return wavenames
2015  endif
2016  if (di.ndims < 2)
2017  print "error: rank of dataset < 2"
2018  result = -2
2019  return wavenames
2020  else if (di.ndims < 3)
2021  progress = 0
2022  endif
2023 
2024  variable idx, idy, idz, idt
2025  variable transpose = WhichListItem(datawavename, kTransposedDatasets) >= 0
2026  if (transpose)
2027  idx = 1
2028  idy = 0
2029  else
2030  idx = 0
2031  idy = 1
2032  endif
2033  idz = 2
2034  idt = 3
2035 
2036  variable nx, ny, nz, nt, nzt
2037  nx = di.dims[idx]
2038  ny = di.dims[idy]
2039  nz = di.dims[idz]
2040  nt = di.dims[idt]
2041  // adjust singleton dimensions
2042  nz = max(nz, 1)
2043  nt = max(nt, 1)
2044  nzt = nz * nt
2045 
2046  // load data image by image
2047  HDF5MakeHyperslabWave("slab", max(di.ndims, 4))
2048  wave slab
2049  slab[][%Start] = 0
2050  slab[][%Stride] = 1
2051  slab[][%Count] = 1
2052  slab[][%Block] = 1
2053  slab[idx][%Block] = nx
2054  slab[idy][%Block] = ny
2055 
2056  // set up multi threading
2057  if (nthreads < 0)
2058  nthreads = ThreadProcessorCount
2059  endif
2060  if (nthreads > 0)
2061  variable threadGroupID = ThreadGroupCreate(nthreads)
2062  variable ithread
2063  for (ithread = 0; ithread < nthreads; ithread += 1)
2064  ThreadStart threadGroupID, ithread, reduce_slab_worker(reduction_func)
2065  endfor
2066  else
2067  make /n=(nzt) /df /free processing_folders
2068  endif
2069 
2070  if (progress)
2071  display_progress_panel("HDF5 Import", "Loading data (step 1 of 2)...", nzt)
2072  endif
2073 
2074  // create a template wave with the correct scales and labels
2075  make /n=(nx,ny) /d /o $datawavename
2076  wave template = $datawavename
2077  ps_set_dimlabels2(template, datawavename)
2078  ps_scale_dataset(template)
2079 
2080  variable iz, it, izt
2081  string dfname
2082  izt = 0
2083  for (iz = 0; iz < nz; iz += 1)
2084  for (it = 0; it < nt; it += 1)
2085  // load hyperslab
2086  slab[idz][%Start] = iz
2087  slab[idt][%Start] = it
2088  dfname = "processing_" + num2str(izt)
2089  newdatafolder /s $dfname
2090  HDF5LoadData /O /Q /Z /SLAB=slab /N=slabdata fileID, datasetpath
2091 
2092  // send to processing queue
2093  duplicate template, image
2094  variable /g r_index = iz
2095  variable /g s_index = it
2096  string /g func_param = reduction_param
2097 
2098  if (nthreads > 0)
2099  WaveClear image
2100  ThreadGroupPutDF threadGroupID, :
2101  else
2102  processing_folders[izt] = GetDataFolderDFR()
2103  make /n=1/d profile1, profile2
2104  wave slabdata
2105  variable /g func_result
2106  func_result = reduce_slab_image(slabdata, image, profile1, profile2, reduction_func, func_param)
2107  WaveClear slabdata, image, profile1, profile2
2108  setdatafolder ::
2109  endif
2110 
2111  izt += 1
2112  // progress window
2113  if (progress)
2114  if (update_progress_panel(izt))
2115  print "user abort"
2116  result = -4
2117  break
2118  endif
2119  endif
2120  endfor
2121  endfor
2122 
2123  killwaves /z slab, slabdata, template
2124  if (progress)
2125  update_progress_panel(0, message="Processing data (step 2 of 2)...")
2126  endif
2127 
2128  dfref dfr
2129  for (izt = 0; (izt < nzt) && (result == 0); izt += 1)
2130  if (nthreads > 0)
2131  do
2132  if (progress)
2133  if (update_progress_panel(izt))
2134  print "user abort"
2135  result = -4
2136  break
2137  endif
2138  endif
2139  dfr = ThreadGroupGetDFR(threadGroupID, 1000)
2140  if (DatafolderRefStatus(dfr) != 0)
2141  break
2142  endif
2143  while (1)
2144  else
2145  if (progress)
2146  if (update_progress_panel(izt))
2147  print "user abort"
2148  result = -4
2149  break
2150  endif
2151  endif
2152  dfr = processing_folders[izt]
2153  endif
2154 
2155  if (result != 0)
2156  break
2157  endif
2158 
2159  nvar rr = dfr:r_index
2160  nvar ss = dfr:s_index
2161  nvar func_result = dfr:func_result
2162  wave profile1 = dfr:profile1
2163  wave profile2 = dfr:profile2
2164 
2165  if (func_result == 0)
2166  if (izt == 0)
2167  make /n=(dimsize(profile1, 0), nz, nt) /d /o ReducedData1
2168  make /n=(dimsize(profile2, 0), nz, nt) /d /o ReducedData2
2169  setdimlabel 0, -1, $getdimlabel(profile1, 0, -1), ReducedData1
2170  setdimlabel 0, -1, $getdimlabel(profile2, 0, -1), ReducedData2
2171  setdimlabel 1, -1, $kScanDimLabel, ReducedData1
2172  setdimlabel 1, -1, $kScanDimLabel, ReducedData2
2173  ps_scale_dataset(ReducedData1)
2174  ps_scale_dataset(ReducedData2)
2175  setscale /p x dimoffset(profile1, 0), dimdelta(profile1, 0), waveunits(profile1, 0), ReducedData1
2176  setscale /p x dimoffset(profile2, 0), dimdelta(profile2, 0), waveunits(profile2, 0), ReducedData2
2177  setscale d 0, 0, waveunits(profile1, -1), ReducedData1
2178  setscale d 0, 0, waveunits(profile2, -1), ReducedData2
2179  endif
2180  ReducedData1[][rr][ss] = profile1[p]
2181  ReducedData2[][rr][ss] = profile2[p]
2182  else
2183  print "error during data reduction."
2184  result = -3
2185  break
2186  endif
2187  endfor
2188 
2189  if (nthreads > 0)
2190  variable tstatus = ThreadGroupRelease(threadGroupID)
2191  if (tstatus == -2)
2192  print "error: thread did not terminate properly."
2193  result = -5
2194  endif
2195  else
2196  for (izt = 0; izt < nzt; izt += 1)
2197  KillDataFolder /Z processing_folders[izt]
2198  endfor
2199  endif
2200 
2201  if (result == 0)
2202  if (nz == 1)
2203  redimension /n=(-1, 0, 0) ReducedData1
2204  redimension /n=(-1, 0, 0) ReducedData2
2205  else if (nt == 1)
2206  redimension /n=(-1, nz, 0) ReducedData1
2207  redimension /n=(-1, nz, 0) ReducedData2
2208  endif
2209  wavenames = "ReducedData1;ReducedData2;"
2210  endif
2211  if (progress)
2213  endif
2214 
2215  setdatafolder base_df
2216  return wavenames
2217 };
2218 
2219 threadsafe static variable reduce_slab_worker(funcref reduction_func){
2220  funcref adh5_default_reduction reduction_func
2221  do
2222  // wait for job from main thread
2223  do
2224  dfref dfr = ThreadGroupGetDFR(0, 1000)
2225  if (DataFolderRefStatus(dfr) == 0)
2226  if (GetRTError(2))
2227  return 0// no more jobs
2228  endif
2229  else
2230  break
2231  endif
2232  while (1)
2233 
2234  // get input data
2235  wave slabdata = dfr:slabdata
2236  wave image = dfr:image
2237  svar func_param = dfr:func_param
2238  nvar rr = dfr:r_index
2239  nvar ss = dfr:s_index
2240 
2241  // do the work
2242  newdatafolder /s outDF
2243  make /n=1/d profile1, profile2
2244  variable /g r_index = rr
2245  variable /g s_index = ss
2246  variable /g func_result
2247  func_result = reduce_slab_image(slabdata, image, profile1, profile2, reduction_func, func_param)
2248 
2249  // send output to queue and clean up
2250  WaveClear slabdata, image, profile1, profile2
2251  ThreadGroupPutDF 0, :
2252  KillDataFolder dfr
2253  while (1)
2254 
2255  return 0
2256 };
2257 
2258 threadsafe static variable reduce_slab_image(wave slabdata, wave image, wave profile1, wave profile2, funcref reduction_func, string reduction_param){
2259  wave slabdata
2260  wave image
2261  wave profile1
2262  wave profile2
2263  funcref adh5_default_reduction reduction_func
2264  string reduction_param
2265 
2266  // the multiplication by detector sensitivity assumes that we are loading a ScientaImage.
2267  image = slabdata[q][p][0][0] * kDetectorSensitivity
2268 
2269  return reduction_func(image, profile1, profile2, reduction_param)
2270 };
2271 
2286 string psh5_load_info(string APathName, string AFileName){
2287  string APathName
2288  string AFileName
2289 
2290  dfref saveDF = GetDataFolderDFR()
2291  dfref fileDF = NewFreeDataFolder()
2292  setdatafolder fileDF
2293 
2294  variable fileID
2295  string filepath
2296  string scanpaths
2297  variable nscans
2298  variable iscan
2299  string scanpath
2300  string info = ""
2301 
2302  HDF5OpenFile /P=$APathName /R fileID as AFileName
2303  if (v_flag == 0)
2304  filepath = s_path + s_filename
2305  scanpaths = psh5_list_scans(fileID)
2306  nscans = ItemsInList(scanpaths)
2307  for (iscan = 0; iscan < nscans; iscan += 1)
2308  scanpath = StringFromList(iscan, scanpaths)
2309  info = info + scanpath + "\r"
2310  info = info + psh5_load_scan_info(fileID, scanpath)
2311  endfor
2312  HDF5CloseFile fileID
2313  endif
2314 
2315  setdatafolder saveDF
2316  return info
2317 };
2318 
2333 string psh5_load_scan_info(variable fileID, string scanpath){
2334  variable fileID
2335  string scanpath
2336 
2337  string info = ""
2338  string positions = ""
2339  string positioners = ""
2340  string readables = ""
2341  string detectors = ""
2342  string regions = ""
2343 
2344  psh5_load_scan_meta(fileID, scanpath)
2345 
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 
2361  variable i, m, n
2362  string s
2363  if (WaveExists(ScanReadables) && (numpnts(ScanReadables) >= 1))
2364  readables = twave2list(ScanReadables, ",")
2365  n = ItemsInList(readables, ",")
2366  for (i = 0; i < n; i += 1)
2367  s = StringFromList(i, readables, ",")
2368  m = ItemsInList(s, "/")
2369  if (m > 1)
2370  s = StringFromList(m - 1, s, "/")
2371  endif
2372  if (WhichListItem(s, detectors, ",") < 0)
2373  detectors = AddListItem(s, detectors, ",", inf)
2374  endif
2375  endfor
2376  detectors = "detectors = " + detectors
2377  info = AddListItem(detectors, info, "\r", inf)
2378  endif
2379 
2380  regions = psh5_list_scan_regions(fileID, scanpath)
2381  if (strlen(regions) > 0)
2382  regions = "regions = " + regions
2383  info = AddListItem(regions, info, "\r", inf)
2384  endif
2385 
2386  return info
2387 };
2388 
2392 static string twave2list(wave wt, string sep){
2393  wave /t wt
2394  string sep
2395 
2396  string list = ""
2397  variable n = numpnts(wt)
2398  variable i
2399  for (i = 0; i < n; i += 1)
2400  list = AddListItem(wt[i], list, sep, inf)
2401  endfor
2402 
2403  return list
2404 };
2405 
2409 static string wave2list(wave w, string format, string sep){
2410  wave w
2411  string format
2412  string sep
2413 
2414  string list = ""
2415  variable n = numpnts(w)
2416  variable i
2417  string s
2418  for (i = 0; i < n; i += 1)
2419  sprintf s, format, w[i]
2420  list = AddListItem(s, list, sep, inf)
2421  endfor
2422 
2423  return list
2424 };
2425 
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
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.
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...
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.
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.
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.