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

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

Update loader for multidata and multientry items. TODO: differentiate 1D and 2D data, load in multiple detectors (VSANS), and create an NSORT method that outputs in the NXcanSAS format.

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