#pragma rtGlobals=3 // Use modern global access method and strict wave access. // Function designed to take as input the name of a Multi-peak Fit 2 // set folder found in root:Packages:MultiPeakFit2:, along with a // list of input data waves. This function loops through the list using // the coefficient waves found in the data folder as the initial guesses // for each of the data waves found in ywavelist, xwavelist. // Example usage: MultiPeakBatchFitExtended("root:packages:MultiPeakFit2:MPF_SetFolder_1CP") Function MultiPeakBatchFitExtended(datafolderName) String datafolderName //Loop through all the traces in the top graph: String ywavelist = TraceNameList("", ";", 1) string ywave String remove1,remove2,rmv Variable nfits = ItemsInList(ywavelist) // The structure required by MPF2_DoMPFit() STRUCT MPFitInfoStruct MPStruct Variable i, err String saveDF = GetDataFolder(1) //Delete all previous "batchpeakfit" folders SetDataFolder saveDF string folderlist=DataFolderDir(1) variable lastspot=strsearch(folderlist,"BatchPeakFit",Inf,1) variable lastwave=0 string foldertokill="" variable killfolder=0 if(lastspot>-1) lastspot+=13 lastwave=str2num(folderlist[lastspot,lastspot+3]) // add 0 for up to 9 folders, add 1 for up to 99 folders, add 2 for up to 999 folders do foldertokill="BatchPeakFit_"+num2str(killfolder) KillDataFolder $foldertokill killfolder+=1 while (killfolder <= lastwave) Print "Killed old fit data folders." endif // Switch to the Multi-peak fit folder and look up some stuff from the initial guess fit //String saveDF = GetDataFolder(1) SetDataFolder datafolderName // Look up the function type list saved by Multi-peak Fit SVAR SavedFunctionTypes MPStruct.ListOfFunctions = SavedFunctionTypes // Create the list of coefficient waves and hold strings MPStruct.ListOfCWaveNames = "" MPStruct.ListOfHoldStrings = "" Wave/Z cw = 'Baseline Coefs' if (WaveExists(cw)) MPStruct.ListOfCWaveNames = NameOfWave(cw) endif MPStruct.ListOfCWaveNames += ";" Variable npeaks = 0 do Wave/Z cw = $("Peak "+num2istr(npeaks)+" Coefs") if (!WaveExists(cw)) break endif MPStruct.ListOfCWaveNames += NameOfWave(cw)+";" npeaks += 1 while (1) variable howmanypeaks = npeaks //Add hold strings Wave/T/Z hsw = 'HoldStrings' string holdinfo="" string holdstrings="" variable myi=0 do holdinfo=hsw[myi] holdstrings += holdinfo +";" myi += 1 while (myi <= howmanypeaks) MPStruct.ListOfHoldStrings = holdstrings //Get constraints wave/T ctw=$"constraintsTextWave" string constring="", cons="",newcons="" variable imax=0, pk=0,ia=0,totalcount=0,maxval=nan,minval=nan for(pk=0;pk"+num2str(minval)+";" endif endif totalcount+=0.5 endfor endfor if(strlen(newcons)!=0) Print "Applying constraints." endif SetDataFolder saveDF // fill in more members of the structure MPStruct.NPeaks = npeaks MPStruct.XPointRangeBegin = 0 // this function always fits the entire data set MPStruct.FitCurvePoints = 1000 MPStruct.fitOptions = 4 // you might want to change this to 4 // loop through each of the data sets, calling MPF2_DoMPFit // on each one. After each call, the results are checked and acted // on appropriately. variable wasalert=0 for (i = 0; i < nfits; i += 1) // We make a copy of the Multi-peak fit folder for // each data set. That also duplicates all the coefficient waves // so that we preserve the results for each fit. The duplicated data folder // is created inside the current data folder. String BatchDFName = "BatchPeakFit_"+num2str(i) DuplicateDataFolder $datafolderName, $BatchDFName // Most of the contents of the structure don't need to change. // Naturally, we have to put in a wave reference to the // data set being fit this time through the loop ywave = StringFromList(i,ywavelist) //ywave = ywave[1,(strlen(ywave)-2)] //uncomment this line if single quotes needed //Wave MPStruct.yWave = $StringFromList(i, ywavelist) // works if no quotes around wave Wave MPStruct.yWave = $ywave //apply constraints if any were found if(strlen(newcons)!=0) //Print newcons Make/N=1/O/T fittingconstraints fittingconstraints=newcons Wave/T MPStruct.Constraints = fittingconstraints endif //print which point is which wave from the top graph string messag="Point " + num2str((i)) + " wave " + ywave rmv=ywave ywave="'"+ywave+"'" Print messag // just in case the new wave has a different number of points MPStruct.XPointRangeEnd = numpnts(MPStruct.yWave)-1 err = MPF2_DoMPFit(MPStruct, saveDF+BatchDFName+":") if (err) // error return from MPF2_DoMPFit generally indicates // a programmer error DoAlert 0, "Error calling MPF2_DoMPFit: "+num2str(err) return err endif if (MPStruct.fitQuitReason == 2) // if the user aborts a fit, we assume that the whole process // should be aborted DoAlert 0, "User aborted batch fit" return -1 endif if (MPStruct.fitError) // Something went wrong with the current fit, and it // failed to converge. We note this fact to the user via // an alert, then move on to the next one. You may wish // to do something more sophisticated than this. // Avoid a long line by concatenating the message // in small pieces String alertMsg = "Error doing fit to " alertMsg += StringFromList(i, ywavelist)+": " alertMsg += num2str(MPStruct.fitError)+ " | " alertMsg += MPStruct.fitErrorMsg alertMsg += "; continuing with next fit." Print alertMsg wasalert=1 //DoAlert 0, alertMsg endif remove1 = "fit_"+rmv remove2 = "Res_"+rmv RemoveFromGraph $remove1,$remove2 endfor if(wasalert==1) alertMsg="Error detected, check history window." DoAlert 0,alertMsg endif ////customize remaining code depending on what peak paramaters you're interested in///// SetDataFolder saveDF Make/O/N=(nfits) extractedparam variable param for (i = 0; i < nfits; i += 1) // Get desired peak data by looping through folders BatchDFName = saveDF+"BatchPeakFit_"+num2str(i) SetDataFolder BatchDFName wave peakvars='Peak 0 Coefs' //wave peak1vars='Peak 1 Coefs' param=peakvars[0] SetDataFolder saveDF extractedparam[i]=param endfor Display extractedparam end