source: sans/Dev/trunk/NCNR_User_Procedures/Reduction/SANS/HFIR_DataReadWrite.ipf @ 740

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

bug fix from Jae-Hie in the HFIR writer.

File size: 56.7 KB
Line 
1#pragma rtGlobals=1             // Use modern global access method.
2#pragma version=5.0
3#pragma IgorVersion=6.1
4
5//*************************************************************************************************
6//
7// Vers. ????
8// Vers. ???? - branched from main reduction to split out facility
9//                     specific calls
10//
11///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
12//                                      NIST CNR Igor Pro Data Reduction Package
13//                                 HFIR SANS version for SPICE raw data format:
14//
15//                                              University of Tennessee / NIST
16//                                                         DANSE/SANS
17//                                                              Jun. 2009: JHC
18///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
19//
20// - RAW data files are read into the RAW folder - integer data from the detector
21//   is decompressed and given the proper orientation
22// - header information is placed into real,integer, or text waves in the order they appear
23//   in the file header
24//
25// Work data (DIV File) is read into the DIV folder
26//
27//*************************************************************************************************
28
29//simple, main entry procedure that will load a RAW sans data file (not a work file)
30//into the RAW dataFolder. It is up to the calling procedure to display the file
31//
32// called by MainPanel.ipf and ProtocolAsPanel.ipf
33//
34Function LoadRawSANSData(msgStr)
35        String msgStr
36
37        String filename = ""
38
39        //each routine is responsible for checking the current (displayed) data folder
40        //selecting it, and returning to root when done
41        PathInfo/S catPathName          //should set the next dialog to the proper path...
42        //get the filename, then read it in
43        filename = PromptForPath(msgStr)//in SANS_Utils.ipf
44       
45        //check for cancel from dialog
46        if(strlen(filename)==0)
47                //user cancelled, abort
48                SetDataFolder root:
49                DoAlert 0, "No file selected, action aborted"
50                return(1)
51        Endif
52       
53        Variable t1=ticks
54       
55        variable error
56        String errorMsg
57       
58        error=ReadHeaderAndData(filename)       //this is the full Path+file
59
60        if (error < 0)
61                String windowName =""
62                switch(error)                                   // fileID holds the return code; check it
63                        case -1:                       
64                                //errorMsg = filename+ ": \r\t Failed to parse XML..."          //No Alert for this case...
65                                break
66                        case -2:                       
67                                //errorMsg = filename+ ": \r\t Either not found or cannot be opened for reading..."             //No Alert for this case...
68                                break
69                        case -3:
70                                errorMsg =  "\r\t XMLutils needs an upgrade:  http://www.igorexchange.com/project/XMLutils"
71                                break
72                        case -4:
73                                errorMsg = filename+ " ===> Not supported version of xml or SPICE..."   
74                                break
75                endswitch
76                SetDataFolder root:
77                //print "Failed loading", filename, "..."
78                DoAlert 0, errorMsg
79                //Clean up waves...
80                //KillWaves/Z M_listAttr, nsList,W_xmlcontentnodes
81                return(1)               //Do not change.
82        endif
83///***** done by a call to UpdateDisplayInformation()
84//      //the calling macro must change the display type
85//      String/G root:myGlobals:gDataDisplayType="RAW"          //displayed data type is raw
86//     
87//      //data is displayed here
88//      fRawWindowHook()
89        SetDataFolder root:
90       
91        Print "Time to load and display (s) = ",(ticks-t1)/60.15
92        Return(0)               //Do not change.
93End
94
95
96//function that does the guts of reading the binary data file
97//fname is the full path:name;vers required to open the file
98//VAX record markers are skipped as needed
99//VAX data as read in is in compressed I*2 format, and is decompressed
100//immediately after being read in. The final root:RAW:data wave is the real
101//neutron counts and can be directly operated on
102//
103// header information is put into three waves: integersRead, realsRead, and textRead
104// logicals in the header are currently skipped, since they are no use in the
105// data reduction process.
106//
107// The output is the three R/T/I waves that are filled at least with minimal values
108// and the detector data loaded into an array named "data"
109//
110// see documentation for the expected information in each element of the R/T/I waves
111// and the minimum set of information. These waves can be increased in length so that
112// more information can be accessed as needed (propagating changes...)
113//
114// called by multiple .ipfs (when the file name is known)
115//
116Function ReadHeaderAndData(filename)
117        String filename
118       
119        String curPath = "root:Packages:NIST:RAW:"     
120        //***NOTE ****
121        // the "current path" gets mysteriously reset to "root:" after the SECOND pass through
122        // this read routine, after the open dialog is presented
123        // the "--read" waves end up in the correct folder, but the data does not! Why?
124        //must re-set data folder before writing data array (done below)
125        SetDataFolder curPath   
126        //full filename and path is now passed in...
127        //actually open the file
128        //Open/R refNum as fname
129        STRING/G errorMsg       
130        Variable refNum,t1=ticks
131        //print "Loading", filename, "..."     
132        if (stringmatch(filename,"*.xml") <1)
133                //print "\r  ==> Failed: Not a *.xml file."
134                return (-1)                             //Not *.xml. Do nothing...
135        endif
136        //actually open the file
137        refNum = XmlOpenFile(filename) 
138        if (refNum < 0)
139                XmlCloseFile(refNum,0)
140                //print "\r  ==> Failed: Not a standard xml file format."
141                return (-2)                             //Not a xml file. Do nothing...
142        endif
143       
144        /////////////////////////////////////////////////////////////////////////////////////////////////\/\/\/\/ from P. R. Jemian     
145        //      test to see if XMLutils has the needed upgrade
146        XMLlistXpath(refNum, "/*", "") 
147        IF ( EXISTS( "M_listXPath" ) == 0 )
148                XmlCloseFile(refNum,0)
149                //errorMsg = "XMLutils needs an upgrade:  http://www.igorexchange.com/project/XMLutils"
150       
151                SetDataFolder root:
152                RETURN(-3)                                              // XOPutils needs an upgrade
153        ENDIF
154        ///////////////////////////////////////////////////////////////////////////////////////////////\/\/\/\ from P. R. Jemian
155       
156        // Check if  it is the SPICE version = 1.1
157        String ns_ver = "1.1"
158        Variable ns = 0
159        ns = str2num(XMLstrFmXpath(refNum, "//SPICErack/@SPICE_version","",""))
160       
161        // older version       
162        if (ns <1.1)
163                //errorMsg = filename + ": This SPICE version is not supported"
164                XmlCloseFile(refNum,0)
165                SetDataFolder root:
166                return (-4)
167        endif
168       
169        //this function is for reading in RAW data only, so it will always put data in RAW folder
170       
171        String curFolder="RAW"
172        SetDataFolder curPath           //use the full path, so it will always work
173        Variable/G root:Packages:NIST:RAW:gIsLogScale = 0               //initial state is linear, keep this in RAW folder
174        Variable integer,realval
175        String sansfname,textstr
176       
177        Make/O/N=23 $"root:Packages:NIST:RAW:IntegersRead"
178        Make/O/N=52 $"root:Packages:NIST:RAW:RealsRead"
179        Make/O/T/N=11 $"root:Packages:NIST:RAW:TextRead"
180       
181        Wave intw=$"root:Packages:NIST:RAW:IntegersRead"
182        Wave realw=$"root:Packages:NIST:RAW:RealsRead"
183        Wave/T textw=$"root:Packages:NIST:RAW:TextRead"
184       
185        //Make/O/N=16384 $"root:Pacakges:NIST:RAW:data"
186        //WAVE data=$"root:Packages:NIST:RAW:data"
187       
188        //intw = 0
189        //realw = 0
190        //textw = ""
191       
192       
193        //Redimension/N=(192,192) data                  //NIST raw data is 128x128 - do not generalize
194        //data =0
195       
196        //ORNL HFIR SANS DATA
197        String tempheadhfir =""
198       ReadHFIRSansRaw(refNum,curFolder,tempheadhfir)
199
200       //Take the file name from "actual file name", not from the header: (JC found some cases that those are different.)
201       //This  can be removed where the problem is solved....
202       textw[0]=GetFName(filename,  1)
203
204        SetDataFolder curPath
205        String/G fileList = textw[0]
206        //return the data folder to root
207        SetDataFolder root:
208
209        Return 0
210
211End
212
213
214//****************
215//main entry procedure for reading a "WORK.DIV" file
216//displays a quick image of the  file, to check that it's correct
217//data is deposited in root:DIV data folder
218//
219// local, currently unused
220//
221//
222
223Proc ReadWork_DIV()
224       
225        String fname = PromptForPath("Select detector sensitivity file")
226        ReadHeaderAndWork("DIV",fname)          //puts what is read in work.div
227       
228        String waveStr = "root:Packages:NIST:DIV:data"
229        NewImage/F/K=1/S=2 $waveStr             //this is an experimental IGOR operation
230        ModifyImage '' ctab= {*,*,YellowHot,0}
231
232        String/G root:Packages:NIST:DIV:fileList = "WORK.DIV"
233       
234        SetDataFolder root:             //(redundant)
235End
236
237
238//this function is the guts of reading a binary VAX file of real (4-byte) values
239// (i.e. a WORK.aaa file)
240// work files have the same header structure as RAW SANS data, just with
241//different data (real, rather than compressed integer data)
242//
243//************
244//this routine incorrectly reads in several data values where the VAX record
245//marker splits the 4-byte real (at alternating record markers)
246//this error seems to not be severe, but shoud be corrected (at great pain)
247//************
248//
249// called from ProtocolAsPanel.ipf
250//
251//
252Function ReadHeaderAndWork(type,fname)
253        String type,fname
254       
255        //type is the desired folder to read the workfile to
256        //this data will NOT be automatically displayed gDataDisplayType is unchanged
257
258//      SVAR cur_folder=root:myGlobals:gDataDisplayType
259        String cur_folder = type
260        String curPath = "root:Packages:NIST:"+cur_folder
261        SetDataFolder curPath           //use the full path, so it will always work
262       
263        Variable refNum,integer,realval
264        String sansfname,textstr
265        Variable/G $(curPath + ":gIsLogScale") = 0              //initial state is linear, keep this in DIV folder
266       
267        Make/O/N=23 $(curPath + ":IntegersRead")
268        Make/O/N=52 $(curPath + ":RealsRead")
269        Make/O/T/N=11 $(curPath + ":TextRead")
270       
271        WAVE intw=$(curPath + ":IntegersRead")
272        WAVE realw=$(curPath + ":RealsRead")
273        WAVE/T textw=$(curPath + ":TextRead")
274       
275        //***NOTE ****
276        // the "current path" gets mysteriously reset to "root:" after the SECOND pass through
277        // this read routine, after the open dialog is presented
278        // the "--read" waves end up in the correct folder, but the data does not! Why?
279        //must re-set data folder before writing data array (done below)
280       
281        SetDataFolder curPath
282        if (stringmatch(fname,"*.xml") <1)
283                return 0                                //Not *.xml. Do nothing...
284        endif
285        //actually open the file
286        refNum = XmlOpenFile(fname)     
287        if (refNum < 0)
288                XMLclosefile(refNum, 0)
289                return 0                                //Not a xml file. Do nothing...
290        endif
291       
292        //ORNL HFIR SANS DATA
293        String tempheadhfir =""
294       ReadHFIRSansRaw(refNum,cur_folder,tempheadhfir)
295
296        //Take the file name from "actual file name", not from the header: (JC found some cases that those are different.)
297       //This  can be removed where the problem is solved....
298       textw[0]=GetFName(fname,  1)
299       
300        //keep a string with the filename in the DIV folder
301        String/G $(curPath + ":fileList") = textw[0]
302
303        //return the data folder to root
304        SetDataFolder root:
305        Return(0)
306End
307
308/////   ASC FORMAT READER  //////
309/////   FOR WORKFILE MATH PANEL //////
310
311//function to read in the ASC output of SANS reduction
312// currently the file has 20 header lines, followed by a single column
313// of 16384 values, Data is written by row, starting with Y=1 and X=(1->128)
314//
315//returns 0 if read was ok
316//returns 1 if there was an error
317//
318// called by WorkFileUtils.ipf
319//
320Function ReadASCData(fname,destPath)
321        String fname, destPath
322        //this function is for reading in ASCII data so put data in user-specified folder
323        SetDataFolder "root:"+destPath
324
325        NVAR pixelsX = root:myGlobals:gNPixelsX
326        NVAR pixelsY = root:myGlobals:gNPixelsY
327        Variable refNum=0,ii,p1,p2,tot,num=pixelsX,numHdrLines=20
328        String str=""
329        //data is initially linear scale
330        Variable/G :gIsLogScale=0
331        Make/O/T/N=(numHdrLines) hdrLines
332        Make/O/D/N=(pixelsX*pixelsY) data                       //,linear_data
333       
334        //full filename and path is now passed in...
335        //actually open the file
336//      SetDataFolder destPath
337        Open/R/Z refNum as fname                // /Z flag means I must handle open errors
338        if(refnum==0)           //FNF error, get out
339                DoAlert 0,"Could not find file: "+fname
340                Close/A
341                SetDataFolder root:
342                return(1)
343        endif
344        if(V_flag!=0)
345                DoAlert 0,"File open error: V_flag="+num2Str(V_Flag)
346                Close/A
347                SetDataFolder root:
348                return(1)
349        Endif
350        //
351        for(ii=0;ii<numHdrLines;ii+=1)          //read (or skip) 18 header lines
352                FReadLine refnum,str
353                hdrLines[ii]=str
354        endfor
355        //     
356        Close refnum
357       
358//      SetDataFolder destPath
359        LoadWave/Q/G/D/N=temp fName
360        Wave/Z temp0=temp0
361        data=temp0
362        Redimension/N=(pixelsX,pixelsY) data            //,linear_data
363       
364        //linear_data = data
365       
366        KillWaves/Z temp0
367        Close/A
368        //return the data folder to root
369        SetDataFolder root:
370       
371        Return(0)
372End
373
374// fills the "default" fake header so that the SANS Reduction machinery does not have to be altered
375// pay attention to what is/not to be trusted due to "fake" information.
376// uses what it can from the header lines from the ASC file (hdrLines wave)
377//
378// destFolder is of the form "myGlobals:WorkMath:AAA"
379//
380//
381// called by WorkFileUtils.ipf
382//
383Function FillFakeHeader_ASC(destFolder)
384        String destFolder
385        Make/O/N=23 $("root:"+destFolder+":IntegersRead")
386        Make/O/N=52 $("root:"+destFolder+":RealsRead")
387        Make/O/T/N=11 $("root:"+destFolder+":TextRead")
388       
389        Wave intw=$("root:"+destFolder+":IntegersRead")
390        Wave realw=$("root:"+destFolder+":RealsRead")
391        Wave/T textw=$("root:"+destFolder+":TextRead")
392       
393        //Put in appropriate "fake" values
394        //parse values as needed from headerLines
395        Wave/T hdr=$("root:"+destFolder+":hdrLines")
396        Variable monCt,lam,offset,sdd,trans,thick
397        Variable xCtr,yCtr,a1,a2,a1a2Dist,dlam,bsDiam
398        String detTyp=""
399        String tempStr="",formatStr="",junkStr=""
400        formatStr = "%g %g %g %g %g %g"
401        tempStr=hdr[3]
402        sscanf tempStr, formatStr, monCt,lam,offset,sdd,trans,thick
403//      Print monCt,lam,offset,sdd,trans,thick,avStr,step
404        formatStr = "%g %g %g %g %g %g %g %s"
405        tempStr=hdr[5]
406        sscanf tempStr,formatStr,xCtr,yCtr,a1,a2,a1a2Dist,dlam,bsDiam,detTyp
407//      Print xCtr,yCtr,a1,a2,a1a2Dist,dlam,bsDiam,detTyp
408       
409        realw[16]=xCtr          //xCtr(pixels)
410        realw[17]=yCtr  //yCtr (pixels)
411        realw[18]=sdd           //SDD (m)
412        realw[26]=lam           //wavelength (A)
413        //
414        // necessary values
415        realw[10]=5                     //detector calibration constants, needed for averaging
416        realw[11]=10000
417        realw[12]=0
418        realw[13]=5
419        realw[14]=10000
420        realw[15]=0
421        //
422        // used in the resolution calculation, ONLY here to keep the routine from crashing
423        realw[20]=65            //det size
424        realw[27]=dlam  //delta lambda
425        realw[21]=bsDiam        //BS size
426        realw[23]=a1            //A1
427        realw[24]=a2    //A2
428        realw[25]=a1a2Dist      //A1A2 distance
429        realw[4]=trans          //trans
430        realw[3]=0              //atten
431        realw[5]=thick          //thick
432        //
433        //
434        realw[0]=monCt          //def mon cts
435
436        // fake values to get valid deadtime and detector constants
437        //
438        textw[9]=detTyp+"  "            //6 characters 4+2 spaces
439        textw[3]="[NGxSANS00]"  //11 chars, NGx will return default values for atten trans, deadtime...
440       
441        //set the string values
442        formatStr="FILE: %s CREATED: %s"
443        sscanf hdr[0],formatStr,tempStr,junkStr
444
445        String/G $("root:"+destFolder+":fileList") = tempStr
446        textw[0] = tempStr              //filename
447        textw[1] = junkStr              //run date-time
448       
449        tempStr = hdr[1]
450        tempStr = tempStr[0,strlen(tempStr)-2]          //clean off the last LF
451
452        textW[6] = tempStr      //sample label
453       
454        return(0)
455End
456
457// read specific bits of information from the header
458// each of these operations MUST take care of open/close on their own
459
460Function/S getStringFromHeader(fname,wantedterm)
461        String fname, wantedterm                                //full path:name, term name
462       
463        String str = ""
464        Variable refNum,i
465       
466        //check the ext.
467        if (stringmatch(fname,"*.xml") <1)
468                //print "Failed: Not a *.xml file."
469                return (str)                            //Not *.xml. Do nothing...
470        endif
471        //actually open the file
472        refNum = XmlOpenFile(fname)     
473        if (refNum < 0)
474                //print "Failed: Not a xml file."
475                XmlCloseFile(refNum,0)
476                return (str)                            //Not a xml file. Do nothing...
477        endif
478
479        //ORNL HFIR SANS strings meta DATA
480        if (stringmatch("*filename",wantedterm)>0)
481                str =GetFName(fname,  1)
482        else
483                str=ReadSFromHHead(refNum,wantedterm)  //Get it from the header.
484       endif
485       
486        //return the data folder to root
487        //SetDataFolder root:
488               
489        return(str)
490End
491
492// file suffix (NCNR data file name specific)
493
494// file suffix (13 characters @ byte 19)
495Function/S getSuffix(fname)
496        String fname
497       
498        return(getStringFromHeader(fname,"//suffix"))           //!!!!!!!!!!!!!!!!!!!!!!!!!
499End
500
501// associated file suffix (for transmission)
502
503Function/S getAssociatedFileSuffix(fname)
504        String fname
505       
506        return(getStringFromHeader(fname,"//assoc_suffix"))             //!!!!!!!!!!!!!!!!!!!!!!!!!
507End
508
509// sample label (60 characters @ byte 98)
510Function/S getSampleLabel(fname)
511        String fname
512       
513        return(getStringFromHeader(fname,"//Header/Scan_Title"))
514End
515
516// file creation date (20 characters @ byte 55)
517Function/S getFileCreationDate(fname)
518        String fname
519 
520        return(getStringFromHeader(fname,"//SPICErack/@start_time"))
521End
522
523// Check if the file is transmission file?
524Function/S getIsTrans(fname)
525        String fname
526        return(getStringFromHeader(fname,"//Header/Transmission"))
527End
528
529// read a single real value with GBLoadWave
530Function getRealValueFromHeader(fname,wantedterm,unit)
531        String fname, wantedterm,unit
532       
533        Variable vresult
534        Variable refNum
535       
536        if (stringmatch(fname,"*.xml") <1)
537                //print "Failed: Not a *.xml file."
538                return 0                                //Not *.xml. Do nothing...
539        endif
540        //actually open the file
541        refNum = XmlOpenFile(fname)     
542        if (refNum < 0)
543                //print "Failed: Not a xml file."
544                return 0                                //Not a xml file. Do nothing...
545        endif
546
547        //ORNL HFIR SANS strings meta DATA
548       vresult=ReadVFromHHead(refNum,wantedterm,unit)
549       
550        return(vresult)
551End
552
553//monitor count is at byte 39
554Function getMonitorCount(fname)
555        String fname
556       
557        return(getRealValueFromHeader(fname,"//Counters/monitor",""))
558end
559
560//saved monitor count is at byte 43
561Function getSavMon(fname)
562        String fname
563       
564        return(getRealValueFromHeader(fname,"//Counters/monitor",""))  //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!??
565end
566
567//detector count is at byte 47
568Function getDetCount(fname)
569        String fname
570       
571        return(getRealValueFromHeader(fname,"//Counters/psd",""))   //Need to check!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
572end
573
574//Attenuator number is at byte 51
575Function getAttenNumber(fname)
576        String fname
577       
578        return(getRealValueFromHeader(fname,"//Motor_Positions/attenuation","percent")) //in unit of percents
579end
580
581//transmission is at byte 158
582Function getSampleTrans(fname)
583        String fname
584        return(getRealValueFromHeader(fname,"//Transmission_for_Sample",""))
585end
586
587//box counts are stored at byte 494
588Function getBoxCounts(fname)
589        String fname
590       
591        return(getRealValueFromHeader(fname,"//Box_Counts",""))                 
592end
593
594//whole detector trasmission is at byte 392
595Function getSampleTransWholeDetector(fname)
596        String fname
597       
598        return(getRealValueFromHeader(fname,"//Counters/detector","")) //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
599end
600
601//SampleThickness is at byte 162
602Function getSampleThickness(fname)
603        String fname
604       
605        return(getRealValueFromHeader(fname,"//Header/Sample_Thickness","cm"))
606end
607
608//Sample Rotation Angle is at byte 170
609Function getSampleRotationAngle(fname)
610        String fname
611       
612        return(getRealValueFromHeader(fname,"",""))                     //ToDo: define this...
613end
614
615//temperature is at byte 186
616Function getTemperature(fname)
617        String fname
618       
619        return(getRealValueFromHeader(fname,"//Parameter_Positions/tsample","C"))   
620end
621
622//field strength is at byte 190
623Function getFieldStrength(fname)
624        String fname
625       
626        return(getRealValueFromHeader(fname,"//magnetic_field","G"))
627end
628
629//beam xPos is at byte 252
630Function getBeamXPos(fname)
631        String fname
632       
633        return(getRealValueFromHeader(fname,"//Header/beam_center_x_pixel",""))
634end
635
636//beam Y pos is at byte 256
637Function getBeamYPos(fname)
638        String fname
639       
640        return(getRealValueFromHeader(fname,"//Header/beam_center_y_pixel",""))
641end
642
643//sample to detector distance is at byte 260
644Function getSDD(fname)
645        String fname
646       
647        return(getRealValueFromHeader(fname,"//Motor_Positions/sample_det_dist","m"))
648end
649
650//detector offset is at byte 264
651Function getDetectorOffset(fname)
652        String fname
653       
654        return(getRealValueFromHeader(fname,"//Motor_Positions/detector_trans","cm"))  //cm:  HFIR mm
655end
656
657//Beamstop diameter is at byte 272
658Function getBSDiameter(fname)
659        String fname
660       
661        return(getRealValueFromHeader(fname,"//Motor_Positions/beam_trap_size","mm"))  //check if this beamstop diameter?
662end
663
664//source aperture diameter is at byte 280
665Function getSourceApertureDiam(fname)
666        String fname
667       
668        return(getRealValueFromHeader(fname,"//Header/source_aperture_size","mm"))
669end
670
671//sample aperture diameter is at byte 284
672Function getSampleApertureDiam(fname)
673        String fname
674       
675        return(getRealValueFromHeader(fname,"//Header/sample_aperture_size","mm"))
676end
677
678//source AP to Sample AP distance is at byte 288
679Function getSourceToSampleDist(fname)
680        String fname
681       
682        return(getRealValueFromHeader(fname,"//Header/source_distance","m")) //unit=m   :hfir = mm
683end
684
685//wavelength is at byte 292
686Function getWavelength(fname)
687        String fname
688       
689        return(getRealValueFromHeader(fname,"//Header/wavelength", "A"))
690end
691
692//wavelength spread is at byte 296
693Function getWavelengthSpread(fname)
694        String fname
695       
696        return(getRealValueFromHeader(fname,"//Header/wavelength_spread",""))
697end
698
699//transmission detector count is at byte 388
700Function getTransDetectorCounts(fname)
701        String fname
702       
703        return(getRealValueFromHeader(fname,"",""))  // (Unused, return 0)
704end
705
706//detector pixel X size is at byte 220
707Function getDetectorPixelXSize(fname)
708        String fname
709       
710        return(getRealValueFromHeader(fname,"//Header/x_mm_per_pixel","mm"))
711end
712
713//detector pixel Y size is at byte 232
714Function getDetectorPixelYSize(fname)
715        String fname
716       
717        return(getRealValueFromHeader(fname,"//Header/y_mm_per_pixel","mm"))
718end
719
720//total count time is at byte 31       
721Function getCountTime(fname)
722        String fname
723        Variable mtime
724       
725        mtime = getRealValueFromHeader(fname,"//Counters/time","")
726        if (mtime == 0)
727                mtime = 1               //get rid of a singular for calculating a rate in case.
728        endif
729        return(mtime)
730end
731
732//////  integer values
733//////Not used !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
734Function getIntegerFromHeader(fname,wanted)   ///Not used !!!!!!!!!
735        String fname                            //full path:name
736        String wanted           //starting byte
737
738        Variable refNum                                                               
739        Variable vresult
740       
741        if (stringmatch(fname,"*.xml") <1)
742                //print "Failed: Not a *.xml file."
743                return 0                                //Not *.xml. Do nothing...
744        endif
745        //actually open the file
746        refNum = XmlOpenFile(fname)
747        XMLclosefile(refNum, 0)
748        if (refNum < 0)
749                //print "Failed: Not a xml file."
750                return 0                                //Not a xml file. Do nothing...
751        endif
752
753        //ORNL HFIR SANS strings meta DATA
754       vresult=ReadVFromHHead(refNum,wanted, "")
755               
756        return(0)
757End
758//////////////////////////////////////////////////////////////////////////////////
759
760//reads the wavelength from a reduced data file (not very reliable)
761// - does not work with NSORTed files
762// - only used in FIT/RPA (which itself is almost NEVER used...)
763//
764Function GetLambdaFromReducedData(tempName)
765        String tempName
766       
767        String junkString
768        Variable lambdaFromFile, fileVar, junkVal
769        lambdaFromFile = 6.0
770
771        Open/R/P=catPathName fileVar as tempName
772        FReadLine fileVar, junkString
773        FReadLine fileVar, junkString
774        FReadLine fileVar, junkString
775        if(strsearch(LowerStr(junkString),"lambda",0) != -1)
776                FReadLine/N=11 fileVar, junkString
777                FReadLine/N=10 fileVar, junkString
778                sscanf  junkString, "%f",junkVal
779
780                lambdaFromFile = junkVal
781        endif
782        Close fileVar
783       
784        return(lambdaFromFile)
785End
786
787/////   TRANSMISSION RELATED FUNCTIONS    ////////
788//box coordinate are returned by reference
789//
790// box to sum over is bounded (x1,y1) to (x2,y2)
791//
792// this function returns the bounding coordinates as stored in
793// the header
794//
795// if not using the NCNR Transmission module, this function default to
796// returning 0000, and no changes needed
797Function getXYBoxFromFile(fname,x1,x2,y1,y2)
798        String fname
799        Variable &x1,&x2,&y1,&y2
800       
801        Variable refnum
802        String tmpFile = FindValidFilename(fname)
803        // tmpFile is only a parital path
804       
805        // return your bounding box coordinates or default values of 0
806        x1=getRealValueFromHeader(fname,"//XYBox_x1","")
807        x2=getRealValueFromHeader(fname,"//XYBox_x2","")
808        y1=getRealValueFromHeader(fname,"//XYBox_y1","")
809        y2=getRealValueFromHeader(fname,"//XYBox_y2","")
810       
811        if (x1 == -1 || x2 == -1 || y1 == -1 || y2 == -1)
812                x1 = 0
813                x2 = 0
814                y1 = 0
815                y2 = 0
816        endif
817       
818        return(0)
819End
820
821// Writes the coordinates of the box to the header after user input
822//
823// box to sum over bounded (x1,y1) to (x2,y2)
824//
825// if not using the NCNR Transmission module, this function is null
826Function WriteXYBoxToHeader(fname,x1,x2,y1,y2)
827        String fname
828        Variable x1,x2,y1,y2
829       
830        // your code to write bounding box to the header, or nothing
831        String x1str = "", x2str = "", y1str = "", y2str = ""
832        sprintf x1str, "%d", x1
833        sprintf x2str, "%d", x2
834        sprintf y1str, "%d", y1
835        sprintf y2str, "%d", y2
836
837        WriteHFIRHead(fname,x1str,"/SPICErack/XYBox_x1" ,"")   
838        WriteHFIRHead(fname,x2str,"/SPICErack/XYBox_x2" ,"")
839        WriteHFIRHead(fname,y1str,"/SPICErack/XYBox_y1" ,"")
840        WriteHFIRHead(fname,y2str,"/SPICErack/XYBox_y2" ,"")
841       
842        return(0)
843End
844
845// for transmission calculation, writes an NCNR-specific alphanumeric identifier
846// (suffix of the data file)
847//
848Function WriteAssocFileSuffixToHeader(fname,suffix)
849        String fname,suffix
850               
851       
852        WriteHFIRHead(fname,suffix,"/SPICErack/assoc_suffix" ,"text")
853        return(0)
854end
855
856
857//// ==================================================================
858//Keep these functions in case NIST changes: We need these...
859// TrimWhiteSpace (code from Jon Tischler)
860Function/T   HFIR_TrimWS(strg)
861   
862   String strg
863   return HFIR_TrimWSL(HFIR_TrimWSR(strg))
864End
865
866Function/T   HFIR_TrimWSL(strg)
867    String strg
868    Variable i, N=strlen(strg)
869    for (i=0;char2num(strg[i])<=32 && i<N;i+=1)    // find first non-white space
870    endfor
871    return strg[i,Inf]
872End
873
874Function/T   HFIR_TrimWSR(strg)
875    String strg
876    Variable i
877    for (i=strlen(strg)-1; char2num(strg[i])<=32 && i>=0; i-=1)    // find last non-white space
878   endfor
879    return strg[0,i]
880End
881//// ==================================================================
882
883Function ReadHFIRRaw(refNum,prtname,pname)   //NOT USED!!!!!!!!
884        Variable refNum
885        String pname, prtname
886       
887        //temp list of ns
888        MAKE/T/N=(1)/O nsList
889        nsList[0] = "1.1"
890       
891        // Check if  it is the SPICE version = 1.1
892        Variable  item,i
893        String thislocation, ns=""
894        Variable nns
895
896        for (item = 0; item < DimSize(nsList, 0); item += 1)            // loop over all possible namespaces
897                XMLlistAttr(refNum, prtname, nsList[item])
898                wave/T M_listAttr
899       
900                for (i = 0; i < DimSize(M_listAttr,0); i+=1)                    // loop over all available attributes
901                        // Expect the required hfir XML header (will fail if "schemalocation" is not found)
902                        if ( CmpStr(  LowerStr(M_listAttr[i][1]),  LowerStr(pname) ) == 0 )
903                                thisLocation = HFIR_TrimWS(M_listAttr[i][2])
904                                if ( StringMatch(thisLocation, nsList[item] + "*") )
905                                        ns = nsList[item]
906                                        Break
907                                endif
908                        endif
909                endfor
910                if (strlen(ns))
911                        Break           
912                endif
913        endfor
914        sscanf ns,"%f",nns
915return nns
916END
917
918
919////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
920//       Read ORNL HFIR SANS data ( xml format) file:general loading from display raw data
921////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
922Function ReadHFIRSansRaw(refNum,curFolder,tempheadhfir)
923    Variable refNum
924    String curFolder,tempheadhfir
925     
926        String curPath="root:Packages:NIST:"+curFolder
927        SetDataFolder curPath
928        Make/O/N=23 $(curPath+":IntegersRead")
929        Make/O/N=52 $(curPath+":RealsRead")
930        Make/O/T/N=11 $(curPath+":TextRead")
931       
932        Wave intw=$(curPath+":IntegersRead")
933        Wave realw=$(curPath+":RealsRead")
934        Wave/T textw=$(curPath+":TextRead")
935       
936        Variable ind,i,j,centerdata=1
937        Variable pixnumx=0,pixnumy=0
938        String val = "", pix_num = ""// numerical and text values
939        Variable value = 0.0,t1=ticks
940        String unitstr =""      //unit string
941
942        //Initialize wave values         
943         realw=0
944         intw=0
945         textw=""
946         textw[2]=curFolder
947         textw[3]=""
948         textw[4]="C"                                ///???
949         textw[7]="C"                        // temperature unit C
950         textw[10]="xml"                        //HFIR SANS RAW data file extension
951         realw[4]  = 1                          //Default for transmission for sample
952         realw[12]=0.00                       //following 6 values are for non-linear spatial corrections to a detector (RC timing)
953         realw[15]=0.00                        // 10 and 13 are the X and Y pixel dimensions,,(11,12 and 13,14 are set to values for a linear response, as from a new Ordela detector)
954         realw[11]=10000.00                          //nonlinear spatial pix(x) //Do not change unless knowing what you are doing...
955         realw[14]=10000.00                          //nonlinear spatial pix(y)
956         // detector physical width (right now assumes square...) (in cm)
957         // beam stop X-position (motor reading, approximate cm from zero position)
958         // currently NCNR-specific use to identify transmission measurements
959         // you return 0
960         realw[37] = 0
961         //textw[2]="RAW"      //????
962 
963//      Print "Time to list attributes (s) = ",(ticks-t1)/60.15
964//      Print "Time to list elements (s) = ",(ticks-t1)/60.15
965
966        // Get and set the number of pixels from the line just above data.
967        pix_num = XMLstrFmXpath(refNum,"//Data/Detector/@type","","")
968        pixnumx=Str2num(StringFromList(0,StringFromList(1,pix_num ,","),"]"))   
969        pixnumy=Str2num(StringFromList(1,StringFromList(0,pix_num ,","),"["))
970        Variable/G root:myGlobals:gNPixelsX=pixnumx
971        Variable/G root:myGlobals:gNPixelsY=pixnumy     
972        SetDataFolder curPath
973
974                        //******Below deleted since HFIR prefers to use <Data type="INT32[xxx,xxx]" for pixnumbers
975                        //********Leave the following lines in case they change the policy.
976                        //if (stringmatch(tempheadhfir,"Number_of_X_Pixels")>0)                 
977                        //      pixnumx=Str2num(val)     
978                        //      Variable/G root:myGlobals:gNPixelsX=pixnumx     
979                        //       SetDataFolder curPath
980                        //elseif  (stringmatch(tempheadhfir,"Number_of_Y_Pixels")>0)
981                        //      pixnumy=Str2num(val)
982                        //      Variable/G root:myGlobals:gNPixelsY=pixnumy
983                        //       SetDataFolder curPath
984                        // Note for units: If in-unit is null, out will be unity.
985                        textw[6] = XMLstrFmXpath(refNum,"//Header/Scan_Title","","")
986               
987                        textw[3] = XMLstrFmXpath(refNum,"//Header/Users","","")         //ToDo: Define   
988                               
989                        textw[9] = XMLstrFmXpath(refNum,"//Header/Instrument","","")                            //ToDo: Define
990                       
991                        value = ValfromUnit(refNum,"//Transmission_for_Sample","")
992                        if (value <= 0)
993                                value = 1               //HFIR default = -1 while NIST package not working if it is <=0: Set default =1. <=NOT good!!!
994                        endif
995                        realw[4] = value
996                       
997                        realw[3] = ValfromUnit(refNum,"//Motor_Positions/attenuation","percent")
998                        realw[8] = ValfromUnit(refNum,"//Parameter_Positions/tsample","C")
999                        realw[0] = ValfromUnit(refNum,"//Counters/monitor","")
1000                        realw[5] = ValfromUnit(refNum,"//Header/Sample_Thickness","cm")
1001                        realw[2] = ValfromUnit(refNum,"//Counters/psd","")       ////Need to check!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1002                        realw[10] = ValfromUnit(refNum,"//Header/x_mm_per_pixel","mm") 
1003                        realw[13] = ValfromUnit(refNum,"//Header/y_mm_per_pixel","mm") 
1004                        Variable/G root:myGlobals:PixelResDefault = unit_convert(realw[13],"mm","cm") //back to cm unit for this default value??!!
1005                        SetDataFolder curPath
1006                       
1007                        realw[16] = ValfromUnit(refNum,"//Header/beam_center_x_pixel","") 
1008                        realw[17] = ValfromUnit(refNum,"//Header/beam_center_y_pixel","") 
1009                        realw[21] = ValfromUnit(refNum,"//Motor_Positions/beam_trap_size","mm")    //what is different from the beam trap diameter in the file???
1010                        realw[18] = ValfromUnit(refNum,"//Motor_Positions/sample_det_dist","m")
1011                        intw[1]  = ValfromUnit(refNum,"//Counters/time","sec")     //Not supported. Assumed in "sec"
1012                        intw[2] = intw[1] //???
1013                        realw[23]  = ValfromUnit(refNum,"//Header/source_aperture_size","mm")      //diameter???
1014                        realw[24]  = ValfromUnit(refNum,"//Header/sample_aperture_size","mm")      //diameter???
1015                        realw[25]  = ValfromUnit(refNum,"//Header/source_distance","m")         
1016                        realw[26]  = ValfromUnit(refNum,"//Header/wavelength","a")     
1017                        realw[27]  = ValfromUnit(refNum,"//Header/wavelength_spread","")       
1018                       
1019                        //Set pixel numbers
1020                        //SetDataFolder curPath
1021                        NVAR pixnumx1= root:myGlobals:gNPixelsX                     
1022                        NVAR pixnumy1= root:myGlobals:gNPixelsY
1023                        Variable pixnx = pixnumx1, pixny = pixnumy1
1024                        realw[20] = realw[10]*pixnx/10.0                        // physical detector width  in cm  // ToDo: Need to check for ypix size???
1025                       
1026                        //prepare to get data
1027                        Make/O/N=(pixnumx1*pixnumy1) $(curPath+":data")
1028                        WAVE  data=$(curPath+":data")
1029                        //set the globals to the detector dimensions (pixels)
1030                        Redimension/N=(pixnx,pixny) data                        //ORNL pixnums are given from the data file
1031                        Variable intens = 0
1032       
1033                        // Read 2d data
1034                        XMLwaveFmXpath(refNum,"/SPICErack/Data/Detector",""," \t\n\r")
1035                        WAVE/T M_xmlContent
1036                        for (i=0;i<pixnx;i+=1)
1037                                for  (j=0;j<pixny;j+=1)
1038                                        sscanf M_xmlContent[j+i*pixny],"%i", intens
1039                                        data[i][j]=intens
1040                                endfor
1041                        endfor
1042                       
1043
1044                       
1045                        ///////unit test 1/2//////////////////////////////////////////////////////////////////////////////////////////////////////////////
1046                        //if  (stringmatch(tempheadhfir,"Detector")<1 ||stringmatch(tempheadhfir,"data"))
1047                        //      print tempheadhfir+"="+val+"["+unitstr+"]"
1048                        //endif
1049                        /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1050               
1051
1052
1053          //If the data is a sensitivity data, need to be narmalize so that the average over the detector should be 1.
1054         If (stringmatch(curFolder, "DIV") >0)
1055                //Variable V_avg
1056                 WaveStats/Z/Q data
1057                data /= V_avg
1058          endif
1059                       
1060
1061        //keep a string of the filename in the RAW folder
1062       
1063        Variable strpos
1064               
1065        textw[0] = RemoveAllSpaces(XMLstrFmXpath(refNum,"//SPICErack/@filename","","") )    //////ShortFileName(RemoveAllSpaces(XMLstrFmXpath(refNum,"//SPICErack/@filename","","") )  )         // file name
1066        textw[1] =   XMLstrFmXpath(refNum,"//SPICErack/@start_time","","")              //Date and Time
1067        textw[5]=StringFromList(0,textw[1]," ")                                                                         //Date
1068       
1069        //String/G $(curPath+":FileList") = textw[0]
1070       
1071        ///////unit test 2/2//////////////////////////////////////////////////////////////////////////////////////////////////////////////
1072        //SetDataFolder curPath
1073        //print "****** ["+num2str(pixnx)+","+num2str(pixny)+"]*******"
1074        //for (i=0;i<Dimsize(textw,0);i+=1)
1075        //      print "textw["+num2str(i)+"] ="+textw[i]
1076        //endfor
1077        //for (i=0;i<Dimsize(realw,0);i+=1)
1078        //      print "realw["+num2str(i)+"] ="+num2str(realw[i])
1079        //endfor
1080        //for (i=0;i<Dimsize(intw,0);i+=1)
1081        //      print "intw["+num2str(i)+"] ="+num2str(intw[i])
1082        //endfor
1083        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1084        // We have everything from file: Need to close the file soon as possible
1085        XMLclosefile(refNum, 0)
1086        SetDataFolder curPath
1087        Killwaves/Z M_listXPath
1088End
1089
1090/// Get real value in NIST unit ///////////////////////////////////////////////////////////////////////////////////////////////////
1091Function ValfromUnit(refNum,wantedterm,NISTunit)
1092        Variable refNum    //FileID
1093        String wantedterm,NISTunit  //Xpath, value in string, unit from HFIR, unit from NIST
1094       
1095        String val="", unitstr=""
1096        Variable value = 0.0
1097        //SetDataFolder curPath ////????????/
1098       
1099        val =   XMLstrFmXpath(refNum,wantedterm,"","")
1100        unitstr =  RemoveAllSpaces(XMLstrFmXpath(refNum,wantedterm+"/@units","",""))
1101       
1102        //The units of the source_distance is treated special...
1103        if (stringmatch(wantedterm,"*source_distance")>0 )
1104                if  (strlen(unitstr)==0)
1105                        unitstr = "mm"          //Give mm unit since no unit is provided from the file. ///This needs to be corrected soon!!!!
1106                 endif
1107        endif
1108        //String to double
1109        sscanf val, "%f", value
1110        Variable data
1111        data = unit_convert(value,unitstr,NISTunit)
1112
1113        return data
1114End
1115
1116
1117//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1118//Read Real Values from HFIR data 
1119//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1120Function ReadVFromHHead(refNum,wantedterm,NCunit)
1121      Variable refNum
1122      String wantedterm, NCunit
1123     
1124      Variable vresult=-1  // (wantedterm=="", return -1)
1125        Variable ind=0,i=0, value = 0
1126        String  ntype = ""
1127        String savedDataFolder = GetDataFolder(1)
1128        //Default for transmission rate (between 0 to 1): HFIR not provide this as a Float number???? ==>make one: if exist, read it below.
1129        if (stringmatch(wantedterm,"//Transmission_for_Sample")>0)
1130                vresult=1               
1131        endif
1132       
1133        String unitstr = "", typestr="",tempheadhfir="", val=""
1134
1135        if (stringmatch(wantedterm,"") >0 ) // set zero if wnatedterm is "" ,not defined(eg., rotation angle).
1136                vresult =0
1137                //close here
1138                XMLclosefile(refNum, 0)
1139                return vresult
1140        else
1141                //Find the value,unit, and type of the value: a little ugly but faster...
1142                val =   XMLstrFmXpath(refNum,wantedterm,"","")
1143                unitstr =  RemoveAllSpaces(XMLstrFmXpath(refNum,wantedterm+"/@units","",""))
1144                typestr =  RemoveAllSpaces(XMLstrFmXpath(refNum,wantedterm+"/@type","",""))
1145                //close here
1146                XMLclosefile(refNum, 0)
1147        endif
1148       
1149        if   (stringmatch(typestr , "INT*")>0)
1150                ntype = "i"             //INT32
1151        elseif (stringmatch(typestr , "FLOAT*")>0)
1152                ntype ="f"              //FLOAT32
1153        else
1154                ntype ="s"              //TEXT
1155        endif   
1156       
1157        String ustr ="%f"                               //default: float
1158        if (stringmatch(ntype,"i") > 0) //for integer   
1159                ustr = "%d"
1160        endif   
1161                                       
1162        //Special case starts!!!
1163        //No unit found in hfir ("mm") but needs to convert to meters.
1164        //The following 3 lines should be removed once HFIR puts th units on the raw data files.
1165        if (stringmatch(wantedterm,"*source_distance")>0&& strlen(unitstr) ==0)
1166                unitstr = "mm"         
1167        endif
1168        //Special case ends!!!
1169       
1170        //Do NOT use str2num(): will loose many decimal digits.
1171        sscanf val, ustr, value
1172        vresult = unit_convert(value,unitstr,NCunit)
1173        if (stringmatch(wantedterm,"*Transmission_for_Sample")>0 && vresult == 0)
1174                 //Transmission default value if it was set to 0.
1175                 vresult = 1
1176        endif
1177                       
1178        //Set PixResDefault from y_mm_per_pixel (not x_mm_per_pixel!!!!!!!!)
1179        if (stringmatch(wantedterm,"*y_mm_per_pixel")>0)
1180                 Variable/G root:myGlobals:PixelResDefault = unit_convert(vresult,"mm","cm") //back to cm unit for this default value??!!
1181                 SetDataFolder savedDataFolder          //In case...
1182        endif
1183
1184               
1185        return (vresult)
1186
1187End
1188
1189/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1190//Read Strings from HFIR data 
1191/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1192Function/S ReadSFromHHead(refNum,wantedterm)
1193      Variable refNum
1194      String wantedterm
1195     
1196      String tempheadhfir = ""
1197      String result = "",gotterm ="n" ,name
1198        Variable ind,i
1199
1200      if   (stringmatch(wantedterm,"")>0)
1201                result = ""
1202                XMLclosefile(refNum, 0)
1203                return (result)
1204        endif
1205       
1206        result =  XMLstrFmXpath(refNum,wantedterm,"","")
1207        if (stringmatch(result, "") != -1 )     
1208                gotterm ="y"   
1209        endif
1210
1211        //HFIR header does not have "suffix" tag but one can get the info from file name before user writes the tag into the header.
1212        if (stringmatch("",result)>0     && stringmatch("//suffix",wantedterm)>0 )
1213                name = RemoveAllSpaces(XMLstrFmXpath(refNum,"//SPICErack/@filename","",""))
1214                result=StringFromList(2,StringFromList(0, name,"."), "_")+"_"+StringFromList(3,StringFromList(0,name,"."), "_")
1215        endif
1216
1217        //Close file here.
1218        XMLclosefile(refNum, 0)
1219       
1220        if (stringmatch(gotterm,"n")>0 )
1221                result = ""
1222        endif   
1223
1224      return (result)
1225End
1226
1227
1228//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1229//WRITE Real Values to HFIR data file 
1230//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1231
1232Function WriteHFIRHead(filename,value,wantedterm,NCunit)
1233     
1234      String filename, value,wantedterm, NCunit //where value is a string...
1235     
1236        String valstr
1237      Variable/D vresult = 0
1238      Variable refNum
1239        Variable ind=0,i=0, vals
1240       
1241        Variable typenum = 0
1242        String ntype = ""       //Do not change this initial, "".
1243        String nstr = "/SPICErack"              //to add new nodes and content: NEVER CAHNGE this string
1244        String errorMsg =""
1245       
1246        //print "Loading", filename, "..."
1247        if (stringmatch(filename,"*.xml") <1)
1248                //print "\r  ==>  Failed: Not a *.xml file."
1249                return 0                                //Not *.xml. Do nothing...
1250        endif
1251        //actually open the file
1252        refNum = XmlOpenFile(filename) 
1253
1254        if (refNum < 0)
1255                switch(refNum)                                 
1256                        case -1:
1257                                errorMsg = errorMsg+filename+ "  ==>  Not a standard xml file format; Please check if the file is not broken..."
1258                        break
1259                        case -2:
1260                                errorMsg = errorMsg+filename+"  ==>  Please check if the file name is same as that written in the header..."
1261                        break
1262                endswitch
1263                print errorMsg
1264                XMLclosefile(refNum, 0)
1265                return -1                               //Not a xml file. Do nothing...
1266        endif
1267
1268                String unitstr = "",typestr="", val=""
1269
1270                if  (strlen(wantedterm)==0)     
1271                        vresult =0                              //If input is NULL, do nothing...
1272                        nstr = ""                                       //reset as No new node
1273
1274                else   //(stringmatch(tempheadhfir,wantedterm)>0)       
1275                        val =   XMLstrFmXpath(refNum,wantedterm,"","")
1276               
1277                        //Special case starts!!!
1278                        //No unit founds in hfir ("mm") file but needs to convert to meters. Let's give it one.
1279                        if (stringmatch(wantedterm,"*source_distance")>0&& strlen(unitstr) ==0)
1280                                unitstr = "mm" 
1281                                ntype ="f"     
1282                        //Special case ends!!!
1283                        else
1284                                unitstr =  XMLstrFmXpath(refNum,wantedterm+"/@units","","")
1285                                typestr =  RemoveAllSpaces(XMLstrFmXpath(refNum,wantedterm+"/@type","",""))
1286       
1287                                ntype ="s"              //TEXT 
1288                               
1289                                        if  (strlen(typestr)==0)
1290                                                ntype = "s"
1291                                        elseif   (stringmatch(typestr, "INT*")>0)
1292                                                ntype = "i"             //INT32
1293                                        elseif (stringmatch(typestr, "FLOAT*")>0)
1294                                                ntype ="f"              //FLOAT32
1295                                        endif   
1296                        endif
1297                       
1298                        if (stringmatch(ntype,"s") > 0) //for strings           
1299                                vresult = 1                     
1300                                valstr =value
1301                        else
1302                                String ustr ="%f"                               //default: float
1303                                if (stringmatch(ntype,"i") > 0) //for integer   
1304                                        ustr = "%d"
1305                                endif                   
1306                                sscanf  value,ustr, vals
1307                                vresult = unit_convert(vals,NCunit,unitstr)     //Unit correction...(back to the HFIR unit)
1308                               
1309                                sprintf valstr,ustr, vresult
1310                        endif
1311                       
1312                        if (stringmatch(wantedterm,"/SPICErack/*")>0&& strlen(val) ==0)
1313                                nstr = "/SPICErack"
1314                                // remove "/SPICErack/" from wantedterm
1315                                wantedterm = StringFromList(2, wantedterm,"/SPICErack/")
1316                        else
1317                                XMLsetNodeStr(refNum,wantedterm,"",valstr)      //to set
1318                                nstr = ""                               //reset as No new node
1319                        endif
1320                        //break
1321                 endif         
1322        //to write new  attr name and value which are not found in the raw file.
1323        if (strlen(nstr)>2)                             
1324                 XMLaddNode(refNum,nstr,"",wantedterm,value,1)
1325                 // nstr to add new node
1326                 nstr = "//"+wantedterm
1327                 // get unit
1328                 if (stringmatch(NCunit,"text")>0)     
1329                        ntype = "text"
1330                        vresult = 1
1331                 else
1332                        XMLsetAttr(refNum,nstr,"","units",NCunit)       //use NIST units.
1333                        ntype = "FLOAT32"                                               //Let's set the any number as float for now... 
1334                        sscanf  value, "%f", vals
1335                        vresult = vals         
1336                 endif
1337                 //print "*** Note:*** \r     *** No parameter named",wantedterm, "was found, so it was added to the end of your data file."
1338                 XMLsetAttr(refNum,nstr,"","type",ntype)       
1339        endif
1340
1341        //KillWaves/Z W_ElementList,M_xmlContent,M_listXPath,M_listAttr                 //clean up
1342        if      (strlen(wantedterm)==0 && vresult == -1)
1343                XMLclosefile(refNum, 0)
1344                //print "Failed writing",wantedterm, "on", filename, "..."
1345        else
1346                XMLclosefile(refNum, 1)                                         //save and close the file.
1347                //print "Finished writing",wantedterm,"=",value,"[",NCunit,"]  on", filename, "..."
1348        endif
1349        return (vresult)
1350
1351End
1352
1353
1354Function UserGetWLPanel_ContButton(cntrlName)
1355      String cntrlName
1356      DoWindow /K WaveLengthInput
1357End
1358
1359Function Daskcheckbox(cntrlName,checked)
1360String cntrlName
1361Variable checked
1362
1363Wave realw=$"root:RAW:RealsRead"
1364Variable/G root:myGlobals:globDask=checked
1365      if (checked==1)
1366           Variable /G root:myGlobals:globwlfix=realw[26]
1367           Variable /G root:myGlobals:globdwlfix=realw[27]
1368      endif
1369
1370 End
1371 
1372 
1373Function Daskcheckbox1(cntrlName,checked)
1374String cntrlName
1375Variable checked
1376
1377Wave templw=$"root:RAW:tempwave1"
1378Variable/G root:myGlobals:globDask1=checked
1379      if (checked==1)
1380           Variable /G root:myGlobals:globwlfix=templw[0]
1381           Variable /G root:myGlobals:globdwlfix=templw[1]
1382      endif
1383
1384 End
1385 
1386//Write whether Transmission is True or False.
1387Function Write_isTransmissionToHeader(fname,str)
1388        String fname,str
1389
1390        WriteHFIRHead(fname,str, "//Header/Transmission","text")       
1391        return(0)
1392End
1393
1394//sample transmission is a real value at byte 158
1395Function WriteTransmissionToHeader(fname,trans)
1396        String fname
1397        Variable trans
1398
1399        String transstr = ""
1400        sprintf transstr, "%f", trans
1401
1402         WriteHFIRHead(fname,transstr,"/SPICErack/Transmission_for_Sample" ,"")                 
1403        return(0)
1404End
1405
1406//whole transmission is a real value at byte 392
1407Function WriteWholeTransToHeader(fname,trans)
1408        String fname
1409        Variable trans
1410
1411        String transstr = ""
1412        sprintf transstr, "%f", trans
1413
1414        WriteHFIRHead(fname,transstr,"//Counters/detector" ,"")         //????????????????????????????????????????????????????????
1415        return(0)
1416End
1417
1418//box sum counts is a real value
1419// used for transmission calculation module
1420//box sum counts is a real value at byte 494
1421Function WriteBoxCountsToHeader(fname,counts)
1422        String fname
1423        Variable counts
1424
1425        String countsstr = ""
1426        sprintf countsstr, "%f", counts
1427
1428        WriteHFIRHead(fname,countsstr,"/SPICErack/Box_Counts" ,"")     
1429        return(0)
1430End
1431
1432//Below units refer to NIST units..
1433//beam stop X-pos is at byte 368
1434Function WriteBSXPosToHeader(fname,xpos)
1435        String fname
1436        Variable xpos
1437
1438        String xposstr = ""
1439        sprintf xposstr, "%f", xpos
1440
1441        WriteHFIRHead(fname,xposstr,"//Motor_Positions/beam_trap_x","mm")       ///Is this diameter?
1442        return(0)
1443End
1444
1445//sample thickness is at byte 162
1446Function WriteThicknessToHeader(fname,num)
1447        String fname
1448        Variable num
1449
1450        String numstr = ""
1451        sprintf numstr, "%f", num
1452
1453        WriteHFIRHead(fname,numstr,"//Header/Sample_Thickness","cm")
1454        return(0)
1455End
1456
1457//beam center X pixel location is at byte 252
1458Function WriteBeamCenterXToHeader(fname,num)
1459        String fname
1460        Variable num
1461
1462        String numstr = ""
1463        sprintf numstr, "%f", num
1464
1465        WriteHFIRHead(fname,numstr,"//Header/beam_center_x_pixel" ,"")
1466        return(0)
1467End
1468
1469//beam center Y pixel location is at byte 256
1470Function WriteBeamCenterYToHeader(fname,num)
1471        String fname
1472        Variable num
1473
1474        String numstr = ""
1475        sprintf numstr, "%f", num
1476
1477        WriteHFIRHead(fname,numstr,"//Header/beam_center_y_pixel","")
1478        return(0)
1479End
1480
1481//Attenuation (percent) 0 for no attanuation (not its transmission)
1482Function WriteAttenNumberToHeader(fname,num)
1483        String fname
1484        Variable num
1485
1486        String numstr = ""
1487        sprintf numstr, "%f", num
1488
1489        WriteHFIRHead(fname,numstr,"//Motor_Positions/attenuation","percent")   // HFIR has attenuation % instead of this. thus user has to use patch unless somebody change the format!!!!
1490        return(0)
1491End
1492
1493//monitor count is at byte 39
1494Function WriteMonitorCountToHeader(fname,num)
1495        String fname
1496        Variable num
1497
1498        String numstr = ""
1499        sprintf numstr, "%f", num
1500
1501        WriteHFIRHead(fname,numstr,"//Counters/monitor","")
1502        return(0)
1503End
1504
1505//total detector count is at byte 47
1506Function WriteDetectorCountToHeader(fname,num)
1507        String fname
1508        Variable num
1509
1510        String numstr = ""
1511        sprintf numstr, "%f", num
1512
1513        WriteHFIRHead(fname,numstr,"//Counters/psd","")
1514        return(0)
1515End
1516
1517//transmission detector count is at byte 388
1518Function WriteTransDetCountToHeader(fname,num)
1519        String fname
1520        Variable num
1521
1522        String numstr = ""
1523        sprintf numstr, "%f", num
1524
1525        WriteHFIRHead(fname,numstr,"//Counters/detector","")   ///Check with Steve & Ken!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1526        return(0)
1527End
1528
1529//wavelength is at byte 292
1530Function WriteWavelengthToHeader(fname,num)
1531        String fname
1532        Variable num
1533
1534        String numstr = ""
1535        sprintf numstr, "%f", num
1536
1537        WriteHFIRHead(fname,numstr,"//Header/wavelength" ,"angstroms")
1538        return(0)
1539End
1540
1541//wavelength spread is at byte 296
1542Function WriteWavelengthDistrToHeader(fname,num)
1543        String fname
1544        Variable num
1545
1546        String numstr = ""
1547        sprintf numstr, "%f", num
1548
1549        WriteHFIRHead(fname,numstr,"//Header/wavelength_spread","")
1550        return(0)
1551End
1552
1553//temperature is at byte 186
1554Function WriteTemperatureToHeader(fname,num)
1555        String fname
1556        Variable num
1557
1558        String numstr = ""
1559        sprintf numstr, "%f", num
1560
1561        WriteHFIRHead(fname,numstr,"//Parameter_Positions/tsample" ,"C")
1562        return(0)
1563End
1564
1565//magnetic field is at byte 190
1566Function WriteMagnFieldToHeader(fname,num)
1567        String fname
1568        Variable num
1569
1570        String numstr = ""
1571        sprintf numstr, "%f", num
1572
1573        WriteHFIRHead(fname,numstr,"/SPICErack/magnetic_field","G")  //Not defined on HFIR file...  Should be changed the name when decided...
1574        return(0)
1575End
1576
1577//Source Aperture diameter is at byte 280
1578Function WriteSourceApDiamToHeader(fname,num)
1579        String fname
1580        Variable num
1581
1582        String numstr = ""
1583        sprintf numstr, "%f", num
1584
1585        WriteHFIRHead(fname,numstr,"//Header/source_aperture_size","mm")
1586        return(0)
1587End
1588
1589//Sample Aperture diameter is at byte 284
1590Function WriteSampleApDiamToHeader(fname,num)
1591        String fname
1592        Variable num
1593
1594        String numstr = ""
1595        sprintf numstr, "%f", num
1596
1597        WriteHFIRHead(fname,numstr,"//Header/sample_aperture_size","mm")
1598        return(0)
1599End
1600
1601//Source to sample distance is at byte 288
1602Function WriteSrcToSamDistToHeader(fname,num)
1603        String fname
1604        Variable num
1605
1606        String numstr = ""
1607        sprintf numstr, "%f", num
1608
1609        WriteHFIRHead(fname,numstr,"//Header/source_distance","m")     //unit=m   :hfir = mm ???????????????
1610        return(0)
1611End
1612
1613//detector offset is at byte 264
1614Function WriteDetectorOffsetToHeader(fname,num)
1615        String fname
1616        Variable num
1617
1618        String numstr = ""
1619        sprintf numstr, "%f", num
1620
1621        WriteHFIRHead(fname,numstr,"//Header/detector_trans","cm")  //cm:  HFIR = mm !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1622        return(0)
1623End
1624
1625//beam stop diameter is at byte 272
1626Function WriteBeamStopDiamToHeader(fname,num)
1627        String fname
1628        Variable num
1629       
1630        String numstr = ""
1631        sprintf numstr, "%f", num
1632       
1633        WriteHFIRHead(fname,numstr,"//Motor_Positions/beam_trap_size","mm")  //check !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1634        return(0)
1635End
1636
1637//sample to detector distance is at byte 260
1638Function WriteSDDToHeader(fname,num)
1639        String fname
1640        Variable num
1641
1642        String numstr = ""
1643        sprintf numstr, "%f", num
1644       
1645        WriteHFIRHead(fname,numstr,"//Motor_Positions/sample_det_dist","m")
1646        return(0)
1647End
1648
1649//detector pixel X size (mm) is at byte 220
1650Function WriteDetPixelXToHeader(fname,num)
1651        String fname
1652        Variable num
1653
1654        String numstr = ""
1655        sprintf numstr, "%f", num
1656       
1657        WriteHFIRHead(fname,numstr, "//Header/x_mm_per_pixel","mm")
1658        return(0)
1659End
1660
1661//detector pixel Y size (mm) is at byte 232
1662Function WriteDetPixelYToHeader(fname,num)
1663        String fname
1664        Variable num
1665       
1666        String numstr = ""
1667        sprintf numstr, "%f", num
1668       
1669        WriteHFIRHead(fname,numstr, "//Header/y_mm_per_pixel","mm")
1670        return(0)
1671End
1672
1673// sample label
1674// limit to 60 characters
1675Function WriteSamLabelToHeader(fname,str)
1676        String fname,str
1677       
1678        if(strlen(str) > 60)
1679                str = str[0,59]
1680        endif
1681        WriteHFIRHead(fname,str, "//Header/Scan_Title","text") //Users tend to put the sample descrpt here instead of "Sample_Name"...
1682        return(0)
1683End
1684
1685
1686Function WriteCountTimeToHeader(fname,num)
1687        String fname
1688        Variable num
1689       
1690        String numstr = ""
1691        sprintf numstr, "%f", num
1692       
1693        WriteHFIRHead(fname,numstr,"//Counters/time","sec")
1694        return(0)
1695End
1696
1697
1698/////Handy Unit converter for length & time units"
1699Function length_unit_convert(from,to)  // input: ("m", cm")==> output=10,....;   input: ("", "") ==> out = 1
1700        String from, to
1701       
1702        Variable i, out
1703       
1704        Make/O/T/N=(18,2) munit
1705       
1706        //ToDo: to combine the same units       
1707        //length units
1708        munit[0][0]="m"   //popular units first...
1709        munit[0][1]= "1"
1710        munit[1][0]="cm"
1711        munit[1][1]= "0.01"
1712        munit[2][0]="mm"
1713        munit[2][1]= "0.001"
1714        munit[3][0]="angstroms"  //HFIR used this rather than A
1715        munit[3][1]= "1e-10"
1716        munit[4][0]="meters"
1717        munit[4][1]= "1"
1718        munit[5][0]="um"
1719        munit[5][1]= "1e-06"
1720        munit[6][0]="nm"
1721        munit[6][1]= "1e-09"
1722        munit[7][0]="km"
1723        munit[7][1]= "1000"
1724        munit[8][0]="a"
1725        munit[8][1]= "1e-10"
1726        munit[9][0]="angstrom"
1727        munit[9][1]= "1e-10"
1728        munit[10][0]="microns"
1729        munit[10][1]= "1e-6"
1730        munit[11][0]="meter"
1731        munit[11][1]= "1"
1732       
1733        //time units
1734        munit[12][0]="sec"
1735        munit[12][1]= "1"
1736        munit[13][0]="seconds"
1737        munit[13][1]= "1"
1738        munit[14][0]="min"
1739        munit[14][1]= "60"
1740        munit[15][0]="minutes"
1741        munit[15][1]= "60"
1742        munit[16][0]="hrs"
1743        munit[16][1]= "3600"
1744        munit[17][0]="hours"
1745        munit[17][1]= "3600"
1746        //Add more units here...
1747         
1748        String  v_from="", v_to=""
1749        for (i = 0; i<DimSize(munit,0); i+=1)
1750                if (stringmatch(munit[i][0],from)>0)  // IgorPro "stringmatch()" function handles both lower & upper cases.
1751                        v_from = munit[i][1]
1752                        break
1753                endif
1754        endfor
1755       
1756        for (i = 0; i<DimSize(munit,0); i+=1)
1757                if (stringmatch(munit[i][0],to)>0)
1758                        v_to = munit[i][1]
1759                        break
1760                endif
1761        endfor
1762       
1763        KillWaves/Z munit
1764       
1765       
1766        if (strlen(v_from)==0 || strlen(v_to) ==0)
1767                out = 1                 //Do nothing...
1768        else
1769                Variable vf, vt
1770                sscanf  v_to, "%f", vt
1771                sscanf  v_from, "%f", vf
1772                out = vf / vt
1773        endif
1774        return out
1775End
1776
1777
1778///For length and temperature units
1779Function unit_convert(val, from,to)  // input: ("m", cm")==> output=10,....;   input: ("", "") ==> out = 1
1780        Variable val
1781        String from, to
1782
1783        from = RemoveAllSpaces(from)
1784        to = RemoveAllSpaces(to)
1785                       
1786        Variable i, out = val
1787
1788        //Search for two same strings, or one with none.
1789        if (stringmatch(from,to)>0 ||strlen(from) == 0||strlen(to)==0)
1790                out = val
1791               
1792        //Temperature unit: support only C and K
1793        elseif (stringmatch(from,"C")>0 || stringmatch(to,"K")>0||stringmatch(to,"C")>0 || stringmatch(from,"K")>0)
1794                out =temp_unit_convert(val, from,to)
1795               
1796        //Length unit                   
1797        else
1798                out = val*length_unit_convert(from,to)                                                 
1799        endif
1800
1801        return out
1802End
1803
1804//temperature unit converter: Only support K and C.
1805Function temp_unit_convert(val, from,to) 
1806        Variable val
1807        String from, to
1808       
1809        Variable i, j, out = val
1810
1811        Make/O/T/N=(2,2) tunit
1812       
1813        tunit[0][0]="C"   //popular units first...
1814        tunit[0][1]= "-273.15"
1815        tunit[1][0]="K"
1816        tunit[1][1]= "0"       
1817
1818        String  v_from="", v_to=""
1819
1820        for (i = 0; i<DimSize(tunit,0); i+=1)
1821                if (stringmatch(tunit[i][0],from)==1)  // IgorPro "stringmatch()" function handles both lower & upper cases.
1822                        v_from = tunit[i][1]
1823                        break
1824                endif
1825        endfor
1826
1827        for (j = 0; j<DimSize(tunit,0); j+=1)
1828                if (stringmatch(tunit[j][0],to)==1)
1829                        v_to = tunit[j][1]
1830                        break
1831                endif   
1832        endfor 
1833        KillWaves/Z tunit
1834        if (strlen(v_from)==0 || strlen(v_to) ==0)
1835                out = 1                 //Do nothing...
1836        else
1837                Variable vt, vf
1838                sscanf  v_to, "%f", vt
1839                sscanf  v_from, "%f", vf
1840                out = val + (vt - vf)
1841        endif
1842        return out
1843End
1844
1845
1846///This function make HFIR SANS data file shorter which is more than 30 characters causing problem taking other names after the file name.
1847//Will remove instrumental name.
1848Function/S ShortFileName(fileName)
1849        String fileName
1850        //Default: just passing
1851        String fname = fileName
1852
1853        //Check whether it is from HiResSANS or BioSANS and remove the head
1854        if (stringmatch(fileName,"HiResSANS_*.*")>0 )
1855                fname = ReplaceString("HiResSANS_",fname,"HS_",0,1)   
1856        elseif (stringmatch(filename,"BioSANS_*.*")>0)
1857                fname = ReplaceString("BioSANS_",fname,"BS_",0,1)     
1858        endif
1859        return fname
1860END
1861
1862//Not used
1863///This function return the original HFIR SANS data file name that was shorten before.
1864//Put them back to HiResSANS*** or BioSANS***.
1865Function/S FullFileName(fname)
1866        String fname
1867        //Default: just passing
1868        String fileName = fname
1869       
1870        //Check whether it is from HiResSANS or BioSANS
1871        if (stringmatch(fname,"*HS_*.*")>0 )
1872                fileName = ReplaceString("HS_",fname,"HiResSANS_",0,1) 
1873        elseif (stringmatch(fname,"*BS_*.*")>0)
1874                fileName = ReplaceString("BS_",fname,"BioSANS_",0,1)   
1875        endif
1876
1877        return fileName
1878END
1879
1880
1881///Find file name from full Path+file
1882Function/S GetFName(path,  length)
1883        String path
1884        Variable length // 1 for full name, 0 for shorten name, others pass the name
1885       
1886        Variable index
1887        String ofname, mfname
1888       
1889        // get index of the file name
1890        index = ItemsInList(path,":") - 1
1891        // get file name
1892        ofname = StringFromList(index,path,":")
1893        //modify the name if need otherwise return w/o change
1894        if (length == 0)
1895                mfname = ShortFileName(ofname)
1896        elseif (length == 1)
1897                mfname = FullFileName(ofname)
1898        else
1899                mfname = ofname
1900        endif
1901        // return the path+modified file name
1902        return mfname
1903End
1904
1905
1906///Find file name from full Path+file and replace file name to a shorter or full name in path+file.
1907Function/S ReplaceFName(path,  length)
1908        String path
1909        Variable length // 1 for full name, 0 for shorten name
1910       
1911        Variable index
1912        String ofname,mfname
1913       
1914        // get index of the file name
1915        index = ItemsInList(path,":") - 1
1916        // get file name
1917        ofname = StringFromList(index,path,":")
1918        //modify the name if need otherwise return w/o change
1919        if (length == 0)
1920                mfname = ShortFileName(ofname)
1921        else
1922                mfname = FullFileName(ofname)
1923        endif
1924        // return the path+modified file name
1925        return ReplaceString(ofname,path,mfname,0,1)
1926End
1927
1928////Unused ///Not working well
1929// Change file name before and after Xml open
1930Function/S XmlFileOpen(fname)
1931        String fname
1932       
1933        // fname = path + full file name
1934        fname = ReplaceFName(fname,  1)
1935        XmlOpenFile(fname)
1936        // path + short file name
1937        return ReplaceFName(fname,  0)
1938End
1939
1940
1941////// OCT 2009, facility specific bits from ProDiv()
1942//"type" is the data folder that has the corrected, patched, and normalized DIV data array
1943//
1944// the header of this file is rather unimportant. Filling in a title at least would be helpful/
1945//
1946Function Write_DIV_File(type)
1947        String type
1948       
1949        // Your file writing function here. Don't try to duplicate the VAX binary format...
1950       
1951        return(0)
1952End
1953
1954////// OCT 2009, facility specific bits from MonteCarlo functions()
1955//"type" is the data folder that has the data array that is to be (re)written as a full
1956// data file, as if it was a raw data file
1957//
1958// not really necessary
1959//
1960Function Write_RawData_File(type,fullpath,dialog)
1961        String type,fullpath
1962        Variable dialog         //=1 will present dialog for name
1963       
1964        // Your file writing function here. Don't try to duplicate the VAX binary format...
1965        Print "Write_RawData_File stub"
1966       
1967        return(0)
1968End
Note: See TracBrowser for help on using the repository browser.