#pragma rtGlobals=1 // Use modern global access method. #pragma version=1.2 #pragma IgorVersion=6.0 /////////////////////////////// //procedures for creating and initializing the Linearized FIT panel //global variables (numerical only) are kept in root:Packages:NIST:FIT folder // // this is based on the FIT routines in the SANS Reduction package, and has been modified here // only to make it independent of the Reduction routines, and into "Package" format // // These procedures WILL conflict in namespace with the SANS Reduction routines // in both Fit_Ops and VAX_Utils (and probably others...) so DO NOT // try to include these... // // SRK 11 JAN 05 // // Prepended "A_" to all of the procs and functions to avoid name conflicts // with the FIT included in the reduction package // - DID NOT prepend "A_" to the loader/unloader which is unique to this package // // /////////////////////////////// //main procedures to open the panel, initializing the data folder and global variables //as necessary. All are kept in a :FIT subfolder to avoid overlap with other variables // // To use any of the fit functions in the FIT panel, I(Q) data must already // be loaded into memory (using "plot" from the 1-D data operations // ** this may be useful to change in the future, replacing the 3 popups // with a list box - allowing the user to pick/load the data from the fit panel // and not offering any choice of q/i/s waves to use. (more consistent with the operation // of the FIT/RPA panel) // Proc A_OpenFitPanel() If(WinType("A_FitPanel") == 0) //create the necessary data folder NewDataFolder/O root:Packages NewDataFolder/O root:Packages:NIST NewDataFolder/O root:Packages:NIST:FIT //initialize the values Variable/G root:Packages:NIST:FIT:gLolim = 0.02 Variable/G root:Packages:NIST:FIT:gUplim = 0.04 Variable/G root:Packages:NIST:FIT:gExpA = 1 Variable/G root:Packages:NIST:FIT:gExpB = 1 Variable/G root:Packages:NIST:FIT:gExpC = 1 Variable/G root:Packages:NIST:FIT:gBack = 0 String/G root:Packages:NIST:FIT:gDataPopList = "none" A_FitPanel() else //window already exists, just bring to front for update DoWindow/F A_FitPanel CheckBox check0,value=0 //deselect the checkbox to use cursors endif //pop the file menu A_FIT_FilePopMenuProc("",1,"") End //the actual window recreation macro to draw the fit panel. Globals and data folder must // already be initialized Window A_FitPanel() //String angst = root:Packages:NIST:gAngstStr String angst = "A" PauseUpdate; Silent 1 // building window... NewPanel /W=(461,46,735,455)/K=1 ModifyPanel cbRGB=(32768,54615,65535), fixedSize=1 SetDrawLayer UserBack DrawText 56,20,"Select Experimental Data" DrawText 66,138,"q-range to fit ("+angst+"^-1)" DrawText 42,268,"Select the y and x-axis scaling" DrawLine 1,21,271,21 DrawLine -1,272,273,272 DrawLine -1,140,272,140 PopupMenu ywave,pos={13,60},size={154,19},title="Data File" PopupMenu ywave,help={"Select the experimental intensity values"} PopupMenu ywave,mode=1,value=root:Packages:NIST:FIT:gDataPopList,proc=A_FIT_FilePopMenuProc Button loadButton,pos={13,92},size={130,20},proc=A_FIT_Load_Proc,title="Load and Plot File" Button loadButton,help={"After choosing a file, load it into memory and plot it with this button."} Button helpButton,pos={237,28},size={25,20},proc=A_showFITHelp,title="?" Button helpButton,help={"Show help file for linearized fitting"} PopupMenu ymodel,pos={20,281},size={76,19},title="y-axis" PopupMenu ymodel,help={"This popup selects how the y-axis will be linearized based on the chosen data"} 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)\"" Button GoFit,pos={60,367},size={70,20},proc=A_DispatchModel,title="Do the Fit" Button GoFit,help={"This button will do the specified fit using the selections in this panel"} Button DoneButton,pos={180,367},size={50,20},proc=A_FITDoneButton,title="Done" Button DoneButton,help={"This button will close the panel and the associated graph"} SetVariable lolim,pos={64,147},size={134,17},title="Lower Limit" SetVariable lolim,help={"Enter the lower q-limit to perform the fit ("+angst+"^-1)"} SetVariable lolim,limits={0,5,0},value= root:Packages:NIST:FIT:gLolim SetVariable uplim,pos={63,169},size={134,17},title="Upper Limit" SetVariable uplim,help={"Enter the upper q-limit to perform the fit ("+angst+"^-1)"} SetVariable uplim,limits={0,5,0},value= root:Packages:NIST:FIT:gUplim SetVariable expa,pos={13,311},size={80,17},title="pow \"a\"" 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"} SetVariable expa,limits={-2,10,0},value= root:Packages:NIST:FIT:gExpA SetVariable expb,pos={98,311},size={80,17},title="pow \"b\"" 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"} SetVariable expb,limits={0,10,0},value= root:Packages:NIST:FIT:gExpB PopupMenu xmodel,pos={155,280},size={79,19},title="x-axis" PopupMenu xmodel,help={"This popup selects how the x-axis will be linearized given the chosen data"} PopupMenu xmodel,mode=1,value= #"\"q;log(q);q^2;q^c\"" CheckBox check0,pos={18,223},size={240,20},title="Use cursor range from FitWindow" 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 SetVariable back,pos={70,338},size={139,17},title="background" SetVariable back,help={"This constant background value will be subtracted from the experimental intensity before fitting is done"} SetVariable back,limits={-Inf,Inf,0},value= root:Packages:NIST:FIT:gBack SetVariable expc,pos={182,310},size={80,17},title="pow \"c\"" 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"} SetVariable expc,limits={-10,10,0},value= root:Packages:NIST:FIT:gExpC Button sh_all,pos={65,193},size={130,20},proc=A_ShowAllButtonProc,title="Show Full q-range" Button sh_all,help={"Use this to show the entire q-range of the data rather than just the fitted range."} Button FIT_PathButton,pos={10,28},size={80,20},proc=A_FIT_PickPathButtonProc,title="Pick Path" EndMacro Proc A_FITDoneButton(ctrlName): ButtonControl String ctrlName DoWindow/K A_FitWindow DoWindow/K A_FitPanel end Proc A_showFITHelp(ctrlName): ButtonControl String ctrlName DisplayHelpTopic/Z/K=1 "Linearized Fits" if(V_flag != 0) DoAlert 0, "The Linearized Fit Help file can not be found" endif end //Loads the selected file for fitting //graphs the data as needed Proc A_FIT_Load_Proc(ctrlName): ButtonControl String ctrlName //Load the data String tempName="",partialName="" Variable err ControlInfo $"ywave" //find the file from the partial filename If( (cmpstr(S_value,"")==0) || (cmpstr(S_value,"none")==0) ) //null selection, or "none" from any popup Abort "no file selected in popup menu" else //selection not null partialName = S_value Endif //get a valid file based on this partialName and catPathName tempName = A_FindValidFilename(partialName) //prepend path to tempName for read routine PathInfo catPathName tempName = S_path + tempName //load in the data (into the root directory) A_LoadOneDDataWithName(tempName,0) //let A_Rescale_Data() do the plotting //Print S_fileName //Print tempName String cleanLastFileName = CleanupName(partialName,0) String dataStr = "root:"+cleanLastFileName+":" tempName=dataStr + cleanLastFileName+"_q" Duplicate/O $tempName xAxisWave tempName=dataStr + cleanLastFileName+"_i" Duplicate/O $tempName yAxisWave tempName=dataStr + cleanLastFileName+"_s" Duplicate/O $tempName yErrWave //Plot, and adjust the scaling to match the axis scaling set by the popups A_Rescale_Data(dataStr) End //gets a valid file list (simply not the files with ".SAn" in the name) // Function A_FIT_FilePopMenuProc(ctrlName,popNum,popStr) : PopupMenuControl String ctrlName Variable popNum String popStr String tempStr=A_filterButtonProc(ctrlName) if(strlen(tempStr)==0) tempStr = "Pick the data path" Endif String/G root:Packages:NIST:FIT:gDataPopList =tempStr ControlUpdate ywave End //direct porting of the fit program from the VAX, with no corrections and only //minor modifications of additional linearizations and the option //to subtract a constant (q-independent) background value before doing any //of the fits. The original data on disk (and as loaded) is never modified, all //manipulation is done from a copy of the data. //button procedure to show the entire axis range of the data, rather than just //the fitted range, which is the default display after a fit is performed // Function A_ShowAllButtonProc(ctrlName) : ButtonControl String ctrlName //bring the FitWindow to the front and Autoscale the axes DoWindow/F A_FitWindow SetAxis/A End // function that takes the current dataset (already loaded) // and replots it based on the X/Y axis scaling selected in the popups // (does not fit the data) // // dataStr is the root:folder: of the data that was loaded Function A_Rescale_Data(dataStr) String dataStr //Scaling exponents and background value Variable pow_a,pow_b,pow_c,bkg ControlInfo/W=A_FitPanel expa pow_a = V_value ControlInfo/W=A_FitPanel expb pow_b = V_value ControlInfo/W=A_FitPanel expc pow_c = V_value ControlInfo/W=A_FitPanel back bkg = V_value //check for physical limits on exponent values // if bad values found, alert, and reset to good values so the rescaling can continue NVAR gA = root:Packages:NIST:FIT:gExpA NVAR gB = root:Packages:NIST:FIT:gExpB NVAR gC = root:Packages:NIST:FIT:gExpC if((pow_a < -2) || (pow_a > 10)) DoAlert 0,"Exponent a must be in the range (-2,10) - the exponent a has been reset to 1" gA = 1 endif if((pow_b < 0) || (pow_b > 10)) DoAlert 0,"Exponent b must be in the range (0,10) - the exponent b has been reset to 1" gB = 1 endif //if q^c is the x-scaling, c must be be within limits and also non-zero ControlInfo/W=A_FitPanel xModel If (cmpstr("q^c",S_Value) == 0) if(pow_c == 0) DoAlert 0,"Exponent c must be non-zero, c has been reset to 1" gC = 1 endif if((pow_c < -10) || (pow_c > 10)) DoAlert 0,"Exponent c must be in the range (-10,10), c has been reset to 1" gC = 1 endif endif //do the rescaling of the data // get the current experimental q, I, and std dev. waves (as they would be loaded ) String baseStr = ParseFilePath(0,dataStr,":",1,0) //give me the last part of the path Wave xw = $(dataStr+baseStr+"_q") Wave yw = $(dataStr+baseStr+"_i") Wave ew = $(dataStr+baseStr+"_s") //variables set for each model to control look of graph Variable xlow,xhigh,ylow,yhigh,yes_cursors String xlabel,ylabel,xstr,ystr //check for proper y-scaling selection, make the necessary waves ControlInfo/W=A_FitPanel yModel ystr = S_Value // print "ystr = ",ystr do // make the new yaxis waves, including weighting wave Duplicate/O yw yAxisWave,yErrWave,yWtWave,residWave //subtract the background value from yAxisWave before doing any rescaling yAxisWave = yw - bkg If (cmpstr("I",S_Value) == 0) SetScale d 0,0,"1/cm",yAxisWave yErrWave = ew yWtWave = 1/yErrWave yAxisWave = yAxisWave ylabel = "I(q)" break endif If (cmpstr("ln(I)",S_Value) == 0) SetScale d 0,0,"",yAxisWave yErrWave = ew/yAxisWave yWtWave = 1/yErrWave yAxisWave = ln(yAxisWave) ylabel = "ln(I)" break endif If (cmpstr("log(I)",S_Value) == 0) SetScale d 0,0,"",yAxisWave yErrWave = ew/(2.30*yAxisWave) yWtWave = 1/yErrWave yAxisWave = log(yAxisWave) ylabel = "log(I)" break endif If (cmpstr("1/I",S_Value) == 0) SetScale d 0,0,"",yAxisWave yErrWave = ew/yAxisWave^2 yWtWave = 1/yErrWave yAxisWave = 1/yAxisWave ylabel = "1/I" break endif If (cmpstr("I^a",S_Value) == 0) SetScale d 0,0,"",yAxisWave yErrWave = ew*abs(pow_a*(yAxisWave^(pow_a-1))) yWtWave = 1/yErrWave yAxisWave = yAxisWave^pow_a ylabel = "I^"+num2str(pow_a) break endif If (cmpstr("Iq^a",S_Value) == 0) SetScale d 0,0,"",yAxisWave yErrWave = ew*xw^pow_a yWtWave = 1/yErrWave yAxisWave = yAxisWave*xw^pow_a ylabel = "I*q^"+num2str(pow_a) break endif If (cmpstr("I^a q^b",S_Value) == 0) SetScale d 0,0,"",yAxisWave yErrWave = ew*abs(pow_a*(yAxisWave^(pow_a-1)))*xw^pow_b yWtWave = 1/yErrWave yAxisWave = yAxisWave^pow_a*xw^pow_b ylabel = "I^" + num2str(pow_a) + "q^"+num2str(pow_b) break endif If (cmpstr("1/sqrt(I)",S_Value) == 0) SetScale d 0,0,"",yAxisWave yErrWave = 0.5*ew*yAxisWave^(-1.5) yWtWave = 1/yErrWave yAxisWave = 1/sqrt(yAxisWave) ylabel = "1/sqrt(I)" break endif If (cmpstr("ln(Iq)",S_Value) == 0) SetScale d 0,0,"",yAxisWave yErrWave =ew/yAxisWave yWtWave = 1/yErrWave yAxisWave = ln(xw*yAxisWave) ylabel = "ln(q*I)" break endif If (cmpstr("ln(Iq^2)",S_Value) == 0) SetScale d 0,0,"",yAxisWave yErrWave = ew/yAxisWave yWtWave = 1/yErrWave yAxisWave = ln(xw*xw*yAxisWave) ylabel = "ln(I*q^2)" break endif //more ifs for each case // if selection not found, abort DoAlert 0,"Y-axis scaling incorrect. Aborting" Abort while(0) //end of "case" statement for y-axis scaling //check for proper x-scaling selection Variable low,high ControlInfo/W=A_FitPanel lolim low = V_value ControlInfo/W=A_FitPanel uplim high = V_value if ((high ptHigh) tmp= ptLow ptLow=ptHigh ptHigh=tmp endif // keep extended point range in bounds ptLow = (ptLow-extraPts) >= 0 ? ptLow-extraPts : 0 ptHigh = (ptHigh+extraPts) <= (num-1) ? ptHigh + extraPts : num-1 xlow = xAxisWave[ptLow] xhigh = xAxisWave[ptHigh] //old way // xlow = xAxisWave[xcsr(A)] // xhigh = xAxisWave[xcsr(B)] // if(xlow > xhigh) // xhigh = xlow // xlow = xAxisWave[xcsr(B)] // endif //y-levels (old way) // FindLevel/P/Q xAxisWave, xlow // if(V_flag == 1) //level NOT found // DoAlert 0,"Lower q-limit not in experimental q-range. Re-enter a better value" // endif // yptlow = V_LevelX // FindLevel/P/Q xAxisWave, xhigh // if(V_flag == 1) // DoAlert 0,"Upper q-limit not in experimental q-range. Re-enter a better value" // endif // ypthigh = V_LevelX // Print xlow,xhigh,yptlow,ypthigh // Print yAxisWave[yptlow],yAxisWave[ypthigh] // make sure ylow/high are in the correct order, since the slope could be + or - yhigh = max(yAxisWave[ptlow],yAxisWave[pthigh]) ylow = min(yAxisWave[ptlow],yAxisWave[pthigh]) // Print ptLow,ptHigh // print xlow,xhigh // print ylow,yhigh SetAxis bottom,xlow,xhigh SetAxis left ylow,yhigh End ///// procedures added from other SANS Reduction files // // //function called by the popups to get a file list of data that can be sorted // this procedure simply removes the raw data files from the string - there //can be lots of other junk present, but this is very fast... // // could also use the alternate procedure of keeping only file with the proper extension // // another possibility is to get a listing of the text files, but is unreliable on // Windows, where the data file must be .txt (and possibly OSX) // Function/S A_filterButtonProc(ctrlName) String ctrlName String list="",newList="",item="" Variable num,ii //check for the path PathInfo catPathName if(V_Flag==0) DoAlert 0, "Data path does not exist - pick the data path from the button on the FIT panel" Return("") Endif list = IndexedFile(catpathName,-1,"????") num=ItemsInList(list,";") //print "num = ",num for(ii=(num-1);ii>=0;ii-=1) item = StringFromList(ii, list ,";") //simply remove all that are not raw data files (SA1 SA2 SA3) if( !stringmatch(item,"*.SA1*") && !stringmatch(item,"*.SA2*") && !stringmatch(item,"*.SA3*") ) if( !stringmatch(item,".*") && !stringmatch(item,"*.pxp") && !stringmatch(item,"*.DIV")) //eliminate mac "hidden" files, pxp, and div files newlist += item + ";" endif endif endfor //remove VAX version numbers newList = A_RemoveVersNumsFromList(newList) //sort newList = SortList(newList,";",0) return newlist End //procedures to clean up after itself Function UnloadLinFit() if (WinType("A_FitPanel") == 7) DoWindow/K A_FitPanel endif if (WinType("A_FitWindow") != 0) DoWindow/K $"A_FitWindow" endif SetDataFolder root: Killwaves/Z xAxisWave,yAxisWave,yErrWave,residWave,yWtWave,fit_yAxisWave SVAR fileVerExt=root:Packages:NIST:SANS_ANA_EXTENSION String fname="LinearizedFits" Execute/P "DELETEINCLUDE \""+fname+fileVerExt+"\"" Execute/P "COMPILEPROCEDURES " end Menu "SANS Models" Submenu "Packages" "Unload Linear Fitting", UnloadLinFit() End end Function A_FIT_PickPathButtonProc(ctrlName) : ButtonControl String ctrlName A_PickPath() //pop the file menu A_FIT_FilePopMenuProc("",1,"") End