#pragma rtGlobals=1 // Use modern global access method. #pragma IgorVersion=6.1 // **** search for TODO to find items still to be fixed in other procedures ********** // TODO: // x- on the decay panel. need to be able to manually enter a date that is to or an offset // number of hours. currently it takes the first file as t=0, which is often not correct // // Polarized Beam Reduction Procedures // // // input panels to set and calculate polarization parameters necessary for the // matrix corrections to the cross sections // // -1- Fundamental Cell Parameters -- these are constants, generally not editable. (this file) // -2- Decay Parameters -- these are fitted values based on transmission mearurements (this file) // -3- Flipper Panel is in its own procedure (Pol_FlipperPanel.ipf) // -4- PolCor_Panel is in Pol_PolarizationCorrection.ipf // // // Driven by 4 panels to get the necessary information from the users // -1- Fundamental cell parameters: root:Packages:NIST:Polarization:Cells // - default cell parameters are loaded. More cell definitions can be added as more cells are used // - changes are saved per experiment // - important parameters are held in global key=value strings gCell_ // - cell names and parameters are used by the 2nd panel for calculation of the Decay constant // // -2- Decay Constant Panel // - decay constant determined for each cell. // - popping the cell name makes 2 waves, Decay_ and DecayCalc_ // - Decay_ is the wave presented in the table. Specified transmission run numbers are entered // and "Calc Sel Row" does the calculation of mu and Pcell (for all rows, actually) // - DimLabels are used for the arrays to make the column identity more readable than simply an index // - time=0 is taken from the first file // - Calculations are based on the count rate of the file, corrected for monitor and attenuation // - alerts are posted for files in any row that are not at the same attenuation or SDD // - if "include" column is == 1, that row will be included in the fit of the decay data // - excluded points are plotted in red // - results of the fit are printed on the panel, and written to the wave note of the Decay_ wave // (not DecayCalc_) for use in the next panel // - manual entry of all of the parameters in the wave note is allowed. // // // -3- Flipper Panel (not in this procedure - in Pol_FlipperPanel.ipf) // - calculates the flipper and supermirror efficiencies for a given "condition" // - this "condition" may have contributions from multiple cells // - start by entering a condition name // - Waves Cond_ and CondCalc_, and CondCell are created // - DimLabels are used for the arrays to make the column identity more readable than simply an index // - Enter the name of the cell in the first column (the cell must be defined and decay calculated) // - enter transmission run numbers as specified in the table // - Do Average will calculate the Psm and PsmPfl values (and errors) and average if more than // one row of data is present (and included) // - results are printed on the panel, and written to the wave note of Cond_ // - results are used in the calculation of the polarization matrix // - (the cell name is not entered using a contextual menu, since this is difficult for a subwindow) // - (the wave note no longer needs the cell name) // // -4- PolCor_Panel (not in this procedure - in Pol_PolarizationCorrection.ipf) // - gets all of the parameters from the user to do the polariztion correction, then the "normal" SANS reduction // - up to 10 files can be added together for each of the different spin states (more than this??) // - one polarization condition is set for everything with the popup @ the top // - two-column list boxes for each state hold the run number and the cell name // - the same list boxes are duplicated (hidden) for the SAM/EMP/BGD tabs as needed // - on loading of the data, the 2-letter spin state is tagged onto the loaded waves (all of them) // - displayed data is simply re-pointed to the desired data // - on loading, the raw files are added together as ususal, normalized to monitor counts. Then each contribution // of the file to the polarization matrix is added (scaling each by mon/1e8) // - loaded data and PolMatrix are stored in the ususal SAM, EMP, BGD folders. // - Polarization correction is done with one click (one per tab). "_pc" tags are added to the resulting names, // and copies of all of the associated waves are again copied (wasteful), but makes switching display very easy // - Once all of the polarization correction is done, then the UU_pc (etc.) data can be reduced as usual (xx_pc = 4 passes) // - protocol is built as ususal, from this panel only (since the SAM, EMP, and BGD need to be switched, rather than loaded // - protocols can be saved/recalled. // - reduction will always ask for a protocol rather than using what's on the panel. // - closing the panel will save the state (except the protocol). NOT initializing when re-opening will restore the // state of the entered runs and the popups of conditions. // // // // // for the menu Menu "Macros" "Flipping Ratio",ShowFlippingRatioPanel() "1 Fundamental Cell Parameters",ShowCellParamPanel() "2 Cell Decay",ShowCellDecayPanel() "3 Flipper States",ShowFlipperPanel() "4 Polarization Correction",ShowPolCorSetup() "-" Submenu "Save State of..." "Fundamental Cell Parameters",SaveCellParameterTable() "Cell Decay Panel",SaveCellDecayTable() "Flipper Condition Panel",SaveFlipperTable() "Polarization Correction Panel",SavePolCorPanelState() End Submenu "Restore State of..." "Fundamental Cell Parameters",RestoreCellParameterTable() "Cell Decay Panel",RestoreCellDecayTable() "Flipper Condition Panel",RestoreFlipperTable() "Polarization Correction Panel",RestorePolCorPanelState() End End // // Panel -1- // // Fundamental He cell parameters. Most of these are pre-defined, so that they are supplied as a // static table, only edited as parameters are refined. // // work with this as kwString // cell=nameStr // lambda=num // Te=num // err_Te=num // mu=num // err_mu=num // // // for this panel, the cell parameters are stored as kw strings // all of the strings start w/ "gCell_" // Proc ShowCellParamPanel() // init folders // ASK before initializing cell constants // open the panel DoWindow/F CellParamPanel if(V_flag == 0) InitPolarizationFolders() DoAlert 1,"Do you want to use default parameters?" if(V_flag == 1) InitPolarizationGlobals() endif Make_HeCell_ParamWaves() DrawCellParamPanel() endif // be sure that the panel is onscreen DoIgorMenu "Control","Retrieve Window" end // setup the data folder, etc // // Function InitPolarizationFolders() NewDataFolder/O root:Packages:NIST:Polarization NewDataFolder/O root:Packages:NIST:Polarization:Cells //holds the cell constants and waves SetDataFolder root: return(0) End // // add more cells here as they are defined, // // first clear out the list, then rebuild it // Function InitPolarizationGlobals() SetDataFolder root:Packages:NIST:Polarization:Cells String listStr=StringList("gCell_*",";"),item Variable ii,num=ItemsInList(listStr,";") for(ii=0;ii numRows) DoAlert 0,"The DecayCalc_ is larger than displayed. Seek help." err = 1 return(err) else diff = numRows - ncalc InsertPoints/M=0 ncalc, diff, calc endif endif // GetSelection table, DecayPanel#T0, 1 // selRow = V_startRow Variable sum_muP, err_avg_muP, sum_Po, err_avg_Po, avg_muP, avg_Po, overrideT0 sum_muP = 0 sum_Po = 0 err_avg_muP = 0 err_avg_Po = 0 ControlInfo/W=DecayPanel check0 overrideT0 = V_Value for(selRow=0;selRow y = y0 + A*exp(-Bx) // W_coef[0] = y0 should be close to zero (or fixed at zero) // W_coef[1] = A should be close to the initial muP value // W_coef[2] = B is 1/Gamma // WAVE W_coef=W_coef WAVE W_sigma=W_sigma Variable gamma_val,err_gamma,muPo, err_muPo, Po, err_Po String noteStr="" SVAR gCellKW = $("root:Packages:NIST:Polarization:Cells:gCell_"+cellStr) SVAR gGamma = root:Packages:NIST:Polarization:Cells:gGamma SVAR gMuPo = root:Packages:NIST:Polarization:Cells:gMuPo SVAR gPo = root:Packages:NIST:Polarization:Cells:gPo Variable mu,err_mu if(plot_P == 1) Po = fitCoef[1] err_Po = W_sigma[1] // calc muPo inline here, since the Calc_muP function uses a different method // cell constants mu = NumberByKey("mu", gCellKW, "=", ",", 0) err_mu = NumberByKey("err_mu", gCellKW, "=", ",", 0) muPo = Po*mu err_muPo = muPo*sqrt( (err_Po/Po)^2 + (err_mu/mu)^2 ) else muPo = fitCoef[1] err_muPo = W_sigma[1] Po = Calc_Po(gCellKW,muPo,err_muPo,err_Po) endif // if exp_XOffset used gamma_val = fitCoef[2] err_Gamma = W_sigma[2] // calculating the error using exp is the inverse of coef[2]: // gamma_val = 1/fitCoef[2] // err_gamma = W_sigma[2]/(fitCoef[2])^2 // for the wave note noteStr = note(decay) noteStr = ReplaceNumberByKey("muP", noteStr, MuPo ,"=", ",", 0) noteStr = ReplaceNumberByKey("P0", noteStr, Po ,"=", ",", 0) noteStr = ReplaceNumberByKey("err_muP", noteStr, err_muPo ,"=", ",", 0) noteStr = ReplaceNumberByKey("err_P0", noteStr, err_Po ,"=", ",", 0) noteStr = ReplaceNumberByKey("gamma", noteStr, gamma_val ,"=", ",", 0) noteStr = ReplaceNumberByKey("err_gamma", noteStr, err_gamma ,"=", ",", 0) // replace the string Note/K decay Note decay, noteStr // for the panel display sprintf gMuPo, "%g +/- %g",muPo,err_muPo sprintf gPo, "%g +/- %g",Po,err_Po sprintf gGamma, "%g +/- %g",gamma_val,err_gamma SetDataFolder root: break case -1: // control being killed break endswitch return 0 End // clear just the row // Function ClearDecayWavesRowButton(ba) : ButtonControl STRUCT WMButtonAction &ba String popStr="" Variable selRow switch( ba.eventCode ) case 2: // mouse up // click code here DoAlert 1,"Clear the selected row?" if(V_flag !=1) return(0) endif SetDataFolder root:Packages:NIST:Polarization:Cells ControlInfo/W=DecayPanel popup_0 popStr = S_Value Wave decay = $("Decay_"+popStr) Wave calc = $("DecayCalc_"+popStr) // Delete just those points GetSelection table, DecayPanel#T0, 1 selRow = V_startRow DeletePoints selRow,1,decay,calc // clear the graph and the results SVAR gMuPo = root:Packages:NIST:Polarization:Cells:gMuPo SVAR gPo = root:Packages:NIST:Polarization:Cells:gPo SVAR gGamma = root:Packages:NIST:Polarization:Cells:gGamma SVAR gT0 = root:Packages:NIST:Polarization:Cells:gT0 gMuPo = "0" gPo = "0" gGamma = "0" gT0 = "recalculate" SetDataFolder root: break case -1: // control being killed break endswitch return 0 End // for this, do I want to clear everything, or just a selected row?? // // Function ClearDecayWavesButton(ba) : ButtonControl STRUCT WMButtonAction &ba String popStr="" switch( ba.eventCode ) case 2: // mouse up // click code here DoAlert 1,"Clear all of the decay waves for the selected cell?" if(V_flag !=1) return(0) endif SetDataFolder root:Packages:NIST:Polarization:Cells ControlInfo/W=DecayPanel popup_0 popStr = S_Value Wave decay = $("Decay_"+popStr) Wave calc = $("DecayCalc_"+popStr) // re-initialize the decay waves, so it appears as a blank, initialized table MakeDecayResultWaves(popStr) decay = 0 calc = 0 // clear the graph and the results? SVAR gMuPo = root:Packages:NIST:Polarization:Cells:gMuPo SVAR gPo = root:Packages:NIST:Polarization:Cells:gPo SVAR gGamma = root:Packages:NIST:Polarization:Cells:gGamma SVAR gT0 = root:Packages:NIST:Polarization:Cells:gT0 gMuPo = "0" gPo = "0" gGamma = "0" gT0 = "recalculate" SetDataFolder root: break case -1: // control being killed break endswitch return 0 End Function DecayHelpParButtonProc(ba) : ButtonControl STRUCT WMButtonAction &ba switch( ba.eventCode ) case 2: // mouse up // click code here DisplayHelpTopic/Z/K=1 "Cell Decay Constant Panel" if(V_flag !=0) DoAlert 0,"The Cell Decay Help file could not be found" endif break case -1: // control being killed break endswitch return 0 End // E=-5 is a PNG, =8 is PDF // there are other options to do EPS, embed fonts, etc. // Function WindowSnapshotButton(ba) : ButtonControl STRUCT WMButtonAction &ba switch( ba.eventCode ) case 2: // mouse up // click code here SavePICT /E=-5/SNAP=1 break case -1: // control being killed break endswitch return 0 End Function SaveDecayPanelButton(ba) : ButtonControl STRUCT WMButtonAction &ba switch( ba.eventCode ) case 2: // mouse up // click code here SaveCellDecayTable() break case -1: // control being killed break endswitch return 0 End Function RestoreDecayPanelButton(ba) : ButtonControl STRUCT WMButtonAction &ba switch( ba.eventCode ) case 2: // mouse up // click code here RestoreCellDecayTable() break case -1: // control being killed break endswitch return 0 End // null condition is not right. if the loop fails, then the // retStr will be ";;;;", not zero length. What's the proper test? // Does it matter? the list of default gCell_sss should already be there. // Function/S D_CellNameList() String retStr="",listStr,item Variable num,ii SetDataFolder root:Packages:NIST:Polarization:Cells // get a list of the cell strings listStr=StringList("gCell_*",";") num=ItemsInList(listStr,";") // print listStr // parse the strings to fill the table for(ii=0;ii tol) || (abs(sdd2 - sdd3) > tol) || (abs(sdd1 - sdd3) > tol) ) DoAlert 0,"Files in row "+num2str(selRow)+" are not all at the same detector distance" err = 1 endif if( (atten1 != atten2) || (atten2 != atten3) || (atten1 != atten3) ) DoAlert 0,"Files in row "+num2str(selRow)+" are not all collected with the same attenuation. Just so you know." err = 0 endif return(err) end //////////////////////////////////////////// // // a simple little panel to calculate the flipping ratio. // 3 input files, calculates the flipping ratio, then simply reports the result // Proc ShowFlippingRatioPanel() // init folders // ASK before initializing cell constants // open the panel DoWindow/F FlipRatio if(V_flag == 0) FlippingRatioPanel() endif end Proc FlippingRatioPanel() PauseUpdate; Silent 1 // building window... NewPanel /W=(455,44,805,245)/N=FlipRatio/K=1 as "Flipping Ratio" ModifyPanel cbRGB=(65535,49157,16385) // ShowTools/A SetDrawLayer UserBack GroupBox group0,pos={12,9},size={307,123},title="Flipping Ratio" SetVariable setvar0,pos={23,35},size={150,15},title="UU or DD File" SetVariable setvar0,limits={-inf,inf,0},value= _NUM:0 SetVariable setvar1,pos={23,58},size={150,15},title="UD or DU File" SetVariable setvar1,limits={-inf,inf,0},value= _NUM:0 SetVariable setvar2,pos={23,82},size={150,15},title="Blocked beam" SetVariable setvar2,limits={-inf,inf,0},value= _NUM:0 SetVariable setvar3,pos={23,104},size={240,16},title="Flipping Ratio",fSize=12 SetVariable setvar3,fStyle=1,limits={-inf,inf,0},value= _STR:"enter the run numbers" Button button0,pos={214,55},size={90,20},proc=CalcFlippingRatioButtonProc,title="Calculate" EndMacro Function CalcFlippingRatioButtonProc(ba) : ButtonControl STRUCT WMButtonAction &ba Variable num0,num1,num2,cr0,cr1,cr2,err_cr0,err_cr1,err_cr2 Variable tmp0,tmp1,tmp2,flip,flip_err String str="" switch( ba.eventCode ) case 2: // mouse up // click code here ControlInfo setvar0 num0 = V_Value ControlInfo setvar1 num1 = V_Value ControlInfo setvar2 num2 = V_Value cr0 = TotalCR_FromRun(num0,err_cr0,0) //last zero means yes, normalize everything to zero atten cr1 = TotalCR_FromRun(num1,err_cr1,0) cr2 = TotalCR_FromRun(num2,err_cr2,0) // this one is the blocked beam flip = (cr0-cr2)/(cr1-cr2) tmp0 = 1/(cr1-cr2) tmp1 = -1*flip/(cr1-cr2) tmp2 = flip/(cr1-cr2) - 1/(cr1-cr2) flip_err = tmp0^2*err_cr0^2 + tmp1^2*err_cr1^2 +tmp2^2*err_cr2^2 flip_err = sqrt(flip_err) Printf "Flipping ratio = %g +/- %g (%g%)\r",flip,flip_err,flip_err/flip*100 str = num2str(flip)+" +/- "+num2str(flip_err) SetVariable setvar3,value=_STR:str break case -1: // control being killed break endswitch return 0 End /////////////////////////////////////