source: sans/Dev/branches/nxcansas_writer/NCNR_User_Procedures/Common/NIST_NXcanSAS_v709.ipf @ 1193

Last change on this file since 1193 was 1193, checked in by krzywon, 3 years ago

Load 2D NXcanSAS data correctly.

File size: 15.9 KB
Line 
1#pragma rtGlobals=3             // Use modern global access method.
2#pragma version=5.0
3#pragma IgorVersion=6.1
4
5#include <HDF5 Browser>
6
7//************************
8// Vers 1.15 20171003
9//
10//************************
11
12
13///////////////////////////////////////////////////////////////////////////
14//
15// Basic file open/create and file initialization routines
16
17// Generic open or create file
18Function NXcanSAS_OpenOrCreate(dialog,fullpath,base)
19        Variable dialog
20        String fullpath,base
21        Variable fileID
22        if(dialog || stringmatch(fullpath, ""))
23                fileID = NxCansas_DoSaveFileDialog(base)
24        else
25                fileID = NxCansas_CreateFile(fullpath,base)
26        Endif
27        if(!fileID)
28                abort "Unable to create file at " + fullpath + "."
29        EndIf
30        return fileID
31End
32
33// Select/create file through prompt
34Function NxCansas_DoSaveFileDialog(base)
35        String base
36        Variable refNum, fileID
37        String message = "Save a file"
38        String outputPath
39        String fileFilters = "Data Files (*.h5):.h5;"
40        fileFilters += "All Files:.*;"
41        Open /D /F=fileFilters /M=message refNum
42        outputPath = S_fileName
43        fileID = NxCansas_CreateFile(outputPath,base)
44        return fileID
45End
46
47// Create file with a known path
48Function NxCansas_CreateFile(fullpath, base)
49        String fullpath,base
50        Variable fileID
51        Make/T/O/N=1 $("root:NXfile_name") = fullpath
52        fullpath = ReplaceString(":\\", fullpath, ":")
53        fullpath = ReplaceString("\\", fullpath, ":")
54        HDF5CreateFile /O/Z fileID as fullpath
55        NXCansas_InitializeFile(fileID, base)
56        return fileID
57End
58
59// Open\ file with a known path
60Function NxCansas_OpenFile(fullpath)
61        String fullpath
62        String fileName
63        Variable fileID
64        fileName = ParseFilePath(3,fullpath,":",0,0)
65        Make/T/O/N=1 $("root:NXfile_name") = fileName
66        fullpath = ReplaceString(":\\", fullpath, ":")
67        fullpath = ReplaceString("\\", fullpath, ":")
68        HDF5OpenFile /Z fileID as fullpath
69        return fileID
70End
71
72// Select/create file through prompt
73Function NxCansas_DoOpenFileDialog()
74        Variable refNum,fileID
75        String message = "Select a file"
76        String inputPath,fileName
77        String fileFilters = "Data Files (*.h5):.h5;"
78        STRUCT HDF5BrowserData bd
79        fileFilters += "All Files:.*;"
80        Open /D /F=fileFilters /M=message refNum as fileName
81        inputPath = S_fileName
82        fileID = NxCansas_OpenFile(inputPath)
83        return fileID
84End
85
86// Initialize the file to a base state
87Function NxCansas_InitializeFile(fileID, base)
88        Variable fileID
89        String base
90        String parent,nxParent
91        Variable sasentry = NumVarOrDefault("root:Packages:NIST:gSASEntryNumber", 1)
92        String location = base + parent
93        NewDataFolder/O/S $(location)
94        Make/O/T/N=1 $(location + ":vals") = {""}
95        Make/O/T/N=3 $(location + ":attr") = {"NX_class", "canSAS_class", "version"}
96        Make/O/T/N=3 $(location + ":attrVals") = {"NXentry", "SASentry", "1.0"}
97        CreateStrNxCansas(fileID,nxParent,"","",$(location + ":vals"),$(location + ":attr"),$(location + ":attrVals"))
98        Make/O/T/N=1 $(location + ":entryAttr") = {""}
99        Make/O/T/N=1 $(location + ":entryAttrVals") = {""}
100        CreateStrNxCansas(fileID,nxParent,"","definition",{"NXcanSAS"},$(location + ":entryAttr"),$(location + ":entryAttrVals"))
101End
102
103//
104///////////////////////////////////////////////////////////////////////////
105
106///////////////////////////////////////////////////////////////////////////
107// Functions used to save data to file
108
109// Intermediate error handler for saving variable waves - this function should be called instead of saveNxCansas
110Function CreateVarNxCansas(fileID,parent,group,var,valueWave,attr,attrValues)
111        Variable fileID
112        String parent,group,var
113        Wave valueWave
114        Wave /T attr,attrValues
115        Variable err
116        err = saveNxCansasVars(fileID,parent,group,var,valueWave,attr,attrValues)
117        if(err)
118                Print "NxCansas write err = ",err
119        endif
120End
121// Intermediate error handler for saving string waves - this function should be called instead of saveNxCansas
122Function CreateStrNxCansas(fileID,parent,group,var,valueWave,attr,attrValues)
123        Variable fileID
124        String parent,group,var
125        Wave /T valueWave,attr,attrValues
126        Variable err
127        err = saveNxCansasStrs(fileID,parent,group,var,valueWave,attr,attrValues)
128        if(err)
129                Print "NxCansas write err = ",err
130        endif
131End
132
133Function NxCansas_writeAttributes(fileID,path,attrNames,attrVals)
134        Variable fileID
135        String path
136        Wave/T attrNames, attrVals
137        int numAttrs,i
138        numAttrs = numpnts(attrNames)
139        Duplicate/O/T attrNames, names
140        Duplicate/O/T attrVals, vals
141       
142        for(i=0; i < numAttrs; i += 1)
143                String name_i = names[i]
144                String vals_i = vals[i]
145                Make/O/T/N=1 vals_i_wave
146                vals_i_wave[0] = vals_i
147                if(!stringmatch(name_i,""))
148                        HDF5SaveData /A=name_i vals_i_wave, fileID, path
149                endif
150        endfor
151       
152End
153
154Function NxCansas_CreateGroup(fileID,parent)
155        Variable fileID
156        String parent
157        Variable groupID
158        try     
159                if(!fileID)
160                        abort "HDF5 file does not exist"
161                endif
162               
163                // Create the group if it doesn't already exist
164                HDF5CreateGroup /Z fileID, parent, groupID
165                       
166        catch
167                // DO something if error is thrown
168                Print "NxCansas write err in saveNxCansas = ",V_AbortCode
169        endtry
170        return groupID
171End
172
173// Write in a single NxCansas element (from the STRUCTURE)
174// This method should only be called by CreateVarNxCansas
175Function saveNxCansasVars(fileID,parent,group,var,valueWave,attr,attrValues)
176
177        Variable fileID
178        String parent,group,var
179        Wave valueWave
180        Wave /T attr,attrValues
181        int i, numAttrs
182       
183        variable err=0, groupID
184        String NXentry_name
185       
186        groupID = NxCansas_CreateGroup(fileID,parent)
187
188        // Save data to disk
189        if(!stringmatch(var,""))
190                HDF5SaveData /O /Z /IGOR=0 valueWave, groupID, var
191                if (V_flag != 0)
192                        err = 1
193                        abort "Cannot save wave to HDF5 dataset " + var + " with V_flag of " + num2str(V_flag)
194                endif
195        endif
196               
197        NxCansas_writeAttributes(fileID,parent+var,attr,attrValues)
198       
199        // Close group and file to release resources
200        if(groupID)
201                HDF5CloseGroup /Z groupID
202        endif
203
204        return err
205end
206
207// Write in a single NxCansas element
208// This method should only be called by CreateStrNxCansas
209Function saveNxCansasStrs(fileID,parent,group,var,valueWave,attr,attrValues)
210        Variable fileID
211        String parent,group,var
212        Wave /T attr,attrValues, valueWave
213        int i, numAttrs
214       
215        variable err=0, groupID
216        String NXentry_name
217       
218        groupID = NxCansas_CreateGroup(fileID,parent)
219
220        // Save data to disk
221        if(!stringmatch(var,""))
222                HDF5SaveData /O /Z /IGOR=0 valueWave, groupID, var
223                if (V_flag != 0)
224                        err = 1
225                        abort "Cannot save wave to HDF5 dataset " + var + " with V_flag of " + num2str(V_flag)
226                endif
227        endif
228               
229        NxCansas_writeAttributes(fileID,parent+var,attr,attrValues)
230       
231        // Close group and file to release resources
232        if(groupID)
233                HDF5CloseGroup /Z groupID
234        endif
235
236        return err
237end
238
239//
240///////////////////////////////////////////////////////////////////////////
241
242///////////////////////////////////////////////////////////////////////////
243//
244// NXcanSAS Reader and Utilities
245
246Function LoadNXcanSASData(fileStr,outstr,doPlot,forceOverwrite)
247        String fileStr, outstr
248        Variable doPlot,forceOverwrite
249       
250        Variable refnum,fileID
251        Variable rr,gg,bb,xdim,ydim
252        SetDataFolder root:             //build sub-folders for each data set under root
253       
254        String filename
255        String I_dataS,Q_dataS,dQ_dataS,dQl_dataS,dQw_dataS,dI_dataS
256        String angst = StrVarOrDefault("root:Packages:NIST:gAngstStr", "A")
257        String/G loadDir = "root:"
258       
259        // Check fullpath and dialog
260        if(stringmatch(fileStr, ""))
261                fileID = NxCansas_DoOpenFileDialog()
262        else
263                fileID = NxCansas_OpenFile(fileStr)
264        Endif
265       
266        filename = ParseFilePath(3,fileStr,":",0,0)
267        String basestr
268        if (!cmpstr(outstr, ""))                //Outstr = "", cmpstr returns 0
269                baseStr = ShortFileNameString(CleanupName(filename,0))
270                baseStr = CleanupName(baseStr,0)                //in case the user added odd characters
271        else
272                baseStr = outstr                        //for output, hopefully correct length as passed in
273        endif
274        String baseFormat = baseStr + "_%d"
275       
276        if(fileID)
277                HDF5ListGroup /F/R/Type=1/Z fileID,"/"
278                String groupList = S_HDF5ListGroup
279                Variable groupID
280                Variable inc=1,ii=0,isMultiData=0
281                String entryUnformatted = "/sasentry%d/"
282                String dataUnformatted = "sasdata%d/"
283                String addDigit = "%d"
284                String entryBase
285                String dataBase = "sasdata/"
286                sPrintf entryBase,entryUnformatted,inc
287                // Open first group
288                HDF5OpenGroup /Z fileID, entryBase + dataBase, groupID
289                If (groupID == 0)
290                        sPrintF dataBase,dataUnformatted,0
291                        HDF5OpenGroup /z fileID, entryBase + dataBase, groupID
292                        isMultiData = 1
293                        sPrintF baseStr,baseformat,0
294                EndIf
295               
296                // Multiple SASentry groups
297                do
298                        //go back to the root folder and clean up before leaving
299                        // Multiple SASdata groups
300                        do
301                                if (isMultiData == 1)
302                                        sPrintF baseStr,baseformat,ii
303                                EndIf
304                                loadDir = "root:" + baseStr
305                                NewDataFolder/O/S $(loadDir)
306                                // Load in data
307                                HDF5LoadData /O/Z/N=$(baseStr + "_i") fileID, entryBase + dataBase + "I"
308                                HDF5LoadData /O/Z/N=$(baseStr + "_q") fileID, entryBase + dataBase + "Q"
309                                HDF5LoadData /O/Z/N=$(baseStr + "_dq") fileID, entryBase + dataBase + "dQ"
310                                HDF5LoadData /O/Z/N=$(baseStr + "_dql") fileID, entryBase + dataBase + "dQl"
311                                HDF5LoadData /O/Z/N=$(baseStr + "_dqw") fileID, entryBase + dataBase + "dQw"
312                                HDF5LoadData /O/Z/N=$(baseStr + "_s") fileID, entryBase + dataBase + "Idev"
313                                if (DimSize($(baseStr + "_i"), 1) > 1)
314                                        // Do not auto-plot 2D data
315                                        doPlot = 0
316                                        xdim = DimSize($(baseStr + "_i"), 0)
317                                        ydim = DimSize($(baseStr + "_i"), 1)
318                                        Wave q = $(baseStr + "_q")
319                                        Wave dq = $(baseStr + "_dq")
320                                        Make/O/N=(xdim,ydim) $(baseStr + "_qx") = q[0]
321                                        Make/O/N=(xdim,ydim) $(baseStr + "_qy") = q[1]
322                                        if (numpnts(dq)>0)
323                                                Make/O/N=(xdim,ydim) $(baseStr + "_dqx") = dq[0]
324                                                Make/O/N=(xdim,ydim) $(baseStr + "_dqy") = dq[1]
325                                        EndIf
326                                        KillWaves $(baseStr + "_q")
327                                EndIf
328                                if (isMultiData)
329                                        sprintf dataBase,dataUnformatted,ii
330                                        // Open next group to see if it exists
331                                        HDF5OpenGroup /Z fileID, entryBase + dataBase, groupID
332                                else
333                                        groupID = 0
334                                endIf
335                                ii += 1
336                                // Load in Meta Data
337                                LoadMetaData(fileID,loadDir,entryBase)
338                        while (groupID != 0)
339                        inc += 1
340                        If (isMultiData)
341                                sprintf dataBase,dataUnformatted,ii
342                        endIf
343                        // Open next group to see if it exists
344                sPrintf entryBase,entryUnformatted,inc
345                        HDF5OpenGroup /Z fileID, entryBase + dataBase, groupID
346                while(groupID != 0)
347               
348                //plot if desired
349                if(doPlot)
350                        Print GetDataFolder(1)
351                       
352                        String w0 = (baseStr + "_q")
353                        String w1 = (baseStr + "_i")
354                        String w2 = (baseStr + "_s")
355                       
356                        // assign colors randomly
357                        rr = abs(trunc(enoise(65535)))
358                        gg = abs(trunc(enoise(65535)))
359                        bb = abs(trunc(enoise(65535)))
360                       
361                        // if target window is a graph, and user wants to append, do so
362                   DoWindow/B Plot_Manager
363                        if(WinType("") == 1)
364                                DoAlert 1,"Do you want to append this data to the current graph?"
365                               
366                                if(V_Flag == 1)
367                                        AppendToGraph $w1 vs $w0
368                                        ModifyGraph mode($w1)=3,marker($w1)=19,msize($w1)=2,rgb($w1)=(rr,gg,bb),tickUnit=1
369                                        ErrorBars/T=0 $w1 Y,wave=($w2,$w2)
370                                        ModifyGraph tickUnit(left)=1
371                                else
372                                //new graph
373                                        Display $w1 vs $w0
374                                        ModifyGraph log=1,mode($w1)=3,marker($w1)=19,msize($w1)=2,rgb($w1)=(rr,gg,bb),tickUnit=1
375                                        ModifyGraph grid=1,mirror=2,standoff=0
376                                        ErrorBars/T=0 $w1 Y,wave=($w2,$w2)
377                                        ModifyGraph tickUnit(left)=1
378                                        Label left "I(q)"
379                                        Label bottom "q ("+angst+"\\S-1\\M)"
380                                        Legend
381                                endif
382                        else
383                        // graph window was not target, make new one
384                                Display $w1 vs $w0
385                                ModifyGraph log=1,mode($w1)=3,marker($w1)=19,msize($w1)=2,rgb($w1)=(rr,gg,bb),tickUnit=1
386                                ModifyGraph grid=1,mirror=2,standoff=0
387                                ErrorBars/T=0 $w1 Y,wave=($w2,$w2)
388                                ModifyGraph tickUnit(left)=1
389                                Label left "I(q)"
390                                Label bottom "q ("+angst+"\\S-1\\M)"
391                                Legend
392                        endif
393                endif
394        endif
395       
396        // Close the file
397        if(fileID)
398                HDF5CloseFile /Z fileID
399        endif
400
401end
402
403Function LoadMetaData(fileID,loadDir,parentBase)
404        String parentBase,loadDir
405        Variable fileID
406        Variable groupID
407        SetDataFolder $(loadDir)
408        Make/O/N=52 $(loadDir + ":realsRead")
409        Make/O/T/N=11 $(loadDir + ":textRead")
410        Wave rw = $(loadDir + ":realsRead")
411        Wave/T textw = $(loadDir + ":textRead")
412        print rw
413        int isMultiDetector = 0, ii = 0
414       
415        // Title
416        HDF5OpenGroup /Z fileID, parentBase, groupID
417        HDF5LoadData /O/Z/N=title fileID, parentBase + "title"
418        Wave/T title = $(loadDir + ":title")
419       
420        // SASinstrument
421        String instrParent = parentBase + "sasinstrument/"
422       
423        // SASaperture
424        String apertureParent = instrParent + "sasaperture/"
425        HDF5OpenGroup /Z fileID, apertureParent, groupID
426        HDF5LoadData /O/Z/N=xg fileID, apertureParent + "x_gap"
427        Wave xg = $(loadDir + ":xg")
428       
429        // SAScollimation
430        String collimationParent = instrParent + "sascollimation/"
431        HDF5OpenGroup /Z fileID, collimationParent, groupID
432        HDF5LoadData /O/Z/N=cdis fileID, collimationParent + "distance"
433        Wave cdis = $(loadDir + ":cdis")
434       
435        // SASdetector
436        String detectorParent = instrParent + "sasdetector/"
437        HDF5OpenGroup /Z fileID, detectorParent, groupID
438        If (groupID == 0)
439                isMultiDetector = 1
440                ii = 1
441                String detectorUnformatted = "sasdetector%d/"
442                sprintf detectorParent,instrParent + detectorUnformatted,ii
443                HDF5OpenGroup /Z fileID, detectorParent, groupID
444        EndIf
445        do
446                HDF5LoadData /O/Z/N=detname fileID, detectorParent + "name"
447                HDF5LoadData /O/Z/N=sdd fileID, detectorParent + "SDD"
448                HDF5LoadData /O/Z/N=bcx fileID, detectorParent + "beam_center_x"
449                HDF5LoadData /O/Z/N=bcy fileID, detectorParent + "beam_center_y"
450                HDF5LoadData /O/Z/N=xps fileID, detectorParent + "x_pixel_size"
451                HDF5LoadData /O/Z/N=xpy fileID, detectorParent + "y_pixel_size"
452                Wave/T detname = $(loadDir + ":detname")
453                Wave sdd = $(loadDir + ":sdd")
454                Wave bcx = $(loadDir + ":bcx")
455                Wave bcy = $(loadDir + ":bcy")
456                Wave xps = $(loadDir + ":xps")
457                Wave xpy = $(loadDir + ":xpy")
458                If (isMultiDetector)
459                        ii += 1
460                        sprintf detectorParent,instrParent + detectorUnformatted,ii
461                        HDF5OpenGroup /Z fileID, detectorParent, groupID
462                Else
463                        groupID = 0
464                EndIf
465        while (groupID != 0)
466       
467        // SASsource
468        String sourceParent = instrParent + "sassource/"
469        HDF5OpenGroup /Z fileID, sourceParent, groupID
470        HDF5LoadData /O/Z/N=wvel fileID, sourceParent + "incident_wavelength"
471        HDF5LoadData /O/Z/N=wvels fileID, sourceParent + "incident_wavelength_spread"
472        Wave wvel = $(loadDir + ":wvel")
473        Wave wvels = $(loadDir + ":wvels")
474       
475        // SASsample
476        String sampleParent = parentBase + "sassample/"
477        HDF5OpenGroup /Z fileID, sampleParent, groupID
478        HDF5LoadData /O/Z/N=smplname fileID, sampleParent + "name"
479        HDF5LoadData /O/Z/N=smplthick fileID, sampleParent + "thickness"
480        HDF5LoadData /O/Z/N=smpltrans fileID, sampleParent + "transmission"
481        Wave/T smplname = $(loadDir + ":smplname")
482        Wave smplthick = $(loadDir + ":smplthick")
483        Wave smpltrans = $(loadDir + ":smpltrans")
484       
485        textw[0] = title[0]
486        textw[6] = smplname[0]
487        textw[9] = detname[0]
488        rw[4] = smplthick[0]
489        rw[5] = smpltrans[0]
490        rw[10] = xps[0]
491        rw[13] = xpy[0]
492        rw[16] = bcx[0]
493        rw[17] = bcy[0]
494        rw[18] = sdd[0]
495        rw[24] = xg[0]
496        rw[25] = cdis[0]
497        rw[26] = wvel[0]
498        rw[27] = wvels[0]
499       
500        KillWaves title,smplname,detname,smplthick,smpltrans,xps,xpy,bcx,bcy,sdd,xg,cdis,wvel,wvels
501       
502End
503
504//
505///////////////////////////////////////////////////////////////////////////
506
507
508///////////////////////////////////////////////////////////////////////////
509//
510// Generic Read/Write operations.
511
512//Needed to test whether file is NXcanSAS. The load routine will then either give an error if HDF5 XOP is not present or load the file if it is.
513Function isNXcanSAS(filestr)
514        String filestr
515       
516        Variable fileID=0,groupID=0
517        Int isHDF5File = 0
518       
519        fileID = NxCansas_OpenFile(filestr)
520        HDF5ListGroup /F/R/Type=1/Z fileID,"/"
521        Variable length = strlen(S_HDF5ListGroup)
522       
523        if (numtype(length) != 2)
524                isHDF5File = 1
525        endif
526       
527        if (fileID != 0)
528                // Close the file
529                HDF5CloseFile /Z fileID
530        endif
531       
532        return isHDF5File
533
534end
535
536//
537///////////////////////////////////////////////////////////////////////////
Note: See TracBrowser for help on using the repository browser.