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

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

Two changes:
(1) Changed the behavior of DIV file creation. Now a panel is presented that asks for all of the information - run numbers, transmission, XY box, etc. and then does all of the reduction/replacing/saving with one click. Cedric's ticket #195

(2) Some fixes in USANS notebook generation - filtering out junk.

File size: 16.6 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                       
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.