1 | #pragma rtGlobals=1 // Use modern global access method. |
---|
2 | #pragma version=1.2 |
---|
3 | #pragma IgorVersion=6.1 |
---|
4 | |
---|
5 | /////////////////////////////// |
---|
6 | //procedures for creating and initializing the Linearized FIT panel |
---|
7 | //global variables (numerical only) are kept in root:Packages:NIST:FIT folder |
---|
8 | // |
---|
9 | // this is based on the FIT routines in the SANS Reduction package, and has been modified here |
---|
10 | // only to make it independent of the Reduction routines, and into "Package" format |
---|
11 | // |
---|
12 | // These procedures WILL conflict in namespace with the SANS Reduction routines |
---|
13 | // in both Fit_Ops and VAX_Utils (and probably others...) so DO NOT |
---|
14 | // try to include these... |
---|
15 | // |
---|
16 | // SRK 11 JAN 05 |
---|
17 | // |
---|
18 | // Prepended "A_" to all of the procs and functions to avoid name conflicts |
---|
19 | // with the FIT included in the reduction package |
---|
20 | // - DID NOT prepend "A_" to the loader/unloader which is unique to this package |
---|
21 | // |
---|
22 | // SEP 2010 - absorbed the duplicate procedure file FIT_Ops. |
---|
23 | // - removed "A_" prefix |
---|
24 | // - need to keep A_OpenFitPanel() in case old experiments are looking for this |
---|
25 | // - added the (completely unused) FITRPA procedures to this file |
---|
26 | // |
---|
27 | /////////////////////////////// |
---|
28 | |
---|
29 | //main procedures to open the panel, initializing the data folder and global variables |
---|
30 | //as necessary. All are kept in a :FIT subfolder to avoid overlap with other variables |
---|
31 | // |
---|
32 | // To use any of the fit functions in the FIT panel, I(Q) data must already |
---|
33 | // be loaded into memory (using "plot" from the 1-D data operations |
---|
34 | // ** this may be useful to change in the future, replacing the 3 popups |
---|
35 | // with a list box - allowing the user to pick/load the data from the fit panel |
---|
36 | // and not offering any choice of q/i/s waves to use. (more consistent with the operation |
---|
37 | // of the FIT/RPA panel) |
---|
38 | // |
---|
39 | Proc OpenFitPanel() |
---|
40 | If(WinType("FitPanel") == 0) |
---|
41 | //create the necessary data folder |
---|
42 | NewDataFolder/O root:Packages |
---|
43 | NewDataFolder/O root:Packages:NIST |
---|
44 | NewDataFolder/O root:Packages:NIST:FIT |
---|
45 | //initialize the values |
---|
46 | Variable/G root:Packages:NIST:FIT:gLolim = 0.02 |
---|
47 | Variable/G root:Packages:NIST:FIT:gUplim = 0.04 |
---|
48 | Variable/G root:Packages:NIST:FIT:gExpA = 1 |
---|
49 | Variable/G root:Packages:NIST:FIT:gExpB = 1 |
---|
50 | Variable/G root:Packages:NIST:FIT:gExpC = 1 |
---|
51 | Variable/G root:Packages:NIST:FIT:gBack = 0 |
---|
52 | String/G root:Packages:NIST:FIT:gDataPopList = "none" |
---|
53 | FitPanel() |
---|
54 | else |
---|
55 | //window already exists, just bring to front for update |
---|
56 | DoWindow/F FitPanel |
---|
57 | CheckBox check0,value=0 //deselect the checkbox to use cursors |
---|
58 | endif |
---|
59 | //pop the file menu |
---|
60 | FIT_FilePopMenuProc("",1,"") |
---|
61 | End |
---|
62 | |
---|
63 | Proc A_OpenFitPanel() |
---|
64 | OpenFitPanel() |
---|
65 | End |
---|
66 | |
---|
67 | //the actual window recreation macro to draw the fit panel. Globals and data folder must |
---|
68 | // already be initialized |
---|
69 | Window FitPanel() |
---|
70 | String angst = StrVarOrDefault("root:Packages:NIST:gAngstStr", "A" ) |
---|
71 | // String angst = "A" |
---|
72 | PauseUpdate; Silent 1 // building window... |
---|
73 | NewPanel /W=(461,46,735,455)/K=1 |
---|
74 | ModifyPanel cbRGB=(32768,54615,65535), fixedSize=1 |
---|
75 | SetDrawLayer UserBack |
---|
76 | DrawText 56,20,"Select Experimental Data" |
---|
77 | DrawText 66,138,"q-range to fit ("+angst+"^-1)" |
---|
78 | DrawText 42,268,"Select the y and x-axis scaling" |
---|
79 | DrawLine 1,21,271,21 |
---|
80 | DrawLine -1,272,273,272 |
---|
81 | DrawLine -1,140,272,140 |
---|
82 | PopupMenu ywave,pos={13,60},size={154,19},title="Data File" |
---|
83 | PopupMenu ywave,help={"Select the experimental intensity values"} |
---|
84 | PopupMenu ywave,mode=1,value=root:Packages:NIST:FIT:gDataPopList,proc=FIT_FilePopMenuProc |
---|
85 | Button loadButton,pos={13,92},size={130,20},proc=FIT_Load_Proc,title="Load and Plot File" |
---|
86 | Button loadButton,help={"After choosing a file, load it into memory and plot it with this button."} |
---|
87 | Button helpButton,pos={237,28},size={25,20},proc=showFITHelp,title="?" |
---|
88 | Button helpButton,help={"Show help file for linearized fitting"} |
---|
89 | PopupMenu ymodel,pos={20,281},size={76,19},title="y-axis" |
---|
90 | PopupMenu ymodel,help={"This popup selects how the y-axis will be linearized based on the chosen data"} |
---|
91 | PopupMenu ymodel,mode=1,value= #"\"I;log(I);ln(I);1/I;I^a;Iq^a;I^a q^b;1/sqrt(I);ln(Iq);ln(Iq^2)\"" |
---|
92 | Button GoFit,pos={60,367},size={70,20},proc=DispatchModel,title="Do the Fit" |
---|
93 | Button GoFit,help={"This button will do the specified fit using the selections in this panel"} |
---|
94 | Button DoneButton,pos={180,367},size={50,20},proc=FITDoneButton,title="Done" |
---|
95 | Button DoneButton,help={"This button will close the panel and the associated graph"} |
---|
96 | SetVariable lolim,pos={64,147},size={134,17},title="Lower Limit" |
---|
97 | SetVariable lolim,help={"Enter the lower q-limit to perform the fit ("+angst+"^-1)"} |
---|
98 | SetVariable lolim,limits={0,5,0},value= root:Packages:NIST:FIT:gLolim |
---|
99 | SetVariable uplim,pos={63,169},size={134,17},title="Upper Limit" |
---|
100 | SetVariable uplim,help={"Enter the upper q-limit to perform the fit ("+angst+"^-1)"} |
---|
101 | SetVariable uplim,limits={0,5,0},value= root:Packages:NIST:FIT:gUplim |
---|
102 | SetVariable expa,pos={13,311},size={80,17},title="pow \"a\"" |
---|
103 | SetVariable expa,help={"This sets the exponent \"a\" for some y-axis formats. The value is ignored if the model does not use an adjustable exponent"} |
---|
104 | SetVariable expa,limits={-2,10,0},value= root:Packages:NIST:FIT:gExpA |
---|
105 | SetVariable expb,pos={98,311},size={80,17},title="pow \"b\"" |
---|
106 | SetVariable expb,help={"This sets the exponent \"b\" for some x-axis formats. The value is ignored if the model does not use an adjustable exponent"} |
---|
107 | SetVariable expb,limits={0,10,0},value= root:Packages:NIST:FIT:gExpB |
---|
108 | PopupMenu xmodel,pos={155,280},size={79,19},title="x-axis" |
---|
109 | PopupMenu xmodel,help={"This popup selects how the x-axis will be linearized given the chosen data"} |
---|
110 | PopupMenu xmodel,mode=1,value= #"\"q;log(q);q^2;q^c\"" |
---|
111 | CheckBox check0,pos={18,223},size={240,20},title="Use cursor range from FitWindow" |
---|
112 | CheckBox check0,help={"Checking this will perform a fit between the cursors on the graph in FitWindow and ignore the numerical limits typed above"},value=0 |
---|
113 | SetVariable back,pos={70,338},size={139,17},title="background" |
---|
114 | SetVariable back,help={"This constant background value will be subtracted from the experimental intensity before fitting is done"} |
---|
115 | SetVariable back,limits={-Inf,Inf,0},value= root:Packages:NIST:FIT:gBack |
---|
116 | SetVariable expc,pos={182,310},size={80,17},title="pow \"c\"" |
---|
117 | SetVariable expc,help={"This sets the exponent \"c\" for some x-axis formats. The value is ignored if the model does not use \"c\" as an adjustable exponent"} |
---|
118 | SetVariable expc,limits={-10,10,0},value= root:Packages:NIST:FIT:gExpC |
---|
119 | Button sh_all,pos={65,193},size={130,20},proc=ShowAllButtonProc,title="Show Full q-range" |
---|
120 | Button sh_all,help={"Use this to show the entire q-range of the data rather than just the fitted range."} |
---|
121 | |
---|
122 | Button FIT_PathButton,pos={10,28},size={80,20},proc=FIT_PickPathButtonProc,title="Pick Path" |
---|
123 | |
---|
124 | EndMacro |
---|
125 | |
---|
126 | |
---|
127 | Proc FITDoneButton(ctrlName): ButtonControl |
---|
128 | String ctrlName |
---|
129 | DoWindow/K FitWindow |
---|
130 | DoWindow/K FitPanel |
---|
131 | end |
---|
132 | |
---|
133 | Proc showFITHelp(ctrlName): ButtonControl |
---|
134 | String ctrlName |
---|
135 | DisplayHelpTopic/Z/K=1 "Linearized Fits" |
---|
136 | if(V_flag != 0) |
---|
137 | DoAlert 0, "The Linearized Fit Help file can not be found" |
---|
138 | endif |
---|
139 | end |
---|
140 | |
---|
141 | //Loads the selected file for fitting |
---|
142 | //graphs the data as needed |
---|
143 | Proc FIT_Load_Proc(ctrlName): ButtonControl |
---|
144 | String ctrlName |
---|
145 | |
---|
146 | //Load the data |
---|
147 | String tempName="",partialName="" |
---|
148 | Variable err |
---|
149 | ControlInfo $"ywave" |
---|
150 | //find the file from the partial filename |
---|
151 | If( (cmpstr(S_value,"")==0) || (cmpstr(S_value,"none")==0) ) |
---|
152 | //null selection, or "none" from any popup |
---|
153 | Abort "no file selected in popup menu" |
---|
154 | else |
---|
155 | //selection not null |
---|
156 | partialName = S_value |
---|
157 | Endif |
---|
158 | //get a valid file based on this partialName and catPathName |
---|
159 | tempName = FindValidFilename(partialName) |
---|
160 | |
---|
161 | //prepend path to tempName for read routine |
---|
162 | PathInfo catPathName |
---|
163 | |
---|
164 | tempName = S_path + tempName |
---|
165 | |
---|
166 | //load in the data (into the root directory) |
---|
167 | A_LoadOneDDataWithName(tempName,0) //let Rescale_Data() do the plotting |
---|
168 | //Print S_fileName |
---|
169 | //Print tempName |
---|
170 | |
---|
171 | |
---|
172 | String cleanLastFileName = "",dataStr = "" |
---|
173 | |
---|
174 | cleanLastFileName = CleanupName(partialName,0) |
---|
175 | |
---|
176 | //if the file name was too long, get the updated name |
---|
177 | Variable maxLength=25 |
---|
178 | if(strlen(cleanLastFileName) > maxLength) |
---|
179 | String newStr = root:Packages:NIST:gShortNameStr //set in ShortFileNameString() |
---|
180 | cleanLastFileName = newStr |
---|
181 | endif |
---|
182 | |
---|
183 | dataStr = "root:"+cleanLastFileName+":" |
---|
184 | |
---|
185 | tempName=dataStr + cleanLastFileName+"_q" |
---|
186 | Duplicate/O $tempName xAxisWave |
---|
187 | tempName=dataStr + cleanLastFileName+"_i" |
---|
188 | Duplicate/O $tempName yAxisWave |
---|
189 | tempName=dataStr + cleanLastFileName+"_s" |
---|
190 | Duplicate/O $tempName yErrWave |
---|
191 | |
---|
192 | //Plot, and adjust the scaling to match the axis scaling set by the popups |
---|
193 | Rescale_Data(dataStr) |
---|
194 | |
---|
195 | End |
---|
196 | |
---|
197 | //gets a valid file list (simply not the files with ".SAn" in the name) |
---|
198 | // |
---|
199 | Function FIT_FilePopMenuProc(ctrlName,popNum,popStr) : PopupMenuControl |
---|
200 | String ctrlName |
---|
201 | Variable popNum |
---|
202 | String popStr |
---|
203 | |
---|
204 | String tempStr=filterButtonProc(ctrlName) |
---|
205 | if(strlen(tempStr)==0) |
---|
206 | tempStr = "Pick the data path" |
---|
207 | Endif |
---|
208 | String/G root:Packages:NIST:FIT:gDataPopList =tempStr |
---|
209 | ControlUpdate ywave |
---|
210 | |
---|
211 | End |
---|
212 | |
---|
213 | //direct porting of the fit program from the VAX, with no corrections and only |
---|
214 | //minor modifications of additional linearizations and the option |
---|
215 | //to subtract a constant (q-independent) background value before doing any |
---|
216 | //of the fits. The original data on disk (and as loaded) is never modified, all |
---|
217 | //manipulation is done from a copy of the data. |
---|
218 | |
---|
219 | //button procedure to show the entire axis range of the data, rather than just |
---|
220 | //the fitted range, which is the default display after a fit is performed |
---|
221 | // |
---|
222 | Function ShowAllButtonProc(ctrlName) : ButtonControl |
---|
223 | String ctrlName |
---|
224 | |
---|
225 | //bring the FitWindow to the front and Autoscale the axes |
---|
226 | DoWindow/F FitWindow |
---|
227 | SetAxis/A |
---|
228 | End |
---|
229 | |
---|
230 | // function that takes the current dataset (already loaded) |
---|
231 | // and replots it based on the X/Y axis scaling selected in the popups |
---|
232 | // (does not fit the data) |
---|
233 | // |
---|
234 | // dataStr is the root:folder: of the data that was loaded |
---|
235 | Function Rescale_Data(dataStr) |
---|
236 | String dataStr |
---|
237 | |
---|
238 | //Scaling exponents and background value |
---|
239 | Variable pow_a,pow_b,pow_c,bkg |
---|
240 | ControlInfo/W=FitPanel expa |
---|
241 | pow_a = V_value |
---|
242 | ControlInfo/W=FitPanel expb |
---|
243 | pow_b = V_value |
---|
244 | ControlInfo/W=FitPanel expc |
---|
245 | pow_c = V_value |
---|
246 | ControlInfo/W=FitPanel back |
---|
247 | bkg = V_value |
---|
248 | |
---|
249 | //check for physical limits on exponent values |
---|
250 | // if bad values found, alert, and reset to good values so the rescaling can continue |
---|
251 | NVAR gA = root:Packages:NIST:FIT:gExpA |
---|
252 | NVAR gB = root:Packages:NIST:FIT:gExpB |
---|
253 | NVAR gC = root:Packages:NIST:FIT:gExpC |
---|
254 | if((pow_a < -2) || (pow_a > 10)) |
---|
255 | DoAlert 0,"Exponent a must be in the range (-2,10) - the exponent a has been reset to 1" |
---|
256 | gA = 1 |
---|
257 | endif |
---|
258 | if((pow_b < 0) || (pow_b > 10)) |
---|
259 | DoAlert 0,"Exponent b must be in the range (0,10) - the exponent b has been reset to 1" |
---|
260 | gB = 1 |
---|
261 | endif |
---|
262 | //if q^c is the x-scaling, c must be be within limits and also non-zero |
---|
263 | ControlInfo/W=FitPanel xModel |
---|
264 | If (cmpstr("q^c",S_Value) == 0) |
---|
265 | if(pow_c == 0) |
---|
266 | DoAlert 0,"Exponent c must be non-zero, c has been reset to 1" |
---|
267 | gC = 1 |
---|
268 | endif |
---|
269 | if((pow_c < -10) || (pow_c > 10)) |
---|
270 | DoAlert 0,"Exponent c must be in the range (-10,10), c has been reset to 1" |
---|
271 | gC = 1 |
---|
272 | endif |
---|
273 | endif |
---|
274 | |
---|
275 | //do the rescaling of the data |
---|
276 | // get the current experimental q, I, and std dev. waves (as they would be loaded ) |
---|
277 | String baseStr = ParseFilePath(0,dataStr,":",1,0) //give me the last part of the path |
---|
278 | |
---|
279 | Wave xw = $(dataStr+baseStr+"_q") |
---|
280 | Wave yw = $(dataStr+baseStr+"_i") |
---|
281 | Wave ew = $(dataStr+baseStr+"_s") |
---|
282 | |
---|
283 | //variables set for each model to control look of graph |
---|
284 | Variable xlow,xhigh,ylow,yhigh,yes_cursors |
---|
285 | String xlabel,ylabel,xstr,ystr |
---|
286 | //check for proper y-scaling selection, make the necessary waves |
---|
287 | ControlInfo/W=FitPanel yModel |
---|
288 | ystr = S_Value |
---|
289 | // print "ystr = ",ystr |
---|
290 | do |
---|
291 | // make the new yaxis waves, including weighting wave |
---|
292 | Duplicate/O yw yAxisWave,yErrWave,yWtWave,residWave |
---|
293 | //subtract the background value from yAxisWave before doing any rescaling |
---|
294 | yAxisWave = yw - bkg |
---|
295 | |
---|
296 | If (cmpstr("I",S_Value) == 0) |
---|
297 | SetScale d 0,0,"1/cm",yAxisWave |
---|
298 | yErrWave = ew |
---|
299 | yWtWave = 1/yErrWave |
---|
300 | yAxisWave = yAxisWave |
---|
301 | ylabel = "I(q)" |
---|
302 | break |
---|
303 | endif |
---|
304 | If (cmpstr("ln(I)",S_Value) == 0) |
---|
305 | SetScale d 0,0,"",yAxisWave |
---|
306 | yErrWave = ew/yAxisWave |
---|
307 | yWtWave = 1/yErrWave |
---|
308 | yAxisWave = ln(yAxisWave) |
---|
309 | ylabel = "ln(I)" |
---|
310 | break |
---|
311 | endif |
---|
312 | If (cmpstr("log(I)",S_Value) == 0) |
---|
313 | SetScale d 0,0,"",yAxisWave |
---|
314 | yErrWave = ew/(2.30*yAxisWave) |
---|
315 | yWtWave = 1/yErrWave |
---|
316 | yAxisWave = log(yAxisWave) |
---|
317 | ylabel = "log(I)" |
---|
318 | break |
---|
319 | endif |
---|
320 | If (cmpstr("1/I",S_Value) == 0) |
---|
321 | SetScale d 0,0,"",yAxisWave |
---|
322 | yErrWave = ew/yAxisWave^2 |
---|
323 | yWtWave = 1/yErrWave |
---|
324 | yAxisWave = 1/yAxisWave |
---|
325 | ylabel = "1/I" |
---|
326 | break |
---|
327 | endif |
---|
328 | If (cmpstr("I^a",S_Value) == 0) |
---|
329 | SetScale d 0,0,"",yAxisWave |
---|
330 | yErrWave = ew*abs(pow_a*(yAxisWave^(pow_a-1))) |
---|
331 | yWtWave = 1/yErrWave |
---|
332 | yAxisWave = yAxisWave^pow_a |
---|
333 | ylabel = "I^"+num2str(pow_a) |
---|
334 | break |
---|
335 | endif |
---|
336 | If (cmpstr("Iq^a",S_Value) == 0) |
---|
337 | SetScale d 0,0,"",yAxisWave |
---|
338 | yErrWave = ew*xw^pow_a |
---|
339 | yWtWave = 1/yErrWave |
---|
340 | yAxisWave = yAxisWave*xw^pow_a |
---|
341 | ylabel = "I*q^"+num2str(pow_a) |
---|
342 | break |
---|
343 | endif |
---|
344 | If (cmpstr("I^a q^b",S_Value) == 0) |
---|
345 | SetScale d 0,0,"",yAxisWave |
---|
346 | yErrWave = ew*abs(pow_a*(yAxisWave^(pow_a-1)))*xw^pow_b |
---|
347 | yWtWave = 1/yErrWave |
---|
348 | yAxisWave = yAxisWave^pow_a*xw^pow_b |
---|
349 | ylabel = "I^" + num2str(pow_a) + "q^"+num2str(pow_b) |
---|
350 | break |
---|
351 | endif |
---|
352 | If (cmpstr("1/sqrt(I)",S_Value) == 0) |
---|
353 | SetScale d 0,0,"",yAxisWave |
---|
354 | yErrWave = 0.5*ew*yAxisWave^(-1.5) |
---|
355 | yWtWave = 1/yErrWave |
---|
356 | yAxisWave = 1/sqrt(yAxisWave) |
---|
357 | ylabel = "1/sqrt(I)" |
---|
358 | break |
---|
359 | endif |
---|
360 | If (cmpstr("ln(Iq)",S_Value) == 0) |
---|
361 | SetScale d 0,0,"",yAxisWave |
---|
362 | yErrWave =ew/yAxisWave |
---|
363 | yWtWave = 1/yErrWave |
---|
364 | yAxisWave = ln(xw*yAxisWave) |
---|
365 | ylabel = "ln(q*I)" |
---|
366 | break |
---|
367 | endif |
---|
368 | If (cmpstr("ln(Iq^2)",S_Value) == 0) |
---|
369 | SetScale d 0,0,"",yAxisWave |
---|
370 | yErrWave = ew/yAxisWave |
---|
371 | yWtWave = 1/yErrWave |
---|
372 | yAxisWave = ln(xw*xw*yAxisWave) |
---|
373 | ylabel = "ln(I*q^2)" |
---|
374 | break |
---|
375 | endif |
---|
376 | //more ifs for each case |
---|
377 | |
---|
378 | // if selection not found, abort |
---|
379 | DoAlert 0,"Y-axis scaling incorrect. Aborting" |
---|
380 | Abort |
---|
381 | while(0) //end of "case" statement for y-axis scaling |
---|
382 | |
---|
383 | |
---|
384 | //check for proper x-scaling selection |
---|
385 | Variable low,high |
---|
386 | |
---|
387 | ControlInfo/W=FitPanel lolim |
---|
388 | low = V_value |
---|
389 | ControlInfo/W=FitPanel uplim |
---|
390 | high = V_value |
---|
391 | if ((high<low) || (high==low)) |
---|
392 | DoAlert 0,"Unphysical fitting limits - re-enter better values" |
---|
393 | Abort |
---|
394 | endif |
---|
395 | |
---|
396 | ControlInfo/W=FitPanel xModel |
---|
397 | xstr = S_Value |
---|
398 | do |
---|
399 | // make the new yaxis wave |
---|
400 | Duplicate/o xw xAxisWave |
---|
401 | If (cmpstr("q",S_Value) == 0) |
---|
402 | SetScale d 0,0,"A^-1",xAxisWave |
---|
403 | xAxisWave = xw |
---|
404 | xlabel = "q" |
---|
405 | xlow = low |
---|
406 | xhigh = high |
---|
407 | break |
---|
408 | endif |
---|
409 | If (cmpstr("q^2",S_Value) == 0) |
---|
410 | SetScale d 0,0,"A^-2",xAxisWave |
---|
411 | xAxisWave = xw*xw |
---|
412 | xlabel = "q^2" |
---|
413 | xlow = low^2 |
---|
414 | xhigh = high^2 |
---|
415 | break |
---|
416 | endif |
---|
417 | If (cmpstr("log(q)",S_Value) == 0) |
---|
418 | SetScale d 0,0,"",xAxisWave |
---|
419 | xAxisWave = log(xw) |
---|
420 | xlabel = "log(q)" |
---|
421 | xlow = log(low) |
---|
422 | xhigh = log(high) |
---|
423 | break |
---|
424 | endif |
---|
425 | If (cmpstr("q^c",S_Value) == 0) |
---|
426 | SetScale d 0,0,"",xAxisWave |
---|
427 | xAxisWave = xw^pow_c |
---|
428 | xlabel = "q^"+num2str(pow_c) |
---|
429 | xlow = low^pow_c |
---|
430 | xhigh = high^pow_c |
---|
431 | break |
---|
432 | endif |
---|
433 | |
---|
434 | //more ifs for each case |
---|
435 | |
---|
436 | // if selection not found, abort |
---|
437 | DoAlert 0,"X-axis scaling incorrect. Aborting" |
---|
438 | Abort |
---|
439 | while(0) //end of "case" statement for x-axis scaling |
---|
440 | |
---|
441 | //plot the data |
---|
442 | |
---|
443 | // String cleanLastFileName = "root:"+CleanupName(gLastFileName,0) |
---|
444 | If(WinType("FitWindow") == 0) |
---|
445 | Display /W=(5,42,480,400)/K=1 yAxisWave vs xAxisWave |
---|
446 | ModifyGraph mode=3,standoff=0,marker=8,opaque=1 |
---|
447 | ErrorBars/T=0 yAxisWave Y,wave=(yErrWave,yErrWave) |
---|
448 | DoWindow/C FitWindow |
---|
449 | else |
---|
450 | //window already exists, just bring to front for update |
---|
451 | DoWindow/F FitWindow |
---|
452 | // remove old text boxes |
---|
453 | TextBox/K/N=text_1 |
---|
454 | TextBox/K/N=text_2 |
---|
455 | TextBox/K/N=text_3 |
---|
456 | endif |
---|
457 | SetAxis/A |
---|
458 | ModifyGraph tickUnit=1 //suppress tick units in labels |
---|
459 | TextBox/C/N=textLabel/A=RB "File = "+baseStr |
---|
460 | //clear the old fit from the window, if it exists |
---|
461 | RemoveFromGraph/W=FitWindow/Z fit_yAxisWave |
---|
462 | |
---|
463 | // add the cursors if desired... |
---|
464 | //see if the user wants to use the data specified by the cursors - else use numerical values |
---|
465 | |
---|
466 | ControlInfo/W=FitPanel check0 //V_value = 1 if it is checked, meaning yes, use cursors |
---|
467 | yes_cursors = V_value |
---|
468 | |
---|
469 | DoWindow/F FitWindow |
---|
470 | ShowInfo |
---|
471 | if(yes_cursors) |
---|
472 | xlow = xAxisWave[xcsr(A)] |
---|
473 | xhigh = xAxisWave[xcsr(B)] |
---|
474 | if(xlow > xhigh) |
---|
475 | xhigh = xlow |
---|
476 | xlow = xAxisWave[xcsr(B)] |
---|
477 | endif |
---|
478 | // Print xlow,xhigh |
---|
479 | else |
---|
480 | FindLevel/P/Q xAxisWave, xlow |
---|
481 | if(V_flag == 1) //level NOT found |
---|
482 | DoAlert 0,"Lower q-limit not in experimental q-range. Re-enter a better value" |
---|
483 | //DoWindow/K FitWindow |
---|
484 | //Abort |
---|
485 | endif |
---|
486 | Cursor/P A, yAxisWave,trunc(V_LevelX)+1 |
---|
487 | ylow = V_LevelX |
---|
488 | FindLevel/P/Q xAxisWave, xhigh |
---|
489 | if(V_flag == 1) |
---|
490 | DoAlert 0,"Upper q-limit not in experimental q-range. Re-enter a better value" |
---|
491 | //DoWindow/K FitWindow |
---|
492 | //Abort |
---|
493 | endif |
---|
494 | Cursor/P B, yAxisWave,trunc(V_LevelX) |
---|
495 | yhigh = V_LevelX |
---|
496 | endif //if(V_value) |
---|
497 | //SetAxis bottom,xlow,xhigh |
---|
498 | //SetAxis left,ylow,yhigh |
---|
499 | Label left ylabel |
---|
500 | Label bottom xlabel //E denotes "scaling" - may want to use "units" instead |
---|
501 | |
---|
502 | End |
---|
503 | |
---|
504 | |
---|
505 | //button procedure that is activated to "DotheFit" |
---|
506 | //the panel is parsed for proper fitting limits |
---|
507 | // the appropriate linearization is formed (in the Rescale_Data() function) |
---|
508 | // and the fit is done, |
---|
509 | //and the results are plotted |
---|
510 | // function works in root level data folder (where the loaded 1-d data will be) |
---|
511 | Function DispatchModel(GoFit) : ButtonControl |
---|
512 | String GoFit |
---|
513 | |
---|
514 | //check for the FitWindow - to make sure that there is data to fit |
---|
515 | If(WinType("FitWindow") == 0) //if the window doesn't exist |
---|
516 | Abort "You must Load and Plot a File before fitting the data" |
---|
517 | endif |
---|
518 | |
---|
519 | // rescale the data, to make sure it's as selected on the panel |
---|
520 | ControlInfo/W=FitPanel $"ywave" |
---|
521 | String partialName = CleanupName(S_value,0) |
---|
522 | |
---|
523 | //if the file name was too long, get the updated name. Can't guarantee that the global string set by |
---|
524 | // ShortFileNameString is the currently selected data set, so make the user find the right data set |
---|
525 | // |
---|
526 | Variable maxLength |
---|
527 | if(IgorVersion() < 8) |
---|
528 | maxLength = 25 |
---|
529 | else |
---|
530 | maxLength = 40 |
---|
531 | endif |
---|
532 | |
---|
533 | if(strlen(partialName) > maxLength) |
---|
534 | // get user input, from a list of all of the data folder names |
---|
535 | String dfList = sortList(GetAList(4)) |
---|
536 | String dataFolder="" |
---|
537 | Prompt dataFolder,"Data files to choose from...",popup,dfList |
---|
538 | |
---|
539 | DoPrompt "Select data set",dataFolder |
---|
540 | if(V_Flag==1) //user canceled |
---|
541 | SetDataFolder root: |
---|
542 | return(1) |
---|
543 | endif |
---|
544 | partialName = dataFolder |
---|
545 | endif |
---|
546 | Rescale_Data("root:"+partialName+":") |
---|
547 | |
---|
548 | // now go do the fit |
---|
549 | |
---|
550 | // get the current low and high q values for fitting |
---|
551 | Variable low,high |
---|
552 | |
---|
553 | ControlInfo/W=FitPanel lolim |
---|
554 | low = V_value |
---|
555 | ControlInfo/W=FitPanel uplim |
---|
556 | high = V_value |
---|
557 | if ((high<low) || (high==low)) |
---|
558 | DoAlert 0,"Unphysical fitting limits - re-enter better values" |
---|
559 | Abort |
---|
560 | endif |
---|
561 | |
---|
562 | //try including residuals on the graph /R=residWave, explicitly place on new axis |
---|
563 | //if only /R used, residuals are automatically placed on graph |
---|
564 | // -- NOTE that Rescale_Data() calculates the weighting wave as 1/err (like the old days) so the flag is correctly |
---|
565 | // /I=0, not /I=1 |
---|
566 | |
---|
567 | CurveFit line yAxisWave(xcsr(A),xcsr(B)) /I=0 /X=xAxisWave /W=yWtWave /D |
---|
568 | //CurveFit line yAxisWave(xcsr(A),xcsr(B)) /X=xAxisWave /W=yWtWave /R /D |
---|
569 | ModifyGraph rgb(fit_yAxisWave)=(0,0,0) |
---|
570 | // annotate graph, filtering out special cases of Guinier fits |
---|
571 | // Text Boxes must be used, since ControlBars on graphs DON'T print out |
---|
572 | |
---|
573 | // need access to Global wave, result of fit |
---|
574 | //ystr and xstr are the axis strings - filter with a do-loop |
---|
575 | String ystr="",xstr="" |
---|
576 | //ControlInfo/W=FitPanel ywave |
---|
577 | Wave xw = $("root:"+partialName+":"+partialName + "_q") |
---|
578 | ControlInfo/W=FitPanel yModel |
---|
579 | ystr = S_Value |
---|
580 | ControlInfo/W=FitPanel xModel |
---|
581 | xstr = S_Value |
---|
582 | |
---|
583 | WAVE W_coef=W_coef |
---|
584 | WAVE W_sigma=W_sigma |
---|
585 | String textstr_1,textstr_2,textstr_3 = "" |
---|
586 | Variable rg,rgerr,minfit,maxfit,izerr |
---|
587 | |
---|
588 | textstr_1 = "Slope = " + num2str(W_coef[1]) + " ± " + num2str(W_sigma[1]) |
---|
589 | textstr_1 += "\rIntercept = " + num2str(W_coef[0]) + " ± " + num2str(W_sigma[0]) |
---|
590 | textstr_1 += "\rChi-Squared = " + num2str(V_chisq/(V_npnts - 3)) |
---|
591 | |
---|
592 | minfit = xw[xcsr(A)] |
---|
593 | maxfit = xw[xcsr(B)] |
---|
594 | textstr_2 = "Qmin = " + num2str(minfit) |
---|
595 | textstr_2 += "\rQmax = " + num2str(maxfit) |
---|
596 | |
---|
597 | //model-specific calculations - I(0), Rg, etc. |
---|
598 | //put these in textstr_3, at bottom |
---|
599 | do |
---|
600 | If (cmpstr("I",ystr) == 0) |
---|
601 | textstr_3 = "I(q=0) = " + num2str(W_coef[0]) +" ± "+num2str(W_sigma[0]) |
---|
602 | break |
---|
603 | endif |
---|
604 | If (cmpstr("ln(I)",ystr) == 0) |
---|
605 | izerr = abs(exp(W_coef[0]) - exp(W_coef[0]+W_sigma[0])) |
---|
606 | textstr_3 = "I(q=0) = " + num2str(exp(W_coef[0]))+" ± " + num2str(izerr) |
---|
607 | if(cmpstr("q^2",xstr) == 0) //then a Guinier plot for a sphere (3-d) |
---|
608 | rg = sqrt(-3*W_coef[1]) |
---|
609 | rgerr = 3*W_sigma[1]/(2*rg) |
---|
610 | textstr_3 += "\rRg (A) = " + num2str(rg) + " ± " + num2str(rgerr) |
---|
611 | textstr_3 += "\r" + num2str(rg*minfit) + " < Rg*q < " + num2str(rg*maxfit) |
---|
612 | break |
---|
613 | endif |
---|
614 | break |
---|
615 | endif |
---|
616 | If (cmpstr("log(I)",ystr) == 0) |
---|
617 | if(cmpstr("log(q)",xstr) !=0 ) //extrapolation is nonsense |
---|
618 | textstr_3 = "I(q=0) = " + num2str(10^(W_coef[0])) |
---|
619 | endif |
---|
620 | break |
---|
621 | endif |
---|
622 | If (cmpstr("1/I",ystr) == 0) |
---|
623 | izerr = abs(1/W_coef[0] - 1/(W_coef[0]+W_sigma[0])) |
---|
624 | textstr_3 = "I(q=0) = " + num2str(1/W_coef[0])+" ± " + num2str(izerr) |
---|
625 | break |
---|
626 | endif |
---|
627 | If (cmpstr("I^a",ystr) == 0) |
---|
628 | //nothing |
---|
629 | break |
---|
630 | endif |
---|
631 | If (cmpstr("Iq^a",ystr) == 0) |
---|
632 | //nothing |
---|
633 | break |
---|
634 | endif |
---|
635 | If (cmpstr("I^a q^b",ystr) == 0) |
---|
636 | //nothing |
---|
637 | break |
---|
638 | endif |
---|
639 | If (cmpstr("1/sqrt(I)",ystr) == 0) |
---|
640 | izerr = abs( (W_coef[0])^-2 - (W_coef[0]+W_sigma[0])^-2 ) |
---|
641 | textstr_3 = "I(q=0) = " + num2str((W_coef[0])^-2)+" ± " + num2str(izerr) |
---|
642 | break |
---|
643 | endif |
---|
644 | If (cmpstr("ln(Iq)",ystr) == 0) |
---|
645 | //nothing |
---|
646 | if(cmpstr("q^2",xstr) == 0) //then a x-sect Guinier plot for a rod (2-d) |
---|
647 | // rg now is NOT the radius of gyration, but the x-sect DIAMETER |
---|
648 | rg = 4*sqrt(-W_coef[1]) |
---|
649 | rgerr = 8*W_sigma[1]/rg |
---|
650 | textstr_3 = "Rod diameter (A) = " + num2str(rg) + " ± " + num2str(rgerr) |
---|
651 | textstr_3 += "\r" + num2str(rg*minfit) + " < Rg*q < " + num2str(rg*maxfit) |
---|
652 | break |
---|
653 | endif |
---|
654 | break |
---|
655 | endif |
---|
656 | If (cmpstr("ln(Iq^2)",ystr) == 0) |
---|
657 | //nothing |
---|
658 | if(cmpstr("q^2",xstr) == 0) //then a 1-d Guinier plot for a sheet |
---|
659 | // rg now is NOT the radius of gyration, but the thickness |
---|
660 | rg = sqrt(-12*W_coef[1]) |
---|
661 | rgerr = 6*W_sigma[1]/(2*rg) |
---|
662 | textstr_3 = "Platelet thickness (A) = " + num2str(rg) + " ± " + num2str(rgerr) |
---|
663 | textstr_3 += "\r" + num2str(rg*minfit) + " < Rg*q < " + num2str(rg*maxfit) |
---|
664 | break |
---|
665 | endif |
---|
666 | break |
---|
667 | endif |
---|
668 | |
---|
669 | while(0) |
---|
670 | //kill the old textboxes, if they exist |
---|
671 | TextBox/W=FitWindow/K/N=text_1 |
---|
672 | TextBox/W=FitWindow/K/N=text_2 |
---|
673 | TextBox/W=FitWindow/K/N=text_3 |
---|
674 | // write the new text boxes |
---|
675 | TextBox/W=FitWindow/N=text_1/A=LT textstr_1 |
---|
676 | TextBox/W=FitWindow/N=text_2/A=LC textstr_2 |
---|
677 | If (cmpstr("",textstr_3) != 0) //only display textstr_3 if it isn't null |
---|
678 | TextBox/W=FitWindow/N=text_3/A=LB textstr_3 |
---|
679 | endif |
---|
680 | |
---|
681 | //adjust the plot range to reflect the actual fitted range |
---|
682 | //cursors are already on the graph, done by Rescale_Data() |
---|
683 | AdjustAxisToCursors() |
---|
684 | |
---|
685 | End |
---|
686 | |
---|
687 | // adjusts both the x-axis scaling and y-axis scaling to the cursor range |
---|
688 | // **cursors are already on the graph, done by Rescale_Data() |
---|
689 | // |
---|
690 | // will expand the scale to show an extra 5 points in each direction (if available) |
---|
691 | Function AdjustAxisToCursors() |
---|
692 | |
---|
693 | DoWindow/F FitWindow |
---|
694 | WAVE xAxisWave = root:xAxisWave |
---|
695 | WAVE yAxisWave = root:yAxisWave |
---|
696 | Variable xlow,xhigh,ylow,yhigh,yptlow,ypthigh |
---|
697 | Variable extraPts = 5, num=numpnts(xAxisWave) |
---|
698 | |
---|
699 | String csrA = CsrInfo(A ,"FitWindow") |
---|
700 | String csrB = CsrInfo(B ,"FitWindow") |
---|
701 | |
---|
702 | //x-levels, these are monotonic |
---|
703 | Variable ptLow,ptHigh,tmp |
---|
704 | ptLow = NumberByKey("POINT", csrA ,":" ,";") |
---|
705 | ptHigh = NumberByKey("POINT", csrB ,":" ,";") |
---|
706 | if(ptLow > ptHigh) |
---|
707 | tmp= ptLow |
---|
708 | ptLow=ptHigh |
---|
709 | ptHigh=tmp |
---|
710 | endif |
---|
711 | |
---|
712 | // keep extended point range in bounds |
---|
713 | ptLow = (ptLow-extraPts) >= 0 ? ptLow-extraPts : 0 |
---|
714 | ptHigh = (ptHigh+extraPts) <= (num-1) ? ptHigh + extraPts : num-1 |
---|
715 | |
---|
716 | xlow = xAxisWave[ptLow] |
---|
717 | xhigh = xAxisWave[ptHigh] |
---|
718 | //old way |
---|
719 | // xlow = xAxisWave[xcsr(A)] |
---|
720 | // xhigh = xAxisWave[xcsr(B)] |
---|
721 | // if(xlow > xhigh) |
---|
722 | // xhigh = xlow |
---|
723 | // xlow = xAxisWave[xcsr(B)] |
---|
724 | // endif |
---|
725 | |
---|
726 | //y-levels (old way) |
---|
727 | // FindLevel/P/Q xAxisWave, xlow |
---|
728 | // if(V_flag == 1) //level NOT found |
---|
729 | // DoAlert 0,"Lower q-limit not in experimental q-range. Re-enter a better value" |
---|
730 | // endif |
---|
731 | // yptlow = V_LevelX |
---|
732 | // FindLevel/P/Q xAxisWave, xhigh |
---|
733 | // if(V_flag == 1) |
---|
734 | // DoAlert 0,"Upper q-limit not in experimental q-range. Re-enter a better value" |
---|
735 | // endif |
---|
736 | // ypthigh = V_LevelX |
---|
737 | |
---|
738 | // Print xlow,xhigh,yptlow,ypthigh |
---|
739 | // Print yAxisWave[yptlow],yAxisWave[ypthigh] |
---|
740 | |
---|
741 | |
---|
742 | // make sure ylow/high are in the correct order, since the slope could be + or - |
---|
743 | yhigh = max(yAxisWave[ptlow],yAxisWave[pthigh]) |
---|
744 | ylow = min(yAxisWave[ptlow],yAxisWave[pthigh]) |
---|
745 | |
---|
746 | // Print ptLow,ptHigh |
---|
747 | // print xlow,xhigh |
---|
748 | // print ylow,yhigh |
---|
749 | |
---|
750 | SetAxis bottom,xlow,xhigh |
---|
751 | SetAxis left ylow,yhigh |
---|
752 | |
---|
753 | End |
---|
754 | |
---|
755 | ///// procedures added from other SANS Reduction files |
---|
756 | // |
---|
757 | // |
---|
758 | |
---|
759 | //function called by the popups to get a file list of data that can be sorted |
---|
760 | // this procedure simply removes the raw data files from the string - there |
---|
761 | //can be lots of other junk present, but this is very fast... |
---|
762 | // |
---|
763 | // could also use the alternate procedure of keeping only file with the proper extension |
---|
764 | // |
---|
765 | // another possibility is to get a listing of the text files, but is unreliable on |
---|
766 | // Windows, where the data file must be .txt (and possibly OSX) |
---|
767 | // |
---|
768 | Function/S filterButtonProc(ctrlName) |
---|
769 | String ctrlName |
---|
770 | |
---|
771 | String newList="" |
---|
772 | // String list="",newList="",item="" |
---|
773 | // Variable num,ii |
---|
774 | // |
---|
775 | // //check for the path |
---|
776 | // PathInfo catPathName |
---|
777 | // if(V_Flag==0) |
---|
778 | // DoAlert 0, "Data path does not exist - pick the data path from the button on the FIT panel" |
---|
779 | // Return("") |
---|
780 | // Endif |
---|
781 | // |
---|
782 | // list = IndexedFile(catpathName,-1,"????") |
---|
783 | // num=ItemsInList(list,";") |
---|
784 | // //print "num = ",num |
---|
785 | // for(ii=(num-1);ii>=0;ii-=1) |
---|
786 | // item = StringFromList(ii, list ,";") |
---|
787 | // //simply remove all that are not raw data files (SA1 SA2 SA3) |
---|
788 | // if( !stringmatch(item,"*.SA1*") && !stringmatch(item,"*.SA2*") && !stringmatch(item,"*.SA3*") ) |
---|
789 | // if( !stringmatch(item,".*") && !stringmatch(item,"*.pxp") && !stringmatch(item,"*.DIV")) //eliminate mac "hidden" files, pxp, and div files |
---|
790 | // newlist += item + ";" |
---|
791 | // endif |
---|
792 | // endif |
---|
793 | // endfor |
---|
794 | // //remove VAX version numbers |
---|
795 | // newList = RemoveVersNumsFromList(newList) |
---|
796 | // //sort |
---|
797 | // newList = SortList(newList,";",0) |
---|
798 | |
---|
799 | // Jan 2013 -- replaced with a utility function that filters out raw, div, mask, etc. |
---|
800 | newList = A_ReducedDataFileList("") |
---|
801 | |
---|
802 | return newlist |
---|
803 | End |
---|
804 | |
---|
805 | |
---|
806 | |
---|
807 | //////////////////////////////////////// FIT RPA /////////////////////////////////////////// |
---|
808 | //**************************************** |
---|
809 | //procedures for creating and initializing the FITRPA panel |
---|
810 | //global variables (numerical only) are kept in root:myGlobals:FITRPA folder, |
---|
811 | //created as needed |
---|
812 | // |
---|
813 | // very similar in function to the FIT panel |
---|
814 | // |
---|
815 | Proc OpenFitRPAPanel() |
---|
816 | If(WinType("FitRPAPanel") == 0) |
---|
817 | //create the necessary data folder |
---|
818 | NewDataFolder/O root:myGlobals:FITRPA |
---|
819 | //initialize the values |
---|
820 | Variable/G root:myGlobals:FITRPA:gLolim = 0.02 |
---|
821 | Variable/G root:myGlobals:FITRPA:gUplim = 0.04 |
---|
822 | Variable/G root:myGlobals:FITRPA:gBack = 0 |
---|
823 | Variable/G root:myGlobals:FITRPA:gLambda = 6.0 |
---|
824 | PathInfo/S catPathName |
---|
825 | String localpath = S_path |
---|
826 | if (V_flag == 0) |
---|
827 | //path does not exist - no folder selected |
---|
828 | String/G root:myGlobals:FITRPA:gPathStr = "no folder selected" |
---|
829 | else |
---|
830 | String/G root:myGlobals:FITRPA:gPathStr = localpath |
---|
831 | endif |
---|
832 | String/G root:myGlobals:FITRPA:gDataPopList = "none" |
---|
833 | FitRPAPanel() |
---|
834 | else |
---|
835 | //window already exists, just bring to front for update |
---|
836 | DoWindow/F FitRPAPanel |
---|
837 | endif |
---|
838 | //pop the menu |
---|
839 | FilePopMenuProc("",1,"") |
---|
840 | End |
---|
841 | |
---|
842 | //used on the fit/rpa panel to select the path for the data |
---|
843 | // - automatically pops the file list after the new path selection |
---|
844 | Function FITRPAPickPathButton(ctrlName) : ButtonControl |
---|
845 | String ctrlName |
---|
846 | |
---|
847 | Variable err = A_PickPath() //sets global path value |
---|
848 | SVAR pathStr = root:myGlobals:gCatPathStr |
---|
849 | |
---|
850 | //set the global string for NSORT to the selected pathname |
---|
851 | String/G root:myGlobals:FITRPA:gPathStr = pathStr |
---|
852 | |
---|
853 | //call the popup menu proc's to re-set the menu choices |
---|
854 | FilePopMenuProc("filePopup",1,"") |
---|
855 | |
---|
856 | End |
---|
857 | |
---|
858 | //gets a valid file list (simply not the files with ".SAn" in the name) |
---|
859 | // |
---|
860 | Function FilePopMenuProc(ctrlName,popNum,popStr) : PopupMenuControl |
---|
861 | String ctrlName |
---|
862 | Variable popNum |
---|
863 | String popStr |
---|
864 | |
---|
865 | String tempStr=ReducedDataFileList(ctrlName) |
---|
866 | if(strlen(tempStr)==0) |
---|
867 | tempStr = "Pick the data path" |
---|
868 | Endif |
---|
869 | String/G root:myGlobals:FITRPA:gDataPopList = tempStr //function is in NSORT.ipf |
---|
870 | ControlUpdate filePopup |
---|
871 | |
---|
872 | End |
---|
873 | |
---|
874 | |
---|
875 | |
---|
876 | // window recreation macro to draw the fit/rpa panel |
---|
877 | //globals and data folders must be present before drawing panel |
---|
878 | // |
---|
879 | Window FitRPAPanel() |
---|
880 | |
---|
881 | String angst = root:Packages:NIST:gAngstStr |
---|
882 | PauseUpdate; Silent 1 // building window... |
---|
883 | NewPanel /W=(250,266,591,579)/K=1 |
---|
884 | ModifyPanel cbRGB=(32768,54528,65280) |
---|
885 | ModifyPanel fixedSize=1 |
---|
886 | SetDrawLayer UserBack |
---|
887 | SetDrawEnv fstyle= 1 |
---|
888 | DrawText 81,19,"Select Experimental Data" |
---|
889 | SetDrawEnv fstyle= 1 |
---|
890 | DrawText 97,102,"q-range to fit ("+angst+"^-1)" |
---|
891 | SetDrawEnv fstyle= 1 |
---|
892 | DrawText 87,239,"Select the fit parameters" |
---|
893 | SetDrawEnv fillpat= 0 |
---|
894 | DrawRect 1,103,338,224 |
---|
895 | SetDrawEnv fillpat= 0 |
---|
896 | DrawRect 1,20,337,83 |
---|
897 | SetDrawEnv fillpat= 0 |
---|
898 | DrawRect 2,241,337,275 |
---|
899 | // Button PathButton,pos={6,26},size={80,20},proc=FitRPAPickPathButton,title="Pick Path" |
---|
900 | // Button PathButton,help={"Select the local path to the folder containing your SANS data"} |
---|
901 | // SetVariable setPath,pos={95,29},size={240,17},title="Path:" |
---|
902 | // SetVariable setPath,help={"The current path to the local folder with SANS data"} |
---|
903 | // SetVariable setPath,fSize=10 |
---|
904 | // SetVariable setPath,limits={0,0,0},value= root:myGlobals:FITRPA:gPathStr |
---|
905 | PopupMenu filePopup,pos={8,30},size={96,21},proc=FilePopMenuProc,title="Files" |
---|
906 | PopupMenu filePopup,help={"Select the data file to load."} |
---|
907 | PopupMenu filePopup,mode=5,popvalue="none",value= #"root:myGlobals:FITRPA:gDataPopList" |
---|
908 | SetVariable lambda,pos={111,250},size={120,18},title="Lambda ("+angst+")" |
---|
909 | SetVariable lambda,help={"This sets the wavelength for the multiple scattering corrections."} |
---|
910 | SetVariable lambda,limits={0,10,0},value= root:myGlobals:FITRPA:gLambda |
---|
911 | Button GoFit,pos={60,286},size={80,20},proc=DoFITRPA,title="Do the Fit" |
---|
912 | Button GoFit,help={"This button will do the specified fit using the selections in this panel"} |
---|
913 | SetVariable lolim,pos={82,113},size={134,28},title="Lower Limit" |
---|
914 | SetVariable lolim,help={"Enter the lower q-limit to perform the fit ("+angst+"^-1)"} |
---|
915 | SetVariable lolim,limits={0,5,0},value= root:myGlobals:FITRPA:gLolim |
---|
916 | SetVariable uplim,pos={80,140},size={134,28},title="Upper Limit" |
---|
917 | SetVariable uplim,help={"Enter the upper q-limit to perform the fit ("+angst+"^-1)"} |
---|
918 | SetVariable uplim,limits={0,5,0},value= root:myGlobals:FITRPA:gUplim |
---|
919 | CheckBox RPA_check0,pos={64,198},size={190,20},title="Use cursor range from FitWindow" |
---|
920 | CheckBox RPA_check0,help={"Checking this will perform a fit between the cursors on the graph in FitWindow and ignore the numerical limits typed above"},value=0 |
---|
921 | PopupMenu model,pos={3,249},size={101,21},title="Standard" |
---|
922 | PopupMenu model,help={"This popup selects which standard should be used to fit this data"} |
---|
923 | PopupMenu model,mode=1,popvalue="B",value= #"\"B;C;AS\"" |
---|
924 | Button sh_all,pos={82,168},size={130,20},proc=ShowAllButtonProc,title="Show Full q-range" |
---|
925 | Button sh_all,help={"Use this to show the entire q-range of the data rather than just the fitted range."} |
---|
926 | Button loadButton,pos={20,55},size={70,20},proc=FITRPA_Load_Proc,title="Load File" |
---|
927 | Button loadButton,help={"After choosing a file, load it into memory and plot it with this button."} |
---|
928 | Button helpButton,pos={270,55},size={25,20},proc=showFITHelp,title="?" |
---|
929 | Button helpButton,help={"Show help file for RPA fitting"} |
---|
930 | Button DoneButton,pos={200,286},size={50,20},proc=FITRPADoneButton,title="Done" |
---|
931 | Button DoneButton,help={"This button will close the panel and the associated graph"} |
---|
932 | EndMacro |
---|
933 | |
---|
934 | |
---|
935 | Proc FITRPADoneButton(ctrlName) : ButtonControl |
---|
936 | String ctrlName |
---|
937 | DoWindow/K FitWindow |
---|
938 | DoWindow/K FitRPAPanel |
---|
939 | end |
---|
940 | |
---|
941 | //dispatches the fit to the appropriate model |
---|
942 | //and the appropriate range, based on selections in the panel |
---|
943 | // |
---|
944 | Proc DoFITRPA(ctrlName) : ButtonControl |
---|
945 | String ctrlName |
---|
946 | // |
---|
947 | String cleanLastFileName = CleanupName(root:Packages:NIST:gLastFileName,0) |
---|
948 | String tmpStr = "root:"+cleanLastFileName+":"+cleanLastFileName |
---|
949 | |
---|
950 | Duplicate/O $(tmpStr+"_q") xAxisWave |
---|
951 | Duplicate/O $(tmpStr+"_i") yAxisWave |
---|
952 | Duplicate/O $(tmpStr+"_s") yErrWave,yWtWave,residWave |
---|
953 | |
---|
954 | yWtWave = 1/yErrWave |
---|
955 | |
---|
956 | String xlabel = "q (A^-1)" |
---|
957 | String ylabel = "Intensity" |
---|
958 | //Check to see if the FitWindow exists |
---|
959 | //Plot the data in a FitWindow |
---|
960 | If(WinType("FitWindow") == 0) |
---|
961 | Display /W=(5,42,480,400)/K=1 yAxisWave vs xAxisWave |
---|
962 | ModifyGraph mode=3,standoff=0,marker=8 |
---|
963 | ErrorBars/T=0 yAxisWave Y,wave=(yErrWave,yErrWave) |
---|
964 | DoWindow/C FitWindow |
---|
965 | ShowInfo |
---|
966 | else |
---|
967 | //window already exists, just bring to front for update |
---|
968 | DoWindow/F FitWindow |
---|
969 | // remove old text boxes |
---|
970 | TextBox/K/N=text_1 |
---|
971 | TextBox/K/N=text_2 |
---|
972 | TextBox/K/N=text_3 |
---|
973 | endif |
---|
974 | |
---|
975 | //see if the user wants to use the data specified by the cursors - else use numerical values |
---|
976 | Variable xlow,xhigh,ylow,yhigh,yes_cursors |
---|
977 | ControlInfo/W=FitRPAPanel RPA_check0 //V_value = 1 if it is checked, meaning yes, use cursors |
---|
978 | yes_cursors = V_value |
---|
979 | |
---|
980 | ControlInfo/W=FitRPAPanel lolim |
---|
981 | xlow = V_value |
---|
982 | ControlInfo/W=FitRPAPanel uplim |
---|
983 | xhigh = V_value |
---|
984 | if(yes_cursors) |
---|
985 | xlow = xAxisWave[xcsr(A)] |
---|
986 | xhigh = xAxisWave[xcsr(B)] |
---|
987 | if(xlow > xhigh) |
---|
988 | xhigh = xlow |
---|
989 | xlow = xAxisWave[xcsr(B)] |
---|
990 | endif |
---|
991 | // Print "xlow,xhigh = ",xlow,xhigh |
---|
992 | ylow = yAxisWave[xcsr(A)] |
---|
993 | yhigh = yAxisWave[xcsr(B)] |
---|
994 | if(ylow > yhigh) |
---|
995 | ylow=yhigh |
---|
996 | yhigh = yAxisWave[xcsr(A)] |
---|
997 | endif |
---|
998 | else |
---|
999 | FindLevel/P/Q xAxisWave, xlow |
---|
1000 | if(V_flag == 1) //level NOT found |
---|
1001 | DoAlert 0,"Lower q-limit not in experimental q-range. Re-enter a better value" |
---|
1002 | DoWindow/K FitWindow |
---|
1003 | Abort |
---|
1004 | endif |
---|
1005 | Cursor/P A, yAxisWave,trunc(V_LevelX)+1 |
---|
1006 | ylow = yAxisWave[V_LevelX] |
---|
1007 | FindLevel/P/Q xAxisWave, xhigh |
---|
1008 | if(V_flag == 1) |
---|
1009 | DoAlert 0,"Upper q-limit not in experimental q-range. Re-enter a better value" |
---|
1010 | DoWindow/K FitWindow |
---|
1011 | Abort |
---|
1012 | endif |
---|
1013 | Cursor/P B, yAxisWave,trunc(V_LevelX) |
---|
1014 | yhigh = yAxisWave[V_LevelX] |
---|
1015 | if(ylow > yhigh) |
---|
1016 | yhigh=ylow |
---|
1017 | ylow = yAxisWave[V_levelX] |
---|
1018 | endif |
---|
1019 | endif //if(V_value) |
---|
1020 | SetAxis bottom,xlow,xhigh |
---|
1021 | |
---|
1022 | // print "ylow,yhigh",ylow,yhigh |
---|
1023 | |
---|
1024 | //Get the rest of the data from the panel |
---|
1025 | //such as which standard, the wavelength |
---|
1026 | ControlInfo/W=FitRPAPanel model |
---|
1027 | |
---|
1028 | //find the model name |
---|
1029 | String modelName = S_value |
---|
1030 | |
---|
1031 | Variable first_guess, seglength,iabs,iarb,thick |
---|
1032 | Make/D/O/N=2 fitParams |
---|
1033 | |
---|
1034 | seglength = 6.8 |
---|
1035 | |
---|
1036 | first_guess = 1.0 |
---|
1037 | fitParams[0] = first_guess |
---|
1038 | fitParams[1] = seglength |
---|
1039 | |
---|
1040 | If (cmpstr(modelName,"B")==0) |
---|
1041 | iabs = BStandardFunction(fitParams,xlow) |
---|
1042 | fitParams[0] = yhigh/iabs |
---|
1043 | // Print fitParams[0],fitParams[1] |
---|
1044 | FuncFit BStandardFunction fitParams yAxisWave(xcsr(A),xcsr(B)) /X=xAxisWave /W=yWtWave /D |
---|
1045 | iarb = BStandardFunction(fitParams, 0.0) |
---|
1046 | iabs = iarb/fitParams[0] |
---|
1047 | thick = 0.153 |
---|
1048 | endif |
---|
1049 | If (cmpstr(modelName,"C")==0) |
---|
1050 | iabs = CStandardFunction(fitParams,xlow) |
---|
1051 | fitParams[0] = yhigh/iabs |
---|
1052 | FuncFit CStandardFunction fitParams yAxisWave(xcsr(A),xcsr(B)) /X=xAxisWave /W=yWtWave /D |
---|
1053 | iarb = CStandardFunction(fitParams, 0.0) |
---|
1054 | iabs = iarb/fitParams[0] |
---|
1055 | thick= 0.153 |
---|
1056 | endif |
---|
1057 | If (cmpstr(modelName,"AS")==0) |
---|
1058 | iabs = ASStandardFunction(fitParams,xlow) |
---|
1059 | fitParams[0] = yhigh/iabs |
---|
1060 | FuncFit ASStandardFunction fitParams yAxisWave(xcsr(A),xcsr(B)) /X=xAxisWave /W=yWtWave /D |
---|
1061 | iarb = ASStandardFunction(fitParams, 0.0) |
---|
1062 | iabs = iarb/fitParams[0] |
---|
1063 | thick = 0.1 |
---|
1064 | endif |
---|
1065 | ModifyGraph rgb(fit_yAxisWave)=(0,0,0) |
---|
1066 | Label left ylabel |
---|
1067 | Label bottom xlabel //E denotes "scaling" - may want to use "units" instead |
---|
1068 | |
---|
1069 | ControlInfo/W=FitRPAPanel lambda |
---|
1070 | |
---|
1071 | Variable cor_mult = 1.0 + 2.2e-4*V_Value^2 |
---|
1072 | |
---|
1073 | //WAVE W_coef=W_coef |
---|
1074 | //WAVE W_sigma=W_sigma |
---|
1075 | String textstr_1,textstr_2,textstr_3 = "" |
---|
1076 | textstr_1 = "Scaling Parameter: "+num2str(fitParams[0])+" ± "+num2str(W_sigma[0]) |
---|
1077 | textstr_1 += "\rSegment Length: "+num2str(fitParams[1])+" ± "+num2str(W_sigma[1]) |
---|
1078 | textstr_1 += "\rChi-Squared = " + num2str(V_chisq/(V_npnts - 3)) |
---|
1079 | |
---|
1080 | textstr_2 = "Cross section at q=0: Iabs(0) = "+num2str(iabs)+"cm\S-1\M" |
---|
1081 | textstr_2 += "\rData extrapolated to q=0: Im(0) = "+num2str(iarb)+" Counts/(10\S8\M Mon cts)" |
---|
1082 | textstr_2 += "\rData corrected for multiple scattering: I(0) = "+num2str(iarb/cor_mult)+" Counts/(10\S8\M Mon cnts)" |
---|
1083 | |
---|
1084 | textstr_3 = "In the ABS protocol, " |
---|
1085 | textstr_3 += "\rStandard Thickness, d = "+num2str(thick)+"cm" |
---|
1086 | textstr_3 += "\rI(0), Iarb(0) = "+num2str(iarb/cor_mult)+"Counts/(10\S8\M Mon cts)" |
---|
1087 | textstr_3 += "\rStandard Cross Section, Iabs(0) = "+num2str(iabs)+"cm\S-1\M" |
---|
1088 | TextBox/K/N=text_1 |
---|
1089 | TextBox/K/N=text_2 |
---|
1090 | TextBox/K/N=text_3 |
---|
1091 | TextBox/N=text_2/A=RT textstr_2 |
---|
1092 | TextBox/N=text_3/A=RC textstr_3 |
---|
1093 | TextBox/N=text_1/A=RB textstr_1 |
---|
1094 | |
---|
1095 | End |
---|
1096 | |
---|
1097 | //loads the file selected in the popup for fitting with POL |
---|
1098 | //standard functions. Reads the wavelength from the header, using |
---|
1099 | //6 A as the default |
---|
1100 | //plots the data in FitWindow after reading the file |
---|
1101 | //updates lambda and full q-range on the Panel |
---|
1102 | // |
---|
1103 | Proc FITRPA_Load_Proc(ctrlName): ButtonControl |
---|
1104 | String ctrlName |
---|
1105 | //Load the data |
---|
1106 | String tempName="",partialName="" |
---|
1107 | Variable err |
---|
1108 | ControlInfo $"filePopup" |
---|
1109 | //find the file from the partial filename |
---|
1110 | If( (cmpstr(S_value,"")==0) || (cmpstr(S_value,"none")==0) ) |
---|
1111 | //null selection, or "none" from any popup |
---|
1112 | Abort "no file selected in popup menu" |
---|
1113 | else |
---|
1114 | //selection not null |
---|
1115 | partialName = S_value |
---|
1116 | //Print partialName |
---|
1117 | Endif |
---|
1118 | //get a valid file based on this partialName and catPathName |
---|
1119 | tempName = FindValidFilename(partialName) |
---|
1120 | |
---|
1121 | Variable lambdaFromFile=GetLambdaFromReducedData(tempName) |
---|
1122 | Variable/G root:myGlobals:FITRPA:gLambda = lambdaFromFile |
---|
1123 | Print "Lambda in file read as:", lambdaFromFile |
---|
1124 | |
---|
1125 | //prepend path to tempName for read routine |
---|
1126 | PathInfo catPathName |
---|
1127 | tempName = S_path + tempName |
---|
1128 | |
---|
1129 | //load in the data (into the root directory) |
---|
1130 | LoadOneDDataWithName(tempName,0) |
---|
1131 | //Print S_fileName |
---|
1132 | //Print tempName |
---|
1133 | |
---|
1134 | String cleanLastFileName = CleanupName(root:Packages:NIST:gLastFileName,0) |
---|
1135 | String tmpStr = "root:"+cleanLastFileName+":"+cleanLastFileName |
---|
1136 | |
---|
1137 | Duplicate/o $(tmpStr+"_q") xAxisWave |
---|
1138 | Duplicate/o $(tmpStr+"_i") yAxisWave |
---|
1139 | Duplicate/o $(tmpStr+"_s") yErrWave |
---|
1140 | |
---|
1141 | Variable xmin, xmax |
---|
1142 | WaveStats/Q xAxisWave |
---|
1143 | root:myGlobals:FITRPA:gLolim=V_min |
---|
1144 | root:myGlobals:FITRPA:gUplim=V_max |
---|
1145 | ControlUpdate/W=FITRPAPanel/A |
---|
1146 | |
---|
1147 | //Check to see if the FitWindow exists |
---|
1148 | //Plot the data in a FitWindow |
---|
1149 | If(WinType("FitWindow") == 0) |
---|
1150 | Display /W=(5,42,480,400)/K=1 yAxisWave vs xAxisWave |
---|
1151 | ModifyGraph mode=3,standoff=0,marker=8 |
---|
1152 | ErrorBars/T=0 yAxisWave Y,wave=(yErrWave,yErrWave) |
---|
1153 | TextBox/C/N=textLabel/A=RB "File = "+cleanLastFileName |
---|
1154 | DoWindow/C FitWindow |
---|
1155 | ShowInfo |
---|
1156 | else |
---|
1157 | //window already exists, just bring to front for update |
---|
1158 | DoWindow/F FitWindow |
---|
1159 | TextBox/C/N=textLabel/A=RB "File = "+cleanLastFileName |
---|
1160 | endif |
---|
1161 | // remove old text boxes |
---|
1162 | TextBox/K/N=text_1 |
---|
1163 | TextBox/K/N=text_2 |
---|
1164 | TextBox/K/N=text_3 |
---|
1165 | RemoveFromGraph/W=fitWindow /Z fit_yAxisWave |
---|
1166 | SetAxis/A |
---|
1167 | |
---|
1168 | //put cursors on the graph at first and last points |
---|
1169 | Cursor/P A yAxisWave 0 |
---|
1170 | Cursor/P B yAxisWave (numpnts(yAxisWave) - 1) |
---|
1171 | End |
---|
1172 | |
---|
1173 | //Fitting function for the POL-B standards |
---|
1174 | // |
---|
1175 | Function BStandardFunction(parameterWave, x) |
---|
1176 | Wave parameterWave; Variable x |
---|
1177 | |
---|
1178 | //Model parameters |
---|
1179 | Variable KN=4.114E-3,CH=9.613E4, CD=7.558E4, NH=1872, ND=1556 |
---|
1180 | Variable INC=0.32, CHIV=2.2E-6 |
---|
1181 | //Correction based on absolute flux measured 5/93 |
---|
1182 | Variable CORR = 1.1445 |
---|
1183 | |
---|
1184 | //Local variables |
---|
1185 | Variable AP2,QRGH,QRGD,IABS_RPA,IABS |
---|
1186 | |
---|
1187 | //Calculate the function here |
---|
1188 | ap2=parameterWave[1]^2 |
---|
1189 | qrgh = x*sqrt(nh*ap2/6) |
---|
1190 | qrgd = x*sqrt(nd*ap2/6) |
---|
1191 | iabs_rpa = kn/(1/(ch*FIT_dbf(qrgh)) + 1/(cd*FIT_dbf(qrgd)) - chiv) |
---|
1192 | iabs = corr*iabs_rpa + inc |
---|
1193 | |
---|
1194 | //return the result |
---|
1195 | return parameterWave[0]*iabs |
---|
1196 | |
---|
1197 | End |
---|
1198 | |
---|
1199 | //Fitting function for the POL-C standards |
---|
1200 | // |
---|
1201 | Function CStandardFunction(parameterWave, x) |
---|
1202 | Wave parameterWave; Variable x |
---|
1203 | |
---|
1204 | //Model parameters |
---|
1205 | Variable KN=4.114E-3,CH=2.564E5, CD=1.912E5, NH=4993, ND=3937 |
---|
1206 | Variable INC=0.32, CHIV=2.2E-6 |
---|
1207 | //Correction based on absolute flux measured 5/93 |
---|
1208 | Variable CORR = 1.0944 |
---|
1209 | |
---|
1210 | //Local variables |
---|
1211 | Variable AP2,QRGH,QRGD,IABS_RPA,IABS |
---|
1212 | |
---|
1213 | //Calculate the function here |
---|
1214 | ap2=parameterWave[1]^2 |
---|
1215 | qrgh = x*sqrt(nh*ap2/6) |
---|
1216 | qrgd = x*sqrt(nd*ap2/6) |
---|
1217 | iabs_rpa = kn/(1/(ch*FIT_dbf(qrgh)) + 1/(cd*FIT_dbf(qrgd)) - chiv) |
---|
1218 | iabs = corr*iabs_rpa + inc |
---|
1219 | |
---|
1220 | //return the result |
---|
1221 | return parameterWave[0]*iabs |
---|
1222 | |
---|
1223 | End |
---|
1224 | |
---|
1225 | //fitting function for the POL-AS standards |
---|
1226 | // |
---|
1227 | Function ASStandardFunction(parameterWave, x) |
---|
1228 | Wave parameterWave; Variable x |
---|
1229 | |
---|
1230 | //Model parameters |
---|
1231 | Variable KN=64.5,CH=1.0, CD=1.0, NH=766, ND=766 |
---|
1232 | Variable INC=0.32, CHIV=0.0 |
---|
1233 | |
---|
1234 | //Local variables |
---|
1235 | Variable AP2,QRGH,QRGD,IABS_RPA,IABS |
---|
1236 | |
---|
1237 | //Calculate the function here |
---|
1238 | ap2=parameterWave[1]^2 |
---|
1239 | qrgh = x*sqrt(nh*ap2/6) |
---|
1240 | |
---|
1241 | //The following lines were commented out in the fortran function |
---|
1242 | //qrgd = x*sqrt(nd*ap2/6) |
---|
1243 | //iabs_rpa = kn/(1/(ch*FIT_dbf(qrgh)) + 1/(cd*FIT_dbf(qrgd)) - chiv) |
---|
1244 | |
---|
1245 | iabs_rpa = kn*FIT_dbf(qrgh) |
---|
1246 | iabs = iabs_rpa + inc |
---|
1247 | |
---|
1248 | //return the result |
---|
1249 | return parameterWave[0]*iabs |
---|
1250 | |
---|
1251 | End |
---|
1252 | |
---|
1253 | //Debye Function used for polymer standards |
---|
1254 | Function FIT_dbf(rgq) |
---|
1255 | Variable rgq |
---|
1256 | Variable x |
---|
1257 | |
---|
1258 | x=rgq*rgq |
---|
1259 | if (x < 5.0E-3) |
---|
1260 | return 1.0 - x/3 + x^2/12 |
---|
1261 | else |
---|
1262 | return 2*(exp(-x) + x - 1)/x^2 |
---|
1263 | endif |
---|
1264 | End |
---|
1265 | |
---|
1266 | |
---|
1267 | //////////////////////////////// EMD FIT RPA ////////////////////////////////////// |
---|
1268 | |
---|
1269 | |
---|
1270 | |
---|
1271 | |
---|
1272 | |
---|
1273 | |
---|
1274 | |
---|
1275 | |
---|
1276 | //procedures to clean up after itself |
---|
1277 | // |
---|
1278 | // -- note that it's never going to unload if the SANS Reduction is open too - since |
---|
1279 | // the old FIT_Ops was always loaded, and now points to this file. |
---|
1280 | // |
---|
1281 | Function UnloadLinFit() |
---|
1282 | |
---|
1283 | if (WinType("FitPanel") == 7) |
---|
1284 | DoWindow/K FitPanel |
---|
1285 | endif |
---|
1286 | if (WinType("FitWindow") != 0) |
---|
1287 | DoWindow/K $"FitWindow" |
---|
1288 | endif |
---|
1289 | SetDataFolder root: |
---|
1290 | Killwaves/Z xAxisWave,yAxisWave,yErrWave,residWave,yWtWave,fit_yAxisWave |
---|
1291 | |
---|
1292 | SVAR/Z fileVerExt=root:Packages:NIST:SANS_ANA_EXTENSION |
---|
1293 | if(SVAR_Exists(fileVerExt) == 0) |
---|
1294 | return 0 |
---|
1295 | endif |
---|
1296 | |
---|
1297 | String fname="LinearizedFits" |
---|
1298 | Execute/P "DELETEINCLUDE \""+fname+fileVerExt+"\"" |
---|
1299 | Execute/P "COMPILEPROCEDURES " |
---|
1300 | end |
---|
1301 | |
---|
1302 | #if(exists("root:Packages:NIST:SANS_ANA_EXTENSION") != 0) |
---|
1303 | //this keeps the SANS Models menu from appearing in the SANS Reduction package |
---|
1304 | Menu "SANS Models" |
---|
1305 | Submenu "Packages" |
---|
1306 | "Unload Linear Fitting", UnloadLinFit() |
---|
1307 | End |
---|
1308 | end |
---|
1309 | |
---|
1310 | #endif |
---|
1311 | |
---|
1312 | Function FIT_PickPathButtonProc(ctrlName) : ButtonControl |
---|
1313 | String ctrlName |
---|
1314 | |
---|
1315 | A_PickPath() |
---|
1316 | //pop the file menu |
---|
1317 | FIT_FilePopMenuProc("",1,"") |
---|
1318 | End |
---|