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

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

Add 2D NXcanSAS output as SANS reduction option.

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