source: sans/Dev/trunk/NCNR_User_Procedures/Reduction/SANS/ProDiv.ipf @ 544

Last change on this file since 544 was 544, checked in by srkline, 14 years ago

Lots of changes to add the first version of a USANS simulator, like SASCALC

(!) first issue is with the entanglement of dependencies - need to load SANS macros first!

otherwise, worth a first test for interface and accuracy. behavior is similar to the 1D SASCALC

File size: 18.1 KB
Line 
1#pragma rtGlobals=1             // Use modern global access method.
2#pragma version=5.0
3#pragma IgorVersion=6.0
4
5
6//********************
7// Vers. 1.2 092101
8//
9// Procedures to create a "DIV" file for use as a detector sensitivity file
10// Follows the same procedure as PRODIV on the VAX
11// -requires two "full" reduced runs from plexiglass or water
12// -prompts the user for the locations of the offset and no-offset files
13// and for the range of data to replace
14// - then writes of the "div" file and fake-VAX format, which is rather ugly
15// since the DIV file is floating point...
16//
17//
18// 08 AUG 03
19// allowed for creation of DIV files on 8m SANS with two beamstops
20//
21// JAN2006 - not modified! still hard-wired to take a 128x128 detector image
22//
23//*********************
24
25//writes an VAX-style WORK file, "exactly" as it would be output from the VAX
26//except for the "dummy" header and the record markers - the record marker bytes are
27// in the files - they are just written as zeros and are meaningless
28//file is:
29//      516 bytes header
30// 128x128=16384 (x4) bytes of data
31// + 2 byte record markers interspersed just for fun
32// = 66116 bytes
33//prompts for name of the output file.
34//
35Function WriteVAXWorkFile(type)
36        String type
37       
38        Wave data=$("root:Packages:NIST:"+type+":data")
39       
40        Variable refnum,ii=0,hdrBytes=516,a,b,offset
41        String fullpath=""
42       
43        Duplicate/O data,tempData
44        Redimension/S/N=(128*128) tempData
45        tempData *= 4
46       
47        PathInfo/S catPathName
48        fullPath = DoSaveFileDialog("Save data as")       //won't actually open the file
49        If(cmpstr(fullPath,"")==0)
50                //user cancel, don't write out a file
51          Close/A
52          Abort "no data file was written"
53        Endif
54       
55        Make/B/O/N=(hdrBytes) hdrWave
56        hdrWave=0
57        FakeDIVHeader(hdrWave)
58       
59        Make/Y=2/O/N=(510) bw510                //Y=2 specifies 32 bit (=4 byte) floating point
60        Make/Y=2/O/N=(511) bw511
61        Make/Y=2/O/N=(48) bw48
62
63        Make/O/B/N=2 recWave            //two bytes
64
65        //actually open the file
66        Open/C="????"/T="TEXT" refNum as fullpath
67        FSetPos refNum, 0
68        //write header bytes (to be skipped when reading the file later)
69       
70        FBinWrite /F=1 refnum,hdrWave
71       
72        ii=0
73        a=0
74        do
75                //write 511 4-byte values (little-endian order), 4* true value
76                bw511[] = tempData[p+a]
77                FBinWrite /B=3/F=4 refnum,bw511
78                a+=511
79                //write a 2-byte record marker
80                FBinWrite refnum,recWave
81               
82                //write 510 4-byte values (little-endian) 4* true value
83                bw510[] = tempData[p+a]
84                FBinWrite /B=3/F=4 refnum,bw510
85                a+=510
86               
87                //write a 2-byte record marker
88                FBinWrite refnum,recWave
89               
90                ii+=1   
91        while(ii<16)
92        //write out last 48  4-byte values (little-endian) 4* true value
93        bw48[] = tempData[p+a]
94        FBinWrite /B=3/F=4 refnum,bw48
95        //close the file
96        Close refnum
97       
98        //go back through and make it look like a VAX datafile
99        Make/W/U/O/N=(511*2) int511             // /W=16 bit signed integers /U=unsigned
100        Make/W/U/O/N=(510*2) int510
101        Make/W/U/O/N=(48*2) int48
102       
103        //skip the header for now
104        Open/A/T="????TEXT" refnum as fullPath
105        FSetPos refnum,0
106       
107        offset=hdrBytes
108        ii=0
109        do
110                //511*2 integers
111                FSetPos refnum,offset
112                FBinRead/B=2/F=2 refnum,int511
113                Swap16BWave(int511)
114                FSetPos refnum,offset
115                FBinWrite/B=2/F=2 refnum,int511
116               
117                //skip 511 4-byte FP = (511*2)*2 2byte int  + 2 bytes record marker
118                offset += 511*2*2 + 2
119               
120                //510*2 integers
121                FSetPos refnum,offset
122                FBinRead/B=2/F=2 refnum,int510
123                Swap16BWave(int510)
124                FSetPos refnum,offset
125                FBinWrite/B=2/F=2 refnum,int510
126               
127                //
128                offset += 510*2*2 + 2
129               
130                ii+=1
131        while(ii<16)
132        //48*2 integers
133        FSetPos refnum,offset
134        FBinRead/B=2/F=2 refnum,int48
135        Swap16BWave(int48)
136        FSetPos refnum,offset
137        FBinWrite/B=2/F=2 refnum,int48
138
139        //move to EOF and close
140        FStatus refnum
141        FSetPos refnum,V_logEOF
142       
143        Close refnum
144       
145        Killwaves/Z hdrWave,bw48,bw511,bw510,recWave,temp16,int511,int510,int48
146End
147
148// given a 16 bit integer wave, read in as 2-byte pairs of 32-bit FP data
149// swap the order of the 2-byte pairs
150//
151Function Swap16BWave(w)
152        Wave w
153
154        Duplicate/O w,temp16
155        //Variable num=numpnts(w),ii=0
156
157        //elegant way to swap even/odd values, using wave assignments
158        w[0,*;2] = temp16[p+1]
159        w[1,*;2] = temp16[p-1]
160
161//crude way, using a loop       
162//      for(ii=0;ii<num;ii+=2)
163//              w[ii] = temp16[ii+1]
164//              w[ii+1] = temp16[ii]
165//      endfor
166       
167        return(0)       
168End
169
170// writes a fake label into the header of the DIV file
171//
172Function FakeDIVHeader(hdrWave)
173        WAVE hdrWave
174       
175        //put some fake text into the sample label position (60 characters=60 bytes)
176        String day=date(),tim=time(),lbl=""
177        Variable start=98,num,ii
178       
179        lbl = "Sensitivity (DIV) created "+day +" "+tim
180        num=strlen(lbl)
181        for(ii=0;ii<num;ii+=1)
182                hdrWave[start+ii] = char2num(lbl[ii])
183        endfor
184
185        return(0)
186End
187
188//works on the data in "type" folder
189//sums all of the data, and normalizes by the number of cells (=128*128)
190// calling procedure must make sure that the folder is on linear scale FIRST
191Function NormalizeDIV(type)
192        String type
193       
194        WAVE data=$("root:Packages:NIST:"+type+":data")
195        Variable totCts=sum(data,Inf,-Inf)              //sum all of the data
196       
197        data /= totCts
198        data *= 128*128
199       
200        return(0)
201End
202
203// prompts the user for the location of the "COR" -level data
204// data can be copied to any data folder (except DIV) for use here...
205//
206// then there is a "pause for user" to allow the user to select the "box"
207// in the ON-AXIS datset that is to be replaced by the data in the off-axis data
208//
209// corrections are done...
210//
211// finally, the DIV file is written to disk
212Function MakeDIVFile(ctrType,offType)
213        String ctrType,offType
214       
215        Prompt ctrType,"On-Center Plex data (corrected)",popup,"STO;SUB;BGD;COR;CAL;SAM;EMP;"
216        Prompt offType,"Offset Plex data (corrected)",popup,"STO;SUB;BGD;COR;CAL;SAM;EMP;"
217        DoPrompt "Pick the data types",ctrType,offType
218        //"COR" data in both places - reduction must be done ahead of time
219       
220        //temporarily set data display to linear
221        NVAR gLog = root:myGlobals:gLogScalingAsDefault
222        Variable oldState = gLog
223        gLog=0  //linear
224       
225        if(V_Flag==1)
226                //user cancelled
227                return(1)
228        endif
229       
230        //show the ctrType
231        //get the xy range to replace
232        Execute "ChangeDisplay(\""+ctrType+"\")"
233       
234        NewPanel/K=2/W=(139,341,382,432) as "Get XY Range"
235        DoWindow/C tmp_GetXY
236        AutoPositionWindow/E/M=1/R=SANS_Data
237        DrawText 15,20,"Find the (X1,X2) and (Y1,Y2) range to"
238        DrawText 15,40,"replace and press continue"
239        Button button0, pos={80,58},size={92,20},title="Continue"
240        Button button0,proc=XYContinueButtonProc
241       
242        PauseForUser tmp_GetXY,SANS_Data
243       
244        //replace the center section of the "on" data with the center of the "off" data
245        Variable x1,x2,y1,y2
246        GetXYRange(x1,x2,y1,y2)
247        Printf "X=(%d,%d)  Y=(%d,%d)\r", x1,x2,y1,y2
248        ReplaceDataBlock(ctrType,offType,x1,x2,y1,y2)
249       
250        DoAlert 1,"Is this NG1 data with a second beamstop?"
251        if(V_flag==1)
252                GetXYRange(x1,x2,y1,y2)
253                Printf "X=(%d,%d)  Y=(%d,%d)\r", x1,x2,y1,y2
254                ReplaceDataBlock(ctrType,offType,x1,x2,y1,y2)
255        endif
256       
257        //normalize the new data (and show it)
258        NormalizeDiv(ctrtype)
259        UpdateDisplayInformation(ctrtype)
260        //write out the new data file
261        WriteVAXWorkFile(ctrtype)
262        gLog = oldState         //set log/lin pref back to user - set preference
263        Return(0)
264End
265
266//ctrData is changed -- offData is not touched
267//simple replacement of the selected data...
268//
269Function ReplaceDataBlock(ctrType,offType,x1,x2,y1,y2)
270        String ctrType,offType
271        Variable x1,x2,y1,y2
272       
273        //do it crudely, with nested for loops
274        WAVE ctrData=$("root:Packages:NIST:"+ctrtype+":data")
275        WAVE offData=$("root:Packages:NIST:"+offtype+":data")
276        Variable ii,jj
277       
278        for(ii=x1;ii<=x2;ii+=1)
279                for(jj=y1;jj<=y2;jj+=1)
280                        ctrData[ii][jj] = offData[ii][jj]
281                endfor
282        endfor
283       
284        return(0)
285End
286
287//continue button waiting for the user to pick the range, and continue the execution
288//
289Function XYContinueButtonProc(ctrlName)
290        String ctrlName
291       
292        DoWindow/K tmp_GetXY
293End
294
295// prompts the user to enter the XY range for the box replacement
296// user can get these numbers by printing out marquee coordinates to the command window
297//
298Function GetXYRange(x1,x2,y1,y2)
299        Variable &x1,&x2,&y1,&y2
300       
301        Variable x1p,x2p,y1p,y2p
302        Prompt x1p,"X1"
303        Prompt x2p,"X2"
304        Prompt y1p,"Y1"
305        Prompt y2p,"Y2"
306        DoPrompt "Enter the range to replace",x1p,x2p,y1p,y2p
307        x1=x1p
308        x2=x2p
309        y1=y1p
310        y2=y2p
311       
312//      Print x1,x2,y1,y2
313        Return(0)
314End
315
316
317/////////////////////
318//
319// for the DIV "protocol" panel, I probably need to have parts of the protocol panel initialized...
320// folders are generated at the startup initialization, before protocol panel
321//
322Proc BuildDIVPanel()
323        DoWindow/F DIV_Panel
324        if(V_flag==0)
325                InitDIVPanel()
326                DIV_Panel()
327        Endif
328End
329
330//initialization procedure for the protocol panel
331//note that :gAbsStr is also shared (common global) to that used in
332//the questionnare form of the protcol (see protocol.ipf)
333//
334//0901, uses 8 points in protocol wave
335Proc InitDIVPanel()
336
337        //set up the global variables needed for the protocol panel
338        //global strings to put in a temporary protocol textwave
339        Variable ii=0,nsteps=8
340        String waveStr="DIV_Protocol"
341        SetDataFolder root:myGlobals:Protocols
342        Make/O/T/N=(nsteps) $"root:myGlobals:Protocols:DIV_Protocol" = ""
343       
344        DIV_protocol[2] = "none"
345        DIV_protocol[3] = "none"
346        DIV_protocol[4] = "none"
347        DIV_protocol[5] = "AVTYPE=none;"
348        DIV_protocol[6] = "DRK=none,DRKMODE=0,"
349       
350
351        String/G root:myGlobals:Protocols:gPlex="Plex"
352        String/G root:myGlobals:Protocols:gPlexBgd="Bgd"
353        String/G root:myGlobals:Protocols:gPlexEmp="Emp"
354        String/G root:myGlobals:Protocols:gPlex_off="Plex offset"
355        String/G root:myGlobals:Protocols:gPlexBgd_off="Bgd offset"
356        String/G root:myGlobals:Protocols:gPlexEmp_off="Emp offset"
357        String/G root:myGlobals:Protocols:gPlexName="Plex_date.div"
358       
359        Variable/G root:myGlobals:Protocols:gPlexX1=45
360        Variable/G root:myGlobals:Protocols:gPlexX2=87
361        Variable/G root:myGlobals:Protocols:gPlexY1=43
362        Variable/G root:myGlobals:Protocols:gPlexY2=85
363        Variable/G root:myGlobals:Protocols:gPlexTrans=0.48
364       
365        SetDataFolder root:
366       
367End
368
369// load in one on-center file and show the box
370//
371Function ShowBoxButtonProc(ba) : ButtonControl
372        STRUCT WMButtonAction &ba
373
374        switch( ba.eventCode )
375                case 2: // mouse up
376                        // click code here
377                        if(cmpstr(ba.ctrlName, "ShowBox") == 0)
378                       
379                                //parse for the first run number
380                                SVAR gPlex = root:myGlobals:Protocols:gPlex
381                                String item,fname
382                               
383                                item = StringFromList(0, gPlex ,",")
384                                fname = FindFileFromRunNumber(str2num(item))
385                                if(strlen(fname) == 0)
386                                        Abort "Bad file number in Plex field"
387                                endif
388                                // load the file
389                                ReadHeaderAndData(fname)        //this is the full Path+file
390                                UpdateDisplayInformation("RAW")
391                                //draw a box of the specified size. This is persistent on the display as you scroll to the offset data
392                                NVAR x1 = root:myGlobals:Protocols:gPlexX1
393                                NVAR x2 = root:myGlobals:Protocols:gPlexX2
394                                NVAR y1 = root:myGlobals:Protocols:gPlexY1
395                                NVAR y2 = root:myGlobals:Protocols:gPlexY2
396                               
397                                SetDrawLayer/W=SANS_Data/K UserFront                    //set the layer, and clear it
398                                SetDrawEnv/W=SANS_Data xcoord=bottom,ycoord=left,fillpat=0,linethick=3,linefgc=(65535, 65535, 65535)
399                                DrawRect/W=SANS_Data x1, y2, x2, y1
400                               
401                                Button $ba.ctrlName,title="Clear Box",rename=HideBox,win=DIV_Panel
402                               
403                        else
404                                if(winType("SANS_Data")==1)
405                                        SetDrawLayer/W=SANS_Data/K UserFront                    //set the layer, and clear it
406                                        Button $ba.ctrlName,title="Show Box",rename=ShowBox,win=DIV_Panel
407                                else
408                                        Button $ba.ctrlName,title="Show Box",rename=ShowBox,win=DIV_Panel
409                                endif
410                        endif   
411                       
412                        break
413        endswitch
414
415        return 0
416End
417
418// do everything...
419//
420Function GenerateDIVButtonProc(ba) : ButtonControl
421        STRUCT WMButtonAction &ba
422
423        switch( ba.eventCode )
424                case 2: // mouse up
425                        // click code here
426                       
427                        //temporarily set data display to linear
428                        NVAR gLog = root:myGlobals:gLogScalingAsDefault
429                        Variable oldState = gLog
430                        gLog=0  //linear
431                       
432                       
433                        SVAR gPlex = root:myGlobals:Protocols:gPlex
434                        SVAR gPlexBgd = root:myGlobals:Protocols:gPlexBgd
435                        SVAR gPlexEmp = root:myGlobals:Protocols:gPlexEmp
436                        SVAR gPlex_off = root:myGlobals:Protocols:gPlex_off
437                        SVAR gPlexBgd_off = root:myGlobals:Protocols:gPlexBgd_off
438                        SVAR gPlexEmp_off = root:myGlobals:Protocols:gPlexEmp_off
439                        SVAR gPlexName = root:myGlobals:Protocols:gPlexName
440                       
441                        NVAR X1 = root:myGlobals:Protocols:gPlexX1
442                        NVAR X2 = root:myGlobals:Protocols:gPlexX2
443                        NVAR Y1 = root:myGlobals:Protocols:gPlexY1
444                        NVAR Y2 = root:myGlobals:Protocols:gPlexY2
445                        NVAR gPlexTrans = root:myGlobals:Protocols:gPlexTrans
446                       
447                        WAVE/T proto = $"root:myGlobals:Protocols:DIV_Protocol"
448                       
449                        String item,fname,str
450                        Variable ii,num
451                // reduce the on-center
452                        //patch trans
453                        num = ItemsInList(gPlex, ",")
454                        for(ii=0;ii<num;ii+=1)
455                                item = StringFromList(ii, gPlex ,",")
456                                fname = FindFileFromRunNumber(str2num(item))
457                                if(strlen(fname) == 0)
458                                        Abort "Bad file number in no offset Plex field"
459                                endif
460                                WriteTransmissionToHeader(fname,gPlexTrans)
461                        endfor
462                       
463                        //go through the protocol
464                        str = ParseRunNumberList(gPlexBgd)
465                        if(strlen(str) > 0)
466                                proto[0] = str
467                        else
468                                Abort "Bad file number in no offset Bgd"
469                        endif
470                        str = ParseRunNumberList(gPlexEmp)
471                        if(strlen(str) > 0)
472                                proto[1] = str
473                        else
474                                Abort "Bad file number in no offset Emp"
475                        endif
476                        str = ParseRunNumberList(gPlex)
477                        if(strlen(str) > 0)
478                                ExecuteProtocol("root:myGlobals:Protocols:DIV_Protocol",str)
479                        else
480                                Abort "Bad file number in no offset Plex"
481                        endif
482                        // move it into STO
483                        Execute "CopyWorkFolder(\"COR\",\"STO\")"
484                       
485                       
486                       
487                // reduce the off-center, keep in STO
488                        //patch trans
489                        num = ItemsInList(gPlex_off, ",")
490                        for(ii=0;ii<num;ii+=1)
491                                item = StringFromList(ii, gPlex_off ,",")
492                                fname = FindFileFromRunNumber(str2num(item))
493                                if(strlen(fname) == 0)
494                                        Abort "Bad file number in Plex field"
495                                endif
496                                WriteTransmissionToHeader(fname,gPlexTrans)
497                        endfor
498                       
499                        //go through the protocol
500                        str = ParseRunNumberList(gPlexBgd_off)
501                        if(strlen(str) > 0)
502                                proto[0] = str
503                        else
504                                Abort "Bad file number in offset Bgd"
505                        endif
506                        str = ParseRunNumberList(gPlexEmp_off)
507                        if(strlen(str) > 0)
508                                proto[1] = str
509                        else
510                                Abort "Bad file number in offset Emp"
511                        endif
512                        str = ParseRunNumberList(gPlex_off)
513                        if(strlen(str) > 0)
514                                ExecuteProtocol("root:myGlobals:Protocols:DIV_Protocol",str)
515                        else
516                                Abort "Bad file number in offset Emp"
517                        endif
518                        ConvertFolderToLinearScale("COR")
519                       
520                       
521                // replace the patch
522                // on-center data is changed (STO)
523                        ReplaceDataBlock("STO","COR",x1,x2,y1,y2)
524                // normalize
525                        NormalizeDiv("STO")
526                        UpdateDisplayInformation("STO")
527                //write out the new data file
528                        WriteVAXWorkFile("STO")
529                               
530                        gLog=oldState           //revert display preference to old state       
531                        break
532        endswitch
533
534        return 0
535End
536
537// if a dark color is used, then
538//¥SetVariable setvar0 labelBack=(65535,65535,65535)
539// for each variable will give a white background to the label text
540Window DIV_Panel() : Panel
541        PauseUpdate; Silent 1           // building window...
542        NewPanel /W=(594,44,932,570)/K=1 as "DIV_Panel"
543//      ModifyPanel cbRGB=(35867,28177,65535)           //purple
544//      ModifyPanel cbRGB=(1,16019,65535)                               //electric blue
545        ModifyPanel cbRGB=(36631,59604,33902)           //spring green
546        SetDrawLayer UserBack
547        DrawRect 71,324,145,391
548        TitleBox title0,pos={14,16},size={50,20},title="No Offset"
549        TitleBox title0_1,pos={17,125},size={35,20},title="Offset"
550        SetVariable setvar0,pos={15,46},size={250,15},title="PLEX",value= root:myGlobals:Protocols:gPlex
551        SetVariable setvar0_1,pos={16,69},size={250,15},title="EMP",value= root:myGlobals:Protocols:gPlexEmp
552        SetVariable setvar0_2,pos={14,92},size={250,15},title="BGD",value= root:myGlobals:Protocols:gPlexBgd
553        SetVariable setvar1,pos={17,158},size={250,15},title="PLEX",value= root:myGlobals:Protocols:gPlex_off
554        SetVariable setvar001,pos={18,181},size={250,15},title="EMP",value= root:myGlobals:Protocols:gPlexEmp_off
555        SetVariable setvar002,pos={16,204},size={250,15},title="BGD",value= root:myGlobals:Protocols:gPlexBgd_off
556        SetVariable setvar002_1,pos={14,251},size={150,15},title="Transmission"
557        SetVariable setvar002_1,limits={0,1,0.01},value= root:myGlobals:Protocols:gPlexTrans
558//      SetVariable setvar003,pos={16,441},size={250,15},title="DIV FILE NAME"
559//      SetVariable setvar003,value= root:myGlobals:Protocols:gPlexName
560        Button ShowBox,pos={226,325},size={90,20},proc=ShowBoxButtonProc,title="Show Box"
561        Button button1,pos={25,441},size={150,20},proc=GenerateDIVButtonProc,title="Generate DIV File"
562        Button button2,pos={25,481},size={150,20},proc=ReloadDIVButtonProc,title="Load DIV File"
563        Button button4,pos={240,481},size={80,20},proc=DoneDIVButtonProc,title="Done"
564        Button button3,pos={240,10},size={50,20},proc=DIVHelpButtonProc,title="Help"
565        SetVariable setvar00201,pos={84,297},size={50,15},limits={0,128,1},title=" ",value= root:myGlobals:Protocols:gPlexY2
566        SetVariable setvar00202,pos={15,350},size={50,15},limits={0,128,1},title=" ",value= root:myGlobals:Protocols:gPlexX1
567        SetVariable setvar00203,pos={85,399},size={50,15},limits={0,128,1},title=" ",value= root:myGlobals:Protocols:gPlexY1
568        SetVariable setvar00204,pos={156,348},size={50,15},limits={0,128,1},title=" ",value= root:myGlobals:Protocols:gPlexX2
569EndMacro
570
571
572// done
573//
574Function DoneDIVButtonProc(ba) : ButtonControl
575        STRUCT WMButtonAction &ba
576
577        switch( ba.eventCode )
578                case 2: // mouse up
579                        // click code here
580                        DoWindow/K DIV_Panel
581                        break
582        endswitch
583
584        return 0
585End
586
587// load in a DIV file, print out the stats, display in SANS_Data
588//
589Function ReloadDIVButtonProc(ba) : ButtonControl
590        STRUCT WMButtonAction &ba
591
592        switch( ba.eventCode )
593                case 2: // mouse up
594                        // click code here
595                        Execute "ReadWork_DIV()"
596                        WaveStats root:Packages:NIST:DIV:data
597                        Print "*"                       
598//                      Execute "ChangeDisplay(\"DIV\")"       
599                        break
600        endswitch
601
602        return 0
603End
604
605//
606Function DIVHelpButtonProc(ba) : ButtonControl
607        STRUCT WMButtonAction &ba
608
609        switch( ba.eventCode )
610                case 2: // mouse up
611                        // click code here
612                        DisplayHelpTopic/Z/K=1 "SANS Data Reduction Tutorial[Detector Sensitivity File]"
613                        if(V_flag !=0)
614                                DoAlert 0,"The SANS Data Reduction Tutorial Help file could not be found"
615                        endif
616                        break
617        endswitch
618
619        return 0
620End
Note: See TracBrowser for help on using the repository browser.