PEARL Procedures rev-distro-2.1.1-1-gf419e92-dirty Igor procedures for the analysis of PEARL data

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