source: sans/Dev/trunk/NCNR_User_Procedures/Common/NIST_XML_v40.ipf @ 690

Last change on this file since 690 was 690, checked in by srkline, 12 years ago

Added model documentation for FuzzySpheres? and CSParallelpiped

Added axis labels to data loaded through XML loader

Writing of XML USANS data is now properly handling cursors

File size: 34.3 KB
Line 
1#pragma rtGlobals=1             // Use modern global access method.
2#pragma version=1.00
3#pragma IgorVersion=6.1
4
5
6#if( Exists("XmlOpenFile") )
7
8#include "cansasXML", version >= 1.10
9
10// The function is called "LoadNISTXMLData" but is actually more generic
11// and will load any canSAS XML v1 dataset
12// Dec 2008 :
13//                       Caveats - Assumes Q in /A and I in /cm
14// Takes outStr as output name. If outStr is specified then we must load only the first SASData in the firstSASEntry,
15// since anything else doesn't make sense. This is a bit of a hack to support NSORT.
16
17
18function LoadNISTXMLData(filestr,outStr,doPlot,forceOverwrite)
19        String filestr,outStr
20        Variable doPlot,forceOverwrite
21       
22       
23        Variable rr,gg,bb
24        Variable dQv
25//      NVAR/Z dQv = root:Packages:NIST:USANS_dQv               //let USANS_CalcWeights set the dQv value
26
27               
28//      Print "Trying to load canSAS XML format data"
29        Variable result = CS_XMLReader(filestr)
30       
31        String xmlReaderFolder = "root:Packages:CS_XMLreader:"
32       
33        if (result == 0)
34                        SetDataFolder xmlReaderFolder
35                                               
36                        Variable i,j,numDataSets
37                        Variable np
38                       
39                        String w0,w1,w2,w3,w4,w5,basestr,fileName
40                        String xmlDataFolder,xmlDataSetFolder
41                       
42                        Variable numSASEntries
43                       
44                        if(!cmpStr(outStr,""))
45                                //no outStr defined
46                                numSASEntries = CountObjects(xmlReaderFolder,4)
47                        else
48                                numSASEntries = 1
49                        endif
50                       
51                        for (i = 0; i < numSASEntries; i+=1)
52                                                               
53                                xmlDataFolder = xmlReaderFolder+GetIndexedObjName(xmlReaderFolder,4,i)+":"
54                                if (!cmpstr(outstr,""))
55                                        numDataSets = CountObjects(xmlDataFolder,4)
56                                else
57                                        numDataSets = 0
58                                endif
59                               
60                                if (numDataSets > 0)
61                                        //Multiple SASData sets in this SASEntry
62                                        for (j = 0; j < numDataSets; j+=1)
63                                               
64                                                xmlDataSetFolder = xmlDataFolder+GetIndexedObjName(xmlDataFolder,4,j)+":"
65                                       
66                                                SetDataFolder xmlDataSetFolder 
67                                                //                      enforce a short enough name here to keep Igor objects < 31 chars
68                                                // Multiple data sets so we need to use titles and run numbers for naming
69                                                basestr = ShortFileNameString(CleanupName(getXMLDataSetTitle(xmlDataSetFolder,j,useFilename=0),0))
70                                                baseStr = CleanupName(baseStr,0)                //in case the user added odd characters
71                                               
72                                                //String basestr = ParseFilePath(3, ParseFilePath(5,filestr,":",0,0),":",0,0)                           
73                                                fileName =  ParseFilePath(0,ParseFilePath(5,filestr,":",0,0),":",1,0)
74                                                       
75                                                       
76                                                //print "In NIST XML Loader"
77                                                //print "fileStr: ",fileStr
78                                                //print "basestr: ",basestr
79                                                //print "fileName: ",fileName
80                                                //remove the semicolon AND period from files from the VAX
81//                                              print basestr
82                                                w0 = basestr + "_q"
83                                                w1 = basestr + "_i"
84                                                w2 = basestr + "_s"
85                                                w3 = basestr + "sq"
86                                                w4 = basestr + "qb"
87                                                w5 = basestr + "fs"
88                                               
89                                                if(DataFolderExists("root:"+baseStr))
90                                                        if(!forceOverwrite)
91                                                                DoAlert 1,"The data set " + basestr + " from file "+fileName+" has already been loaded. Do you want to load the new data file, overwriting the data in memory?"
92                                                                if(V_flag==2)   //user selected No, don't load the data
93                                                                        SetDataFolder root:
94                                                                        if(DataFolderExists("root:Packages:NIST"))
95                                                                                String/G root:Packages:NIST:gLastFileName = filename
96                                                                        endif           //set the last file loaded to the one NOT loaded
97                                                                        return  0       //quits the macro
98                                                                endif
99                                                        endif
100                                                        SetDataFolder $("root:"+baseStr)
101                                                else
102                                                        NewDataFolder/S $("root:"+baseStr)
103                                                endif
104                       
105                                                Duplicate/O $(xmlDataSetFolder+"Qsas") $w0
106                                                Duplicate/O $(xmlDataSetFolder+"Isas") $w1
107                                                Duplicate/O $(xmlDataSetFolder+"Idev") $w2
108
109                                               
110                                                if (exists(xmlDataSetFolder+"Qdev"))
111                                                        Wave Qsas = $(xmlDataSetFolder+"Qsas")
112                                                        Wave Qdev = $(xmlDataSetFolder+"Qdev")
113                                                       
114                                                        Duplicate/O Qdev, $w3
115                                                // make a resolution matrix for SANS data
116                                                         np=numpnts($w0)
117                                                        Make/D/O/N=(np,4) $(baseStr+"_res")
118                                                        Wave reswave =  $(baseStr+"_res")
119                                                       
120                                                        reswave[][0] = Qdev[p]          //sigQ
121                                                        reswave[][3] = Qsas[p]  //Qvalues
122                                                        if(exists(xmlDataSetFolder+"Qmean"))
123                                                                Wave Qmean = $(xmlDataSetFolder+"Qmean")
124                                                                Duplicate/O Qmean,$w4
125                                                                reswave[][1] = Qmean[p]         //qBar
126                                                        endif
127                                                        if(exists(xmlDataSetFolder+"Shadowfactor"))
128                                                                Wave Shadowfactor = $(xmlDataSetFolder+"Shadowfactor")
129                                                                Duplicate/O Shadowfactor, $w5
130                                                                reswave[][2] = Shadowfactor[p]          //fShad
131                                                        endif
132                                                elseif(exists(xmlDataSetFolder+"dQl"))
133                                                        //USAS Data
134                                                        Wave dQl = $(xmlDataSetFolder+"dQl")
135                                                        dQv = dQl[0]
136                                               
137                                                        USANS_CalcWeights(baseStr,dQv)
138                                                else
139                                                        //No resolution data
140                                                endif
141                                                        //get rid of the resolution waves that are in the matrix
142                                       
143                                                        SetScale d,0,0,"1/A",$w0
144                                                        SetScale d,0,0,"1/cm",$w1
145                                               
146                                                       
147                               
148                                                //////
149                                                if(DataFolderExists("root:Packages:NIST"))
150                                                        String/G root:Packages:NIST:gLastFileName = filename
151                                                endif
152                                       
153                                               
154                                                //plot if desired
155                                                if(doPlot)
156                                                        // assign colors randomly
157                                                        rr = abs(trunc(enoise(65535)))
158                                                        gg = abs(trunc(enoise(65535)))
159                                                        bb = abs(trunc(enoise(65535)))
160                                                       
161                                                        // if target window is a graph, and user wants to append, do so
162                                                   DoWindow/B Plot_Manager
163                                                        if(WinType("") == 1)
164                                                                DoAlert 1,"Do you want to append this data to the current graph?"
165                                                                if(V_Flag == 1)
166                                                                        AppendToGraph $w1 vs $w0
167                                                                        ModifyGraph mode($w1)=3,marker($w1)=19,msize($w1)=2,rgb($w1) =(rr,gg,bb),tickUnit=1
168                                                                        ErrorBars/T=0 $w1 Y,wave=($w2,$w2)
169                                                                        ModifyGraph tickUnit(left)=1
170                                                                else
171                                                                //new graph
172                                                                        Display $w1 vs $w0
173                                                                        ModifyGraph log=1,mode($w1)=3,marker($w1)=19,msize($w1)=2,rgb($w1)=(rr,gg,bb),tickUnit=1
174                                                                        ModifyGraph grid=1,mirror=2,standoff=0
175                                                                        ErrorBars/T=0 $w1 Y,wave=($w2,$w2)
176                                                                        ModifyGraph tickUnit(left)=1
177                                                                        Label left "I(q)"
178                                                                        Label bottom "q (A\\S-1\\M)"
179                                                                        Legend
180                                                                endif
181                                                        else
182                                                        // graph window was not target, make new one
183                                                                Display $w1 vs $w0
184                                                                ModifyGraph log=1,mode($w1)=3,marker($w1)=19,msize($w1)=2,rgb($w1)=(rr,gg,bb),tickUnit=1
185                                                                ModifyGraph grid=1,mirror=2,standoff=0
186                                                                ErrorBars/T=0 $w1 Y,wave=($w2,$w2)
187                                                                ModifyGraph tickUnit(left)=1
188                                                                Label left "I(q)"
189                                                                Label bottom "q (A\\S-1\\M)"
190                                                                Legend
191                                                        endif
192                                                endif
193                                       
194                                        endfor
195                                       
196                                       
197                                else
198                                        //No multiple SASData sets for this SASEntry
199                                        SetDataFolder xmlDataFolder                                     
200                                       
201//                                      print xmlDataFolder
202                                       
203                                        //if outstr has been specified, we'll find ourselves here....
204                                        //We should default to using the filename here to make life easier on people who have used the NIST reduction...
205                                        if (!cmpstr(outstr,""))
206                                                basestr = ShortFileNameString(CleanupName(getXMLDataSetTitle(xmlDataFolder,0,useFilename=1),0))
207                                        else
208                                                basestr = ShortFileNameString(CleanupName(outstr,0))
209                                        endif
210                                       
211                                        //String basestr = ParseFilePath(3, ParseFilePath(5,filestr,":",0,0),":",0,0)                           
212                                        fileName =  ParseFilePath(0,ParseFilePath(5,filestr,":",0,0),":",1,0)
213                                                                                                                               
214                                        //print "In NIST XML Loader"
215                                        //print "fileStr: ",fileStr
216                                        //print "basestr: ",basestr
217                                        //print "fileName: ",fileName
218                                        w0 = basestr + "_q"
219                                        w1 = basestr + "_i"
220                                        w2 = basestr + "_s"
221                                       
222                                        if(DataFolderExists("root:"+baseStr))
223                                                if(!forceOverwrite)
224                                                        DoAlert 1,"The data set " + basestr + " from file "+fileName+" has already been loaded. Do you want to load the new data file, overwriting the data in memory?"
225                                                        if(V_flag==2)   //user selected No, don't load the data
226                                                                SetDataFolder root:
227                                                                if(DataFolderExists("root:Packages:NIST"))
228                                                                        String/G root:Packages:NIST:gLastFileName = filename
229                                                                endif           //set the last file loaded to the one NOT loaded
230                                                                return  0       //quits the macro
231                                                        endif
232                                                endif
233                                                SetDataFolder $("root:"+baseStr)
234                                        else
235                                                NewDataFolder/S $("root:"+baseStr)
236                                        endif
237               
238                                        Duplicate/O $(xmlDataFolder+"Qsas") $w0
239                                        Duplicate/O $(xmlDataFolder+"Isas") $w1
240                                        Duplicate/O $(xmlDataFolder+"Idev") $w2
241       
242       
243                                               
244                                        if (exists(xmlDataFolder+"Qdev"))
245                                                Wave Qsas = $(xmlDataFolder+"Qsas")
246                                                Wave Qdev = $(xmlDataFolder+"Qdev")
247                                       
248                                        // make a resolution matrix for SANS data
249                                                np=numpnts($w0)
250                                                Make/D/O/N=(np,4) $(baseStr+"_res")
251                                                Wave reswave =  $(baseStr+"_res")
252                                               
253                                                reswave[][0] = Qdev[p]          //sigQ
254                                                reswave[][3] = Qsas[p]  //Qvalues
255                                                if(exists(xmlDataFolder+"Qmean"))
256                                                        Wave Qmean = $(xmlDataFolder+"Qmean")
257                                                        reswave[][1] = Qmean[p]         //qBar
258                                                endif
259                                                if(exists(xmlDataFolder+"Shadowfactor"))
260                                                        Wave Shadowfactor = $(xmlDataFolder+"Shadowfactor")
261                                                        reswave[][2] = Shadowfactor[p]          //fShad
262                                                endif
263                                        elseif(exists(xmlDataFolder+"dQl"))
264                                                //USAS Data
265                                                Wave dQl = $(xmlDataFolder+"dQl")
266                                                dQv = - dQl[0]          //make it positive again
267                                       
268                                                USANS_CalcWeights(baseStr,dQv)
269                                        else
270                                                //No resolution data
271                                        endif
272                                                //get rid of the resolution waves that are in the matrix
273                               
274                                                SetScale d,0,0,"1/A",$w0
275                                                SetScale d,0,0,"1/cm",$w1
276                                       
277                                               
278                       
279                                        //////
280                                        if(DataFolderExists("root:Packages:NIST"))
281                                                String/G root:Packages:NIST:gLastFileName = filename
282                                        endif
283                               
284                                       
285                                        //plot if desired
286                                        if(doPlot)
287                                                // assign colors randomly
288                                                rr = abs(trunc(enoise(65535)))
289                                                gg = abs(trunc(enoise(65535)))
290                                                bb = abs(trunc(enoise(65535)))
291                                               
292                                                // if target window is a graph, and user wants to append, do so
293                                           DoWindow/B Plot_Manager
294                                                if(WinType("") == 1)
295                                                        DoAlert 1,"Do you want to append this data to the current graph?"
296                                                        if(V_Flag == 1)
297                                                                AppendToGraph $w1 vs $w0
298                                                                ModifyGraph mode($w1)=3,marker($w1)=19,msize($w1)=2,rgb($w1) =(rr,gg,bb),tickUnit=1
299                                                                ErrorBars/T=0 $w1 Y,wave=($w2,$w2)
300                                                                ModifyGraph tickUnit(left)=1
301                                                        else
302                                                        //new graph
303                                                                Display $w1 vs $w0
304                                                                ModifyGraph log=1,mode($w1)=3,marker($w1)=19,msize($w1)=2,rgb($w1)=(rr,gg,bb),tickUnit=1
305                                                                ModifyGraph grid=1,mirror=2,standoff=0
306                                                                ErrorBars/T=0 $w1 Y,wave=($w2,$w2)
307                                                                ModifyGraph tickUnit(left)=1
308                                                                Label left "I(q)"
309                                                                Label bottom "q (A\\S-1\\M)"
310                                                                Legend
311                                                        endif
312                                                else
313                                                // graph window was not target, make new one
314                                                        Display $w1 vs $w0
315                                                        ModifyGraph log=1,mode($w1)=3,marker($w1)=19,msize($w1)=2,rgb($w1)=(rr,gg,bb),tickUnit=1
316                                                        ModifyGraph grid=1,mirror=2,standoff=0
317                                                        ErrorBars/T=0 $w1 Y,wave=($w2,$w2)
318                                                        ModifyGraph tickUnit(left)=1
319                                                        Label left "I(q)"
320                                                        Label bottom "q (A\\S-1\\M)"
321                                                        Legend
322                                                endif
323                                        endif
324                               
325                                endif
326                        endfor
327        endif
328
329        //go back to the root folder and clean up before leaving
330        SetDataFolder root:
331        //KillDataFolder xmlReaderFolder
332       
333
334end
335
336
337function/S getXMLDataSetTitle(xmlDF,dsNum,[useFilename])
338        String xmlDF
339        Variable dsNum
340        Variable useFilename
341
342        SVAR title = root:Packages:NIST:gXMLLoader_Title
343
344        String mdstring = xmlDF+"metadata"
345        String filename
346
347        Wave/T meta = $mdstring
348
349        //Get filename to use if useFilename is specified or as a fall back if title is missing.
350        FindValue/TEXT="xmlFile"/TXOP=4/Z meta
351        filename = ParseFilePath(0,TrimWS(meta[V_Value][1]),":",1,0)
352       
353        if (useFilename)
354                return filename
355        endif
356       
357        //Check for value when there are multiple datasets
358        //Note that the use of FindValue here assumes that the tag is in column 0 so that V_Value
359        //represents the row number
360        //This will almost certainly break if your title was "Title" or "Run"
361        FindValue/TEXT="Title"/TXOP=4/Z meta
362        if (V_Value >= 0)
363        //This should always be true as title is required in canSAS XML format
364                title = TrimWS(meta[V_Value][1])
365        else
366                title = filename
367        endif   
368         //Check for Run value
369         //If you get a run value, put it at the start of the string so it isn't lost if there is truncation
370         //One hopes that the run number will be unique...
371         FindValue/TEXT="Run_"+num2str(dsNum)/TXOP=4/Z meta
372        if (V_Value >= 0)
373                title = TrimWS(meta[V_Value][1])+" "+title
374                //print title
375        else
376                FindValue/TEXT="Run"/TXOP=4/Z meta
377                if (V_Value >= 0)
378                        title = TrimWS(meta[V_Value][1])+" "+title
379                        //print title
380                endif
381        endif
382       
383        return title
384end
385
386
387//AJJ 12/5/08
388
389//Define struct for file contents
390Structure NISTXMLfile
391//      string filename
392        string Run
393        string title
394
395        //<SASdata>
396        Wave Q,I,Idev,Qdev,Qmean,Shadowfactor,dQl
397        string unitsQ,unitsI,unitsIdev,unitsQdev,unitsQmean,unitsShadowfactor,unitsdQl
398
399//      Variable flux_monitor
400//      string Q_resolution
401
402        //<SASsample>
403        string sample_ID
404        variable sample_thickness
405        string unitssample_thickness
406        variable sample_transmission
407
408        //SASinstrument
409        string nameSASinstrument
410        // SASinstrument/SASsource
411        string radiation
412//      string beam_shape
413        variable wavelength
414        string unitswavelength
415        variable wavelength_spread
416        string unitswavelength_spread
417 
418        //<SAScollimation>
419//      variable collimation_length
420//      string unitscollimation_length
421        variable source_aperture
422        string unitssource_aperture
423        string typesource_aperture
424        variable sample_aperture
425        string unitssample_aperture
426        string typesample_aperture
427
428        //SASdetector         <SASdetector>
429        string detector_name
430        variable offset_angle
431        string unitsoffset_angle
432        variable  SDD
433        string unitsSDD
434        variable beamcenter_X
435        string unitsbeamcenter_X
436        variable beamcenter_Y
437        string unitsbeamcenter_Y
438//      variable pixel_sizeX
439//      string unitspixel_sizeX
440//      variable pixel_sizeY
441//      string unitspixel_sizeY
442//      string detectortype
443
444        // <SASprocess name="NCNR-IGOR">
445        string nameSASprocess
446        string SASprocessnote
447//      string SASprocessdate
448//      string average_type
449//      string SAM_file
450//      string BKD_file
451//      string EMP_file
452//      string DIV_file
453//      string MASK_file
454//      string ABS_parameters
455//      variable TSTAND
456//      variable DSTAND
457//      string unitsDSTAND
458//      variable IZERO
459//      variable XSECT
460//      string unitsXSECT
461        string SASnote
462Endstructure
463
464
465//Function to write NIST canSAS XML files
466//Minimalist XML file - AJJ Dec 2008
467function writeNISTXML(fileName, NISTfile)
468        String fileName
469        Struct NISTXMLfile &NISTfile
470
471        variable fileID
472       
473        //create the sasXML file with SASroot
474        //no namespace, no prefix
475        fileID = xmlcreatefile(fileName,"SASroot","cansas1d/1.0","")
476
477        //create a version attribute for the root element
478        xmlsetAttr(fileID,"/SASroot","","version","1.0")
479        xmlsetAttr(fileID,"/SASroot","","xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance")
480        xmlsetAttr(fileID,"/SASroot","","xsi:schemaLocation","cansas1d/1.0 http://svn.smallangles.net/svn/canSAS/1dwg/trunk/cansas1d.xsd")
481
482
483        //create the SASentry node
484        xmladdnode(fileID,"/SASroot","","SASentry","",1)
485               
486        //create the Title node
487        xmladdnode(fileID,"/SASroot/SASentry","","Title",NISTfile.Title,1)
488
489        //create the Run node
490        xmladdnode(fileID,"/SASroot/SASentry","","Run",NISTfile.Run,1)
491       
492        //create the SASdata node
493        xmladdnode(fileID,"/SASroot/SASentry","","SASdata","",1)
494
495        variable ii
496       
497        if (WaveExists(NISTfile.dQl) == 1)
498                for(ii=0 ; ii<numpnts(NISTfile.Q) ; ii+=1)
499                        xmladdnode(fileID,"/SASroot/SASentry/SASdata","","Idata","",1)
500                        xmladdnode(fileID,"/SASroot/SASentry/SASdata/Idata["+num2istr(ii+1)+"]","","Q",num2str(NISTfile.Q[ii]),1)
501                        xmlsetAttr(fileID,"/SASroot/SASentry/SASdata/Idata["+num2istr(ii+1)+"]/Q","","unit",NISTfile.unitsQ)
502       
503                        xmladdnode(fileID,"/SASroot/SASentry/SASdata/Idata["+num2istr(ii+1)+"]","","I",num2str(NISTfile.I[ii]),1)
504                        xmlsetAttr(fileID,"/SASroot/SASentry/SASdata/Idata["+num2istr(ii+1)+"]/I","","unit",NISTfile.unitsI)
505       
506                        xmladdnode(fileID,"/SASroot/SASentry/SASdata/Idata["+num2istr(ii+1)+"]","","Idev",num2str(NISTfile.Idev[ii]),1)
507                        xmlsetAttr(fileID,"/SASroot/SASentry/SASdata/Idata["+num2istr(ii+1)+"]/Idev","","unit",NISTfile.unitsIdev)     
508       
509                        xmladdnode(fileID,"/SASroot/SASentry/SASdata/Idata["+num2istr(ii+1)+"]","","dQl",num2str(NISTfile.dQl[ii]),1)
510                        xmlsetAttr(fileID,"/SASroot/SASentry/SASdata/Idata["+num2istr(ii+1)+"]/dQl","","unit",NISTfile.unitsdQl)               
511                endfor
512        else
513                for(ii=0 ; ii<numpnts(NISTfile.Q) ; ii+=1)
514                        xmladdnode(fileID,"/SASroot/SASentry/SASdata","","Idata","",1)
515                        xmladdnode(fileID,"/SASroot/SASentry/SASdata/Idata["+num2istr(ii+1)+"]","","Q",num2str(NISTfile.Q[ii]),1)
516                        xmlsetAttr(fileID,"/SASroot/SASentry/SASdata/Idata["+num2istr(ii+1)+"]/Q","","unit",NISTfile.unitsQ)
517       
518                        xmladdnode(fileID,"/SASroot/SASentry/SASdata/Idata["+num2istr(ii+1)+"]","","I",num2str(NISTfile.I[ii]),1)
519                        xmlsetAttr(fileID,"/SASroot/SASentry/SASdata/Idata["+num2istr(ii+1)+"]/I","","unit",NISTfile.unitsI)
520       
521                        xmladdnode(fileID,"/SASroot/SASentry/SASdata/Idata["+num2istr(ii+1)+"]","","Idev",num2str(NISTfile.Idev[ii]),1)
522                        xmlsetAttr(fileID,"/SASroot/SASentry/SASdata/Idata["+num2istr(ii+1)+"]/Idev","","unit",NISTfile.unitsIdev)
523       
524                        xmladdnode(fileID,"/SASroot/SASentry/SASdata/Idata["+num2istr(ii+1)+"]","","Qdev",num2str(NISTfile.Qdev[ii]),1)
525                        xmlsetAttr(fileID,"/SASroot/SASentry/SASdata/Idata["+num2istr(ii+1)+"]/Qdev","","unit",NISTfile.unitsQdev)
526       
527                        xmladdnode(fileID,"/SASroot/SASentry/SASdata/Idata["+num2istr(ii+1)+"]","","Qmean",num2str(NISTfile.Qmean[ii]),1)
528                        xmlsetAttr(fileID,"/SASroot/SASentry/SASdata/Idata["+num2istr(ii+1)+"]/Qmean","","unit",NISTfile.unitsQmean)
529       
530                        xmladdnode(fileID,"/SASroot/SASentry/SASdata/Idata["+num2istr(ii+1)+"]","","Shadowfactor",num2str(NISTfile.shadowfactor[ii]),1)
531                endfor
532        endif
533
534        //SASsample node
535        xmladdnode(fileID,"/SASroot/SASentry","","SASsample","",1)
536        xmladdnode(fileID,"/SASroot/SASentry/SASsample","","ID",NISTfile.sample_ID,1)
537
538        //SASInstrument node
539        xmladdnode(fileID,"/SASroot/SASentry","","SASinstrument","",1)
540        xmladdnode(fileID,"/SASroot/SASentry/SASinstrument","","name",NISTfile.nameSASinstrument,1)
541       
542        //SASsource
543        xmladdnode(fileID,"/SASroot/SASentry/SASinstrument","","SASsource","",1)
544        xmladdnode(fileID,"/SASroot/SASentry/SASinstrument/SASsource","","radiation",NISTfile.radiation,1)
545
546        //SAScollimation
547        xmladdnode(fileID,"/SASroot/SASentry/SASinstrument","","SAScollimation","",1)
548
549        //SASdetector
550        xmladdnode(fileID,"/SASroot/SASentry/SASinstrument","","SASdetector","",1)
551        xmladdnode(fileID,"/SASroot/SASentry/SASinstrument/SASdetector","","name",NISTfile.detector_name,1)
552
553
554        //SASprocess
555        xmladdnode(fileID,"/SASroot/SASentry","","SASprocess","",1)
556        xmlsetAttr(fileID,"/SASroot/SASentry/SASprocess","","name",NISTfile.nameSASprocess)     
557        xmladdnode(fileID,"/SASroot/SASentry/SASprocess","","SASprocessnote",NISTfile.SASprocessnote,1)
558       
559        //SASnote
560        xmladdnode(fileID,"/SASroot/SASentry","","SASnote",NISTfile.SASnote,1)
561       
562        xmlsavefile(fileID)
563        xmlclosefile(fileID,0)
564       
565end
566
567Function convertNISTtoNISTXML(fileStr)
568        String fileStr
569       
570        Struct NISTXMLfile nf
571       
572        Variable rr,gg,bb,refnum,dQv
573        SetDataFolder root:     
574       
575        if (cmpStr(fileStr,"") == 0)
576                //No filename given, open dialog
577                Open/D/R  refnum
578                if (cmpstr(S_filename,"") == 0)
579                        return 0
580                else
581                        fileStr = S_filename
582                endif
583        endif
584
585        //Load the waves, using default waveX names
586        //if no path or file is specified for LoadWave, the default Mac open dialog will appear
587        LoadWave/G/D/A/Q fileStr
588        String fileNamePath = S_Path+S_fileName
589        String basestr = CleanupName(ParseFilePath(3,ParseFilePath(5,fileNamePath,":",0,0),":",0,0),0)
590//      String baseStr = CleanupName(S_fileName,0)
591//              print "basestr :"+basestr
592        String fileName =  ParseFilePath(0,ParseFilePath(5,filestr,":",0,0),":",1,0)
593//              print "filename :"+filename
594        Variable numCols = V_flag
595        String outfileName = S_Path+basestr+".xml"
596
597       
598        if(numCols==3)          //simple 3-column data with no resolution information
599               
600                Wave nf.Q = $(StringFromList(0, S_waveNames ,";" ))
601                Wave nf.I = $(StringFromList(1, S_waveNames ,";" ))
602                Wave nf.Idev = $(StringFromList(2, S_waveNames ,";" ))
603                               
604                //Set units
605                nf.unitsQ = "1/A"
606                nf.unitsI = "1/cm"
607                nf.unitsIdev = "1/cm"
608                               
609        endif           //3-col data
610       
611        if(numCols == 6)                //6-column SANS or USANS data that has resolution information
612               
613                // put the names of the (default named) loaded waves into local names
614                Wave nf.Q = $(StringFromList(0, S_waveNames ,";" ))
615                Wave nf.I  = $(StringFromList(1, S_waveNames ,";" ))
616                Wave nf.Idev  = $(StringFromList(2, S_waveNames ,";" ))
617
618                //Set units
619                nf.unitsQ = "1/A"
620                nf.unitsI = "1/cm"
621                nf.unitsIdev = "1/cm"
622
623                WAVE resTest = $(StringFromList(3, S_waveNames ,";" ))
624
625                // need to switch based on SANS/USANS
626                if (isSANSResolution(resTest[0]))               //checks to see if the first point of the wave is <0]
627                        Wave nf.Qdev  = $(StringFromList(3, S_waveNames ,";" ))
628                        Wave nf.Qmean  = $(StringFromList(4, S_waveNames ,";" ))
629                        Wave nf.Shadowfactor  = $(StringFromList(5, S_waveNames ,";" ))
630                       
631                        //Set units
632                        nf.unitsQdev = "1/A"
633                        nf.unitsQmean = "1/A"
634                else
635                        Wave nf.dQl = $(StringFromList(3, S_waveNames ,";" ))
636                       
637                        //Set units
638                        nf.unitsdQl = "1/A"
639                       
640                endif
641               
642                //Tidy up
643                Variable i = 0
644                do
645                        WAVE/Z wv= $(StringFromList(i,S_waveNames,";"))
646                        if( WaveExists(wv) == 0 )
647                                break
648                        endif
649                        KillWaves wv
650                        i += 1
651                while (1)       // exit is via break statement
652
653       
654        endif   //6-col data
655
656        //Get file header
657        setmetadataFromASCHeader(fileStr,nf)
658
659        //Set required metadata that we can't get from these files
660        nf.detector_name = "Ordela 128x128"
661        nf.nameSASinstrument = "NIST NG3/NG7 SANS"
662        nf.radiation = "neutron"
663        nf.sample_ID = nf.title
664        nf.nameSASProcess = "NIST Data Converter"
665        nf.sasnote = "Data converted from previous NIST format. SASProcessnote contains header from original text file."
666
667        writeNISTXML(outfileName, nf)
668
669end
670
671function setmetadataFromASCHeader(fileStr,NISTfile)
672        String fileStr
673        Struct NISTXMLfile &NISTfile
674
675        String hdr="",buffer=""
676        Variable lineNum = 0, fileref
677        Variable num
678       
679        Open/R fileref as fileStr
680        do
681                FReadLine fileref, buffer
682                if (stringmatch(buffer,"*The 6 columns are*") == 1)
683                        break
684                endif
685                buffer = RemoveEnding(buffer)
686//              print buffer
687                //Get run value
688                if (stringmatch(buffer,"*file:*") == 1)
689                        NISTfile.run = TrimWS(StringFromList(0,StringFromList(1, buffer, ":"),"C"))
690                elseif (stringmatch(buffer,"combined file*") == 1)
691                        NISTfile.run = "Combined Data"
692                endif
693               
694                //Get title value
695                if (stringmatch(buffer,"*FIRST File LABEL:*") == 1)
696                        NISTfile.title = TrimWS(StringFromList(1,buffer, ":"))
697                elseif(stringmatch(buffer,"*LABEL:*") == 1)
698                        NISTfile.title = TrimWS(StringFromList(1,buffer, ":"))
699                endif
700               
701                hdr += buffer+"\n"
702        while(strlen(buffer) > 0)
703       
704        if (strlen(NISTfile.title) == 0)
705                NISTfile.title = CleanupName(ParseFilePath(3,ParseFilePath(5,fileStr,":",0,0),":",0,0),0)
706        endif
707        if (strlen(NISTfile.run) == 0)
708                NISTfile.run = "Unknown"
709        endif
710       
711        NISTfile.sasprocessnote = RemoveEnding(hdr)
712       
713end
714
715//for writing out data (q-i-s) from the "type" folder, and including reduction information
716//if fullpath is a complete HD path:filename, no dialog will be presented
717//if fullpath is just a filename, the save dialog will be presented
718//if dialog = 1, a dialog will always be presented
719//
720// root:myGlobals:Protocols:gProtoStr is the name of the currently active protocol
721//
722//AJJ Nov 2009 : This version of the function currently only works for Circular, Sector and Rectangular averages
723//i.e. anything that produces I vs Q. Need to add ability to handle Annular (I vs theta) but that requires namespace addition to XML format
724//and handling on load.
725Function WriteXMLWaves_W_Protocol(type,fullpath,dialog)
726        String type,fullpath
727        Variable dialog         //=1 will present dialog for name
728       
729        Struct NISTXMLfile nf
730       
731        String destStr=""
732        destStr = "root:Packages:NIST:"+type
733       
734        Variable refNum
735//      String fname,ave="C",hdrStr1="",hdrStr2=""
736//      Variable step=1
737       
738        //*****these waves MUST EXIST, or IGOR Pro will crash, with a type 2 error****
739        WAVE intw=$(destStr + ":integersRead")
740        WAVE rw=$(destStr + ":realsRead")
741        WAVE/T textw=$(destStr + ":textRead")
742        WAVE qvals =$(destStr + ":qval")
743        WAVE inten=$(destStr + ":aveint")
744        WAVE sig=$(destStr + ":sigave")
745        WAVE qbar = $(destStr + ":QBar")
746        WAVE sigmaq = $(destStr + ":SigmaQ")
747        WAVE fsubs = $(destStr + ":fSubS")
748
749
750        SVAR gProtoStr = root:myGlobals:Protocols:gProtoStr
751        Wave/T proto=$("root:myGlobals:Protocols:"+gProtoStr)
752
753       
754        //check each wave
755        If(!(WaveExists(intw)))
756                Abort "intw DNExist BinaryWrite_W_Protocol()"
757        Endif
758        If(!(WaveExists(rw)))
759                Abort "rw DNExist BinaryWrite_W_Protocol()"
760        Endif
761        If(!(WaveExists(textw)))
762                Abort "textw DNExist BinaryWrite_W_Protocol()"
763        Endif
764        If(!(WaveExists(qvals)))
765                Abort "qvals DNExist BinaryWrite_W_Protocol()"
766        Endif
767        If(!(WaveExists(inten)))
768                Abort "inten DNExist BinaryWrite_W_Protocol()"
769        Endif
770        If(!(WaveExists(sig)))
771                Abort "sig DNExist BinaryWrite_W_Protocol()"
772        Endif
773        If(!(WaveExists(qbar)))
774                Abort "qbar DNExist BinaryWrite_W_Protocol()"
775        Endif
776        If(!(WaveExists(sigmaq)))
777                Abort "sigmaq DNExist BinaryWrite_W_Protocol()"
778        Endif
779        If(!(WaveExists(fsubs)))
780                Abort "fsubs DNExist BinaryWrite_W_Protocol()"
781        Endif
782        If(!(WaveExists(proto)))
783                Abort "current protocol wave DNExist BinaryWrite_W_Protocol()"
784        Endif
785       
786        if(dialog)
787                PathInfo/S catPathName
788                fullPath = DoSaveFileDialog("Save data as")
789                If(cmpstr(fullPath,"")==0)
790                        //user cancel, don't write out a file
791                        Close/A
792                        Abort "no data file was written"
793                Endif
794                //Print "dialog fullpath = ",fullpath
795        Endif
796       
797        SVAR samFiles = $("root:Packages:NIST:"+type+":fileList")
798        //actually open the file here
799        //Open refNum as fullpath
800       
801        //Data
802        Wave nf.Q = qvals
803        nf.unitsQ = "1/A"
804        Wave nf.I = inten
805        nf.unitsI = "1/cm"
806        Wave nf.Idev = sig
807        nf.unitsIdev = "1/cm"
808        Wave nf.Qdev = sigmaq
809        nf.unitsQdev = "1/A"
810        Wave nf.Qmean = qbar
811        nf.unitsQmean = "1/A"
812        Wave nf.Shadowfactor = fSubS
813        nf.unitsShadowfactor = "none"
814       
815       
816        //write out the standard header information
817        //fprintf refnum,"FILE: %s\t\t CREATED: %s\r\n",textw[0],textw[1]
818       
819        //AJJ to fix with sensible values
820        nf.run = "Test"
821        String acct = textw[3]
822        nf.nameSASinstrument = acct[1,3]
823        nf.SASnote = ""
824        //
825        nf.sample_ID = textw[6]
826        nf.title = textw[6]
827        nf.radiation = "neutron"
828        nf.wavelength = rw[26]
829        nf.unitswavelength = "A"
830        nf.offset_angle = rw[19]
831        nf.unitsoffset_angle = "cm"
832        nf.SDD = rw[18]
833        nf.unitsSDD = "m"
834        nf.sample_transmission = rw[4]
835        nf.sample_thickness = rw[5]
836        nf.unitssample_thickness = "mm"
837       
838        nf.beamcenter_X = rw[16] 
839        nf.beamcenter_Y = rw[17]
840        nf.unitsbeamcenter_X = "pixels"
841        nf.unitsbeamcenter_Y = "pixels"
842        nf.source_aperture = rw[23]
843        nf.typesource_aperture = "pinhole"
844        nf.unitssource_aperture = "mm"
845        nf.sample_aperture = rw[24]
846        nf.typesample_aperture = "pinhole"
847        nf.unitssample_aperture = "mm"
848        //nf.collimation_length = total length - rw[25]
849        nf.wavelength_spread = rw[27]
850        nf.unitswavelength_spread = "percent"
851        //Do something with beamstop (rw[21])
852        nf.detector_name = textW[9]
853//      fprintf refnum,"MON CNT   LAMBDA   DET ANG   DET DIST   TRANS   THICK   AVE   STEP\r\n"
854//      fprintf refnum,hdrStr1
855
856//      fprintf refnum,"BCENT(X,Y)   A1(mm)   A2(mm)   A1A2DIST(m)   DL/L   BSTOP(mm)   DET_TYP \r\n"
857//      fprintf refnum,hdrStr2
858
859        //insert protocol information here
860        //-1 list of sample files
861        //0 - bkg
862        //1 - emp
863        //2 - div
864        //3 - mask
865        //4 - abs params c2-c5
866        //5 - average params
867        nf.SASprocessnote =  "SAM: "+samFiles+"\n"
868        nf.SASprocessnote += "BGD: "+proto[0]+"\n"
869        nf.SASprocessnote += "EMP: "+Proto[1]+"\n"
870        nf.SASprocessnote += "DIV: "+Proto[2]+"\n"
871        nf.SASprocessnote += "MASK: "+Proto[3]+"\n"
872        nf.SASprocessnote += "ABS Parameters (3-6): "+Proto[4]+"\n"
873        nf.SASprocessnote += "Average Choices: "+Proto[5]+"\n"
874       
875        nf.nameSASProcess = "NIST IGOR"
876
877        //Close refnum
878       
879        writeNISTXML(fullpath, nf)
880       
881        SetDataFolder root:             //(redundant)
882       
883        //write confirmation of write operation to history area
884        Print "Averaged XML File written: ", GetFileNameFromPathNoSemi(fullPath)
885        KillWaves/Z tempShortProto
886        Return(0)
887End
888
889Function WriteNSORTedXMLFile(qw,iw,sw,firstFileName,secondFileName,thirdFileName,normTo,norm12,norm23,[res])
890        Wave qw,iw,sw,res
891        String firstFileName,secondFileName,thirdFileName,normTo
892        Variable norm12,norm23
893
894        Variable err=0,refNum,numCols,dialog=1
895        String fullPath="",formatStr="",str2
896        //check each wave - else REALLY FATAL error when writing file
897        If(!(WaveExists(qw)))
898                err = 1
899                return err
900        Endif
901        If(!(WaveExists(iw)))
902                err = 1
903                return err
904        Endif
905        If(!(WaveExists(sw)))
906                err = 1
907                return err
908        Endif
909       
910        if(WaveExists(res))
911                numCols = 6
912        else
913                numCols = 3
914        endif
915       
916// 05SEP05 SRK -- added to automatically combine files from a table - see the end of NSORT.ipf for details
917// - use the flag set in DoCombineFiles() to decide if the table entries should be used
918//Ê Êroot:myGlobals:CombineTable:useTable= (1) (0)
919//if(exists("root:myGlobals:CombineTable:SaveName"))
920        NVAR/Z useTable = root:myGlobals:CombineTable:useTable
921        if(NVAR_Exists(useTable) && useTable==1)
922                SVAR str=root:myGlobals:CombineTable:SaveNameStr        //messy, but pass in as a global
923                fullPath = str
924//              str2 = "Is the file name "+str+" correct?"
925//              DoAlert 1,str2
926//              if(V_flag==1)
927                        dialog=0                //bypass the dialog if the name is good (assumed, since DoAlert is bypassed)
928//              endif
929        endif
930
931        if(dialog)
932                PathInfo/S catPathName
933                fullPath = DoSaveFileDialog("Save XML data as",fname="",suffix=".ABSx")         //won't actually open the file
934                If(cmpstr(fullPath,"")==0)
935                        //user cancel, don't write out a file
936                        Close/A
937                        Abort "no data file was written"
938                Endif
939                //Print "dialog fullpath = ",fullpath
940        Endif
941
942        Struct NISTxmlfile nf
943       
944        //Data
945        Wave nf.Q = qw
946        nf.unitsQ = "1/A"
947        Wave nf.I = iw
948        nf.unitsI = "1/cm"
949        Wave nf.Idev = sw
950        nf.unitsIdev = "1/cm"
951
952        //write out the standard header information
953        //fprintf refnum,"FILE: %s\t\t CREATED: %s\r\n",textw[0],textw[1]
954       
955        //AJJ to fix with sensible values
956        nf.run = ""
957        nf.nameSASinstrument = "NIST IGOR"
958        nf.SASnote = ""
959        //
960        nf.sample_ID = ParseFilePath(3, fullPath, ":", 0, 0)
961        nf.title = ParseFilePath(3, fullPath, ":", 0, 0)
962        nf.radiation = "neutron"
963        //Do something with beamstop (rw[21])
964        nf.detector_name = "NSORTed Data"       
965        nf.nameSASProcess = "NIST IGOR"
966       
967        nf.sasProcessNote = "COMBINED FILE CREATED: "+date()+"\n"
968        nf.sasProcessNote += "NSORT-ed : " +firstFileName+";"+secondFileName+";"+thirdFileName+"\n"
969        nf.sasProcessNote += "normalized to  "+normTo+"\n"
970        fprintf refNum, "multiplicative factor 1-2 = "+num2str(norm12)+" multiplicative factor 2-3 = "+num2str(norm23)+"\n"
971
972        if (numCols == 3)
973                writeNISTXML(fullpath,nf)
974        elseif (numCols == 6)
975                Make/O/N=(dimsize(res,0)) sigq = res[p][0]
976                Make/O/N=(dimsize(res,0)) qbar = res[p][1]
977                Make/O/N=(dimsize(res,0)) fs = res[p][2]
978       
979                Wave nf.Qdev = sigQ
980                nf.unitsQdev = "1/A"
981                Wave nf.Qmean = qbar
982                nf.unitsQmean = "1/A"
983                Wave nf.Shadowfactor = fs
984                nf.unitsShadowfactor = "none"
985       
986                writeNISTXML(fullpath,nf)
987       
988                Killwaves/Z sigq,qbar,fs
989        endif
990
991        Return err
992End
993
994
995
996
997
998End
999
1000/// See WriteModelData_v40.ipf for 6 column equivalent
1001Function ReWrite1DXMLData(folderStr)
1002        String folderStr
1003
1004        String fullpath=""
1005        Variable dialog=1
1006        String dataSetFolderParent,basestr,fullBase
1007       
1008        Struct NISTXMLfile nf
1009
1010        //Abuse ParseFilePath to get path without folder name
1011        dataSetFolderParent = ParseFilePath(1,folderStr,":",1,0)
1012        //Abuse ParseFilePath to get basestr
1013        basestr = ParseFilePath(0,folderStr,":",1,0)
1014
1015        SetDataFolder $(dataSetFolderParent+basestr)
1016        WAVE/Z qw = $(baseStr+"_q")
1017        WAVE/Z iw = $(baseStr+"_i")
1018        WAVE/Z sw = $(baseStr+"_s")
1019        WAVE/Z resw = $(baseStr+"_res")
1020       
1021        if(WaveExists(qw) == 0)
1022                Abort "q is missing"
1023        endif
1024        if(WaveExists(iw) == 0)
1025                Abort "i is missing"
1026        endif
1027        if(WaveExists(sw) == 0)
1028                Abort "s is missing"
1029        endif
1030        if(WaveExists(resw) == 0)
1031                Abort "Resolution information is missing."
1032        endif
1033       
1034        Duplicate/O qw qbar,sigQ,fs
1035               
1036
1037               
1038        //Data
1039        Wave nf.Q = qw
1040        nf.unitsQ = "1/A"
1041        Wave nf.I = iw
1042        nf.unitsI = "1/cm"
1043        Wave nf.Idev = sw
1044        nf.unitsIdev = "1/cm"
1045        Wave nf.Qdev = sigQ
1046        nf.unitsQdev = "1/A"
1047        Wave nf.Qmean = qbar
1048        nf.unitsQmean = "1/A"
1049        Wave nf.Shadowfactor = fs
1050        nf.unitsShadowfactor = "none"
1051       
1052       
1053        //write out the standard header information
1054        //fprintf refnum,"FILE: %s\t\t CREATED: %s\r\n",textw[0],textw[1]
1055       
1056        //AJJ to fix with sensible values
1057        nf.run = ""
1058        nf.nameSASinstrument = "NIST IGOR Procedures"
1059        nf.SASnote = ""
1060        //
1061        nf.sample_ID = baseStr
1062        nf.title = baseStr
1063        nf.radiation = "neutron"
1064        //Do something with beamstop (rw[21])
1065        nf.detector_name = "Re-written data"
1066
1067        nf.SASprocessnote =  "Modified data written from folder "+baseStr+" on "+(date()+" "+time())
1068       
1069        nf.nameSASProcess = "NIST IGOR"
1070
1071        //Close refnum
1072       
1073        if(dialog)
1074                PathInfo/S catPathName
1075                fullPath = DoSaveFileDialog("Save data as",fname=baseStr+".xml")
1076                If(cmpstr(fullPath,"")==0)
1077                        //user cancel, don't write out a file
1078                        Close/A
1079                        Abort "no data file was written"
1080                Endif
1081                //Print "dialog fullpath = ",fullpath
1082        Endif
1083       
1084       
1085        writeNISTXML(fullpath,nf)
1086        //write confirmation of write operation to history area
1087        Print "XML File written: ", GetFileNameFromPathNoSemi(fullPath)
1088        KillWaves/Z tempShortProto
1089        Return(0)
1090End
1091
1092
1093
1094
1095#else   // if( Exists("XmlOpenFile") )
1096        // No XMLutils XOP: provide dummy function so that IgorPro can compile dependent support code
1097        FUNCTION LoadNISTXMLData(fileName,doPlot)
1098            String fileName
1099            Variable doPlot
1100            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)"
1101            RETURN(-6)
1102        END
1103       
1104
1105        Function writeNISTXML(fileName, NISTfile)
1106                String fileName, NISTfile
1107                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)"
1108                RETURN(-6)
1109        End
1110       
1111        Function WriteXMLWaves_W_Protocol(type,fullpath,dialog)
1112                String type,fullpath
1113                Variable dialog         //=1 will present dialog for name
1114       
1115            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)"
1116                return(-6)
1117        end
1118       
1119        Function WriteNSORTedXMLFile(q3,i3,sig3,firstFileName,secondFileName,thirdFileName,normTo,norm12,norm23,[res])
1120                Wave q3,i3,sig3,res
1121                String firstFileName,secondFileName,thirdFileName,normTo
1122                Variable norm12,norm23
1123
1124                 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)"
1125                return(-6)
1126        End
1127
1128        Function ReWrite1DXMLData(folderStr)
1129                String folderStr
1130       
1131                 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)"
1132                return(-6)
1133        end
1134#endif
1135
1136        // if( Exists("XmlOpenFile")
1137//Needed to test whether file is XML. The load routine will then either give an error if XMLutils is not present or load the file if it is.
1138function isXML(filestr)
1139        String filestr
1140       
1141        String line
1142        Variable fileref
1143       
1144        Open/R fileref as filestr
1145        FReadLine fileref,  line
1146        Close fileref
1147       
1148        //Hopefully this will distinguish between other formats and the XML
1149        //Previous string match would match normal files that have a .xml file as their progenitor...
1150        return GrepString(line, "(?iU).*\<.*xml.*")     
1151
1152end
Note: See TracBrowser for help on using the repository browser.