#pragma rtGlobals=3 // Use modern global access method and strict wave access. //// a bunch of test functions to try to automate data reduction // // OCT 2014 // // // // // // 1) start with gathering some basic information // AskForConfigurations() // // 2) then sort the configurations from low Q to high Q // SortConfigs() // // // 3) fill in the other files for the configuration. Currently a manual operation // // // 4) from the matrix of file numbers and some default choices, // save (n) configurations as config_n, to match row (n) of the matrix // // -- panel must be open // ReductionProtocolPanel() // FillInProtocol(index) -- need to set the ABS parameters before saving // --save the protocol (I pick the name) // Auto_SaveProtocol(index) // // ---- Run as: // Auto_FillSaveProtocols() // // 5) calculate all of the transmissions // -- start by opening the Transmission panel // -- list all of the files // then: // - for each empty beam file: // setXYBox (writes out box and counts to the file) // check if there are transmission measurements at this config (SDD && lam) // if so, this is the empty beam // so try to guess the scattering files and calc transmission // // go get another transmission at this configuration // // go get another empty beam file // // - at the end, search through all of the scattering files. look at // the S_Transmission wave for: T=1 (be sure these are blocked beam) and search for // T > 1, as these are wrong. // // -- may need user intervention if things go wrong. // // ---- to Run: // Auto_Transmission() // then // ListFiles_TransUnity() // ListFiles_TransTooLarge() // // // // 6) reduce all of the data at each configuration // // - open the MRED panel // - for each configuration // - pick the configuration // - get the SDD, and the list of scattering files // - set the list and reduce all files // - when saving the files, can I enforce a prefix C0_, C1_etc. on the files? // // ---- Run As: // Auto_MRED() // // // 7) figure out how to combine the data // // -- get listings of what I think I should be combining - this is saved from the transmission assignment // (default trim of data points for overlap, no rescaling) // // // -- look for the beamstop shadow at the beginning of the file // -- trim a default 5? 10? from the high Q end // // -- then just concatentate and sort. // // ---- Run As: // Auto_NSORT(tableOnly=1) to allow editing of the list of files and names // Auto_NSORT(tableOnly=0) does the combination // // /////////////////////////////////// // // TODO // // // --properly generate the help file (reformat), link it to the help button, and get it into the SANS reduction // help file. // -- make a better entry point from the Macros menu, and the SANS menu // // -- may want to allow for some user feedback in NSORT in selecting the exact points to keep // this is still a step where human judgement is rather useful. // -- make it easier to edit the NSORT table. may be helpful to see the sample labels. This was // clearly the case with 4 configs (one lens) since they fell in different piles during transmission // calculation, so they did not appear together for combining files. // // ///////// A simple panel so I don't have to run the commands // // --there is nothing to initialize // Proc Auto_Reduce_Panel() : Panel PauseUpdate; Silent 1 // building window... NewPanel /W=(1323,334,1574,663) /K=1 DoWindow/C AutoReduce ModifyPanel cbRGB=(26205,52428,1) SetDrawLayer UserBack SetDrawEnv fname= "Monaco",fstyle= 1 DrawText 7,28,"(1)" SetDrawEnv fname= "Monaco",fstyle= 1 DrawText 7,68,"(2)" SetDrawEnv fname= "Monaco",fstyle= 1 DrawText 7,108,"(3)" SetDrawEnv fname= "Monaco",fstyle= 1 DrawText 7,148,"(4)" SetDrawEnv fname= "Monaco",fstyle= 1 DrawText 27,174,"(4.1)" SetDrawEnv fname= "Monaco",fstyle= 1 DrawText 27,193,"(4.2)" SetDrawEnv fname= "Monaco",fstyle= 1 DrawText 7,228,"(5)" SetDrawEnv fname= "Monaco",fstyle= 1 DrawText 7,269,"(6)" SetDrawEnv fname= "Monaco",fstyle= 1 DrawText 27,295,"(6.1)" SetDrawEnv fstyle= 1 SetDrawEnv save Button button0,pos={35,10},size={150,20},proc=AutoAskForConfigButton,title="Ask for Config" Button button1,pos={35,50},size={150,20},proc=AutoSortConfigButton,title="Fill Config" Button button2,pos={35,90},size={150,20},proc=AutoFillProtocolButton,title="Fill Protocols" Button button3,pos={35,130},size={150,20},proc=AutoCalcTransButton,title="Calc Transmission" Button button4,pos={70,155},size={150,20},proc=AutoFindUnityTransButton,title="Unity Transm" Button button5,pos={70,175},size={150,20},proc=AutoFindLargeTransButton,title="Large Transm" Button button6,pos={35,210},size={150,20},proc=AutoReduceEverythingButton,title="Reduce Everything" Button button7,pos={35,250},size={150,20},proc=AutoNSORTTableButton,title="NSORT Table" Button button8,pos={70,275},size={150,20},proc=AutoNSORTEverythingButton,title="NSORT Everything" Button button9,pos={220,5},size={20,20},proc=AutoReduceHelpButton,title="?" EndMacro // make the matrix a numeric wave. // assume that the DIV file can be found from the file list as ".DIV" // and the MASK file can be found as ".MASK" (if not, ask for help) // // Function AskForConfigurations() Variable num Prompt num,"How many configurations were used?" DoPrompt "Enter the number of configs",num Make/O/D/N=(num,5) Configs WAVE w = Configs // set the column labels SetDimLabel 1,0,'SDD',w SetDimLabel 1,1,'Wavelength',w SetDimLabel 1,2,'BKG',w SetDimLabel 1,3,'EMP',w SetDimLabel 1,4,'Empty Beam',w Edit w.ld ModifyTable width(Configs.l)=20 DoAlert 0, "Fill in the SDD and wavelength for each configuration" return(0) end // // Function SortConfigs() WAVE w = Configs Variable num = DimSize(w, 0 ) Make/O/D/N=(num) wave0,wave1 wave0 = w[p][%'SDD'] wave1 = w[p][%'Wavelength'] Sort/R {wave0,wave1},wave0,wave1 w[][%'SDD'] = wave0[p] w[][%'Wavelength'] = wave1[p] KillWaves wave0,wave1 // now try to find the configurations as best as I can // loop over the rows Variable ii for(ii=0;ii 1, as these are wrong. // // -- may need user intervention if things go wrong. // Function Auto_Transmission() //open the panel Execute "CalcTrans()" //list the files - this is equivalent to pressing the button Execute "BuildFileTables()" // get all of the empty beam files (from the initial setup) WAVE configs = root:configs // declare all of the necessary TransTable files so that I can check, and do assignments WAVE/T TransFiles = $"root:myGlobals:TransHeaderInfo:T_Filenames" WAVE/T EmpAssignments = $"root:myGlobals:TransHeaderInfo:T_EMP_Filenames" Variable nEmpFiles,nTransFiles,ii,jj,empNum,empLam,empSDD,testNum,numChars String empName="",pathStr,testName PathInfo catPathName pathStr = S_path numChars = 8 //for the trans guess nEmpFiles = DimSize(configs, 0) nTransFiles = numpnts(TransFiles) // this is only to save the "matches" for use later in combining the reduced data SVAR gMatchSamStr = root:myGlobals:TransHeaderInfo:gMatchingSampleFiles Make/O/T/N=(nTransFiles) savedMatches savedMatches = "" for(ii=0;ii1 // let the user know that these are incorrect and need to be repaired Function ListFiles_TransTooLarge() WAVE/T S_FileNames = $"root:myGlobals:TransHeaderInfo:S_FileNames" WAVE/T S_Labels = $"root:myGlobals:TransHeaderInfo:S_Labels" WAVE S_Transmission = $"root:myGlobals:TransHeaderInfo:S_Transmission" Variable num,ii num = numpnts(S_Transmission) for(ii=0;ii 1) printf "File %s = %s has T=1. This is NOT OK!\r",S_FileNames[ii],S_Labels[ii] endif endfor return(0) End // TOO -- rewrite this correctly, using a proper "fuzzy" match for the wavelength, // adding items that do not match to a growing list of "different" wavelengths to check against // -- use 1% tol, not 5% // // use the function "CloseEnough()" // Function HowManyWavelengths() Variable num WAVE lam = root:myGlobals:CatVSHeaderInfo:Lambda Variable ii,npt,tol npt = numpnts(lam) tol = 1.01 // 1% Duplicate/O lam,tmp sort tmp,tmp num = 1 Make/O/D/N=1 numLam numLam[0] = tmp[0] for(ii=1;ii tol*numLam[num-1]) InsertPoints num, 1, numLam numLam[num] = tmp[ii] num += 1 endif endfor Printf "Found %d different wavelengths\r",num return(num) End // somewhat tricky -- look for combinations of different // SDD and wavelength. -- if lenses are used, often they are both at the // same SDD, but at different wavelengths -- for lenses Function HowManyConfigurations() Variable num WAVE SDD = root:myGlobals:CatVSHeaderInfo:SDD WAVE lam = root:myGlobals:CatVSHeaderInfo:Lambda return(num) End ///// // // Function Auto_MRED() // open the panel Execute "ReduceMultipleFiles()" WAVE w = root:Configs SVAR protoList = root:myGlobals:MRED:gMRProtoList Variable num,ii,sdd,item String str num = DimSize(w,0) // protocols are named "config_n" for(ii=0;ii tol) //just get the integer portion of the difference - very coarse comparison DeletePoints ii, 1, filenames,suffix,labels,sdd,runnum,isTrans endif ii-=1 while(ii>=0) // now sort Sort RunNum, filenames,suffix,labels,sdd,runnum,isTrans return(0) End // does no scaling, only the basic (default) trim of the ends, concatenate, sort, and save // // Function Auto_NSORT(tableOnly) variable tableOnly Wave/T SavedMatches = root:savedMatches if(tableOnly) Duplicate/T/O savedMatches saveName saveName = "" Endif DoWindow/F Auto_NSORT_Table if(V_flag == 0) Edit/N=Auto_NSORT_Table savedMatches,saveName endif Variable num,ii,numitems,numChars,jj,nEnd String item,path,tmpStr,cmd,folderStr // number of characters in the file label to keep for the file name numChars = 16 // number of points to trim from end nEnd = 10 PathInfo catPathName path = S_Path if(tableOnly) num=numpnts(savedMatches) // guess at the file names for(ii=0;ii 4) //it's USANS put -dQv back in the last 3 columns NVAR/Z dQv = USANS_dQv if(NVAR_Exists(dQv) == 0) SetDataFolder root: Abort "It's USANS data, and I don't know what the slit height is." endif sigQ = -dQv qbar = -dQv fs = -dQv else //it's SANS sigQ = resw[p][0] qbar = resw[p][1] fs = resw[p][2] endif PathInfo catPathName fullPath = S_Path + folderStr Open refnum as fullpath fprintf refnum,"Combined data written from folder %s on %s\r\n",folderStr,(date()+" "+time()) formatStr = "%15.4g %15.4g %15.4g %15.4g %15.4g %15.4g\r\n" fprintf refnum, "The 6 columns are | Q (1/A) | I(Q) (1/cm) | std. dev. I(Q) (1/cm) | sigmaQ | meanQ | ShadowFactor|\r\n" wfprintf refnum,formatStr,qw,iw,sw,sigQ,qbar,fs Close refnum KillWaves/Z sigQ,qbar,fs SetDataFolder root: return(0) End // concatentate folder1 to the end of folder2 // // this seems like a lot of extra work to do something so simple... // Function Auto_Concatenate(folder1,folder2) String folder1,folder2 Concatenate/NP {$("root:"+folder1+":"+folder1+"_q"),$("root:"+folder2+":"+folder2+"_q")},tmp_q Concatenate/NP {$("root:"+folder1+":"+folder1+"_i"),$("root:"+folder2+":"+folder2+"_i")},tmp_i Concatenate/NP {$("root:"+folder1+":"+folder1+"_s"),$("root:"+folder2+":"+folder2+"_s")},tmp_s Concatenate/NP {$("root:"+folder1+":res0"),$("root:"+folder2+":res0")},tmp_res0 Concatenate/NP {$("root:"+folder1+":res1"),$("root:"+folder2+":res1")},tmp_res1 Concatenate/NP {$("root:"+folder1+":res2"),$("root:"+folder2+":res2")},tmp_res2 Concatenate/NP {$("root:"+folder1+":res3"),$("root:"+folder2+":res3")},tmp_res3 // move the concatenated result into the destination folder (killing the old stuff first) KillWaves/Z $("root:"+folder2+":"+folder2+"_q") KillWaves/Z $("root:"+folder2+":"+folder2+"_i") KillWaves/Z $("root:"+folder2+":"+folder2+"_s") KillWaves/Z $("root:"+folder2+":res0") KillWaves/Z $("root:"+folder2+":res1") KillWaves/Z $("root:"+folder2+":res2") KillWaves/Z $("root:"+folder2+":res3") Duplicate/O tmp_q $("root:"+folder2+":"+folder2+"_q") Duplicate/O tmp_i $("root:"+folder2+":"+folder2+"_i") Duplicate/O tmp_s $("root:"+folder2+":"+folder2+"_s") Duplicate/O tmp_res0 $("root:"+folder2+":res0") Duplicate/O tmp_res1 $("root:"+folder2+":res1") Duplicate/O tmp_res2 $("root:"+folder2+":res2") Duplicate/O tmp_res3 $("root:"+folder2+":res3") KillWaves/Z tmp_q,tmp_i,tmp_s,tmp_res0,tmp_res1,tmp_res2,tmp_res3 return(0) End Function Auto_Sort(folderStr) String folderStr if(DataFolderExists("root:"+folderStr) == 0) return(0) endif SetDataFolder $("root:"+folderStr) Wave qw = $(folderStr + "_q") Wave iw = $(folderStr + "_i") Wave sw = $(folderStr + "_s") Wave res0 = res0 Wave res1 = res1 Wave res2 = res2 Wave res3 = res3 // sort the waves Sort qw, qw,iw,sw,res0,res1,res2,res3 // restore the res wave KillWaves/Z $(folderStr+"_res") Make/O/D/N=(numpnts(qw),4) $(folderStr+"_res") WAVE resWave = $(folderStr+"_res") //Put resolution contents back reswave[][0] = res0[p] reswave[][1] = res1[p] reswave[][2] = res2[p] reswave[][3] = res3[p] SetDataFolder root: return(0) End // trims the beamstop out (based on shadow) // trims num from the highQ end // splits the res wave into individual waves in anticipation of concatenation // Function Auto_TrimData(folderStr,nEnd) String folderStr Variable nEnd if(DataFolderExists("root:"+folderStr) == 0) return(0) endif SetDataFolder $("root:"+folderStr) Wave qw = $(folderStr + "_q") Wave iw = $(folderStr + "_i") Wave sw = $(folderStr + "_s") Wave res = $(folderStr + "_res") variable num,ii num=numpnts(qw) //Break out resolution wave into separate waves Make/O/D/N=(num) res0 = res[p][0] // sigQ Make/O/D/N=(num) res1 = res[p][1] // qBar Make/O/D/N=(num) res2 = res[p][2] // fshad Make/O/D/N=(num) res3 = res[p][3] // qvals // trim off the last nEnd points from everything DeletePoints num-nEnd,nEnd, qw,iw,sw,res0,res1,res2,res3 // delete all points where the shadow is < 0.98 num=numpnts(qw) for(ii=0;ii