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

Last change on this file since 511 was 511, checked in by ajj, 14 years ago

Fixed odd bug where offset COR data in DIV file creation had incorrect values in. Added call to ConvertFolderToLinearData?() and that seems to fix matters.

File size: 17.2 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                        //parse for the first run number
378                        SVAR gPlex = root:myGlobals:Protocols:gPlex
379                        String item,fname
380                       
381                        item = StringFromList(0, gPlex ,",")
382                        fname = FindFileFromRunNumber(str2num(item))
383                        if(strlen(fname) == 0)
384                                Abort "Bad file number in Plex field"
385                        endif
386                        // load the file
387                        ReadHeaderAndData(fname)        //this is the full Path+file
388                        UpdateDisplayInformation("RAW")
389                        //draw a box of the specified size. This is persistent on the display as you scroll to the offset data
390                        NVAR x1 = root:myGlobals:Protocols:gPlexX1
391                        NVAR x2 = root:myGlobals:Protocols:gPlexX2
392                        NVAR y1 = root:myGlobals:Protocols:gPlexY1
393                        NVAR y2 = root:myGlobals:Protocols:gPlexY2
394                       
395                        SetDrawLayer/W=SANS_Data/K UserFront                    //set the layer, and clear it
396                        SetDrawEnv/W=SANS_Data xcoord=bottom,ycoord=left,fillpat=0,linethick=3,linefgc=(65535, 65535, 65535)
397                        DrawRect/W=SANS_Data x1, y2, x2, y1
398                                               
399                        break
400        endswitch
401
402        return 0
403End
404
405// do everything...
406//
407Function GenerateDIVButtonProc(ba) : ButtonControl
408        STRUCT WMButtonAction &ba
409
410        switch( ba.eventCode )
411                case 2: // mouse up
412                        // click code here
413                        SVAR gPlex = root:myGlobals:Protocols:gPlex
414                        SVAR gPlexBgd = root:myGlobals:Protocols:gPlexBgd
415                        SVAR gPlexEmp = root:myGlobals:Protocols:gPlexEmp
416                        SVAR gPlex_off = root:myGlobals:Protocols:gPlex_off
417                        SVAR gPlexBgd_off = root:myGlobals:Protocols:gPlexBgd_off
418                        SVAR gPlexEmp_off = root:myGlobals:Protocols:gPlexEmp_off
419                        SVAR gPlexName = root:myGlobals:Protocols:gPlexName
420                       
421                        NVAR X1 = root:myGlobals:Protocols:gPlexX1
422                        NVAR X2 = root:myGlobals:Protocols:gPlexX2
423                        NVAR Y1 = root:myGlobals:Protocols:gPlexY1
424                        NVAR Y2 = root:myGlobals:Protocols:gPlexY2
425                        NVAR gPlexTrans = root:myGlobals:Protocols:gPlexTrans
426                       
427                        WAVE/T proto = $"root:myGlobals:Protocols:DIV_Protocol"
428                       
429                        String item,fname,str
430                        Variable ii,num
431                // reduce the on-center
432                        //patch trans
433                        num = ItemsInList(gPlex, ",")
434                        for(ii=0;ii<num;ii+=1)
435                                item = StringFromList(ii, gPlex ,",")
436                                fname = FindFileFromRunNumber(str2num(item))
437                                if(strlen(fname) == 0)
438                                        Abort "Bad file number in no offset Plex field"
439                                endif
440                                WriteTransmissionToHeader(fname,gPlexTrans)
441                        endfor
442                       
443                        //go through the protocol
444                        str = ParseRunNumberList(gPlexBgd)
445                        if(strlen(str) > 0)
446                                proto[0] = str
447                        else
448                                Abort "Bad file number in no offset Bgd"
449                        endif
450                        str = ParseRunNumberList(gPlexEmp)
451                        if(strlen(str) > 0)
452                                proto[1] = str
453                        else
454                                Abort "Bad file number in no offset Emp"
455                        endif
456                        str = ParseRunNumberList(gPlex)
457                        if(strlen(str) > 0)
458                                ExecuteProtocol("root:myGlobals:Protocols:DIV_Protocol",str)
459                        else
460                                Abort "Bad file number in no offset Plex"
461                        endif
462                        // move it into STO
463                        Execute "CopyWorkFolder(\"COR\",\"STO\")"
464                       
465                       
466                       
467                // reduce the off-center, keep in STO
468                        //patch trans
469                        num = ItemsInList(gPlex_off, ",")
470                        for(ii=0;ii<num;ii+=1)
471                                item = StringFromList(ii, gPlex_off ,",")
472                                fname = FindFileFromRunNumber(str2num(item))
473                                if(strlen(fname) == 0)
474                                        Abort "Bad file number in Plex field"
475                                endif
476                                WriteTransmissionToHeader(fname,gPlexTrans)
477                        endfor
478                       
479                        //go through the protocol
480                        str = ParseRunNumberList(gPlexBgd_off)
481                        if(strlen(str) > 0)
482                                proto[0] = str
483                        else
484                                Abort "Bad file number in offset Bgd"
485                        endif
486                        str = ParseRunNumberList(gPlexEmp_off)
487                        if(strlen(str) > 0)
488                                proto[1] = str
489                        else
490                                Abort "Bad file number in offset Emp"
491                        endif
492                        str = ParseRunNumberList(gPlex_off)
493                        if(strlen(str) > 0)
494                                ExecuteProtocol("root:myGlobals:Protocols:DIV_Protocol",str)
495                        else
496                                Abort "Bad file number in offset Emp"
497                        endif
498                        ConvertFolderToLinearScale("COR")
499                       
500                       
501                // replace the patch
502                // on-center data is changed (STO)
503                        ReplaceDataBlock("STO","COR",x1,x2,y1,y2)
504                // normalize
505                        NormalizeDiv("STO")
506                        UpdateDisplayInformation("STO")
507                //write out the new data file
508                        WriteVAXWorkFile("STO")
509                                       
510                        break
511        endswitch
512
513        return 0
514End
515
516// if a dark color is used, then
517//¥SetVariable setvar0 labelBack=(65535,65535,65535)
518// for each variable will give a white background to the label text
519Window DIV_Panel() : Panel
520        PauseUpdate; Silent 1           // building window...
521        NewPanel /W=(594,44,932,570)/K=1 as "DIV_Panel"
522//      ModifyPanel cbRGB=(35867,28177,65535)           //purple
523//      ModifyPanel cbRGB=(1,16019,65535)                               //electric blue
524        ModifyPanel cbRGB=(36631,59604,33902)           //spring green
525        SetDrawLayer UserBack
526        DrawRect 71,324,145,391
527        TitleBox title0,pos={14,16},size={50,20},title="No Offset"
528        TitleBox title0_1,pos={17,125},size={35,20},title="Offset"
529        SetVariable setvar0,pos={15,46},size={250,15},title="PLEX",value= root:myGlobals:Protocols:gPlex
530        SetVariable setvar0_1,pos={16,69},size={250,15},title="EMP",value= root:myGlobals:Protocols:gPlexEmp
531        SetVariable setvar0_2,pos={14,92},size={250,15},title="BGD",value= root:myGlobals:Protocols:gPlexBgd
532        SetVariable setvar1,pos={17,158},size={250,15},title="PLEX",value= root:myGlobals:Protocols:gPlex_off
533        SetVariable setvar001,pos={18,181},size={250,15},title="EMP",value= root:myGlobals:Protocols:gPlexEmp_off
534        SetVariable setvar002,pos={16,204},size={250,15},title="BGD",value= root:myGlobals:Protocols:gPlexBgd_off
535        SetVariable setvar002_1,pos={14,251},size={150,15},title="Transmission"
536        SetVariable setvar002_1,limits={0,1,0.01},value= root:myGlobals:Protocols:gPlexTrans
537//      SetVariable setvar003,pos={16,441},size={250,15},title="DIV FILE NAME"
538//      SetVariable setvar003,value= root:myGlobals:Protocols:gPlexName
539        Button button0,pos={226,325},size={90,20},proc=ShowBoxButtonProc,title="Show Box"
540        Button button1,pos={25,441},size={150,20},proc=GenerateDIVButtonProc,title="Generate DIV File"
541        Button button2,pos={25,481},size={150,20},proc=ReloadDIVButtonProc,title="Load DIV File"
542        Button button3,pos={240,10},size={50,20},proc=DIVHelpButtonProc,title="Help"
543        SetVariable setvar00201,pos={84,297},size={50,15},limits={0,128,1},title=" ",value= root:myGlobals:Protocols:gPlexY2
544        SetVariable setvar00202,pos={15,350},size={50,15},limits={0,128,1},title=" ",value= root:myGlobals:Protocols:gPlexX1
545        SetVariable setvar00203,pos={85,399},size={50,15},limits={0,128,1},title=" ",value= root:myGlobals:Protocols:gPlexY1
546        SetVariable setvar00204,pos={156,348},size={50,15},limits={0,128,1},title=" ",value= root:myGlobals:Protocols:gPlexX2
547EndMacro
548
549
550// load in a DIV file, print out the stats, display in SANS_Data
551//
552Function ReloadDIVButtonProc(ba) : ButtonControl
553        STRUCT WMButtonAction &ba
554
555        switch( ba.eventCode )
556                case 2: // mouse up
557                        // click code here
558                        Execute "ReadWork_DIV()"
559                        WaveStats root:Packages:NIST:DIV:data
560                        Print "*"                       
561//                      Execute "ChangeDisplay(\"DIV\")"       
562                        break
563        endswitch
564
565        return 0
566End
567
568//
569Function DIVHelpButtonProc(ba) : ButtonControl
570        STRUCT WMButtonAction &ba
571
572        switch( ba.eventCode )
573                case 2: // mouse up
574                        // click code here
575                        DisplayHelpTopic/Z/K=1 "SANS Data Reduction Tutorial[Detector Sensitivity File]"
576                        if(V_flag !=0)
577                                DoAlert 0,"The SANS Data Reduction Tutorial Help file could not be found"
578                        endif
579                        break
580        endswitch
581
582        return 0
583End
Note: See TracBrowser for help on using the repository browser.