source: sans/Dev/trunk/NCNR_User_Procedures/Reduction/SANS/RawWindowHook.ipf @ 665

Last change on this file since 665 was 665, checked in by srkline, 13 years ago

Made preferences a common panel (moved to PlotUtilsMacro?.ipf and globals to root:Packages:NIST:) and added menu items for all packages. Many files had to be modified so that the preferences could be properly accessed

File Open dialog now is set to "All files" so that XML can be selected. I think that all open access that doesn't already have the full path go through this common function.

File size: 16.0 KB
Line 
1#pragma rtGlobals=1             // Use modern global access method.
2#pragma version=5.0
3#pragma IgorVersion=6.1
4
5//*****************************
6// Vers. 1.2 092101
7//
8// hook function and associated procedures that interact with the user
9// and the SANS_Data window
10// -displays pixel counts
11// - displays Q, qx, qy values
12// - displays q axes and pixel axes
13//
14// - of course, displays the detector image, w/ nice colors, legend, sliders to adjust color mapping
15// and a control bar to let the user adjust scaling, do averaging...
16//
17// allows the display default to be set to log scaling
18//*****************************
19
20
21//main procedure for display of SANS data files
22//uses "hook" functions to interact witht the user to get live cursor readout
23//based on the IGOR Pro Demo experiment- "SimpleDemoHook" - see the original
24//demo for more details of implementation
25//
26Function fRawWindowHook()
27        //globals for the main data display window are kept in root:myGlobals
28        Variable/G root:myGlobals:gXPos=0
29        Variable/G root:myGlobals:gYPos=0
30        Variable/G root:myGlobals:gQX=0
31        Variable/G root:myGlobals:gQY=0
32        Variable/G root:myGlobals:gQQ=0
33        Variable/G root:myGlobals:gNCounts=0
34        String/G root:myGlobals:gCurDispFile = "default string"
35        String/G root:myGlobals:gCurTitle = ""
36        Make/O/N=2 root:myGlobals:q_x_axis,root:myGlobals:q_y_axis
37       
38        NVAR pixelsX = root:myGlobals:gNPixelsX
39        NVAR pixelsY = root:myGlobals:gNPixelsY
40       
41        //get the current displayed data (so the correct folder is used)
42        SVAR cur_folder=root:myGlobals:gDataDisplayType
43        SVAR cur_title = root:myGlobals:gCurTitle
44        String curPath = "root:Packages:NIST:"+cur_folder
45        Wave/T tw=$(curPath+":TextRead")
46        cur_title = tw[6]                       //always update the title string
47       
48        DoWindow/F SANS_Data
49        if( V_Flag==0 )
50                //no SANS_Data window - make one
51
52                //Create NIH colors if needed
53                if(!WaveExists($"root:myGlobals:NIHColors"))
54                        NIHColorIndex()
55                Endif
56               
57                //window creation stuff
58                Display /W=(10,50,400,490) /K=1 //K=1 flag suppresses saveMacro dialog
59                DoWindow/C SANS_Data
60                DoWindow/T SANS_Data,cur_folder
61                SetWindow SANS_Data,hook=RawWindowHook,hookevents=2
62                ControlBar 100
63
64                SetVariable xpos,pos={7,5},size={50,17},title="X"
65                SetVariable xpos,limits={-Inf,Inf,0},value= root:myGlobals:gXPos
66                SetVariable xpos,help={"x-position on the detector"},frame=0,noedit=1
67                SetVariable ypos,pos={7,29},size={50,17},title="Y"
68                SetVariable ypos,limits={-Inf,Inf,0},value= root:myGlobals:gYPos
69                SetVariable ypos,help={"y-position on the detector"},frame=0,noedit=1
70                SetVariable counts,pos={7,59},size={150,17},title="Counts"
71                SetVariable counts,limits={-Inf,Inf,0},value= root:myGlobals:gNCounts
72                SetVariable counts,help={"Neutron counts"},frame=0,noedit=1
73                Button bisLin,pos={230,23},size={50,20},proc=Log_Lin,title="isLin"
74                Button bisLin,help={"\"isLin\" means the counts displayed are on linear scale. \"isLog\" means the counts displayed are on log(base10) scale."}
75                SetVariable qxval,pos={68,2},size={85,17},title="qX"
76                SetVariable qxval,help={"q value in the x-direction on the detector"},frame=0,noedit=1
77                SetVariable qxval,format="%+7.5f",limits={-Inf,Inf,0},value= root:myGlobals:gQX
78                SetVariable qyval,pos={68,21},size={85,17},title="qY"
79                SetVariable qyval,help={"q value in the y-direction on the detector"},frame=0,noedit=1
80                SetVariable qyval,format="%+7.5f",limits={-Inf,Inf,0},value= root:myGlobals:gQY
81                SetVariable q_pos,pos={68,40},size={85,17},title="q "
82                SetVariable q_pos,help={"q-value on the detector at (x,y)"},format="%+7.5f"
83                SetVariable q_pos,limits={-Inf,Inf,0},value= root:myGlobals:gQQ,frame=0,noedit=1
84                SetVariable CurFile,pos={170,4},size={210,17},title="File"
85                SetVariable CurFile,help={"Currently displayed file"},frame=0,noedit=1
86                SetVariable CurFile,limits={-Inf,Inf,0},value= root:myGlobals:gCurDispFile
87               
88                SetVariable CurTitle,pos={4,81},size={360,17},title=" "//,title="LABEL:"
89                SetVariable CurTitle,help={"Title string for currently displayed file"},frame=0,noedit=1
90                SetVariable CurTitle,fstyle=1,limits={-Inf,Inf,0},value= root:myGlobals:gCurTitle
91                Button Print_status,pos={170,23},size={50,20},proc=StatusButton,title="Status"
92                Button Print_status,help={"Print out information about the currently displayed file into the history window"}
93                Button maskButton size={84,20}, pos={170,53}, proc=maskButtonProc,title="Show Mask"
94                Button maskButton help={"If a mask has been loaded this will overlay it on the current plot"}
95               
96                GroupBox slideGrp,pos={268,46},size={124,48},title="Color Map"
97                //draw after the group box so these are on "top" of the group box
98                Button doAve,pos={290,23},size={50,20},proc=ShowAvgPanel_SANSData,title="I vs. Q"
99                Button doAve,help={"This will circularly average the data to I vs. Q"}
100                Slider loSlide,pos={280,77},size={100,16},proc=MapSliderProc
101                Slider loSlide,limits={0,1,0.01},value= 0,vert= 0,ticks= 0
102                Slider loSlide,help={"Adjust the low threshold of the color map"}
103                Slider hiSlide,pos={280,60},size={100,16},proc=MapSliderProc
104                Slider hiSlide,limits={0,1,0.01},value= 1,vert= 0,ticks= 0
105                Slider hiSlide,help={"Adjust the high threshold of the color map"}
106
107        endif
108       
109        //window was already open, or has just been created, add (or remove)
110        //controls specific for RAW data (specified by the current folder)
111        if(cmpstr(cur_folder,"RAW")==0)
112                //show the "next" buttons
113                //these buttons should only be available in RAW data type
114                Button backOne size={20,20},pos={350,23},proc=BackOneFileButtonProc,title="<"
115                Button backOne help={"Display the previous RAW data file run number"}
116                Button forwardOne size={20,20},pos={375,23},proc=ForwardOneFileButtonProc,title=">"
117                Button forwardOne help={"Display the next RAW data file run number"}
118                //
119        else
120                //kill them
121                KillControl backOne
122                KillControl forwardOne
123        Endif
124       
125        //reset the slider values to 0,1
126        Slider loSlide,value=0
127        Slider hiSlide,value=1
128       
129        //remove old data and add new data to it
130        //data display/modification stuff
131        RemoveImage/Z data
132        WAVE data = $(curPath + ":data")
133        WAVE NIHColors = $"root:myGlobals:NIHColors"
134        AppendImage data
135        WaveStats/Q $(curPath + ":data")
136        if(cmpstr(cur_folder,"MSK")==0)
137                ModifyImage data ctab={0,1,BlueRedGreen,0}
138   else
139                //Call the procedure that would normally be called if the sliders were moved
140//              MapSliderProc("both", 0, 1)
141                MapSliderProc("reset", 0, 1)
142    //  ScaleColorsToData(V_min, V_max, NIHColors)
143         //  ModifyImage data cindex=NIHColors
144        endif
145        //make the pixels square, color the backgrounds
146        ModifyGraph width={plan,1,bottom,left},mirror=0
147        ModifyGraph axisenab(bottom)={0,0.7}
148        ModifyGraph axOffset(left)=-3
149        ModifyGraph standoff=0
150        ModifyGraph wbRGB=(65535,54611,49151),gbRGB=(65535,54611,49151),cbRGB=(1,52428,52428)
151       
152        //add the qx and qy axes
153        Wave q_x_axis=$"root:myGlobals:q_x_axis"
154        Wave q_y_axis=$"root:myGlobals:q_y_axis"
155        Set_Q_Axes(q_x_axis,q_y_axis,curPath)
156        RemoveFromGraph/Z q_x_axis,q_y_axis
157        AppendToGraph/T q_x_axis
158        AppendToGraph/R=Right_Q q_y_axis                                //plot on a free axis, crossing at x=127 (pixelsX)
159        ModifyGraph freePos(Right_q)={pixelsX-1,bottom}
160        ModifyGraph minor(top)=1,minor(Right_Q)=1,lowTrip(top)=1e-05,lowTrip(Right_Q)=1e-05
161        ModifyGraph mode(q_x_axis)=2,mode(q_y_axis)=2           //dots
162        ModifyGraph axisEnab(top)={0,0.7}
163
164        //add the color bar
165        ColorScale/N=colBar/A=RT/X=-3/Y=-1.5/Z=1 image=data, heightPct=100, widthPct=4,notation=1
166        ColorScale/C/N=colBar/B=(65535,60076,49151)
167       
168        //update the displayed filename, using FileList in the current data folder
169        SVAR FileList = $(curPath + ":FileList")
170        String/G root:myGlobals:gCurDispFile = FileList
171       
172        //update the window title
173        DoWindow/T SANS_Data,cur_folder
174       
175        // reset the initial state of the "isLin" button if it is reading "isLog", since the initial data state is
176        //always set to linear
177        //re-draw the data on the graph to make sure "data" from the current folder is being used
178        ControlInfo bisLog
179        if(V_flag ==1)  //if bisLog exists, this will return true
180                Button bisLog,title="isLin",rename=bisLin
181        endif
182        //now that button state and data are sure to match (both are linear)
183        // set the display to log scale, if the global has been set
184        NVAR gLogScalingAsDefault=root:Packages:NIST:gLogScalingAsDefault
185        if(gLogScalingAsDefault)
186                Log_lin("bisLin")
187        endif
188       
189        //force an update of everything in the window
190        DoUpdate
191       
192        //return data folder to root before exiting (redundant)
193        SetDataFolder root:     
194End
195
196//this is the hook function that is associated with the SANS_Data graph window
197//only mouse moved events are processed, although much more could be done
198//for more elaborate interaction with the user.
199//- sets globals (that are displayed in the control bar of the graph) for the
200//x and y positions (in Detector coordinates (1,128))
201//qx, qy, and q (in Angstroms)
202//and the actual neutron counts (if raw)
203//or the data array value
204//
205Function RawWindowHook(s)
206        String s
207       
208        //get the current displayed data (so the correct folder is used)
209        SVAR cur_folder=root:myGlobals:gDataDisplayType
210        SetDataFolder "root:Packages:NIST:"+cur_folder          //use the full path, so it will always work
211        String curPath = "root:Packages:NIST:" + cur_folder
212        NVAR dataIsLog=$(curPath + ":gIsLogScale")              //now a global variable in the current folder, not the globals folder
213        if (dataIsLog)
214                wave w=$(curPath + ":linear_data")
215        else
216                wave w=$(curPath + ":data")
217      endif
218        wave reals=$(curPath + ":realsread")
219       
220        String/G root:myGlobals:gHookStr= s
221        Variable xpix,ypix,xaxval,yaxval,xint,yint,rawval
222        String msg
223       
224        NVAR pixelsX = root:myGlobals:gNPixelsX
225        NVAR pixelsY = root:myGlobals:gNPixelsY
226       
227        //only do something for mousemoved events
228        if( StrSearch(s,"EVENT:mousemoved;",0) > 0 )
229                xpix= NumberByKey("MOUSEX",s)
230                ypix= NumberByKey("MOUSEY",s)
231                xaxval= AxisValFromPixel("","bottom",xpix)
232                yaxval= AxisValFromPixel("","left",ypix)
233                xint = round(xaxval)
234                yint = round(yaxval)
235               
236                if((xint<0) || (xint>pixelsX-1) || (yint<0) || (yint>pixelsY-1))        //make sure cursor is on the image
237                        rawval = 0
238                else
239                        rawval = w[xint][yint] 
240                        //update q, qX, and qY
241                        if(cmpstr(cur_folder,"MSK")!=0)
242                                Variable xctr=reals[16],yctr=reals[17],sdd=reals[18],lam=reals[26],pixSize=reals[13]/10
243                                Variable/G root:myGlobals:gQQ = CalcQval(xaxval+1,yaxval+1,xctr,yctr,sdd,lam,pixSize)
244                                Variable/G root:myGlobals:gQX = CalcQX(xaxval+1,yaxval+1,xctr,yctr,sdd,lam,pixSize)
245                                Variable/G root:myGlobals:gQY = CalcQY(xaxval+1,yaxval+1,xctr,yctr,sdd,lam,pixSize)
246                        else
247                                Variable/G root:myGlobals:gQQ = 0
248                                Variable/G root:myGlobals:gQX = 0
249                                Variable/G root:myGlobals:gQY = 0
250                        endif
251                        //add one to the x and y values to get from IGOR array indexing 0->127 to 1->128 detector
252                        Variable/G root:myGlobals:gXPos=xint+1
253                        Variable/G root:myGlobals:gYPos=yint+1
254                        Variable/G root:myGlobals:gNCounts=rawval
255                endif
256        endif
257       
258        //set data folder back to root
259        SetDataFolder root:
260       
261        return 0
262end
263       
264//function to calculate the overall q-value, given all of the necesary trig inputs
265//NOTE: detector locations passed in are pixels = 0.5cm real space on the detector
266//and are in detector coordinates (1,128) rather than axis values
267//the pixel locations need not be integers, reals are ok inputs
268//sdd is in meters
269//wavelength is in Angstroms
270//
271//returned magnitude of Q is in 1/Angstroms
272//
273Function CalcQval(xaxval,yaxval,xctr,yctr,sdd,lam,pixSize)
274        Variable xaxval,yaxval,xctr,yctr,sdd,lam,pixSize
275       
276        Variable dx,dy,qval,two_theta,dist
277       
278        Variable pixSizeX=pixSize
279        Variable pixSizeY=pixSize
280       
281        sdd *=100               //convert to cm
282        dx = (xaxval - xctr)*pixSizeX           //delta x in cm
283        dy = (yaxval - yctr)*pixSizeY           //delta y in cm
284        dist = sqrt(dx^2 + dy^2)
285       
286        two_theta = atan(dist/sdd)
287
288        qval = 4*Pi/lam*sin(two_theta/2)
289       
290        return qval
291End
292
293//calculates just the q-value in the x-direction on the detector
294//input/output is the same as CalcQval()
295//ALL inputs are in detector coordinates
296//
297//NOTE: detector locations passed in are pixel = 0.5cm real space on the Ordela detector
298//sdd is in meters
299//wavelength is in Angstroms
300//
301// repaired incorrect qx and qy calculation 3 dec 08 SRK (Lionel and C. Dewhurst)
302// now properly accounts for qz
303//
304Function CalcQX(xaxval,yaxval,xctr,yctr,sdd,lam,pixSize)
305        Variable xaxval,yaxval,xctr,yctr,sdd,lam,pixSize
306
307        Variable qx,qval,phi,dx,dy,dist,two_theta
308       
309        qval = CalcQval(xaxval,yaxval,xctr,yctr,sdd,lam,pixSize)
310       
311        sdd *=100               //convert to cm
312        dx = (xaxval - xctr)*pixSize            //delta x in cm
313        dy = (yaxval - yctr)*pixSize            //delta y in cm
314        phi = FindPhi(dx,dy)
315       
316        //get scattering angle to project onto flat detector => Qr = qval*cos(theta)
317        dist = sqrt(dx^2 + dy^2)
318        two_theta = atan(dist/sdd)
319
320        qx = qval*cos(two_theta/2)*cos(phi)
321       
322        return qx
323End
324
325//calculates just the q-value in the y-direction on the detector
326//input/output is the same as CalcQval()
327//ALL inputs are in detector coordinates
328//NOTE: detector locations passed in are pixel = 0.5cm real space on the Ordela detector
329//sdd is in meters
330//wavelength is in Angstroms
331//
332// repaired incorrect qx and qy calculation 3 dec 08 SRK (Lionel and C. Dewhurst)
333// now properly accounts for qz
334//
335Function CalcQY(xaxval,yaxval,xctr,yctr,sdd,lam,pixSize)
336        Variable xaxval,yaxval,xctr,yctr,sdd,lam,pixSize
337       
338        Variable dy,qval,dx,phi,qy,dist,two_theta
339       
340        qval = CalcQval(xaxval,yaxval,xctr,yctr,sdd,lam,pixSize)
341       
342        sdd *=100               //convert to cm
343        dx = (xaxval - xctr)*pixSize            //delta x in cm
344        dy = (yaxval - yctr)*pixSize            //delta y in cm
345        phi = FindPhi(dx,dy)
346       
347        //get scattering angle to project onto flat detector => Qr = qval*cos(theta)
348        dist = sqrt(dx^2 + dy^2)
349        two_theta = atan(dist/sdd)
350       
351        qy = qval*cos(two_theta/2)*sin(phi)
352       
353        return qy
354End
355
356//calculates just the z-component of the q-vector, not measured on the detector
357//input/output is the same as CalcQval()
358//ALL inputs are in detector coordinates
359//NOTE: detector locations passed in are pixel = 0.5cm real space on the Ordela detector
360//sdd is in meters
361//wavelength is in Angstroms
362//
363// not actually used, but here for completeness if anyone asks
364//
365Function CalcQZ(xaxval,yaxval,xctr,yctr,sdd,lam,pixSize)
366        Variable xaxval,yaxval,xctr,yctr,sdd,lam,pixSize
367       
368        Variable dy,qval,dx,phi,qz,dist,two_theta
369       
370        qval = CalcQval(xaxval,yaxval,xctr,yctr,sdd,lam,pixSize)
371       
372        sdd *=100               //convert to cm
373       
374        //get scattering angle to project onto flat detector => Qr = qval*cos(theta)
375        dx = (xaxval - xctr)*pixSize            //delta x in cm
376        dy = (yaxval - yctr)*pixSize            //delta y in cm
377        dist = sqrt(dx^2 + dy^2)
378        two_theta = atan(dist/sdd)
379       
380        qz = qval*sin(two_theta/2)
381       
382        return qz
383End
384
385//phi is defined from +x axis, proceeding CCW around [0,2Pi]
386Threadsafe Function FindPhi(vx,vy)
387        variable vx,vy
388       
389        variable phi
390       
391        phi = atan(vy/vx)               //returns a value from -pi/2 to pi/2
392       
393        // special cases
394        if(vx==0 && vy > 0)
395                return(pi/2)
396        endif
397        if(vx==0 && vy < 0)
398                return(3*pi/2)
399        endif
400        if(vx >= 0 && vy == 0)
401                return(0)
402        endif
403        if(vx < 0 && vy == 0)
404                return(pi)
405        endif
406       
407       
408        if(vx > 0 && vy > 0)
409                return(phi)
410        endif
411        if(vx < 0 && vy > 0)
412                return(phi + pi)
413        endif
414        if(vx < 0 && vy < 0)
415                return(phi + pi)
416        endif
417        if( vx > 0 && vy < 0)
418                return(phi + 2*pi)
419        endif
420       
421        return(phi)
422end
423
424
425//function to set the q-axis scaling after the data has been read in
426// - needs the location of the currently displayed data to get the header information
427// to be able to calculate q-values at the edges of the detector
428//** assumes a linear correspondence between pixel->q-values (which should bea a really
429// safe bet, since we're using the small -angle approximation...)
430//
431// actually re-scales the qy wave that is on the SANS_Data image
432// the qy dataset is 2 values, plotted as "dots", nearly invisible...
433// but does an adequate job of getting ticks on the right and top axes
434//
435Function Set_Q_Axes(qx,qy,curPath)
436        Wave qx,qy
437        String curPath
438
439        NVAR pixelsX = root:myGlobals:gNPixelsX
440        NVAR pixelsY = root:myGlobals:gNPixelsY
441       
442        WAVE reals=$(curPath + ":realsread")
443        Variable xctr=reals[16],yctr=reals[17],sdd=reals[18],lam=reals[26]
444        Variable pixSize=reals[13]/10           //pixel size in cm to pass
445        Variable maxX,minX,maxY,minY
446       
447        minX = CalcQX(1,yctr,xctr,yctr,sdd,lam,pixSize)
448        maxX = CalcQX(pixelsX,yctr,xctr,yctr,sdd,lam,pixSize)
449        SetScale/I x minX,maxX,"",qx
450       
451        minY = CalcQY(xctr,1,xctr,yctr,sdd,lam,pixSize)
452        maxY = CalcQY(xctr,pixelsY,xctr,yctr,sdd,lam,pixSize)
453        qy[0] = minY
454        qy[1] = maxY
455       
456        return(0)
457End
458
459Function ToggleDefaultMapping()
460        NVAR value = root:Packages:NIST:gLogScalingAsDefault
461        value = !(value)
462End
Note: See TracBrowser for help on using the repository browser.