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

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

Rename and move Reduction/SANS/WriteHDF5.ipf to Common/NIST_NXcanSAS_v709.ipf. Added a basic data loader for plotting.

File size: 27.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// - WriteNxCanSAS1D - Method for writing 1D NXcanSAS data
15// Creates an HDF5 file, with reduced 1D data and stores all meta data
16// If dialog and fullpath are left blank (0 and ""), fake data will be used
17
18Function WriteNxCanSAS1D(type,fullpath,dialog)
19        // Define input variables
20        String type // data location, in memory, relative to root:Packages:NIST:
21        String fullpath // file path and name where data will be saved
22        Variable dialog // if 1, prompt user for file path, otherwise, use fullpath
23       
24        // Define local function variables
25        Variable fileID
26        String destStr=""
27        String parentBase = "/sasentry/" // HDF5 base path for all
28        String/G base = "root:NXcanSAS_file"
29       
30        KillDataFolder/Z $base
31       
32        // Define local waves
33        Wave/T vals,attr,attrVals
34       
35        // Define folder for data heirarchy
36        NewDataFolder/O/S root:NXcanSAS_file
37       
38        // Check fullpath and dialog
39        if(dialog || stringmatch(fullpath, ""))
40                fileID = NxCansas_DoSaveFileDialog()
41        else
42                fileID = NxCansas_CreateFile(fullpath)
43        Endif
44        if(!fileID)
45                Print "Unable to create file at " + fullpath + "."
46        else
47                destStr = "root:Packages:NIST:"+type
48                //*****these waves MUST EXIST, or IGOR Pro will crash, with a type 2 error****
49                WAVE intw = $(destStr + ":integersRead")
50                WAVE rw = $(destStr + ":realsRead")
51                WAVE/T textw=$(destStr + ":textRead")
52                WAVE qvals =$(destStr + ":qval")
53                WAVE inten=$(destStr + ":aveint")
54                WAVE sig=$(destStr + ":sigave")
55                WAVE qbar = $(destStr + ":QBar")
56                WAVE sigmaq = $(destStr + ":SigmaQ")
57                WAVE fsubs = $(destStr + ":fSubS")
58        endif
59
60        ///////////////////////////////////////////////////////////////////////////
61        // Write all data
62       
63        // Define common attribute waves
64        Make/T/N=1 empty = {""}
65        Make/T/N=1 units = {"units"}
66        Make/T/N=1 inv_cm = {"1/cm"}
67        Make/T/N=1 inv_angstrom = {"1/A"}
68       
69        // Run Name and title
70        NewDataFolder/O/S $(base + ":entry1")
71        Make/T/N=1 $(base + ":entry1:title") = {textw[6]}
72        CreateStrNxCansas(fileID,parentBase,"","title",$(base + ":entry1:title"),empty,empty)
73        Make/T/N=1 $(base + ":entry1:run") = {textw[0]}
74        CreateStrNxCansas(fileID,parentBase,"","run",$(base + ":entry1:run"),empty,empty)
75       
76        // SASData
77        String dataParent = parentBase + "sasdata/"
78        // Create SASdata entry
79        String dataBase = base + ":entry1:sasdata"
80        NewDataFolder/O/S $(dataBase)
81        Make/O/T/N=5 $(dataBase + ":attr") = {"canSAS_class","signal","I_axes","NX_class","Q_indices", "timestamp"}
82        Make/O/T/N=5 $(dataBase + ":attrVals") = {"SASdata","I","Q","NXdata","0",textw[1]}
83        CreateStrNxCansas(fileID,dataParent,"","",empty,$(dataBase + ":attr"),$(dataBase + ":attrVals"))
84        // Create q entry
85        NewDataFolder/O/S $(dataBase + ":q")
86        Make/T/N=2 $(dataBase + ":q:attr") = {"units","resolutions"}
87        Make/T/N=2 $(dataBase + ":q:attrVals") = {"1/angstrom","Qdev"}
88        CreateVarNxCansas(fileID,dataParent,"sasdata","Q",qvals,$(dataBase + ":q:attr"),$(dataBase + ":q:attrVals"))
89        // Create i entry
90        NewDataFolder/O/S $(dataBase + ":i")
91        Make/T/N=2 $(dataBase + ":i:attr") = {"units","uncertainties"}
92        Make/T/N=2 $(dataBase + ":i:attrVals") = {"1/cm","Idev"}
93        CreateVarNxCansas(fileID,dataParent,"sasdata","I",inten,$(dataBase + ":i:attr"),$(dataBase + ":i:attrVals"))
94        // Create idev entry
95        CreateVarNxCansas(fileID,dataParent,"sasdata","Idev",sig,units,inv_cm)
96        // Create qdev entry
97        CreateVarNxCansas(fileID,dataParent,"sasdata","Qdev",sigmaq,units,inv_angstrom)
98        CreateVarNxCansas(fileID,dataParent,"sasdata","Qmean",qbar,units,inv_angstrom)
99       
100        // Write all meta data
101        WriteMetaData(fileID,base,parentBase,rw,textw)
102       
103        //
104        ///////////////////////////////////////////////////////////////////////////
105       
106        // Close the file
107        if(fileID)
108                HDF5CloseFile /Z fileID
109        endif
110       
111        KillDataFolder/Z $base
112       
113End
114
115//
116///////////////////////////////////////////////////////////////////////////
117
118
119///////////////////////////////////////////////////////////////////////////
120// - WriteNxCanSAS2D - Method for writing 2D NXcanSAS data
121// Creates an HDF5 file, generates reduced 2D data and stores all meta data
122// If dialog and fullpath are left blank (0 and ""), fake data will be used
123
124Function WriteNxCanSAS2D(type,fullpath,dialog)
125        // Define input variables
126        String type // data location, in memory, relative to root:Packages:NIST:
127        String fullpath // file path and name where data will be saved
128        Variable dialog // if 1, prompt user for file path, otherwise, use fullpath
129       
130        // Define local function variables
131        Variable fileID
132        String destStr="",typeStr=""
133        String parentBase = "/sasentry/" // HDF5 base path for all
134        String/G base = "root:NXcanSAS_file"
135       
136        KillDataFolder/Z $base
137       
138        // Define local waves
139        Wave/T vals,attr,attrVals
140       
141        // Define folder for data heirarchy
142        NewDataFolder/O/S root:NXcanSAS_file
143       
144        // Check fullpath and dialog
145        if(dialog || stringmatch(fullpath, ""))
146                fileID = NxCansas_DoSaveFileDialog()
147        else
148                fileID = NxCansas_CreateFile(fullpath)
149        Endif
150        if(!fileID)
151                Print "Unable to create file at " + fullpath + "."
152        else
153                destStr = "root:Packages:NIST:"+type
154
155                //must select the linear_data to export
156                NVAR isLog = $(destStr+":gIsLogScale")
157                if(isLog==1)
158                        typeStr = ":linear_data"
159                else
160                        typeStr = ":data"
161                endif
162                        NVAR pixelsX = root:myGlobals:gNPixelsX
163                NVAR pixelsY = root:myGlobals:gNPixelsY
164                Wave data=$(destStr+typeStr)
165                Wave data_err=$(destStr+":linear_data_error")
166                WAVE intw=$(destStr + ":integersRead")
167                WAVE rw=$(destStr + ":realsRead")
168                WAVE/T textw=$(destStr + ":textRead")
169        endif
170       
171        ///////////////////////////////////////////////////////////////////////////
172        // Compute Qx, Qy data from pixel space
173       
174        Duplicate/O data,qx_val,qy_val,z_val,qval,qz_val,phi,r_dist
175       
176        Variable xctr,yctr,sdd,lambda,pixSize
177        xctr = rw[16]
178        yctr = rw[17]
179        sdd = rw[18]
180        lambda = rw[26]
181        pixSize = rw[13]/10             //convert mm to cm (x and y are the same size pixels)
182       
183        qx_val = CalcQx(p+1,q+1,rw[16],rw[17],rw[18],rw[26],rw[13]/10)          //+1 converts to detector coordinate system
184        qy_val = CalcQy(p+1,q+1,rw[16],rw[17],rw[18],rw[26],rw[13]/10)
185       
186        Redimension/N=(pixelsX*pixelsY) qx_val,qy_val,z_val
187
188        Variable L2 = rw[18]
189        Variable BS = rw[21]
190        Variable S1 = rw[23]
191        Variable S2 = rw[24]
192        Variable L1 = rw[25]
193        Variable lambdaWidth = rw[27]   
194        Variable usingLenses = rw[28]           //new 2007
195
196        Variable vz_1 = 3.956e5         //velocity [cm/s] of 1 A neutron
197        Variable g = 981.0                              //gravity acceleration [cm/s^2]
198        Variable m_h    = 252.8                 // m/h [=] s/cm^2
199
200        Variable acc,ssd,lambda0,yg_d,qstar
201               
202        G = 981.  //!   ACCELERATION OF GRAVITY, CM/SEC^2
203        acc = vz_1              //      3.956E5 //!     CONVERT WAVELENGTH TO VELOCITY CM/SEC
204        SDD = L2        *100    //1317
205        SSD = L1        *100    //1627          //cm
206        lambda0 = lambda                //              15
207        YG_d = -0.5*G*SDD*(SSD+SDD)*(LAMBDA0/acc)^2
208        qstar = -2*pi/lambda0*2*yg_d/sdd
209
210        // the gravity center is not the resolution center
211        // gravity center = beam center
212        // resolution center = offset y = dy + (2)*yg_d
213        ///************
214        // do everything to write out the resolution too
215        // un-comment these if you want to write out qz_val and qval too, then use the proper save command
216        qval = CalcQval(p+1,q+1,rw[16],rw[17],rw[18],rw[26],rw[13]/10)
217        qz_val = CalcQz(p+1,q+1,rw[16],rw[17],rw[18],rw[26],rw[13]/10)
218        //      phi = FindPhi( pixSize*((p+1)-xctr) , pixSize*((q+1)-yctr))             //(dx,dy)
219        //      r_dist = sqrt(  (pixSize*((p+1)-xctr))^2 +  (pixSize*((q+1)-yctr))^2 )          //radial distance from ctr to pt
220        phi = FindPhi( pixSize*((p+1)-xctr) , pixSize*((q+1)-yctr)+(2)*yg_d)            //(dx,dy+yg_d)
221        r_dist = sqrt(  (pixSize*((p+1)-xctr))^2 +  (pixSize*((q+1)-yctr)+(2)*yg_d)^2 )         //radial distance from ctr to pt
222        Redimension/N=(pixelsX*pixelsY) qz_val,qval,phi,r_dist
223        Make/O/N=(2,pixelsX,pixelsY) qxy_vals
224        //everything in 1D now
225        Duplicate/O qval SigmaQX,SigmaQY
226        Make/O/N=(pixelsX,pixelsY) shadow
227        Make/O/N=(2,pixelsX,pixelsY) SigmaQ_combined
228
229        //Two parameters DDET and APOFF are instrument dependent.  Determine
230        //these from the instrument name in the header.
231        //From conversation with JB on 01.06.99 these are the current good values
232        Variable DDet
233        NVAR apOff = root:myGlobals:apOff               //in cm
234        DDet = rw[10]/10                        // header value (X) is in mm, want cm here
235
236        Variable ret1,ret2,ret3,jj
237        Variable nq = 0
238        Variable ii = 0
239       
240        do
241                jj = 0
242                do
243                        nq = ii * pixelsX + jj
244                        get2DResolution(qval[nq],phi[nq],lambda,lambdaWidth,DDet,apOff,S1,S2,L1,L2,BS,pixSize,usingLenses,r_dist[nq],ret1,ret2,ret3)
245                        qxy_vals[0][ii][jj] = qx_val[nq]
246                        qxy_vals[1][ii][jj] = qy_val[nq]
247                        SigmaQ_combined[0][ii][jj] = ret1       
248                        SigmaQ_combined[1][ii][jj] = ret2
249                        shadow[ii][jj] = ret3   
250                        jj+=1
251                while(jj<pixelsX)
252                ii+=1
253        while(ii<pixelsY)
254        //
255        ///////////////////////////////////////////////////////////////////////////
256
257       
258        ///////////////////////////////////////////////////////////////////////////
259        // Write all data
260       
261        // Define common attribute waves
262        Make/T/N=1 empty = {""}
263        Make/T/N=1 units = {"units"}
264        Make/T/N=1 inv_cm = {"1/cm"}
265        Make/T/N=1 inv_angstrom = {"1/A"}
266       
267        // Run Name and title
268        NewDataFolder/O/S $(base + ":entry1")
269        Make/T/N=1 $(base + ":entry1:title") = {textw[6]}
270        CreateStrNxCansas(fileID,parentBase,"","title",$(base + ":entry1:title"),empty,empty)
271        Make/T/N=1 $(base + ":entry1:run") = {textw[0]}
272        CreateStrNxCansas(fileID,parentBase,"","run",$(base + ":entry1:run"),empty,empty)
273       
274        // SASData
275        String dataParent = parentBase + "sasdata/"
276        // Create SASdata entry
277        String dataBase = base + ":entry1:sasdata"
278        NewDataFolder/O/S $(dataBase)
279        Make/O/T/N=5 $(dataBase + ":attr") = {"canSAS_class","signal","I_axes","NX_class","Q_indices", "timestamp"}
280        Make/O/T/N=5 $(dataBase + ":attrVals") = {"SASdata","I","Q,Q","NXdata","0,1",textw[1]}
281        CreateStrNxCansas(fileID,dataParent,"","",empty,$(dataBase + ":attr"),$(dataBase + ":attrVals"))
282        // Create i entry
283        NewDataFolder/O/S $(dataBase + ":i")
284        Make/T/N=2 $(dataBase + ":i:attr") = {"units","uncertainties"}
285        Make/T/N=2 $(dataBase + ":i:attrVals") = {"1/cm","Idev"}
286        CreateVarNxCansas(fileID,dataParent,"sasdata","I",data,$(dataBase + ":i:attr"),$(dataBase + ":i:attrVals"))
287
288        //
289        // TODO: Reinstate Qdev/resolutions when I can fix the reader issue
290        //
291       
292
293        // Create qx and qy entry
294        NewDataFolder/O/S $(dataBase + ":q")
295        Make/T/N=2 $(dataBase + ":q:attr") = {"units"}//,"resolutions"}
296        Make/T/N=2 $(dataBase + ":q:attrVals") = {"1/angstrom"}//,"Qdev"}
297        CreateVarNxCansas(fileID,dataParent,"sasdata","Q",qxy_vals,$(dataBase + ":q:attr"),$(dataBase + ":q:attrVals"))
298       
299        // Create idev entry
300        CreateVarNxCansas(fileID,dataParent,"sasdata","Idev",data_err,units,inv_cm)
301        // Create qdev entry
302        CreateVarNxCansas(fileID,dataParent,"sasdata","Qdev",SigmaQ_combined,units,inv_angstrom)
303        // Create shadwfactor entry
304        CreateVarNxCansas(fileID,dataParent,"sasdata","ShadowFactor",shadow,empty,empty)
305       
306        // Write all meta data
307        WriteMetaData(fileID,base,parentBase,rw,textw)
308       
309        // Close the file
310        if(fileID)
311                HDF5CloseFile /Z fileID
312        endif
313       
314        KillDataFolder/Z $base
315       
316End
317
318//
319///////////////////////////////////////////////////////////////////////////
320
321///////////////////////////////////////////////////////////////////////////
322// - WriteMetaData - Method used to write non data elements into NXcanSAS
323// format. This is common between 1D and 2D data sets.
324
325Function WriteMetaData(fileID,base,parentBase,rw,textw)
326        String base,parentBase
327        Variable fileID
328        Wave rw
329        Wave/T textw
330       
331        // Define common attribute waves
332        Make/T/N=1 empty = {""}
333        Make/T/N=1 units = {"units"}
334        Make/T/N=1 m = {"m"}
335        Make/T/N=1 mm = {"mm"}
336        Make/T/N=1 cm = {"cm"}
337        Make/T/N=1 pixel = {"pixel"}
338        Make/T/N=1 angstrom = {"A"}
339       
340        // SASinstrument
341        String instrParent = parentBase + "sasinstrument/"
342        // Create SASinstrument entry
343        String instrumentBase = base + ":entry1:sasinstrument"
344        NewDataFolder/O/S $(instrumentBase)
345        Make/O/T/N=5 $(instrumentBase + ":attr") = {"canSAS_class","NX_class"}
346        Make/O/T/N=5 $(instrumentBase + ":attrVals") = {"SASinstrument","NXinstrument"}
347        CreateStrNxCansas(fileID,instrParent,"","",empty,$(instrumentBase + ":attr"),$(instrumentBase + ":attrVals"))
348       
349        // SASaperture
350        String apertureParent = instrParent + "sasaperture/"
351        // Create SASaperture entry
352        String apertureBase = instrumentBase + ":sasaperture"
353        NewDataFolder/O/S $(apertureBase)
354        Make/O/T/N=5 $(apertureBase + ":attr") = {"canSAS_class","NX_class"}
355        Make/O/T/N=5 $(apertureBase + ":attrVals") = {"SASaperture","NXaperture"}
356        CreateStrNxCansas(fileID,apertureParent,"","",empty,$(apertureBase + ":attr"),$(apertureBase + ":attrVals"))
357       
358        //
359        // TODO: Where do I get rectangular dimensions from?
360        //
361       
362        // Create SASaperture shape entry
363        Make/O/T/N=1 $(apertureBase + ":shape") = {"pinhole"}
364        CreateStrNxCansas(fileID,apertureParent,"sasaperture","shape",$(apertureBase + ":shape"),empty,empty)
365        // Create SASaperture x_gap entry
366        Make/O/N=1 $(apertureBase + ":x_gap") = {rw[24]}
367        CreateVarNxCansas(fileID,apertureParent,"sasaperture","x_gap",$(apertureBase + ":x_gap"),units,mm)
368        // Create SASaperture y_gap entry
369        Make/O/N=1 $(apertureBase + ":y_gap") = {rw[24]}
370        CreateVarNxCansas(fileID,apertureParent,"sasaperture","y_gap",$(apertureBase + ":y_gap"),units,mm)
371       
372        // SAScollimation
373        String collimationParent = instrParent + "sascollimation/"
374        // Create SAScollimation entry
375        String collimationBase = instrumentBase + ":sascollimation"
376        NewDataFolder/O/S $(collimationBase)
377        Make/O/T/N=5 $(collimationBase + ":attr") = {"canSAS_class","NX_class"}
378        Make/O/T/N=5 $(collimationBase + ":attrVals") = {"SAScollimation","NXcollimator"}
379        CreateStrNxCansas(fileID,collimationParent,"","",empty,$(collimationBase + ":attr"),$(collimationBase + ":attrVals"))
380        // Create SAScollimation distance entry
381        Make/O/N=1 $(collimationBase + ":distance") = {rw[25]}
382        CreateVarNxCansas(fileID,collimationParent,"sasaperture","distance",$(collimationBase + ":distance"),units,m)
383       
384        // SASdetector
385        String detectorParent = instrParent + "sasdetector/"
386        // Create SASdetector entry
387        String detectorBase = instrumentBase + ":sasdetector"
388        NewDataFolder/O/S $(detectorBase)
389        Make/O/T/N=5 $(detectorBase + ":attr") = {"canSAS_class","NX_class"}
390        Make/O/T/N=5 $(detectorBase + ":attrVals") = {"SASdetector","NXdetector"}
391        CreateStrNxCansas(fileID,detectorParent,"","",empty,$(detectorBase + ":attr"),$(detectorBase + ":attrVals"))
392        // Create SASdetector name entry
393        Make/O/T/N=1 $(detectorBase + ":name") = {textw[9]}
394        CreateStrNxCansas(fileID,detectorParent,"","name",$(detectorBase + ":name"),empty,empty)
395        // Create SASdetector distance entry
396        Make/O/N=1 $(detectorBase + ":SDD") = {rw[18]}
397        CreateVarNxCansas(fileID,detectorParent,"","SDD",$(detectorBase + ":SDD"),units,m)
398        // Create SASdetector beam_center_x entry
399        Make/O/N=1 $(detectorBase + ":beam_center_x") = {rw[16]}
400        CreateVarNxCansas(fileID,detectorParent,"","beam_center_x",$(detectorBase + ":beam_center_x"),units,pixel)
401        // Create SASdetector beam_center_y entry
402        Make/O/N=1 $(detectorBase + ":beam_center_y") = {rw[17]}
403        CreateVarNxCansas(fileID,detectorParent,"","beam_center_y",$(detectorBase + ":beam_center_y"),units,pixel)
404        // Create SASdetector x_pixel_size entry
405        Make/O/N=1 $(detectorBase + ":x_pixel_size") = {rw[10]}
406        CreateVarNxCansas(fileID,detectorParent,"","x_pixel_size",$(detectorBase + ":x_pixel_size"),units,mm)
407        // Create SASdetector y_pixel_size entry
408        Make/O/N=1 $(detectorBase + ":y_pixel_size") = {rw[13]}
409        CreateVarNxCansas(fileID,detectorParent,"","y_pixel_size",$(detectorBase + ":y_pixel_size"),units,mm)
410       
411        // SASsource
412        String sourceParent = instrParent + "sassource/"
413        // Create SASdetector entry
414        String sourceBase = instrumentBase + ":sassource"
415        NewDataFolder/O/S $(sourceBase)
416        Make/O/T/N=5 $(sourceBase + ":attr") = {"canSAS_class","NX_class"}
417        Make/O/T/N=5 $(sourceBase + ":attrVals") = {"SASsource","NXsource"}
418        CreateStrNxCansas(fileID,sourceParent,"","",empty,$(sourceBase + ":attr"),$(sourceBase + ":attrVals"))
419        // Create SASsource radiation entry
420        Make/O/T/N=1 $(sourceBase + ":radiation") = {"Reactor Neutron Source"}
421        CreateStrNxCansas(fileID,sourceParent,"","radiation",$(sourceBase + ":radiation"),empty,empty)
422        // Create SASsource incident_wavelength entry
423        Make/O/N=1 $(sourceBase + ":incident_wavelength") = {rw[26]}
424        CreateVarNxCansas(fileID,sourceParent,"","incident_wavelength",$(sourceBase + ":incident_wavelength"),units,angstrom)
425        // Create SASsource incident_wavelength_spread entry
426        Make/O/N=1 $(sourceBase + ":incident_wavelength_spread") = {rw[27]}
427        CreateVarNxCansas(fileID,sourceParent,"","incident_wavelength_spread",$(sourceBase + ":incident_wavelength_spread"),units,angstrom)
428       
429        // SASsample
430        String sampleParent = parentBase + "sassample/"
431        // Create SASsample entry
432        String sampleBase = base + ":entry1:sassample"
433        NewDataFolder/O/S $(sampleBase)
434        Make/O/T/N=5 $(sampleBase + ":attr") = {"canSAS_class","NX_class"}
435        Make/O/T/N=5 $(sampleBase + ":attrVals") = {"SASsample","NXsample"}
436        CreateStrNxCansas(fileID,sampleParent,"","",empty,$(sampleBase + ":attr"),$(sampleBase + ":attrVals"))
437        // Create SASsample name entry
438        Make/O/T/N=1 $(sampleBase + ":name") = {textw[6]}
439        CreateStrNxCansas(fileID,sampleParent,"","name",$(sampleBase + ":name"),empty,empty)
440        // Create SASsample thickness entry
441        Make/O/N=1 $(sampleBase + ":thickness") = {rw[5]}
442        CreateVarNxCansas(fileID,sampleParent,"","thickness",$(sampleBase + ":thickness"),units,cm)
443        // Create SASsample transmission entry
444        Make/O/N=1 $(sampleBase + ":transmission") = {rw[4]}
445        CreateVarNxCansas(fileID,sampleParent,"","transmission",$(sampleBase + ":transmission"),empty,empty)
446End
447       
448//
449///////////////////////////////////////////////////////////////////////////
450
451
452///////////////////////////////////////////////////////////////////////////
453//
454// Basic file open/create and file initialization routines
455
456// Select/create file through prompt
457Function NxCansas_DoSaveFileDialog()
458        Variable refNum, fileID
459        String message = "Save a file"
460        String outputPath
461        String fileFilters = "Data Files (*.h5):.h5;"
462        fileFilters += "All Files:.*;"
463        Open /D /F=fileFilters /M=message refNum
464        outputPath = S_fileName
465        fileID = NxCansas_CreateFile(outputPath)
466        return fileID
467End
468
469// Create file with a known path
470Function NxCansas_CreateFile(fullpath)
471        String fullpath
472        Variable fileID
473        Make/T/O/N=1 $("root:file_name") = fullpath
474        fullpath = ReplaceString(":\\", fullpath, ":")
475        fullpath = ReplaceString("\\", fullpath, ":")
476        HDF5CreateFile /Z fileID as fullpath
477        NXCansas_InitializeFile(fileID)
478        return fileID
479End
480
481
482// Open\ file with a known path
483Function NxCansas_OpenFile(fullpath)
484        String fullpath
485        String fileName
486        Variable fileID
487        fileName = ParseFilePath(3,fullpath,":",0,0)
488        Print fileName
489        Make/T/O/N=1 $("root:file_name") = fileName
490        fullpath = ReplaceString(":\\", fullpath, ":")
491        fullpath = ReplaceString("\\", fullpath, ":")
492        HDF5OpenFile /Z fileID as fullpath
493        return fileID
494End
495
496// Select/create file through prompt
497Function NxCansas_DoOpenFileDialog()
498        Variable refNum,fileID
499        String message = "Select a file"
500        String inputPath,fileName
501        String fileFilters = "Data Files (*.h5):.h5;"
502        STRUCT HDF5BrowserData bd
503        fileFilters += "All Files:.*;"
504        Open /D /F=fileFilters /M=message refNum as fileName
505        inputPath = S_fileName
506        fileID = NxCansas_OpenFile(inputPath)
507        return fileID
508End
509
510// Initialize the file to a base state
511Function NxCansas_InitializeFile(fileID)
512        Variable fileID
513        String parent
514        String/G base = "root:NXcanSAS_file"
515        Make/T/N=1 $(base + ":vals") = {""}
516        Make/T/N=3 $(base + ":attr") = {"NX_class", "canSAS_class", "version"}
517        Make/T/N=3 $(base + ":attrVals") = {"NXentry", "SASentry", "1.0"}
518        parent = "/sasentry/"
519        CreateStrNxCansas(fileID,parent,"","",$(base + ":vals"),$(base + ":attr"),$(base + ":attrVals"))
520        Make/T/N=1 $(base + ":entryAttr") = {""}
521        Make/T/N=1 $(base + ":entryAttrVals") = {""}
522        CreateStrNxCansas(fileID,parent,"","definition",{"NXcanSAS"},$(base + ":entryAttr"),$(base + ":entryAttrVals"))
523End
524
525//
526///////////////////////////////////////////////////////////////////////////
527
528///////////////////////////////////////////////////////////////////////////
529// Functions used to save data to file
530
531// Intermediate error handler for saving variable waves - this function should be called instead of saveNxCansas
532Function CreateVarNxCansas(fileID,parent,group,var,valueWave,attr,attrValues)
533        Variable fileID
534        String parent,group,var
535        Wave valueWave
536        Wave /T attr,attrValues
537        Variable err
538        err = saveNxCansasVars(fileID,parent,group,var,valueWave,attr,attrValues)
539        if(err)
540                Print "NxCansas write err = ",err
541        endif
542End
543// Intermediate error handler for saving string waves - this function should be called instead of saveNxCansas
544Function CreateStrNxCansas(fileID,parent,group,var,valueWave,attr,attrValues)
545        Variable fileID
546        String parent,group,var
547        Wave /T valueWave,attr,attrValues
548        Variable err
549        err = saveNxCansasStrs(fileID,parent,group,var,valueWave,attr,attrValues)
550        if(err)
551                Print "NxCansas write err = ",err
552        endif
553End
554
555Function NxCansas_writeAttributes(fileID,path,attrNames,attrVals)
556        Variable fileID
557        String path
558        Wave/T attrNames, attrVals
559        int numAttrs,i
560        numAttrs = numpnts(attrNames)
561        Duplicate/O/T attrNames, names
562        Duplicate/O/T attrVals, vals
563       
564        for(i=0; i < numAttrs; i += 1)
565                String name_i = names[i]
566                String vals_i = vals[i]
567                Make/T/N=1 vals_i_wave
568                vals_i_wave[0] = vals_i
569                if(!stringmatch(name_i,""))
570                        HDF5SaveData /A=name_i vals_i_wave, fileID, path
571                endif
572        endfor
573       
574End
575
576Function NxCansas_CreateGroup(fileID,parent)
577        Variable fileID
578        String parent
579        Variable groupID
580        try     
581                if(!fileID)
582                        abort "HDF5 file does not exist"
583                endif
584               
585                // Create the group if it doesn't already exist
586                HDF5CreateGroup /Z fileID, parent, groupID
587                       
588        catch
589                // DO something if error is thrown
590                Print "NxCansas write err in saveNxCansas = ",V_AbortCode
591        endtry
592        return groupID
593End
594
595// Write in a single NxCansas element (from the STRUCTURE)
596// This method should only be called by CreateVarNxCansas
597Function saveNxCansasVars(fileID,parent,group,var,valueWave,attr,attrValues)
598
599        Variable fileID
600        String parent,group,var
601        Wave valueWave
602        Wave /T attr,attrValues
603        int i, numAttrs
604       
605        variable err=0, groupID
606        String NXentry_name
607       
608        groupID = NxCansas_CreateGroup(fileID,parent)
609
610        // Save data to disk
611        if(!stringmatch(var,""))
612                HDF5SaveData /O /Z /IGOR=0 valueWave, groupID, var
613                if (V_flag != 0)
614                        err = 1
615                        abort "Cannot save wave to HDF5 dataset " + var + " with V_flag of " + num2str(V_flag)
616                endif
617        endif
618               
619        NxCansas_writeAttributes(fileID,parent+var,attr,attrValues)
620       
621        // Close group and file to release resources
622        if(groupID)
623                HDF5CloseGroup /Z groupID
624        endif
625
626        return err
627end
628
629// Write in a single NxCansas element
630// This method should only be called by CreateStrNxCansas
631Function saveNxCansasStrs(fileID,parent,group,var,valueWave,attr,attrValues)
632        Variable fileID
633        String parent,group,var
634        Wave /T attr,attrValues, valueWave
635        int i, numAttrs
636       
637        variable err=0, groupID
638        String NXentry_name
639       
640        groupID = NxCansas_CreateGroup(fileID,parent)
641
642        // Save data to disk
643        if(!stringmatch(var,""))
644                HDF5SaveData /O /Z /IGOR=0 valueWave, groupID, var
645                if (V_flag != 0)
646                        err = 1
647                        abort "Cannot save wave to HDF5 dataset " + var + " with V_flag of " + num2str(V_flag)
648                endif
649        endif
650               
651        NxCansas_writeAttributes(fileID,parent+var,attr,attrValues)
652       
653        // Close group and file to release resources
654        if(groupID)
655                HDF5CloseGroup /Z groupID
656        endif
657
658        return err
659end
660
661//
662///////////////////////////////////////////////////////////////////////////
663
664///////////////////////////////////////////////////////////////////////////
665//
666// NXcanSAS Reader and Utilities
667
668Function LoadNXcanSASData(fileStr,outstr,doPlot,forceOverwrite)
669        String fileStr, outstr
670        Variable doPlot,forceOverwrite
671       
672        Variable refnum,fileID
673        Variable rr,gg,bb
674        SetDataFolder root:             //build sub-folders for each data set under root
675       
676        String filename
677        String angst = StrVarOrDefault("root:Packages:NIST:gAngstStr", "A")
678       
679        // Check fullpath and dialog
680        if(stringmatch(fileStr, ""))
681                fileID = NxCansas_DoOpenFileDialog()
682        else
683                fileID = NxCansas_OpenFile(fileStr)
684        Endif
685       
686        filename = ParseFilePath(3,fileStr,":",0,0)
687        Print "file string: ",filename
688        String/G loadDir = "root:" + filename
689       
690        String I_dataStore = filename + "_i"
691        String Q_dataStore = filename + "q"
692        String dI_dataStore = filename + "s"
693       
694        //go back to the root folder and clean up before leaving
695        NewDataFolder/O/S $loadDir
696       
697        if(fileID)
698                HDF5ListGroup /F/R/Type=1/Z fileID,"/"
699                String groupList = S_HDF5ListGroup
700                Print "grouplist: ",groupList
701       
702                Variable groupID
703                HDF5OpenGroup /Z fileID, "/sasentry/sasdata", groupID
704                HDF5LoadData /O/N=$I_dataStore fileID, "/sasentry/sasdata/I"
705                HDF5LoadData /O/N=$Q_dataStore fileID, "/sasentry/sasdata/Q"
706                HDF5LoadData /O/N=$dI_dataStore fileID, "/sasentry/sasdata/Idev"
707               
708                //plot if desired
709                if(doPlot)
710                        Print GetDataFolder(1)
711                       
712                        String w0 = loadDir + ":" + Q_dataStore
713                        String w1 = loadDir + ":" + I_dataStore
714                        String w2 = loadDir + ":" + dI_dataStore
715                       
716                        // assign colors randomly
717                        rr = abs(trunc(enoise(65535)))
718                        gg = abs(trunc(enoise(65535)))
719                        bb = abs(trunc(enoise(65535)))
720                       
721                        // if target window is a graph, and user wants to append, do so
722                   DoWindow/B Plot_Manager
723                        if(WinType("") == 1)
724                                DoAlert 1,"Do you want to append this data to the current graph?"
725                               
726                                if(V_Flag == 1)
727                                        AppendToGraph $w1 vs $w0
728                                        ModifyGraph mode($w1)=3,marker($w1)=19,msize($w1)=2,rgb($w1)=(rr,gg,bb),tickUnit=1
729                                        ErrorBars/T=0 $w1 Y,wave=($w2,$w2)
730                                        ModifyGraph tickUnit(left)=1
731                                else
732                                //new graph
733                                        SetDataFolder $loadDir  //sometimes I end up back in root: here, and I can't figure out why!
734                                        Display $w1 vs $w0
735                                        ModifyGraph log=1,mode($w1)=3,marker($w1)=19,msize($w1)=2,rgb($w1)=(rr,gg,bb),tickUnit=1
736                                        ModifyGraph grid=1,mirror=2,standoff=0
737                                        ErrorBars/T=0 $w1 Y,wave=($w2,$w2)
738                                        ModifyGraph tickUnit(left)=1
739                                        Label left "I(q)"
740                                        Label bottom "q ("+angst+"\\S-1\\M)"
741                                        Legend
742                                endif
743                        else
744                        // graph window was not target, make new one
745                                Display $w1 vs $w0
746                                ModifyGraph log=1,mode($w1)=3,marker($w1)=19,msize($w1)=2,rgb($w1)=(rr,gg,bb),tickUnit=1
747                                ModifyGraph grid=1,mirror=2,standoff=0
748                                ErrorBars/T=0 $w1 Y,wave=($w2,$w2)
749                                ModifyGraph tickUnit(left)=1
750                                Label left "I(q)"
751                                Label bottom "q ("+angst+"\\S-1\\M)"
752                                Legend
753                        endif
754                endif
755               
756        endif
757       
758        // Close the file
759        if(fileID)
760                HDF5CloseFile /Z fileID
761        endif
762       
763        // KillDataFolder /Z $loadDir
764
765end
766
767//
768///////////////////////////////////////////////////////////////////////////
769
770
771///////////////////////////////////////////////////////////////////////////
772//
773// Generic Read/Write operations.
774
775//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.
776Function isNXcanSAS(filestr)
777        String filestr
778       
779        Variable fileID = 0
780        Int isHDF5File = 0
781       
782        fileID = NxCansas_OpenFile(filestr)
783       
784        if (fileID != 0)
785                isHDF5File = 1
786                // Close the file
787                HDF5CloseFile /Z fileID
788        endif
789       
790        return isHDF5File
791
792end
793
794//
795///////////////////////////////////////////////////////////////////////////
Note: See TracBrowser for help on using the repository browser.