source: sans/Dev/trunk/NCNR_User_Procedures/Common/cansasXML.ipf @ 1036

Last change on this file since 1036 was 953, checked in by srkline, 8 years ago

some minor changes to the FFT filling procedures to help out Abhiram

Replaced cansasXML.ipf v1.11 with v1.12 (current version)

some restructuring of the VSANS file names.

File size: 38.6 KB
Line 
1#pragma rtGlobals=1             // rtGlobals=3 requires IgorPro 6.3+
2#pragma version=1.12
3
4// SRK
5// taken from smallangles.net on 10 MAR 2015
6// changed Function/T to Function/S on (unused) TrimWS functions
7//
8//
9
10// file:        cansasXML.ipf
11// author:      Pete R. Jemian <jemian@anl.gov>
12// SVN date:    $Date$
13// SVN rev.:    $Revision$
14// SVN URL:     $HeadURL$
15// SVN ID:      $Id$
16// purpose:  implement an IgorPro file reader to read the canSAS 1-D reduced SAS data in XML files
17//                      adhering to either the cansas1d/1.0 or cansas1d/1.1 standards
18// readme:    http://www.cansas.org/formats/canSAS1d/1.1/doc/binding-igorpro.html
19// URL: http://www.cansas.org/formats/canSAS1d/1.1/doc/
20//
21// requires:    IgorPro (http://www.wavemetrics.com/)
22//                              XMLutils - XOP (http://www.igorexchange.com/project/XMLutils)
23// provides:  CS_XmlReader(String fileName)
24//                              all other functions in this file should not be relied upon
25//
26// Copyright (c) 2013, UChicago Argonne, LLC
27// This file is distributed subject to a Software License Agreement found
28// in the file LICENSE that is included with this distribution.
29
30
31//  ================  ================  =================  ==========
32//  #pragma version   canSAS1d version  namespace          released
33//  ================  ================  =================  ==========
34//  1.12              v1.1              urn:cansas1d:1.1   2013-04-01
35//  1.11              v1.0              cansas1d/1.0       2009-09-25
36//  ================  ================  =================  ==========
37
38
39// ==================================================================
40// CS_XmlReader("../examples/bimodal-test1.xml")
41// CS_XmlReader("../examples/1998spheres.xml")
42// CS_XmlReader("../examples/xg009036_001.xml")
43// CS_XmlReader("../examples/s81-polyurea.xml")
44// CS_XmlReader("../examples/cs_af1410.xml")
45//  testCollette();  prjTest_cansas1d()
46// ==================================================================
47
48
49#if( ! Exists("XmlOpenFile") )
50        // BEFORE we do anything else, check that XMLutils XOP is available.
51        // No XMLutils XOP: provide dummy function so that IgorPro can compile dependent support code
52
53        FUNCTION CS_XmlReader(fileName)
54            String fileName
55                String msg
56                msg = "XML function provided by XMLutils XOP is not available,"
57                msg += " get the XOP from : http://www.igorexchange.com/project/XMLutils"
58                msg += " (see http://www.cansas.org/formats/canSAS1d/1.1/doc/binding-igorpro.html for details)"
59            Abort  msg
60            RETURN(-6)
61        END
62
63#else   // if( Exists("XmlOpenFile") )
64
65FUNCTION CS_XmlReader(fileName)
66        //
67        // open a canSAS 1-D reduced SAS XML data file
68        //      returns:
69        //              0 : successful
70        //              -1: XML file not found
71        //              -2: root element is not <SASroot> with valid canSAS namespace
72        //              -3: <SASroot> version  is not 1.0 or 1.1
73        //              -4: no <SASentry> elements
74        //              -5: XMLutils XOP needs upgrade
75        //              -6: XMLutils XOP not found
76        //
77        STRING fileName
78        STRING origFolder
79        STRING workingFolder = "root:Packages:CS_XMLreader"
80        VARIABLE returnCode
81
82
83        //
84        // set up a work folder within root:Packages
85        // Clear out any progress/results from previous activities
86        //
87        origFolder = GetDataFolder(1)
88        SetDataFolder root:                                     // start in the root data folder
89        NewDataFolder/O  root:Packages          // good practice
90        KillDataFolder/Z  $workingFolder                // clear out any previous work
91        NewDataFolder/O/S  $workingFolder       // Do all our work in root:XMLreader
92
93        //
94        // Try to open the named XML file (clean-up and return if failure)
95        //
96        VARIABLE fileID
97        STRING/G errorMsg, xmlFile
98        xmlFile = fileName
99        fileID = XmlOpenFile(fileName)                  // open and parse the XMLfile
100        IF ( fileID < 0 )
101                SWITCH(fileID)                                  // fileID holds the return code; check it
102                        CASE -1:
103                                errorMsg = fileName + ": failed to parse XML"
104                        BREAK
105                        CASE -2:
106                                errorMsg = fileName + " either not found or cannot be opened for reading"
107                        BREAK
108                ENDSWITCH
109                PRINT errorMsg
110                SetDataFolder $origFolder
111                RETURN(-1)                                              // could not find file
112        ENDIF
113
114        //
115        //      test to see if XMLutils has the needed upgrade
116        //
117        XMLlistXpath(fileID, "/*", "") 
118        IF ( EXISTS( "M_listXPath" ) == 0 )
119                XmlCloseFile(fileID,0)
120                errorMsg = "XMLutils needs an upgrade:  http://www.igorexchange.com/project/XMLutils"
121                PRINT errorMsg
122                SetDataFolder $origFolder
123                RETURN(-5)                                              // XOPutils needs an upgrade
124        ENDIF
125        WAVE/T  M_listXPath
126
127        // check for canSAS namespace string, returns "" if not valid or not found
128        STRING/G ns = CS_getDefaultNamespace(fileID)
129        IF (strlen(ns) == 0 )
130                XmlCloseFile(fileID,0)
131                errorMsg = "root element is not <SASroot> with valid canSAS namespace"
132                PRINT errorMsg
133                SetDataFolder $origFolder
134                RETURN(-2)                                              // root element is not <SASroot> with valid canSAS namespace
135        ENDIF
136        STRING/G nsPre = "cs:"
137        STRING/G nsStr = "cs=" + ns
138
139        SVAR nsPre = root:Packages:CS_XMLreader:nsPre
140        SVAR nsStr = root:Packages:CS_XMLreader:nsStr
141       
142        STRSWITCH(ns)   
143        CASE "cansas1d/1.0":                                                    // version 1.0 of the canSAS 1-D reduced SAS data standard
144        CASE "urn:cansas1d:1.1":                                                // version 1.1 of the canSAS 1-D reduced SAS data standard
145                PRINT fileName, "\t\t identified as: " + ns + " XML file"
146                returnCode = CS_1i_parseXml(fileID)                     //  This is where the action happens!
147                IF (returnCode != 0)
148                        IF (strlen(errorMsg) == 0)
149                                errorMsg = "error while parsing the XML"
150                        ENDIF
151                        PRINT errorMsg
152                        XmlCloseFile(fileID,0)
153                        SetDataFolder $origFolder
154                        RETURN(returnCode)                      // error while parsing the XML
155                ENDIF
156                BREAK
157        CASE "cansas1d/2.0a":                                           // unsupported
158        DEFAULT:                                                        // optional default expression executed
159                errorMsg = fileName + ": <SASroot>, namespace (" + ns + ") is not supported"
160                PRINT errorMsg
161                XmlCloseFile(fileID,0)
162                SetDataFolder $origFolder
163                RETURN(-3)                                              // attribute list must include version="1.0"
164        ENDSWITCH
165
166        XmlCloseFile(fileID,0)                                  // now close the file, without saving
167        fileID = -1
168
169        SetDataFolder root:Packages:CS_XMLreader
170        KillWaves/Z M_listXPath, SASentryList
171        SetDataFolder $origFolder
172        RETURN(0)                                                       // execution finished OK
173END
174
175FUNCTION/S CS_getDefaultNamespace(fileID)
176        // Test here (by guessing) for the various known namespaces.
177        // Return the one found in the "schemaLocation" attribute
178        // since the XMLutils XOP does not provide any xmlns attributes.
179        // It is possible to call XMLelemList and get the namespace directly
180        // but that call can be expensive (time) when there are lots of elements.
181        VARIABLE fileID
182        STRING ns = "", thisLocation
183        VARIABLE i, item
184        MAKE/T/N=(2)/O nsList           // list of all possible namespaces
185        nsList[0] = "cansas1d/1.0"              // first version of canSAS 1-D reduced SAS
186        nsList[1] = "urn:cansas1d:1.1"  // second version of canSAS 1-D reduced SAS
187
188        FOR (item = 0; item < DimSize(nsList, 0); item += 1)            // loop over all possible namespaces
189                XMLlistAttr(fileID, "/cs:SASroot", "cs="+nsList[item])
190                WAVE/T M_listAttr
191                FOR (i = 0; i < DimSize(M_listAttr,0); i+=1)                    // loop over all available attributes
192                        // Expect the required canSAS XML header (will fail if "schemalocation" is not found)
193                        IF ( CmpStr(  LowerStr(M_listAttr[i][1]),  LowerStr("schemaLocation") ) == 0 )
194                                thisLocation = TrimWS(M_listAttr[i][2])
195                                IF ( StringMatch(thisLocation, nsList[item] + "*") )
196                                        ns = nsList[item]
197                                        BREAK           // found it!
198                                ENDIF
199                        ENDIF
200                ENDFOR
201                IF (strlen(ns))
202                        BREAK           // found it!
203                ENDIF
204        ENDFOR
205
206        KillWaves/Z nsList, M_listAttr
207        RETURN ns
208END
209
210// ==================================================================
211
212FUNCTION CS_1i_parseXml(fileID)
213        VARIABLE fileID
214        SVAR errorMsg, xmlFile
215        STRING/G Title, Title_folder
216        VARIABLE i, j, index, SASdata_index, returnCode = 0
217
218        SVAR nsPre = root:Packages:CS_XMLreader:nsPre
219        SVAR nsStr = root:Packages:CS_XMLreader:nsStr
220
221        // locate all the SASentry elements
222        //      assume nsPre = "cs" otherwise
223        // "/"+nsPre+":SASroot//"+nsPre+":SASentry"
224        XmlListXpath(fileID, "/cs:SASroot//cs:SASentry", nsStr)
225        WAVE/T  M_listXPath
226        STRING          SASentryPath
227        DUPLICATE/O/T   M_listXPath, SASentryList
228
229        FOR (i=0; i < DimSize(SASentryList, 0); i += 1)
230                SASentryPath = "/cs:SASroot/cs:SASentry["+num2str(i+1)+"]"
231                SetDataFolder root:Packages:CS_XMLreader
232               
233                title =  CS_1i_locateTitle(fileID, SASentryPath)
234                Title_folder = CS_cleanFolderName(Title)
235                NewDataFolder/O/S  $Title_folder
236
237                XmlListXpath(fileID, SASentryPath + "//cs:SASdata", nsStr)
238                WAVE/T  M_listXPath
239                IF ( DimSize(M_listXPath, 0) == 1)
240                        CS_1i_getOneSASdata(fileID, Title, SASentryPath+"/cs:SASdata")
241                        CS_1i_collectMetadata(fileID, SASentryPath)
242                ELSE
243                        FOR (j = 0; j < DimSize(M_listXPath, 0); j += 1)
244                                // Could make this new behavior optional
245                                STRING SASdata_item = "SASdata_" + num2str(j)
246                                STRING SASdata_node = SASentryPath+"/cs:SASdata["+num2str(j+1)+"]"
247                                // Preferred name obtained from the SASentry/SASdata/@name attribute, if present
248                                STRING SASdata_name = XMLstrFmXpath(fileID,  SASdata_node + "/@name", nsStr, "")
249                                IF (strlen(SASdata_name) == 0)
250                                        IF (DimSize(M_listXPath, 0) == 1)
251                                                // Alternative if only one SASdata block is to use the SASentry/Title
252                                                SASdata_name = XMLstrFmXpath(fileID,  SASentryPath+"/cs:Title", nsStr, "")
253                                        ELSE
254                                                // the original behavior: SASdata_0, SASdata_1, ...
255                                                SASdata_name = SASdata_item
256                                        ENDIF
257                                        // the original behavior: SASdata_0, SASdata_1, ...
258                                        SASdata_name = SASdata_item
259                                ENDIF
260                                STRING SASdataFolder = CS_cleanFolderName(SASdata_name)
261                                NewDataFolder/O/S  $SASdataFolder
262                                CS_1i_getOneSASdata(fileID, Title, SASdata_node)
263                                CS_1i_collectMetadata(fileID, SASentryPath)
264                                SetDataFolder ::                        // back up to parent directory
265                        ENDFOR
266                ENDIF
267
268                // TODO: process any transmission spectra
269                STRING/G ns = CS_getDefaultNamespace(fileID)
270                IF (cmpstr(ns,  "urn:cansas1d:1.1") == 0)
271                        XmlListXpath(fileID, SASentryPath + "//cs:SAStransmission_spectrum", nsStr)
272                        WAVE/T  M_listXPath
273                        print "Searching for SAStransmission_spectrum groups"
274                        print DimSize(M_listXPath, 0) , M_listXPath
275                        // ...
276                ENDIF
277               
278                KillWaves/Z M_listXPath
279        ENDFOR
280
281        SetDataFolder root:Packages:CS_XMLreader
282        KillWaves/Z M_listXPath, SASentryList
283        RETURN(returnCode)
284END
285
286// ==================================================================
287
288FUNCTION/S CS_cleanFolderName(proposal)
289        STRING proposal
290        STRING result
291        result = CleanupName(proposal, 0)
292        IF ( CheckName(result, 11) != 0 )
293                result = UniqueName(result, 11, 0)
294        ENDIF
295        RETURN result
296END
297
298// ==================================================================
299
300FUNCTION CS_1i_getOneSASdata(fileID, Title, SASdataPath)
301        VARIABLE fileID
302        STRING Title, SASdataPath
303        SVAR nsPre = root:Packages:CS_XMLreader:nsPre
304        SVAR nsStr = root:Packages:CS_XMLreader:nsStr
305        VARIABLE i
306        STRING SASdata_name, suffix = ""
307
308        //grab the data and put it in the working data folder
309        CS_1i_GetReducedSASdata(fileID, SASdataPath)
310
311        //start the metadata
312        MAKE/O/T/N=(0,2) metadata
313
314        SVAR xmlFile = root:Packages:CS_XMLreader:xmlFile
315        CS_appendMetaData(fileID, "xmlFile", "", xmlFile)
316
317        SVAR ns = root:Packages:CS_XMLreader:ns
318        CS_appendMetaData(fileID, "namespace", "", ns)
319        CS_appendMetaData(fileID, "Title", "", Title)
320       
321        XmlListXpath(fileID, SASdataPath + "/..//cs:Run", nsStr)
322        WAVE/T  M_listXPath
323        FOR (i=0; i < DimSize(M_listXPath, 0); i += 1)
324                IF ( DimSize(M_listXPath, 0) > 1 )
325                        suffix = "_" + num2str(i)
326                ENDIF
327                CS_appendMetaData(fileID, "Run" + suffix,  SASdataPath + "/../cs:Run["+num2str(i+1)+"]", "")
328                CS_appendMetaData(fileID, "Run/@name" + suffix,  SASdataPath + "/../cs:Run["+num2str(i+1)+"]/@name", "")
329        ENDFOR
330
331        SASdata_name = TrimWS(XMLstrFmXpath(fileID,  SASdataPath + "/@name", nsStr, ""))
332        CS_appendMetaData(fileID, "SASdata/@name", "", SASdata_name)
333
334        KillWaves/Z M_listXPath
335END
336
337// ==================================================================
338
339FUNCTION CS_1i_getOneVector(file,prefix,XML_name,Igor_name)
340        VARIABLE file
341        STRING prefix,XML_name,Igor_name
342        SVAR nsPre = root:Packages:CS_XMLreader:nsPre
343        SVAR nsStr = root:Packages:CS_XMLreader:nsStr
344
345        XmlWaveFmXpath(file,prefix+XML_name,nsStr,"")                   //this loads ALL the vector's nodes at the same time
346        WAVE/T M_xmlcontent
347        WAVE/T W_xmlContentNodes
348        IF (DimSize(M_xmlcontent, 0))                   // test to see if the nodes exist.  not strictly necessary if you know the nodes are there
349                IF (DimSize(M_xmlcontent,1)>DimSize(M_xmlcontent,0))    //if you're not in vector mode
350                        MatrixTranspose M_xmlcontent
351                ENDIF
352                MAKE/O/D/N=(DimSize(M_xmlcontent, 0)) $Igor_name
353                WAVE vect = $Igor_name
354                vect=str2num(M_xmlcontent)
355        ENDIF
356        KILLWAVES/Z M_xmlcontent, W_xmlContentNodes
357END
358
359// ==================================================================
360
361FUNCTION CS_1i_GetReducedSASdata(fileID, SASdataPath)
362        VARIABLE fileID
363        STRING SASdataPath
364        SVAR nsPre = root:Packages:CS_XMLreader:nsPre
365        SVAR nsStr = root:Packages:CS_XMLreader:nsStr
366        STRING prefix = ""
367        VARIABLE pos
368
369        VARIABLE cansasStrict = 1               // !!!software developer's choice!!!
370        IF (cansasStrict)               // only get known canSAS data vectors
371                prefix = SASdataPath + "//cs:"
372                // load ALL nodes of each vector (if exists) at the same time
373                CS_1i_getOneVector(fileID, prefix, "Q",                 "Qsas")
374                CS_1i_getOneVector(fileID, prefix, "I",                 "Isas")
375                CS_1i_getOneVector(fileID, prefix, "Idev",              "Idev")
376                CS_1i_getOneVector(fileID, prefix, "Qdev",              "Qdev")
377                CS_1i_getOneVector(fileID, prefix, "dQw",       "dQw")
378                CS_1i_getOneVector(fileID, prefix, "dQl",               "dQl")
379                CS_1i_getOneVector(fileID, prefix, "Qmean",     "Qmean")
380                CS_1i_getOneVector(fileID, prefix, "Shadowfactor",      "Shadowfactor")
381                // check them for common length
382        ELSE                            // search for _ANY_ data vectors
383                // find the names of all the data columns and load them as vectors
384                // this gets tricky if we want to avoid namespace references
385                XmlListXpath(fileID, SASdataPath+"//cs:Idata[1]/*", nsStr)
386                WAVE/T M_listXPath
387                STRING xmlElement, xPathStr
388                STRING igorWave
389                VARIABLE j
390                FOR (j = 0; j < DimSize(M_listXPath, 0); j += 1)        // loop over all columns in SASdata/Idata[1]
391                        xmlElement = M_listXPath[j][1]
392                        STRSWITCH(xmlElement)
393                                CASE "Q":               // IgorPro does not allow a variable named Q
394                                CASE "I":                       // or I
395                                        igorWave = xmlElement + "sas"
396                                        BREAK
397                                DEFAULT:
398                                        igorWave = xmlElement           // can we trust this one?
399                        ENDSWITCH
400                        //
401//                      // This will need some work to support foreign namespaces here
402//                      //
403//                      //
404//                      xPathStr = M_listXPath[j][0]                                                    // clear name reference
405//                      pos = strsearch(xPathStr, "/", Inf, 3)                                  // peel off the tail of the string and reform
406//                      xmlElement = xPathStr[pos,Inf]                                          // find last element on the path
407//                      prefix = xPathStr[0, pos-1-4]+"/*"                                              // ALL Idata elements
408//                      CS_1i_getOneVector(fileID,prefix, xmlElement, igorWave)         // loads ALL rows (Idata) of the column at the same time
409                        //
410                        //  Could there be a problem with a foreign namespace here?
411                        prefix = SASdataPath+"//cs:Idata"                                               // ALL Idata elements
412                        xmlElement = "cs:" + M_listXPath[j][1]                                  // just this column
413                        CS_1i_getOneVector(fileID,prefix, xmlElement, igorWave)         // loads ALL rows (Idata) of the column at the same time
414                ENDFOR
415                // check them for common length
416        ENDIF
417 
418        //get rid of any mess
419        KILLWAVES/z M_listXPath
420END
421
422// ==================================================================
423
424FUNCTION CS_1i_collectMetadata(fileID, sasEntryPath)
425        VARIABLE fileID
426        STRING sasEntryPath
427        VARIABLE i, j
428        WAVE/T metadata
429        STRING suffix = "", preMeta = "", preXpath = ""
430        STRING value, detailsPath, detectorPath, notePath
431
432        SVAR nsPre = root:Packages:CS_XMLreader:nsPre
433        SVAR nsStr = root:Packages:CS_XMLreader:nsStr
434
435        // collect some metadata
436        // first, fill a table with keywords, and XPath locations, 3rd column will be values
437
438        // handle most <SASsample> fields
439        CS_appendMetaData(fileID, "SASsample/@name",                            sasEntryPath + "/cs:SASsample/@name", "")
440        CS_appendMetaData(fileID, "SASsample/ID",                                       sasEntryPath + "/cs:SASsample/cs:ID", "")
441        CS_appendMetaData(fileID, "SASsample/thickness",                                sasEntryPath + "/cs:SASsample/cs:thickness", "")
442        CS_appendMetaData(fileID, "SASsample/thickness/@unit",                  sasEntryPath + "/cs:SASsample/cs:thickness/@unit", "")
443        CS_appendMetaData(fileID, "SASsample/transmission",                     sasEntryPath + "/cs:SASsample/cs:transmission", "")
444        CS_appendMetaData(fileID, "SASsample/temperature",                      sasEntryPath + "/cs:SASsample/cs:temperature", "")
445        CS_appendMetaData(fileID, "SASsample/temperature/@unit",           sasEntryPath + "/cs:SASsample/cs:temperature/@unit", "")
446        CS_appendMetaData(fileID, "SASsample/position/x",                          sasEntryPath + "/cs:SASsample/cs:position/cs:x", "")
447        CS_appendMetaData(fileID, "SASsample/position/x/@unit",            sasEntryPath + "/cs:SASsample/cs:position/cs:x/@unit", "")
448        CS_appendMetaData(fileID, "SASsample/position/y",                          sasEntryPath + "/cs:SASsample/cs:position/cs:y", "")
449        CS_appendMetaData(fileID, "SASsample/position/y/@unit",            sasEntryPath + "/cs:SASsample/cs:position/cs:y/@unit", "")
450        CS_appendMetaData(fileID, "SASsample/position/z",                          sasEntryPath + "/cs:SASsample/cs:position/cs:z", "")
451        CS_appendMetaData(fileID, "SASsample/position/z/@unit",            sasEntryPath + "/cs:SASsample/cs:position/cs:z/@unit", "")
452        CS_appendMetaData(fileID, "SASsample/orientation/roll",                    sasEntryPath + "/cs:SASsample/cs:orientation/cs:roll", "")
453        CS_appendMetaData(fileID, "SASsample/orientation/roll/@unit",      sasEntryPath + "/cs:SASsample/cs:orientation/cs:roll/@unit", "")
454        CS_appendMetaData(fileID, "SASsample/orientation/pitch",           sasEntryPath + "/cs:SASsample/cs:orientation/cs:pitch", "")
455        CS_appendMetaData(fileID, "SASsample/orientation/pitch/@unit",     sasEntryPath + "/cs:SASsample/cs:orientation/cs:pitch/@unit", "")
456        CS_appendMetaData(fileID, "SASsample/orientation/yaw",                     sasEntryPath + "/cs:SASsample/cs:orientation/cs:yaw", "")
457        CS_appendMetaData(fileID, "SASsample/orientation/yaw/@unit",       sasEntryPath + "/cs:SASsample/cs:orientation/cs:yaw/@unit", "")
458        // <SASsample><details> might appear multiple times, too!
459        XmlListXpath(fileID, sasEntryPath+"/cs:SASsample//cs:details", nsStr)   //output: M_listXPath
460        WAVE/T  M_listXPath
461        DUPLICATE/O/T   M_listXPath, detailsList
462        suffix = ""
463        FOR (i = 0; i < DimSize(detailsList, 0); i += 1)
464                IF (DimSize(detailsList, 0) > 1)
465                        suffix = "_" + num2str(i)
466                ENDIF
467                detailsPath = sasEntryPath+"/cs:SASsample/cs:details["+num2str(i+1)+"]"
468                CS_appendMetaData(fileID, "SASsample/details"+suffix+"/@name",  detailsPath + "/@name", "")
469                CS_appendMetaData(fileID, "SASsample/details"+suffix,           detailsPath, "")
470        ENDFOR
471
472
473        // <SASinstrument>
474        CS_appendMetaData(fileID, "SASinstrument/name",         sasEntryPath + "/cs:SASinstrument/cs:name", "")
475        CS_appendMetaData(fileID, "SASinstrument/@name",        sasEntryPath + "/cs:SASinstrument/@name", "")
476
477        // <SASinstrument><SASsource>
478        preMeta = "SASinstrument/SASsource"
479        preXpath = sasEntryPath + "/cs:SASinstrument/cs:SASsource"
480        CS_appendMetaData(fileID, preMeta + "/@name",                      preXpath + "/@name", "")
481        CS_appendMetaData(fileID, preMeta + "/radiation",                  preXpath + "/cs:radiation", "")
482        CS_appendMetaData(fileID, preMeta + "/beam/size/@name",            preXpath + "/cs:beam_size/@name", "")
483        CS_appendMetaData(fileID, preMeta + "/beam/size/x",                preXpath + "/cs:beam_size/cs:x", "")
484        CS_appendMetaData(fileID, preMeta + "/beam/size/x@unit",           preXpath + "/cs:beam_size/cs:x/@unit", "")
485        CS_appendMetaData(fileID, preMeta + "/beam/size/y",                preXpath + "/cs:beam_size/cs:y", "")
486        CS_appendMetaData(fileID, preMeta + "/beam/size/y@unit",           preXpath + "/cs:beam_size/cs:y/@unit", "")
487        CS_appendMetaData(fileID, preMeta + "/beam/size/z",                preXpath + "/cs:beam_size/cs:z", "")
488        CS_appendMetaData(fileID, preMeta + "/beam/size/z@unit",           preXpath + "/cs:beam_size/cs:z/@unit", "")
489        CS_appendMetaData(fileID, preMeta + "/beam/shape",                 preXpath + "/cs:beam_shape", "")
490        CS_appendMetaData(fileID, preMeta + "/wavelength",                 preXpath + "/cs:wavelength", "")
491        CS_appendMetaData(fileID, preMeta + "/wavelength/@unit",           preXpath + "/cs:wavelength/@unit", "")
492        CS_appendMetaData(fileID, preMeta + "/wavelength_min",             preXpath + "/cs:wavelength_min", "")
493        CS_appendMetaData(fileID, preMeta + "/wavelength_min/@unit",       preXpath + "/cs:wavelength_min/@unit", "")
494        CS_appendMetaData(fileID, preMeta + "/wavelength_max",             preXpath + "/cs:wavelength_max", "")
495        CS_appendMetaData(fileID, preMeta + "/wavelength_max/@unit",       preXpath + "/cs:wavelength_max/@unit", "")
496        CS_appendMetaData(fileID, preMeta + "/wavelength_spread",          preXpath + "/cs:wavelength_spread", "")
497        CS_appendMetaData(fileID, preMeta + "/wavelength_spread/@unit",    preXpath + "/cs:wavelength_spread/@unit", "")
498
499        // <SASinstrument><SAScollimation> might appear multiple times
500        XmlListXpath(fileID, sasEntryPath+"/cs:SASinstrument//cs:SAScollimation", nsStr)        //output: M_listXPath
501        WAVE/T  M_listXPath
502        DUPLICATE/O/T   M_listXPath, SAScollimationList
503        STRING collimationPath
504        FOR (i = 0; i < DimSize(SAScollimationList, 0); i += 1)
505                preMeta = "SASinstrument/SAScollimation"
506                IF (DimSize(SAScollimationList, 0) > 1)
507                        preMeta += "_" + num2str(i)
508                ENDIF
509                collimationPath = sasEntryPath+"/cs:SASinstrument/cs:SAScollimation["+num2str(i+1)+"]"
510                CS_appendMetaData(fileID, preMeta + "/@name",               collimationPath + "/@name", "")
511                CS_appendMetaData(fileID, preMeta + "/length",              collimationPath + "/cs:length", "")
512                CS_appendMetaData(fileID, preMeta + "/length_unit",         collimationPath + "/cs:length/@unit", "")
513                FOR (j = 0; j < DimSize(M_listXPath, 0); j += 1)        // aperture may be repeated!
514                        IF (DimSize(M_listXPath, 0) == 1)
515                                preMeta = "SASinstrument/SAScollimation/aperture"
516                        ELSE
517                                preMeta = "SASinstrument/SAScollimation/aperture_" + num2str(j)
518                        ENDIF
519                        preXpath = collimationPath + "/cs:aperture["+num2str(j+1)+"]"
520                        CS_appendMetaData(fileID, preMeta + "/@name",         preXpath + "/@name", "")
521                        CS_appendMetaData(fileID, preMeta + "/type",          preXpath + "/cs:type", "")
522                        CS_appendMetaData(fileID, preMeta + "/size/@name",     preXpath + "/cs:size/@name", "")
523                        CS_appendMetaData(fileID, preMeta + "/size/x",        preXpath + "/cs:size/cs:x", "")
524                        CS_appendMetaData(fileID, preMeta + "/size/x/@unit",   preXpath + "/cs:size/cs:x/@unit", "")
525                        CS_appendMetaData(fileID, preMeta + "/size/y",        preXpath + "/cs:size/cs:y", "")
526                        CS_appendMetaData(fileID, preMeta + "/size/y/@unit",   preXpath + "/cs:size/cs:y/@unit", "")
527                        CS_appendMetaData(fileID, preMeta + "/size/z",        preXpath + "/cs:size/cs:z", "")
528                        CS_appendMetaData(fileID, preMeta + "/size/z/@unit",   preXpath + "/cs:size/cs:z/@unit", "")
529                        CS_appendMetaData(fileID, preMeta + "/distance",       preXpath + "/cs:distance", "")
530                        CS_appendMetaData(fileID, preMeta + "/distance/@unit", preXpath + "/cs:distance/@unit", "")
531                ENDFOR
532        ENDFOR
533
534        // <SASinstrument><SASdetector> might appear multiple times
535        XmlListXpath(fileID, sasEntryPath+"/cs:SASinstrument//cs:SASdetector", nsStr)   //output: M_listXPath
536        WAVE/T  M_listXPath
537        DUPLICATE/O/T   M_listXPath, SASdetectorList
538        FOR (i = 0; i < DimSize(SASdetectorList, 0); i += 1)
539                preMeta = "SASinstrument/SASdetector"
540                IF (DimSize(SASdetectorList, 0) > 1)
541                        preMeta += "_" + num2str(i)
542                ENDIF
543                detectorPath = sasEntryPath+"/cs:SASinstrument/cs:SASdetector["+num2str(i+1)+"]"
544                CS_appendMetaData(fileID, preMeta + "/@name",                    detectorPath + "/cs:name", "")
545                CS_appendMetaData(fileID, preMeta + "/SDD",                              detectorPath + "/cs:SDD", "")
546                CS_appendMetaData(fileID, preMeta + "/SDD/@unit",                        detectorPath + "/cs:SDD/@unit", "")
547                CS_appendMetaData(fileID, preMeta + "/offset/@name",             detectorPath + "/cs:offset/@name", "")
548                CS_appendMetaData(fileID, preMeta + "/offset/x",                 detectorPath + "/cs:offset/cs:x", "")
549                CS_appendMetaData(fileID, preMeta + "/offset/x/@unit",           detectorPath + "/cs:offset/cs:x/@unit", "")
550                CS_appendMetaData(fileID, preMeta + "/offset/y",                 detectorPath + "/cs:offset/cs:y", "")
551                CS_appendMetaData(fileID, preMeta + "/offset/y/@unit",           detectorPath + "/cs:offset/cs:y/@unit", "")
552                CS_appendMetaData(fileID, preMeta + "/offset/z",                 detectorPath + "/cs:offset/cs:z", "")
553                CS_appendMetaData(fileID, preMeta + "/offset/z/@unit",           detectorPath + "/cs:offset/cs:z/@unit", "")
554
555                CS_appendMetaData(fileID, preMeta + "/orientation/@name",        detectorPath + "/cs:orientation/@name", "")
556                CS_appendMetaData(fileID, preMeta + "/orientation/roll",         detectorPath + "/cs:orientation/cs:roll", "")
557                CS_appendMetaData(fileID, preMeta + "/orientation/roll/@unit",   detectorPath + "/cs:orientation/cs:roll/@unit", "")
558                CS_appendMetaData(fileID, preMeta + "/orientation/pitch",        detectorPath + "/cs:orientation/cs:pitch", "")
559                CS_appendMetaData(fileID, preMeta + "/orientation/pitch/@unit",   detectorPath + "/cs:orientation/cs:pitch/@unit", "")
560                CS_appendMetaData(fileID, preMeta + "/orientation/yaw",          detectorPath + "/cs:orientation/cs:yaw", "")
561                CS_appendMetaData(fileID, preMeta + "/orientation/yaw/@unit",    detectorPath + "/cs:orientation/cs:yaw/@unit", "")
562
563                CS_appendMetaData(fileID, preMeta + "/beam_center/@name",        detectorPath + "/cs:beam_center/@name", "")
564                CS_appendMetaData(fileID, preMeta + "/beam_center/x",            detectorPath + "/cs:beam_center/cs:x", "")
565                CS_appendMetaData(fileID, preMeta + "/beam_center/x/@unit",      detectorPath + "/cs:beam_center/cs:x/@unit", "")
566                CS_appendMetaData(fileID, preMeta + "/beam_center/y",            detectorPath + "/cs:beam_center/cs:y", "")
567                CS_appendMetaData(fileID, preMeta + "/beam_center/y/@unit",      detectorPath + "/cs:beam_center/cs:y/@unit", "")
568                CS_appendMetaData(fileID, preMeta + "/beam_center/z",            detectorPath + "/cs:beam_center/cs:z", "")
569                CS_appendMetaData(fileID, preMeta + "/beam_center/z/@unit",      detectorPath + "/cs:beam_center/cs:z/@unit", "")
570
571                CS_appendMetaData(fileID, preMeta + "/pixel_size/@name",         detectorPath + "/cs:pixel_size/@name", "")
572                CS_appendMetaData(fileID, preMeta + "/pixel_size/x",             detectorPath + "/cs:pixel_size/cs:x", "")
573                CS_appendMetaData(fileID, preMeta + "/pixel_size/x/@unit",       detectorPath + "/cs:pixel_size/cs:x/@unit", "")
574                CS_appendMetaData(fileID, preMeta + "/pixel_size/y",             detectorPath + "/cs:pixel_size/cs:y", "")
575                CS_appendMetaData(fileID, preMeta + "/pixel_size/y/@unit",       detectorPath + "/cs:pixel_size/cs:y/@unit", "")
576                CS_appendMetaData(fileID, preMeta + "/pixel_size/z",             detectorPath + "/cs:pixel_size/cs:z", "")
577                CS_appendMetaData(fileID, preMeta + "/pixel_size/z/@unit",       detectorPath + "/cs:pixel_size/cs:z/@unit", "")
578
579                CS_appendMetaData(fileID, preMeta + "/slit_length",                    detectorPath + "/cs:slit_length", "")
580                CS_appendMetaData(fileID, preMeta + "/slit_length/@unit",              detectorPath + "/cs:slit_length/@unit", "")
581        ENDFOR
582
583        // <SASprocess> might appear multiple times
584        XmlListXpath(fileID, sasEntryPath+"//cs:SASprocess", nsStr)     //output: M_listXPath
585        WAVE/T  M_listXPath
586        DUPLICATE/O/T   M_listXPath, SASprocessList
587        STRING SASprocessPath, prefix
588        FOR (i = 0; i < DimSize(SASprocessList, 0); i += 1)
589                preMeta = "SASprocess"
590                IF (DimSize(SASprocessList, 0) > 1)
591                        preMeta += "_" + num2str(i)
592                ENDIF
593                SASprocessPath = sasEntryPath+"/cs:SASprocess["+num2str(i+1)+"]"
594                CS_appendMetaData(fileID, preMeta+"/@name",        SASprocessPath + "/@name", "")
595                CS_appendMetaData(fileID, preMeta+"/name",         SASprocessPath + "/cs:name", "")
596                CS_appendMetaData(fileID, preMeta+"/date",                 SASprocessPath + "/cs:date", "")
597                CS_appendMetaData(fileID, preMeta+"/description",   SASprocessPath + "/cs:description", "")
598                XmlListXpath(fileID, SASprocessPath+"//cs:term", nsStr)
599                FOR (j = 0; j < DimSize(M_listXPath, 0); j += 1)
600                        prefix = SASprocessPath + "/cs:term[" + num2str(j+1) + "]"
601                        CS_appendMetaData(fileID, preMeta+"/term_"+num2str(j)+"/@name",     prefix + "/@name", "")
602                        CS_appendMetaData(fileID, preMeta+"/term_"+num2str(j)+"/@unit",           prefix + "/@unit", "")
603                        CS_appendMetaData(fileID, preMeta+"/term_"+num2str(j),                            prefix, "")
604                ENDFOR
605                // ignore <SASprocessnote>
606        ENDFOR
607
608        // <SASnote> might appear multiple times
609        XmlListXpath(fileID, sasEntryPath+"//cs:SASnote", nsStr)        //output: M_listXPath
610        WAVE/T  M_listXPath
611        DUPLICATE/O/T   M_listXPath, SASnoteList
612        FOR (i = 0; i < DimSize(SASnoteList, 0); i += 1)
613                preMeta = "SASnote"
614                IF (DimSize(SASnoteList, 0) > 1)
615                        preMeta += "_" + num2str(i)
616                ENDIF
617                notePath = sasEntryPath+"//cs:SASnote["+num2str(i+1)+"]"
618                CS_appendMetaData(fileID, preMeta+"/@name",     notePath + "/@name", "")
619                CS_appendMetaData(fileID, preMeta,              notePath, "")
620        ENDFOR
621
622        KillWaves/Z M_listXPath, detailsList, SAScollimationList, SASdetectorList, SASprocessList, SASnoteList
623END
624
625// ==================================================================
626
627FUNCTION/S CS_1i_locateTitle(fileID, SASentryPath)
628        VARIABLE fileID
629        STRING SASentryPath
630        STRING TitlePath, Title
631        SVAR nsPre = root:Packages:CS_XMLreader:nsPre
632        SVAR nsStr = root:Packages:CS_XMLreader:nsStr
633
634        // /cs:SASroot/cs:SASentry/cs:Title is the expected location, but it could be empty
635        TitlePath = SASentryPath + "/cs:Title"
636        Title = XMLstrFmXpath(fileID,  TitlePath, nsStr, "")
637        // search harder for a title
638        IF (strlen(Title) == 0)
639                TitlePath = SASentryPath + "/@name"
640                Title = XMLstrFmXpath(fileID,  TitlePath, nsStr, "")
641        ENDIF
642        IF (strlen(Title) == 0)
643                TitlePath = SASentryPath + "/cs:SASsample/cs:ID"
644                Title = XMLstrFmXpath(fileID,  TitlePath, nsStr, "")
645        ENDIF
646        IF (strlen(Title) == 0)
647                TitlePath = SASentryPath + "/cs:SASsample/@name"
648                Title = XMLstrFmXpath(fileID,  TitlePath, nsStr, "")
649        ENDIF
650        IF (strlen(Title) == 0)
651                // last resort: make up a title
652                Title = "SASentry"
653                TitlePath = ""
654        ENDIF
655        PRINT "\t Title:", Title
656        RETURN(Title)
657END
658
659// ==================================================================
660
661FUNCTION CS_appendMetaData(fileID, key, xpath, value)
662        VARIABLE fileID
663        STRING key, xpath, value
664        WAVE/T metadata
665        STRING k, v
666
667        SVAR nsPre = root:Packages:CS_XMLreader:nsPre
668        SVAR nsStr = root:Packages:CS_XMLreader:nsStr
669
670        k = TrimWS(key)
671        IF (  strlen(k) > 0 )
672                IF ( strlen(xpath) > 0 )
673                        value = XMLstrFmXpath(fileID,  xpath, nsStr, "")
674                ENDIF
675                // What if the value string has a ";" embedded?
676                //  This could complicate (?compromise?) the wavenote "key=value;" syntax.
677                //  But let the caller deal with it.
678                v = TrimWS(ReplaceString(";", value, " :semicolon: "))
679                IF ( strlen(v) > 0 )
680                        VARIABLE last
681                        last = DimSize(metadata, 0)
682                        Redimension/N=(last+1, 2) metadata
683                        metadata[last][0] = k
684                        metadata[last][1] = v
685                ENDIF
686        ENDIF
687END
688
689// ==================================================================
690
691Function/S   TrimWS(str)
692    // TrimWhiteSpace (code from Jon Tischler)
693    String str
694    return TrimWSL(TrimWSR(str))
695End
696
697// ==================================================================
698
699Function/S   TrimWSL(str)
700    // TrimWhiteSpaceLeft (code from Jon Tischler)
701    String str
702    Variable i, N=strlen(str)
703    for (i=0;char2num(str[i])<=32 && i<N;i+=1)    // find first non-white space
704    endfor
705    return str[i,Inf]
706End
707
708// ==================================================================
709
710Function/S   TrimWSR(str)
711    // TrimWhiteSpaceRight (code from Jon Tischler)
712    String str
713    Variable i
714    for (i=strlen(str)-1; char2num(str[i])<=32 && i>=0; i-=1)    // find last non-white space
715    endfor
716    return str[0,i]
717End
718
719// ==================================================================
720// ==================================================================
721// ==================================================================
722
723
724FUNCTION prj_grabMyXmlData()
725        STRING srcDir = "root:Packages:CS_XMLreader"
726        STRING destDir = "root:PRJ_canSAS"
727        STRING srcFolder, destFolder, theFolder
728        Variable i
729        NewDataFolder/O  $destDir               // for all my imported data
730        FOR ( i = 0; i < CountObjects(srcDir, 4) ; i += 1 )
731                theFolder = GetIndexedObjName(srcDir, 4, i)
732                srcFolder = srcDir + ":" + theFolder
733                destFolder = destDir + ":" + theFolder
734                // PRINT srcFolder, destFolder
735                IF (DataFolderExists(destFolder))
736                        // !!!!!!!!!!!!!!!!! NOTE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
737                        // need to find unique name for destination
738                        // Persons who implement this properly should be more elegant
739                        // For now, I will blast the existing and proceed blindly.
740                        KillDataFolder/Z  $destFolder           // clear out any previous work
741                        DuplicateDataFolder $srcFolder, $destFolder
742                ELSE
743                        DuplicateDataFolder $srcFolder, $destFolder
744                ENDIF
745        ENDFOR
746END
747
748FUNCTION prjTest_cansas1d()
749        // unit tests for the routines under prj-readXML.ipf
750        STRING theFile
751        STRING fList = ""
752        VARIABLE i, result, timerID, seconds
753        // build a table of test data sets
754        fList = AddListItem("elmo.xml",                                 fList, ";", Inf)                // non-existent file
755        fList = AddListItem("cansasXML.ipf",                    fList, ";", Inf)                // this file (should fail on XML parsing)
756        fList = AddListItem("../examples/book.xml",                             fList, ";", Inf)                // good XML example file but not canSAS, not even close
757        fList = AddListItem("../examples/bimodal-test1.xml",            fList, ";", Inf)                // simple dataset
758        fList = AddListItem("../examples/testers/test3.xml",                                    fList, ";", Inf)                // no number provided for wavelength, others, too
759        fList = AddListItem("../examples/ISIS_SANS_Example.xml",        fList, ";", Inf)                // from S. King, 2008-03-17
760        fList = AddListItem("../examples/W1W2.xml",                             fList, ";", Inf)                // from S. King, 2008-03-17
761        fList = AddListItem("../examples/ill_sasxml_example.xml",       fList, ";", Inf)                // from canSAS 2007 meeting, reformatted
762        fList = AddListItem("../examples/isis_sasxml_example.xml",      fList, ";", Inf)                // from canSAS 2007 meeting, reformatted
763        fList = AddListItem("../examples/r586.xml",                                     fList, ";", Inf)                // from canSAS 2007 meeting, reformatted
764        fList = AddListItem("../examples/r597.xml",                                     fList, ";", Inf)                // from canSAS 2007 meeting, reformatted
765        fList = AddListItem("../examples/xg009036_001.xml",             fList, ";", Inf)                // foreign elements with other namespaces
766        fList = AddListItem("../examples/cs_collagen.xml",                      fList, ";", Inf)                // another simple dataset, bare minimum info
767        fList = AddListItem("../examples/cs_collagen_full.xml",                 fList, ";", Inf)                // more Q range than previous
768        fList = AddListItem("../examples/cs_af1410.xml",                        fList, ";", Inf)                // multiple SASentry and SASdata elements
769        fList = AddListItem("../examples/cs_rr_polymers.xml",           fList, ";", Inf)                // Round Robin polymer samples from John Barnes @ NIST
770        fList = AddListItem("../examples/cansas1d-template.xml",        fList, ";", Inf)                // multiple SASentry and SASdata elements
771        fList = AddListItem("../examples/1998spheres.xml",                      fList, ";", Inf)                // 2 SASentry, few thousand data points each
772        fList = AddListItem("../examples/does-not-exist-file.xml",              fList, ";", Inf)                // non-existent file
773        fList = AddListItem("../examples/s81-polyurea.xml",                     fList, ";", Inf)                // polyurea from APS/USAXS/Indra (with extra metadata)
774        fList = AddListItem("../examples/GLASSYC_C4G8G9_w_TL.xml",                      fList, ";", Inf)                // from S. King, with transmission spectra
775       
776        // try to load each data set in the table
777        FOR ( i = 0; i < ItemsInList(fList) ; i += 1 )
778                theFile = StringFromList(i, fList)                                      // walk through all test files
779                // PRINT "file: ", theFile
780                pathInfo home
781                //IF (CS_XmlReader(theFile) == 0)                                       // did the XML reader return without an error code?
782                timerID = StartMStimer
783                result = CS_XmlReader(ParseFilePath(5,S_path,"*",0,0) + theFile)
784                seconds = StopMSTimer(timerID) * 1.0e-6
785                PRINT "\t Completed in ", seconds, " seconds"
786                IF (result == 0)    // did the XML reader return without an error code?
787                        prj_grabMyXmlData()                                             // move the data to my directory
788                ENDIF
789        ENDFOR
790END
791
792
793FUNCTION testCollette()
794                                        // !!!!!!!!!!!!!!!!! NOTE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
795                                        //          THIS IS JUST AN EXAMPLE
796
797// suggestions from ISIS users
798        // 3.   Loading actual data from LOQ caused some problems.
799        //      Data created by Colette names files with run number.
800        //      When entering full path to load the data if you use "…\example\31531.X" Igor will read \3 as a character.
801        //      A simple fix which has worked for this is to use / instead of \ e.g. "…\example/31531.X".
802       
803        //4.    Once data is loaded in Igor it is relatively easy to work with but would be nicer if the SASdata
804        //      was loaded into root directory (named using run number rather than generically as it is at the moment) rather than another folder.
805        //This becomes more problematic when two samples are being loaded for comparison.
806        //      Although still relatively easy to work with, changing the folders can lead to mistakes being made.
807
808        //Say, for Run=31531, then Qsas_31531
809
810        CS_XmlReader("../examples/W1W2.XML")
811        STRING srcDir = "root:Packages:CS_XMLreader"
812        STRING destDir = "root", importFolder, target
813        Variable i, j
814        FOR ( i = 0; i < CountObjects(srcDir, 4) ; i += 1 )
815                SetDataFolder $srcDir
816                importFolder = GetIndexedObjName(srcDir, 4, i)
817                SetDataFolder $importFolder
818                IF ( EXISTS( "metadata" ) == 1 )
819                        // looks like a SAS data folder
820                        WAVE/T metadata
821                        STRING Run = ""
822                        FOR (j = 0; j < DimSize(metadata, 0); j += 1)
823                                IF ( CmpStr( "Run", metadata[j][0]) == 0 )
824                                        // get the Run number and "clean" it up a bit
825                                        Run = TrimWS(  ReplaceString("\\", metadata[j][1], "/")  )
826                                        // !!!!!!!!!!!!!!!!! NOTE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
827                                        // need to find unique name for destination waves       
828                                        //          THIS IS JUST AN EXAMPLE
829                                        // Persons who implement this properly should be more elegant
830                                        // For now, I will blast any existing and proceed blindly.
831                                        target = "root:Qsas_" + Run
832                                        Duplicate/O Qsas, $target
833                                        target = "root:Isas_" + Run
834                                        Duplicate/O Isas, $target
835                                        IF ( exists( "Idev" ) == 1 )
836                                                target = "root:Idev_" + Run
837                                                Duplicate/O Idev, $target
838                                        ENDIF
839                                        IF ( exists( "Qdev" ) == 1 )
840                                                target = "root:Qdev_" + Run
841                                                Duplicate/O Qdev, $target
842                                        ENDIF
843                                        IF ( exists( "dQw" ) == 1 )
844                                                target = "root:QdQw_" + Run
845                                                Duplicate/O dQw, $target
846                                        ENDIF
847                                        IF ( exists( "dQl" ) == 1 )
848                                                target = "root:dQl_" + Run
849                                                Duplicate/O dQl, $target
850                                        ENDIF
851                                        IF ( exists( "Qmean" ) == 1 )
852                                                target = "root:Qmean_" + Run
853                                                Duplicate/O Qmean, $target
854                                        ENDIF
855                                        IF ( exists( "Shadowfactor" ) == 1 )
856                                                target = "root:Shadowfactor_" + Run
857                                                Duplicate/O Shadowfactor, $target
858                                        ENDIF
859                                        target = "root:metadata_" + Run
860                                        Duplicate/O/T metadata, $target
861                                        BREAK
862                                ENDIF
863                        ENDFOR
864                ENDIF
865        ENDFOR
866
867        SetDataFolder root:
868END
869
870#else   // if( Exists("XmlOpenFile") )
871        // No XMLutils XOP: provide dummy function so that IgorPro can compile dependent support code
872        FUNCTION CS_XmlReader(fileName)
873            String fileName
874            Abort  "XML function provided by XMLutils XOP is not available, get the XOP from : http://www.igorexchange.com/project/XMLutils (see http://www.smallangles.net/wgwiki/index.php/cansas1d_binding_IgorPro for details)"
875            RETURN(-6)
876        END
877#endif  // if( Exists("XmlOpenFile") )
Note: See TracBrowser for help on using the repository browser.