optical-znpc / data /igor /procedures /alphaModeling.ipf
hduvallh's picture
feat: package ZnPc clustering demo assets under data/
a3c3dc0 verified
Raw History Blame Contribute Delete
181 kB
#pragma TextEncoding = "UTF-8"
#pragma rtGlobals=3 // Use modern global access method and strict wave access.
Function simDFT(tval,ovpVal,IPwave,mol,alpha,i0,phi,expSpecName,expEnergyName,expFolderPath,fit,rigidShift,thetaList,anchorStep1,anchorStep2,anchorExp1,anchorExp2,stepWid1,stepWid2,stepE1,stepE2,[d,holdAmps,holdWidths,holdPos,NEXAFStype,stepShift,startPre,endPre,startPost,endPost,refine,maskEnergy1,maskEnergy2,pkToRefine,refpw,holdmodTheta])
Variable tval
Variable ovpVal
Wave IPwave
String mol
Variable alpha
Variable i0
Variable phi
String expSpecName //Base name of spectra
String expEnergyName //Base name of experimental energy waves
String expFolderPath
String fit //If yes then try to fit the data, else just model it
Variable rigidShift
Variable stepShift
Variable d
String thetaList //Semicolon separated list of theta values to simulate/fit
Variable holdAmps
Variable holdWidths
Variable holdPos
String NEXAFStype
Variable startPre //At what energy should the preedge start to be defined?
Variable endPre //At what energy should the preedge stop to be defined?
Variable startPost //At what energy should the postedge start to be defined?
Variable endPost //At what energy should the postedge stop to be defined?
Variable anchorStep1,anchorStep2
Variable anchorExp1,anchorExp2
Variable stepWid1,stepWid2,stepE1,stepE2
Variable refine
Variable maskEnergy1
Variable maskEnergy2
Variable pkToRefine
Wave refpw
Variable holdmodTheta
// ======================/ Define defaults/=================================
if(ParamIsDefault(holdAmps))
holdAmps = 0
endif
if(ParamIsDefault(holdWidths))
holdWidths = 1
endif
if(ParamIsDefault(holdPos))
holdPos = 1
endif
if(ParamIsDefault(NEXAFStype))
NEXAFStype = ""
endif
if(ParamIsDefault(refine))
refine = 0
endif
if(ParamIsDefault(holdmodTheta))
holdmodTheta = 1
endif
Variable openParams = 4 - holdAmps - holdWidths - holdPos - holdmodTheta
Variable timerStart = startMSTimer
if(!refine)
Wave pw2d = getParams(tval,ovpVal)
makeTensor(pw2d)
normalizeTensor()
prepSimDFTfit(expSpecName,expEnergyName,mol,IPwave,expFolderPath,anchorStep1,anchorStep2,stepWid1,stepWid2,stepE1,stepE2,stepShift = rigidShift)
make1DparamWave(IPwave,pw2d,alpha,i0,phi,rigidShift = rigidShift)
endif
Wave pWave1D,paramNames,allExpSpec,allExpEnergy,allDFTSteps
Variable n = numpnts(allExpSpec),nSpec = ItemsInList(thetaList),i
if(!refine)
Duplicate/O pWave1D,pwCopy
else
Duplicate/O refpw,refitpWave2
endif
Wave valuesPolar = makePolarWave2(thetaList,n) //Make wave containing theta values
Wave pwAlpha = fitAlpha2(maskEnergy1,maskEnergy2,pWave1D,allExpEnergy,allExpSpec,nSpec,thetaList,alpha,i0,tval,ovpval,allDFTSteps)
pwAlpha[2] = alpha
Wave pwI0 = fitI0(maskEnergy1,maskEnergy2,pwAlpha,allExpEnergy,allExpSpec,valuesPolar,allDFTSteps,nSpec,tval,ovpval)//Fit i0
if(!refine)
Duplicate/O allExpSpec,res,results1,results2,results3,results4,results5,results6,results,weightWave
results = 0;res = 0
endif
Variable nPeaks = (numpnts(pWave1D) - 4 - pWave1D[0])/11
Variable pks2Fit = nPeaks
String H1 = makeHoldString(holdAmps,holdWidths,holdPos,pWave1D,holdModTheta,1,1)
Wave eps1 = makeEpsiltonWave(pWave1D,holdAmps,holdWidths,holdPos,holdModTheta,1,1)
Wave/T constraint1 = makeConstraintWave(holdAmps,holdWidths,holdPos,nPeaks,pWave1D,holdmodTheta,1,1)
//Trim the waves to be fit. Lower energies can be wonky
for(i=n-1;i>=0;i-=1)
Variable cEn = allExpEnergy[i]
if(cEn < 279.9)
DeletePoints i,1,allExpEnergy,allExpSpec,allDFTSteps,res,results1,results2,results3,results4,results5,results6,results,weightWave,valuesPolar
endif
endfor
Wave allExpEnergy,allExpSpec,allDFTSteps,res,results1,results2,results3,results4,results,weightWave,valuesPolar
Variable npnts = numpnts(allExpSpec)
print " ╠═════════════ Refining To NEXAFS ══════════════╣ "
print " ╟───────────────────┬───────────┬───────────────╢ "
print " ║ PARAMS │ CHI SQR │ RED CHI SQR ║ "
print " ╟───────────────────┼───────────┼───────────────╢ "
if(StringMatch(fit,"yes"))
weightWave = 0.0622831*allExpSpec
Variable V_FitTol = 0.00001,V_FitError = 0
if(refine)
fitSinglePeak(refpw,pkToRefine,holdPos,holdWidths,holdAmps,holdmodTheta,tval,ovpVal,alpha,mol)
String newpwName = "refine_pwCopy_pk" + num2str(pkToRefine)
Wave refitpWave = $newpwName
Abort
else
// Refine Amp
// -----------------------------------------------------------------------
Duplicate/O pwI0, pwFit1
Make/O/N=6 rcs2,alphaFit,idFit,gf2,cs2
idFit[0] = 0;idFit[1] = 1;idFit[2] = 2;idFit[3] = 3;idFit[4] = 4;idFit[5] = 5
FuncFit/Q/H=H1/M=2 simDFTfit2,pwFit1, allExpSpec /X={allExpEnergy,valuesPolar,allDFTSteps} /R=res /E=eps1 /D=results1 /I=1 /W=weightWave
if(V_FitError)
V_chiSq = NaN
endif
Wave pwFit
NVAR redchiSqExpCl = root:redchiSqExpCl
NVAR chiSqExpCl = root:chiSqExpCl
chiSqExpCl = V_chisq
redchiSqExpCl = calcRedChiSq(allExpSpec,V_Chisq,nPeaks,1,0)
printf " ║ AMP │ %07.1f │ %05.3f ║ \r", V_chisq, redchiSqExpCl
print " ╟───────────────────┼───────────┼───────────────╢ "
rcs2[0] = redchiSqExpCl
alphaFit[0] = pwFit1[2]
cs2[0] = V_chisq
Wave M_Covar,W_Sigma,pwMolAdj
// Refine Amp & Theta
// -----------------------------------------------------------------------
Duplicate/O pwFit1, pwFit2
H1 = makeHoldString(0,1,1,pwFit2,0,1,2)
Wave eps2 = makeEpsiltonWave(pwFit2,0,1,1,0,1,2)
Wave/T constraint2 = makeConstraintWave(0,1,1,nPeaks,pwFit2,0,1,2)
V_FitTol = 0.00001;V_FitError = 0//;V_FitMaxIters=100
FuncFit/Q/H=H1/M=2 simDFTfit2,pwFit2, allExpSpec /X={allExpEnergy,valuesPolar,allDFTSteps} /R=res /E=eps2 /D=results2 /I=1 /W=weightWave
if(V_FitError)//If something in the fit fails, set V_chiSq to NaN for error handling
V_chiSq = NaN
endif
NVAR redchiSqExpCl = root:redchiSqExpCl
NVAR chiSqExpCl = root:chiSqExpCl
chiSqExpCl = V_chisq
redchiSqExpCl = calcRedChiSq(allExpSpec,V_Chisq,nPeaks,3,0)
printf " ║ AMP/θ │ %07.1f │ %05.3f ║ \r", V_chisq, redchiSqExpCl
print " ╟───────────────────┼───────────┼───────────────╢ "
rcs2[1] = redchiSqExpCl
alphaFit[1] = pwFit2[2]
cs2[1] = V_chisq
// Refine Amp, Theta & Energy
// -----------------------------------------------------------------------
Duplicate/O pwFit2, pwFit3
H1 = makeHoldString(0,1,0,pwFit3,0,1,3)
Wave eps3 = makeEpsiltonWave(pwFit3,0,1,0,0,1,3)
Wave/T constraint3 = makeConstraintWave(0,1,0,nPeaks,pwFit3,0,1,3)
V_FitTol = 0.00001;V_FitError = 0//;V_FitMaxIters=100
FuncFit/Q/H=H1/M=2 simDFTfit2,pwFit3, allExpSpec /X={allExpEnergy,valuesPolar,allDFTSteps} /R=res /E=eps3 /D=results3 /I=1 /W=weightWave
if(V_FitError)//If something in the fit fails, set V_chiSq to NaN for error handling
V_chiSq = NaN
endif
NVAR redchiSqExpCl = root:redchiSqExpCl
NVAR chiSqExpCl = root:chiSqExpCl
chiSqExpCl = V_chisq
redchiSqExpCl = calcRedChiSq(allExpSpec,V_Chisq,nPeaks,3,0)
printf " ║ AMP/θ/POS │ %07.1f │ %05.3f ║ \r", V_chisq, redchiSqExpCl
print " ╟───────────────────┼───────────┼───────────────╢ "
rcs2[2] = redchiSqExpCl
alphaFit[2] = pwFit3[2]
cs2[2] = V_chisq
// Refine All
// -----------------------------------------------------------------------
Duplicate/O pwFit3, pwFit4
H1 = makeHoldString(0,0,0,pwFit4,0,1,4)
Wave eps4 = makeEpsiltonWave(pwFit4,0,0,0,0,1,4)
Wave/T constraint4 = makeConstraintWave(0,0,0,nPeaks,pwFit4,0,1,4)
V_FitTol = 0.00001;V_FitError = 0//;V_FitMaxIters=100
FuncFit/Q/H=H1/M=2 simDFTfit2,pwFit4, allExpSpec /X={allExpEnergy,valuesPolar,allDFTSteps} /R=res /E=eps4 /D=results4 /I=1 /W=weightWave
if(V_FitError)//If something in the fit fails, set V_chiSq to NaN for error handling
V_chiSq = NaN
endif
NVAR redchiSqExpCl = root:redchiSqExpCl
NVAR chiSqExpCl = root:chiSqExpCl
chiSqExpCl = V_chisq
redchiSqExpCl = calcRedChiSq(allExpSpec,V_Chisq,nPeaks,4,0)
printf " ║ ALL │ %07.1f │ %05.3f ║ \r", V_chisq, redchiSqExpCl
print " ╟───────────────────┼───────────┼───────────────╢ "
rcs2[3] = redchiSqExpCl
alphaFit[3] = pwFit4[2]
cs2[3] = V_chisq
// Refine All
// -----------------------------------------------------------------------
Duplicate/O pwFit4, pwFit5
H1 = makeHoldString(0,0,0,pwFit5,0,0,5)
Wave eps5 = makeEpsiltonWave(pwFit5,0,0,0,0,0,5)
Wave/T constraint5 = makeConstraintWave(0,0,0,nPeaks,pwFit5,0,0,5)
V_FitTol = 0.00001;V_FitError = 0//;V_FitMaxIters=100
FuncFit/Q/H=H1/M=2 simDFTfit2,pwFit5, allExpSpec /X={allExpEnergy,valuesPolar,allDFTSteps} /R=res /E=eps5 /D=results5 /I=1 /W=weightWave
if(V_FitError)//If something in the fit fails, set V_chiSq to NaN for error handling
V_chiSq = NaN
endif
NVAR redchiSqExpCl = root:redchiSqExpCl
NVAR chiSqExpCl = root:chiSqExpCl
chiSqExpCl = V_chisq
redchiSqExpCl = calcRedChiSq(allExpSpec,V_Chisq,nPeaks,5,1)
printf " ║ ALL │ %07.1f │ %05.3f ║ \r", V_chisq, redchiSqExpCl
print " ╟───────────────────┼───────────┼───────────────╢ "
rcs2[4] = redchiSqExpCl
alphaFit[4] = pwFit5[2]
cs2[4] = V_chisq
// Refine All
// -----------------------------------------------------------------------
WaveStats/R=[0,4]/Q rcs2
if(V_minloc == 0)
Duplicate/O pwFit1,pwFit6
elseif(V_minloc == 1)
Duplicate/O pwFit2,pwFit6
elseif(V_minloc == 2)
Duplicate/O pwFit3,pwFit6
elseif(V_minloc == 3)
Duplicate/O pwFit4,pwFit6
elseif(V_minloc == 4)
Duplicate/O pwFit5,pwFit6
endif
H1 = makeHoldString(0,0,0,pwFit6,0,0,6)
Wave eps6 = makeEpsiltonWave(pwFit6,0,0,0,0,0,6)
Wave/T constraint6 = makeConstraintWave(0,0,0,nPeaks,pwFit6,0,0,6)
V_FitTol = 0.00001;V_FitError = 0
FuncFit/Q/H=H1/M=2 simDFTfit2,pwFit6, allExpSpec /X={allExpEnergy,valuesPolar,allDFTSteps} /R=res /E=eps6 /D=results6 /I=1 /W=weightWave
if(V_FitError)
V_chiSq = NaN
endif
NVAR redchiSqExpCl = root:redchiSqExpCl
NVAR chiSqExpCl = root:chiSqExpCl
chiSqExpCl = V_chisq
redchiSqExpCl = calcRedChiSq(allExpSpec,V_Chisq,nPeaks,5,1)
printf " ║ ALL │ %07.1f │ %05.3f ║ \r", V_chisq, redchiSqExpCl
print " ╚═══════════════════╧═══════════╧═══════════════╝ "
rcs2[5] = redchiSqExpCl
alphaFit[5] = pwFit6[2]
cs2[5] = V_chisq
WaveStats/Q rcs2
if(idFit[V_minloc] == 0)
Duplicate/O results1,results
Duplicate/O pwFit1,pwFinal
NVAR redchiSqExpCl = root:redchiSqExpCl
NVAR chiSqExpCl = root:chiSqExpCl
redchiSqExpCl = rcs2[0]
chiSqExpCl = cs2[0]
elseif(idFit[V_minloc] == 1)
Duplicate/O results2,results
Duplicate/O pwFit2,pwFinal
NVAR redchiSqExpCl = root:redchiSqExpCl
NVAR chiSqExpCl = root:chiSqExpCl
redchiSqExpCl = rcs2[1]
chiSqExpCl = cs2[1]
elseif(idFit[V_minloc] == 2)
Duplicate/O results3,results
Duplicate/O pwFit3,pwFinal
NVAR redchiSqExpCl = root:redchiSqExpCl
NVAR chiSqExpCl = root:chiSqExpCl
redchiSqExpCl = rcs2[2]
chiSqExpCl = cs2[2]
elseif(idFit[V_minloc] == 3)
Duplicate/O results4,results
Duplicate/O pwFit4,pwFinal
NVAR redchiSqExpCl = root:redchiSqExpCl
NVAR chiSqExpCl = root:chiSqExpCl
redchiSqExpCl = rcs2[3]
chiSqExpCl = cs2[3]
elseif(idFit[V_minloc] == 4)
Duplicate/O results5,results
Duplicate/O pwFit5,pwFinal
NVAR redchiSqExpCl = root:redchiSqExpCl
NVAR chiSqExpCl = root:chiSqExpCl
redchiSqExpCl = rcs2[4]
chiSqExpCl = cs2[4]
elseif(idFit[V_minloc] == 5)
Duplicate/O results6,results
Duplicate/O pwFit6,pwFinal
NVAR redchiSqExpCl = root:redchiSqExpCl
NVAR chiSqExpCl = root:chiSqExpCl
redchiSqExpCl = rcs2[5]
chiSqExpCl = cs2[5]
endif
//Calculate Goodness of Fit (GF) parameter for subsequent BIC analysis
NVAR GFExpCl = root:GFExpCl
GFExpCl = 0
Variable num=0,den=0
for(i=0;i<npnts;i+=1)
num = (results[i]-allExpSpec[i])^2
den = allExpSpec[i]^2
GFExpCl += num/den
endfor
Wave M_Covar,W_Sigma,pwMolAdj
endif
Variable V_FitQuitReason
if(V_FitQuitReason == 0)
makeCoVar(pwFinal,M_Covar,W_Sigma,paramNames,alpha,d=0)
endif
else
Make/O/N=18 alphaWave = {0,5,10,15,20,25,30,40,45,50,55,60,65,70,75,80,85,90}
Variable nAlpha = numpnts(alphaWave)
for(i=0;i<nAlpha;i+=1)
pWave1D[2] = alphaWave[i]
simDFTModel(pwCopy,allExpSpec,allExpEnergy,valuesPolar,allDFTSteps)
endfor
endif
cleanUpTensorWaves2()
//Generate the individual waves the concatenated waves
Wave totalNEXAFS
if(StringMatch(fit,"no"))
NewDataFolder/O Modeling
for(i=0;i<nAlpha;i+=1)
Variable alphaVal = alphaWave[i]
String tnxfsName = "totalNEXAFS_" + num2str(alphaVal)
Wave totalNEXAFS = $tnxfsName
alphaModelPlotting(fit,allExpEnergy,allExpSpec,allExpEnergy,allDFTSteps,results,totalNEXAFS,nSpec,nPeaks,pwCopy,tval,ovpVal,thetaList,d,NEXAFStype,alpha=alphaVal)
organizeTensorWaves(alphaVal,fit)
endfor
elseif(!refine)
getAmpEnFromFit(pwFinal,pwI0,round(pwFinal[2]),tval,ovpVal,pwMolAdj)
alphaModelPlotting(fit,allExpEnergy,allExpSpec,allExpEnergy,allDFTSteps,results,totalNEXAFS,nSpec,nPeaks,pwAlpha,tval,ovpVal,thetaList,d,NEXAFStype)
organizeTensorWaves(round(alpha),fit)
else
alphaModelPlotting(fit,allExpEnergy,allExpSpec,allExpEnergy,allDFTSteps,results,totalNEXAFS,nAlpha,nPeaks,refitpWave,tval,ovpVal,thetaList,d,NEXAFStype)
getAmpEnFromFit(refitpWave,pWave1D,refitpWave[2],tval,ovpVal,pwMolAdj)
organizeTensorWaves(refitpWave[2],fit)
endif
Variable stopTimer = stopMSTimer(timerStart)/1000000
End
Function stepWrapper(allExpEnergy,anchorStep1,anchorStep2,mol,expSpecName,expEnergyName,IPcorr,stepWid1,stepWid2,stepE1,stepE2,nSpec)
Wave allExpEnergy,IPcorr
Variable anchorStep1,anchorStep2,stepWid1,stepWid2,stepE1,stepE2,nSpec
String mol,expSpecName,expEnergyName
Variable pntsPerSpec = numpnts(allExpEnergy)/nSpec
WAVE allDFTSteps = makeStep(IPcorr,pntsPerSpec,stepWid1,stepWid2,stepE1,stepE2,mol,expSpecName,expEnergyName)
End
Function/WAVE scaleDFTStepToBareAtom(allExpEnergy,stepSum,anchorStep1,anchorStep2,mol,method)
Wave stepSum,allExpEnergy
Variable anchorStep1,anchorStep2,method
String mol
Variable tol = 1e-3, scaleDFTstepToBAMA
//Find the bare atom waves
Wave mu_energy = findBAenergy()
Wave mu = findBAMA(mol)
Duplicate/O stepSum,stepSum2
//Find the bare atom energies used for scaling
Variable bareStepLo = findWaveValAtEergy(mu_energy,mu,anchorStep1)
Variable bareStepHi = findWaveValAtEergy(mu_energy,mu,anchorStep2)
//Find the dft energies used for scaling
Variable dftStepLo = findWaveValAtEergy(allExpEnergy,stepSum,anchorStep1)
Variable dftStepHi = findWaveValAtEergy(allExpEnergy,stepSum,anchorStep2)
if(method == 1)
scaleDFTstepToBAMA = bareStepLo / dftStepLo
elseif(method == 2)
scaleDFTstepToBAMA = (bareStepHi-bareStepLo) / (dftStepHi-dftStepLo)
endif
stepSum2 = (stepSum - dftStepLo) * scaleDFTstepToBAMA + bareStepLo
Variable dftStepLo_2 = findWaveValAtEergy(allExpEnergy,stepSum2,anchorStep1)
Variable dif = dftStepLo_2 - bareStepLo
if(abs(dif) > tol)
if(dif > 0)
stepSum2 -= dif
elseif(dif < 0)
stepSum2 += dif
endif
dftStepLo_2 = findWaveValAtEergy(allExpEnergy,stepSum2,anchorStep1)
dif = dftStepLo_2 - bareStepLo
// print dif
endif
return stepSum2
End
Function findWaveValAtEergy(xw,yw,val)
Wave xw,yw
Variable val
Variable p1 = round(BinarySearchInterp(xw,val))
Variable dftLo = yw[p1]
return dftLo
End
Function/WAVE findBAenergy()
String currentFolder=GetdataFolder(1)
SetDataFolder root:Packages:NXA
WAVE/Z mu_energy
String newNameEn = currentFolder + "mu_energy"
Duplicate/O mu_energy,$newNameEn
SetDataFolder currentFolder
return mu_energy
End
Function/WAVE findBAMA(mol)
String mol
String currentFolder=GetdataFolder(1)
SetDataFolder root:Packages:NXA
WAVE/Z mu=$(mol+"_mu")
String newNameMu = currentFolder + "mu"
Duplicate/O mu,$newNameMu
If( !WaveExists(mu) )
Abort "Couldn't find the indicated mass absorption wave! Aborting!"
endif
SetDataFolder currentFolder
return mu
End
Function/WAVE makeLongSpecWave(expSpecName)
String expSpecName
String listOfExpSpec = SortList(WaveList(expSpecName + "*",";",""),";",24)
Make/O/D/N=0 allExpSpec = 0
Concatenate/O/NP listOfExpSpec,allExpSpec
return allExpSpec
End
Function/WAVE makeLongEnWave(expEnName)
String expEnName
String listOfExpEn = SortList(WaveList(expEnName + "*",";",""),";",24)
Make/O/D/N=0 allExpEn = 0
Concatenate/O/NP listOfExpEn,allExpEn
return allExpEn
End
Function/WAVE makeStep(IPcorr,pntsPerSpec,stepWid1,stepWid2,stepE1,stepE2,mol,expSpecName,expEnergyName)
Wave IPcorr
Variable pntsPerSpec
Variable stepWid1,stepWid2,stepE1,stepE2
String mol
String expSpecName //Base name of spectra
String expEnergyName //Base name of experimental energy waves
String listOfExpSpec = SortList(WaveList(expSpecName + "*",";",""),";",24)
String listOfExpEnergy = SortList(WaveList(expEnergyName + "*",";",""),";",24)
Variable nSpec = ItemsInList(listOfExpSpec)
String dummyName = StringFromList(0,listOfExpEnergy)
Wave dummyEnergy = $dummyName
Variable startPre= 240 //At what energy should the preedge start to be defined?
Variable endPre = 284.1 //At what energy should the preedge stop to be defined?
Variable startPost = 284.3 //At what energy should the postedge start to be defined?
Variable endPost = 360 //At what energy should the postedge stop to be defined?
//Determine min and max values for StepEdge
WaveStats/Q IPcorr
Variable stepWid, stepDecay = 0
//Determine pre and post edges of bare atom absoprtion using a polynomial fit
//Find the bare atom waves
Wave mu_energy = findBAenergy()
Wave mu = findBAMA(mol)
FitPoly3(mu,mu_energy,startPre,endPre)
WAVE W_Coef
Duplicate/d/o W_Coef, PreEdge_Coef
FitPoly3(mu,mu_energy,startPost,endPost)
Duplicate/d/o W_Coef, PostEdge_Coef
Variable StitchLow =poly(PreEdge_Coef,endPre)
Variable StitchHigh=poly(PostEdge_Coef,startPost)
//Make step edges for each atom
Variable nAtoms = numpnts(IPcorr),i
Variable dftPreEn2 = round(BinarySearchInterp(dummyEnergy,IPcorr[V_minloc]))
Variable dftPosEn2 = round(BinarySearchInterp(dummyEnergy,IPcorr[V_maxloc]))
Make/O/N=(pntsPerSpec) stepSum=0
for(i=0;i<nAtoms;i+=1)
//Determine width for average value of IP
Variable E0 = IPcorr[i]
//stepWid =(stepWid1) +((stepWid2-stepWid1)/(stepE2-stepE1))*(E0-IPcorr[V_minloc])
stepWid =(stepWid1) +((stepWid2-stepWid1)/(IPcorr[V_maxloc]-IPcorr[V_minloc]))*(E0-IPcorr[V_minloc])
String stepName = "step_" + num2str(i)
Make/o/n=(pntsPerSpec) $stepName
Wave w = $stepName
w=0
w[0,dftPreEn2-1]=poly(PreEdge_Coef,dummyEnergy)
w[dftPreEn2,dftPosEn2]=((StitchHigh-StitchLow)*Gstep(dummyEnergy,E0,stepWid))*exp(-stepDecay*(dummyEnergy-E0-stepWid)) + StitchLow
w[dftPosEn2+1,numpnts(w)-1]=poly(PostEdge_Coef,dummyEnergy)
Smooth 10,w
stepSum += w
endfor
//Get ready to make the bare atom absorption waves set in appropriate energy range and then concatenate
String dftStepList = ""
for(i=0;i<nSpec;i+=1)
dftStepList = AddListItem(NameOfWave(stepSum),dftStepList)
endfor
//Make the generated DFT Step into a concatenated wave for simultaneous fitting
Concatenate/O/NP dftStepList, allDFTSteps
return allDFTSteps
End
// Prepare the DFT calculation for simulating nexafs.
//
// Parameters:
// -----------
// expSpecName: string
// Name pattern of experimental spectra to be found in the data browser
// expEnergyName: string
// Name pattern of experimental energy waves found in the data browser
// mol: string
// Name of the molecule calculated from DFT
// IPwave: string
// Wave containing the Ionization potentials calculated from DFT
// expFolderPath: string
// Path in Igor to find the experiment data
// startPre: variable
// Starting energy used in pre-edge normalization
// endPre: variable
// Ending energy used in pre-edge normalization
// startPost: variable
// Starting energy used in post-edge normalization
// endPost: variable
// Ending energy used in post-edge normalization
// stepShift: variable
// Energy shift applied to the step edge
// anchorStep1: variable
// Energy to anchor the start of the step to the bare atom
// anchorStep2: variable
// Energy to anchor the start of the end of the bare atom
//
// Returns:
// --------
// None
Function prepSimDFTfit(expSpecName,expEnergyName,mol,IPwave,expFolderPath,anchorStep1,anchorStep2,stepWid1,stepWid2,stepE1,stepE2,[startPre,endPre,startPost,endPost,stepShift])
String expSpecName
String expEnergyName
String mol
Wave IPwave
String expFolderPath
Variable startPre
Variable endPre
Variable startPost
Variable endPost
Variable stepShift
Variable anchorStep1
Variable anchorStep2
Variable stepWid1,stepWid2,stepE1,stepE2
//========================/ Setup default parameters /===============
if(ParamIsDefault(startPre))
startPre = 283
endif
if(ParamIsDefault(endPre))
endPre = 284.1
endif
if(ParamIsDefault(startPost))
startPost = 284.7
endif
if(ParamIsDefault(endPost))
endPost = 360
endif
if(ParamIsDefault(stepShift))
stepShift = 0
endif
// Pull experimental data from data browser for some reason. Bad design pattern?
String currentFolder=GetdataFolder(1)
String listOfExpSpec = SortList(WaveList(expSpecName + "*",";",""),";",24)
String listOfExpEnergy = SortList(WaveList(expEnergyName + "*",";",""),";",24)
// Setup Ionization potential and apply the input energy shift
Duplicate/O IPwave, IPcorr
IPcorr = IPwave + stepShift
SetDataFolder expFolderPath
String dummyName = StringFromList(0,listOfExpEnergy)
Wave dummyEnergy = $dummyName
Variable nSpec = ItemsInList(listOfExpSpec),i
String newNameMu = currentFolder + "mu"
String newNameEn = currentFolder + "mu_energy"
SetDataFolder expFolderPath
Wave mu = $newNameMu
Wave mu_energy = $newNameEn
//Concatenate the experimental angle-resolved NEXAFS and corresponding energies
Make/O/D/N=0 allExpSpec = 0 , allExpEnergy = 0
Concatenate/O/NP listOfExpSpec,allExpSpec
Concatenate/O/NP listOfExpEnergy,allExpEnergy
WaveStats/Q allExpEnergy
Variable pntsPerSpec = numpnts(allExpSpec)/ItemsInList(listOfExpSpec)
//Make the step based on the IP from DFT
Wave allDFTSteps = makeStep(IPcorr,pntsPerSpec,stepWid1,stepWid2,stepE1,stepE2,mol,expSpecName,expEnergyName)
//Anchor the intensity of the DFT step function to the intensity of the bare atom absorption. Means that DFT step is now in terms of MA[g/cm^2]
Variable method = 2
Variable alpha1 = 24,alpha2=16,i0=65000,eta=1,etaDel=0.001,etaFin=0.5
String tl = "40;55;70;90"
Wave stepSum2 = scaleDFTStepToBareAtom(allExpEnergy,allDFTSteps,anchorStep1,anchorStep2,mol,method)
Wave allExpSpec = scaleExptoDFTStep2(stepSum2,anchorStep1,anchorStep2,284.4,286.4,293.9,308,mol,method,nSpec,tl,alpha1,alpha2,i0,expSpecName,expEnergyName,eta,etadel,etaFin)
String newNameallExpSpec = currentFolder + "allExpSpec"
String newNameallExpEnergy = currentFolder + "allExpEnergy"
String newNameallDFTSteps = currentFolder + "allDFTSteps"
Duplicate/O allExpSpec ,$newNameallExpSpec
Duplicate/O allExpEnergy,$newNameallExpEnergy
Duplicate/O stepSum2 ,$newNameallDFTSteps
SetDataFolder currentFolder
End
// make1DparamWave
//
// Casts the 2D parameter wave `IPwave` into a 1D parameter wave `tensorPWave`
// suitable for fitting. This process also incorporates additional scalar
// parameters (`alpha`, `i0`, `phi`) and optional parameters (`atomName`,
// `rigidShift`) into the output `tensorPWave`.
//
// The primary purpose of this function is to linearize and aggregate
// parameters from various sources into a single 1D wave. This format
// is commonly required by Igor Pro's multivariate fitting operations,
// such as FuncFit.
//
// Parameters
// ----------
// IPwave : wave
// The input 2D wave. This wave contains the primary set of parameters
// that need to be restructured or "cast" into a 1D format.
// tensorPWave : wave
// The output 1D wave. This wave is populated by the function with
// parameters from `IPwave` along with `alpha`, `i0`, `phi`, and any
// provided optional parameters. It is modified in-place. The structure
// of this wave is tailored for subsequent fitting procedures.
// alpha : variable
// A scalar variable, potentially representing a characteristic angle,
// anisotropic factor, or another model-specific coefficient, to be
// included in `tensorPWave`.
// i0 : variable
// A scalar variable, often representing an initial intensity, baseline
// value, or normalization factor, to be included in `tensorPWave`.
// phi : variable
// A scalar variable, typically representing a phase angle, orientation,
// or rotational offset, to be included in `tensorPWave`.
// atomName : string, optional
// An optional string specifying the name of an atom. If provided,
// this information may be used to select or adjust specific parameters
// related to the named atom during the construction of `tensorPWave`.
// If omitted, the function proceeds without atom-specific adjustments
// or uses a default behavior.
// rigidShift : variable or wave, optional
// An optional scalar variable or 1D wave representing a rigid shift.
// If provided, this shift (e.g., an energy shift, spatial offset)
// is incorporated into the parameters within `tensorPWave`. If omitted,
// no such shift is applied, or a default shift of zero is assumed.
//
// Returns
// -------
// variable
// Returns 0 on successful completion. A non-zero value typically
// indicates an error occurred during the execution of the function
// (following standard Igor Pro function return conventions).
//
// Notes
// -----
// The exact mapping and transformation logic from the input parameters
// to the `tensorPWave` depends on the specific requirements of the
// fitting model for which these parameters are being prepared. This
// function serves as a preparatory step to ensure data is in the correct
// format for Igor Pro's fitting engine.
// Cast the 2D parameter wave into a 1D parameter wave for fitting.
//
// 1D Parameter wave structure:
// [0] - Number of atoms
// [1] - Global intensity scaling factor (i0)
// [2] - Molecular tilt angle (alpha)
// [3] - Azimuthal angle of E-field (phi)
// [4 - 4+nAtoms-1] - Calculated ionization potentials (IP) for each atom
// ... assume nAtoms = 1 for simplicity
// [5] - Transition energy for the first transition
// [6] - Transition width for the first transition
// [7] - Transition amplitude for the first transition
// [8] - XX component of the transition tensor for the first transition
// [9] - XY component of the transition tensor for the first transition
// [10] - XZ component of the transition tensor for the first transition
// [11] - YY component of the transition tensor for the first transition
// [12] - YZ component of the transition tensor for the first transition
// [13] - ZZ component of the transition tensor for the first transition
// [14] - Local orientation (alpha) for the first transition
// [15] - Modified amplitude value for the first transition (initially set to 0)
// [16 - 16+nTransitions*11-1] - Repeat for each transition, where nTransitions is the number of transitions in tensorPWave
Function make1DparamWave(IPwave,tensorPWave,alpha,i0,phi,[atomName,rigidShift])
Wave IPwave //1D wave containing the ionization potentials from DFT
Wave tensorPWave //2D wave containing peak positions,widths and amplitudes
Variable alpha //Molecular tilt angle
Variable i0 //Global intensity scaling factor
Variable phi //Azimuthal angle of E-field. Usually 0 for NEXAFS
String atomName //What element are we processing?
Variable rigidShift //Global energy shift to be applied to DFT energies to match experiment
if(ParamIsDefault(atomName))
atomName = "C"
endif
if(ParamIsDefault(rigidShift))
rigidShift = 0
endif
Variable nTrans = DimSize(tensorPWave,0)
Make/O/D/N=(nTrans,3) pWave2D
Variable nAtoms = numpnts(IPwave)
Variable i,j=0
for(i=0;i<=nTrans-1;i+=1)
pWave2D[i][0] = tensorPWave[i][0] //Peak position
pWave2D[i][1] = tensorPWave[i][2] //Peak width
pWave2D[i][2] = tensorPWave[i][1] //Peak amplitude
endfor
Make/O/D/N=(11*nTrans + nAtoms + 4) pWave1D
//Make text wave with parameter names. Easier to browse parameters.
Make/O/T/N=(11*nTrans + nAtoms + 4) paramNames
//Convert 2D wave to 1D
for(i=nAtoms+4;i<=11*nTrans + nAtoms;i+=11)
pWave1D[i+0] = pWave2D[j][0] + rigidShift //Peak position
pWave1D[i+1] = pWave2D[j][1] //Peak Width
pWave1D[i+2] = pWave2D[j][2] //Peak Max amplitude
pWave1D[i+3] = abs(tensorPWave[j][8]) //XX
pWave1D[i+4] = abs(tensorPWave[j][11]) //XY
pWave1D[i+5] = abs(tensorPWave[j][12]) //XZ
pWave1D[i+6] = abs(tensorPWave[j][9]) //YY
pWave1D[i+7] = abs(tensorPWave[j][13]) //YZ
pWave1D[i+8] = abs(tensorPWave[j][10]) //ZZ
pWave1D[i+9] = alpha //Local orientation
pWave1D[i+10] = 0 //Modified amplitude value to be used for peak refinements
paramNames[i+0] = "peakEnergy_" + num2str(j)
paramNames[i+1] = "peakWidth_" + num2str(j)
paramNames[i+2] = "maxAmplitude_" + num2str(j)
paramNames[i+3] = "OSxx_" + num2str(j)
paramNames[i+4] = "OSxy_" + num2str(j)
paramNames[i+5] = "OSxz_" + num2str(j)
paramNames[i+6] = "OSyy_" + num2str(j)
paramNames[i+7] = "OSyz_" + num2str(j)
paramNames[i+8] = "OSzz_" + num2str(j)
paramNames[i+9] = "LocalAlpha_" + num2str(j)
paramNames[i+10] = "MolTensorTheta_" + num2str(j)
j+=1
endfor
//Check that there no transitions with zero energy
//Add the ionization potentials to make the step edge
for(i=4;i<nAtoms+4;i+=1)
pWave1D[i] = IPwave[i-4]
String ipAtom = atomName + num2str(i-3) + "_IP"
paramNames[i] = ipAtom
endfor
//Add the number of atoms to the parameter wave
pWave1D[0] = nAtoms
paramNames[0] = "nAtoms"
//Add the i0 to the parameter wave
pWave1D[1] = i0
paramNames[1] = "i0"
//Add the alpha value to the parameter wave
pWave1D[2] = alpha//*(Pi/180)
paramNames[2] = "alpha"
//Add the value of phi of the Electric Field to the parameter wave
pWave1D[3] = phi
paramNames[3] = "phi"
End
Function makeTensor1D(pw)
Wave pw
Variable nAtoms = pw[0],i,j=0
Variable nTransitions = (numpnts(pw) - 4 - nAtoms)/11
for(i=0;i<nTransitions;i+=1)
String tensorName = "resonance_" + num2str(i)
Make/O/D/N=(3,3) $tensorName
Wave w = $tensorName
w = 0
endfor
for(i=4 + nAtoms;i<11*nTransitions + nAtoms + 4;i+=11)
tensorName = "resonance_" + num2str(j)
Wave w = $tensorName
w = 0
w[0][0] = pw[i+3]; w[0][1] = pw[i+4]; w[0][2] = pw[i+5] // xx xy xz
w[1][0] = pw[i+4]; w[1][1] = pw[i+6]; w[1][2] = pw[i+7] // yx yy yz
w[2][0] = pw[i+5]; w[2][1] = pw[i+7]; w[2][2] = pw[i+8] // zx zy zz
w = abs(w)
j+=1
endfor
End
Function/WAVE make3DnormWave()
String normTensors = WaveList("norm_*",";","")
Variable nTrans = ItemsInList(normTensors)
Make/O/D/N=(3,3,nTrans) norm3D
Concatenate/O/NP=2 normTensors, norm3D
return norm3D
End
Function/WAVE make3DResonance()
String tensors = WaveList("resonance_*",";","")
Variable nTrans = ItemsInList(tensors)
Make/O/D/N=(3,3,nTrans) tensor3D
Concatenate/O/NP=2 tensors, tensor3D
return tensor3D
End
Function simDFTfit2(pw,yw,ew,thw,sw) :FitFunc
Wave pw //1D Parameter wave. Has peak positions,widths, and amplitudes. has initial guess for alpha and IPs required to build step edge
Wave yw // Output Function wave. Contains the simulated NEXAFS spectrum
Wave ew //Wave containing the energies of the various spectra to be fit (i.e. the x wave)
Wave thw //Wave containing the various values of theta
Wave sw //Wave containing the concatenated steps from the DFT IPs
Variable i,j=0,k,m
Variable targetDP = 10
//Make the absorption tensor for each transition, normalize it, and place each transition into a layer of a 3D wave
makeTensor1D(pw)
normalizeTensor()
Wave norm3D = make3DnormWave()
Wave tensor3D = make3DResonance()
//Add the step edge
yw = sw
//Reference hold Wave. To be used to determine how the peak amplitudes will be defined
Wave holdWave
Variable nTransitions = DimSize(norm3D,2)
Variable pos,wid,amp,alpha,i0,phi,localalpha,amp2
Variable p0,pf,nSpec=howManySpec(thw),cSpec=1,thetaVal
Make/O/N=(3,3,nTransitions) filmTensor3D,r0x3D,r90x3D,r180x3D,r270x3D,tilt3D,correctedMolTensor3D
Variable nAtoms = pw[0]
Make/O/D/N=(3,3) currentTensor = 0
Variable nPnts = numpnts(yw)/nSpec
Make/O/N=(nTransitions) MA = 0,vecAngle = 0,vecAngle2 = 0
//Duplicated parameter wave that will contain the results of rotating the molecular tensor
Duplicate/O pw,pwMolAdj,pwFilm
Wave pwMolAdj,pwFilm
i0 = pw[1]
alpha = pw[2] * (Pi/180)
phi = pw[3] * (Pi/180)
Variable count = 0
for(i=nAtoms + 4 ;i<11*nTransitions + nAtoms;i+=11)
pos = pw[i + 0]
wid = ABS(pw[i + 1])
amp = ABS(pw[i + 2])
localalpha = pw[i + 9]
amp2 = pw[i + 10]
currentTensor = tensor3D[p][q][j]// norm3D[p][q][j]
if(WaveExists(pwMolAdj))
pwMolAdj[i+3] = currentTensor[0][0]
pwMolAdj[i+4] = currentTensor[0][1]
pwMolAdj[i+5] = currentTensor[0][2]
pwMolAdj[i+6] = currentTensor[1][1]
pwMolAdj[i+7] = currentTensor[1][2]
pwMolAdj[i+8] = currentTensor[2][2]
endif
currentTensor *= i0 * amp
variable c = cos(alpha)
variable s = sin(alpha)
variable inplane_component = (currentTensor[0][0] * (1 + c^2) + currentTensor[2][2] * s^2) / 2
variable outofplane_component = (currentTensor[0][0] * s^2 + currentTensor[2][2] * c^2)
MatrixOP/O filmTensor = {{inplane_component, 0, 0}, {0, inplane_component, 0}, {0, 0, outofplane_component}}
Wave filmTensorT = truncate2D(filmTensor,targetDP)
if(WaveExists(pwFilm))
pwFilm[i+3] = filmTensorT[0][0]
pwFilm[i+4] = filmTensorT[0][1]
pwFilm[i+5] = filmTensorT[0][2]
pwFilm[i+6] = filmTensorT[1][1]
pwFilm[i+7] = filmTensorT[1][2]
pwFilm[i+8] = filmTensorT[2][2]
endif
correctedMolTensor3D[][][j] = currentTensor[p][q] //Molecular tensor after rotating ZZ/XX elements by ModTheta
filmTensor3D[][][j] = filmTensorT[p][q] //Film Tensor after tilting molecular tensor by alpha and 4-fold addition
r0x3D[][][j] = RotTensor0X[p][q]
r90x3D[][][j] = RotTensor90X[p][q]
r180x3D[][][j] = RotTensor180X[p][q]
r270x3D[][][j] = RotTensor270X[p][q]
tilt3D[][][j] = tiltedTensorX[p][q]
if(j<nTransitions)
if(cSpec == 1)
p0 = 0
pf = nPnts-1
thetaVal = thw[p0] * (Pi/180)
elseif(cSpec == nSpec)
p0 = (cSpec-1)*nPnts
pf = cSpec*nPnts-1
thetaVal = thw[p0] * (Pi/180)
else
p0 = (cSpec-1)*nPnts
pf = cSpec*nPnts-1
thetaVal = thw[p0] * (Pi/180)
endif
endif
//Need to extract xx and zz tensor elements and create NEXAFS waves from them
//Apply electric field to current tensor to obtain the mass absorbance
Make/O/D/N=(3) eField = {sin(thetaVal)*cos(phi),sin(thetaVal)*sin(phi),cos(thetaVal)}
MatrixOP/O tempMA = eField^t x filmTensor x eField
if(numtype(tempMA[0]) !=0)
print "Transition " + num2str(j) + " with a theta value of " + num2str(thetaVal) + " has a problem"
else
MA[j] = tempMA[0]
endif
//Make the BB peaks for display
String pkName = "pk" + num2str(j) + "_spec" + num2str(cSpec)
Make/O/N=2000 $pkName
Wave z = $pkName
ControlInfo/W=ClusteringAlgorithm Eini
Variable Eini = V_Value
ControlInfo/W=ClusteringAlgorithm Efin
Variable Efin = V_Value
SetScale/i x,Eini,Efin,z
z = 0
z = (MA[j]) * gauss(x,pos,wid)
//yw[p0,pf] += sqrt(2*Pi) * wid * MA[j] * gauss(ew,pos,wid)
yw[p0,pf] += MA[j] * gauss(ew,pos,wid)
j+=1
if(j<=nTransitions)
if(cSpec == 1)
if(j==(nTransitions) && cSpec < nSpec)
i=nAtoms + 4 - 11
cSpec+=1
j=0
endif
else
if(j==(nTransitions) && cSpec < nSpec)
i=nAtoms + 4 - 11
cSpec+=1
j=0
endif
endif
endif
endfor
KillWaves/Z rotMat0,rotMat90,rotMat180,rotMat270,RotTensor0,RotTensor90,RotTensor180,RotTensor270,TEMPma
End
Function simDFTModel(pw,yw,ew,thw,sw) :FitFunc
Wave pw //1D Parameter wave. Has peak positions,widths, and amplitudes. has initial guess for alpha and IPs required to build step edge
Wave yw //Wave containing the different spectra to be fit
Wave ew //Wave containing the energies of the various spectra to be fit (i.e. the x wave)
Wave thw //Wave containing the various values of theta
Wave sw //Step Wave
Variable i,j=0,k,m
//Make the absorption tensor for each transition, normalize it, and place each transition into a layer of a 3D wave
makeTensor1D(pw)
normalizeTensor()
make3DnormWave()
Wave norm3D
Variable nTransitions = DimSize(norm3D,2)
Variable pos,wid,amp,alpha,i0,phi,localalpha,amp2
Variable p0,pf,nSpec=howManySpec(thw),cSpec=1,thetaVal
Variable nAtoms = pw[0]
Variable targetDP = 10
Make/O/D/N=(3,3) currentTensor = 0
//This is the wave that will contain the DFT tensor model NEXAFS
String tNXFSname = "totalNEXAFS_" + num2str(pw[2])
Duplicate/D/O yw,$tNXFSname
Wave totalNEXAFS = $tNXFSname
totalNEXAFS = sw
Variable nPnts = numpnts(yw)/nSpec
Make/O/D/N=(nTransitions) MA = 0
//Make rotation matrices for rotation of 90,180,and 270 degrees around z-axis
Make/O/D/N=(3,3) rotMat0 = {{cos(0*(Pi/180)) ,sin(0*(Pi/180)),0} ,{-sin(0*(Pi/180)) ,cos(0*(Pi/180)),0} ,{0,0,1}}
Make/O/D/N=(3,3) rotMat90 = {{cos(90*(Pi/180)) ,sin(90*(Pi/180)),0} ,{-sin(90*(Pi/180)) ,cos(90*(Pi/180)),0} ,{0,0,1}}
Make/O/D/N=(3,3) rotMat180 = {{cos(180*(Pi/180)),sin(180*(Pi/180)),0},{-sin(180*(Pi/180)),cos(180*(Pi/180)),0},{0,0,1}}
Make/O/D/N=(3,3) rotMat270 = {{cos(270*(Pi/180)),sin(270*(Pi/180)),0},{-sin(270*(Pi/180)),cos(270*(Pi/180)),0},{0,0,1}}
for(i=nAtoms + 4 ;i<11*nTransitions + nAtoms;i+=11)
i0 = pw[1]
alpha = pw[2]//90-pw[i+9]
phi = pw[3]
pos = pw[i + 0]
wid = pw[i + 1]
amp = pw[i + 2]
localalpha = pw[i + 9]
amp2 = pw[i + 10]
currentTensor = i0 * amp * norm3D[p][q][j]
Make/O/D/N=(3,3) rotMatAlignX = {{1,0,0},{0,cos(alpha*(Pi/180)),sin(alpha*(Pi/180))},{0,-sin(alpha*(Pi/180)),cos(alpha*(Pi/180))}}
MatrixOP/O tiltedTensor = rotMatAlignX x currentTensor x rotMatAlignX^t
MatrixOP/O RotTensor0 = rotMat0 x tiltedTensor x rotMat0^t
MatrixOP/O RotTensor90 = rotMat90 x tiltedTensor x rotMat90^t
MatrixOP/O RotTensor180 = rotMat180 x tiltedTensor x rotMat180^t
MatrixOP/O RotTensor270 = rotMat270 x tiltedTensor x rotMat270^t
MatrixOP/O filmTensor = RotTensor0 + RotTensor90 + RotTensor180 + RotTensor270
for(k=0;k<=2;k+=1)
for(m=0;m<=2;m+=1)
Variable currComp = filmTensor[k][m]
targetDP = round(targetDP)
currComp = round(currComp * (10^targetDP)) / (10^targetDP)
if(currComp == -0)
currComp = 0
endif
filmTensor[k][m] = currComp
endfor
endfor
if(j<nTransitions)
if(cSpec == 1)
p0 = 0
pf = nPnts-1
thetaVal = thw[p0]
elseif(cSpec == nSpec)
p0 = (cSpec-1)*nPnts
pf = cSpec*nPnts-1
thetaVal = thw[p0]
else
p0 = (cSpec-1)*nPnts
pf = cSpec*nPnts-1
thetaVal = thw[p0]
endif
endif
Make/O/D/N=(3) eField = {sin(thetaVal*(Pi/180))*cos(phi*(Pi/180)),sin(thetaVal*(Pi/180))*sin(phi*(Pi/180)),cos(thetaVal*(Pi/180))}
MatrixOP/O tempMA = amp * (eField^t x filmTensor x eField)
if(numtype(tempMA[0]) !=0)
MA[j] = 0
else
MA[j] = tempMA[0]
endif
String pkName = "pk" + num2str(j) + "_spec" + num2str(cSpec) + "_Alpha" + num2str(pw[2])
Make/O/N=2000 $pkName
Wave z = $pkName
SetScale/i x,280,360,z
z = MA[j] * gauss(x,pos,wid)
totalNEXAFS[p0,pf] += MA[j] * gauss(ew,pos,wid)
j+=1
if(j<=nTransitions)
if(cSpec == 1)
if(j==(nTransitions) && cSpec < nSpec)
i=nAtoms + 4 - 11
cSpec+=1
j=0
endif
else
if(j==(nTransitions) && cSpec < nSpec)
i=nAtoms + 4 - 11
cSpec+=1
j=0
endif
endif
endif
endfor
End
Function modifyWaves(w,nSpec,thetaList)
Wave w
Variable nSpec
String thetaList
Variable i,j=0,n = DimSize(w,0),pps=n/nSpec,newSpec=ItemsInList(thetaList),newSize = newSpec*pps
Duplicate/O w, test
Redimension/N=(newSize,3) test
//Copy step values and energies into redimensioned wave
for(i=n;i<newSize;i+=1)
test[i][0] = w[j][0]
test[i][2] = w[j][2]
j+=1
if(j>=pps)
j=0
endif
endfor
//Fill the redimensioned wave with new theta values
j=0
for(i=0;i<newSize;i+=1)
Variable cTheta = str2num(StringFromList(j,thetaList))
test[i][1] = cTheta
if((mod(i+1,pps)==0) && i!=0)
j+=1
endif
endfor
End
Function modelWrapper(thetaList,pw,eval,pwOri,d,[fit,fetchWaves,moveStepY])
Wave pw,pwOri
Variable eVal,fit,fetchWaves,moveStepY,d
String thetaList
//Look for the waves used in the fit and to construct the ETS wave?
if(fetchWaves)
Wave holdWave = findHoldWave()
Wave valuesPolar = findThetaWave()
Wave allExpEnergy = findExpEnergyWave()
Wave allDFTSteps = findStepWave()
Wave allExpSpec = findExpSpecWave()
Wave eps = findEpsWave()
else
Wave holdWave,valuesPolar,allExpEnergy,allDFTSteps,allExpSpec,eps
endif
Duplicate/O allDFTSteps,DFTStepNew
DFTStepNew = allDFTSteps + moveStepY
Duplicate/O allExpEnergy,totalNEXAFS
Duplicate/O pw,pwMolAdj,pwFilm,pwRes
totalNEXAFS = 0
simDFTfit2(pw,totalNEXAFS,allExpEnergy,valuesPolar,DFTStepNew)
Wave totalNEXAFS,pwMolAdj
Variable nSpec = ItemsInList(thetaList)
splitSpec(totalNEXAFS,nSpec,"NXFS")
splitSpec(DFTStepNew,nSpec,"dftStep")
//plotAlphaIntensities2(eVal,enw,"NXFS",nSpec,thetaList)
//Make function that plots DFT Model against Experimental NEXAFS
if(!fit)
plotModel(thetaList) //Plot Change in parameters
getAmpEnFromFit(pw,pwOri,20,1,50,pwMolAdj,d=d)
//gaugeChange(pwOri,pw)
else //Fit the model
DFTfitNew(pw,holdWave,valuesPolar,allExpEnergy,allDFTSteps,allExpSpec,eps)
endif
End
Function/WAVE findHoldWave()
String iniFolder = GetDataFolder(1)
String miscFolder = iniFolder + "TensorMisc"
SetDataFolder $miscFolder
Wave holdWave
SetDataFolder $iniFolder
String nName = iniFolder + "holdWave"
Duplicate/O holdWave,$nName
return holdWave
End
Function/WAVE findThetaWave()
String iniFolder = GetDataFolder(1)
String miscFolder = iniFolder + "TensorMisc"
SetDataFolder $miscFolder
Wave valuesPolar
SetDataFolder $iniFolder
String nName = iniFolder + "valuesPolar"
Duplicate/O valuesPolar,$nName
return valuesPolar
End
Function/WAVE findExpEnergyWave()
String iniFolder = GetDataFolder(1)
String miscFolder = iniFolder + "TensorMisc"
SetDataFolder $miscFolder
Wave allExpEnergy
SetDataFolder $iniFolder
String nName = iniFolder + "allExpEnergy"
Duplicate/O allExpEnergy,$nName
return allExpEnergy
End
Function/WAVE findStepWave()
String iniFolder = GetDataFolder(1)
String miscFolder = iniFolder + "TensorMisc"
SetDataFolder $miscFolder
Wave allDFTSteps
SetDataFolder $iniFolder
String nName = iniFolder + "allDFTSteps"
Duplicate/O allDFTSteps,$nName
return allDFTSteps
End
Function/WAVE findExpSpecWave()
String iniFolder = GetDataFolder(1)
String miscFolder = iniFolder + "TensorMisc"
SetDataFolder $miscFolder
Wave allExpSpec
SetDataFolder $iniFolder
String nName = iniFolder + "allExpSpec"
Duplicate/O allExpSpec,$nName
return allExpSpec
End
Function/WAVE findEpsWave()
String iniFolder = GetDataFolder(1)
String miscFolder = iniFolder + "TensorMisc"
SetDataFolder $miscFolder
Wave eps
SetDataFolder $iniFolder
String nName = iniFolder + "eps"
Duplicate/O eps,$nName
return eps
End
Function plotModel(thetaList,[fit])
String thetaList
Variable fit
Variable n = ItemsInList(thetaList),i,pDiff
Make/O/N=(n) percentDiff
String iniFolder = GetDataFolder(1)
String DFTNXFS = WaveList("NXFS*",";",""),fitNXFS = WaveList("fitResult*",";","")
String pks = WaveList("pk*"+num2str(2),";","")
Variable npks = ItemsInList(pks)
String fitFolder = iniFolder + "TensorMisc"
SetDataFolder $fitFolder
String energies = WaveList("expEnergy*",";",""),enWaveName = StringFromList(0,energies)
Wave enWave = $enWaveName
String expNXFS = WaveList("expSpec*",";","")
String steps = WaveList("dftStep*",";","")
Wave step = $StringFromList(0,steps)
DoWindow ModelvsExpPlot
String Rlist = "0;1;39321;65535",Glist = "3204;34817;1;43690",Blist = "13107;52428;1;0"
DoWindow ModelvsExpPlot
if(!V_Flag)
Display/N=ModelvsExpPlot/K=1/W=(0,0,1500,400)
NewFreeAxis/L residuals
NewFreeAxis/L peaks
for(i=0;i<n;i+=1)
Variable r = str2num(StringFromList(i,Rlist)) ,g = str2num(StringFromList(i,Glist)),b = str2num(StringFromList(i,Blist))
SetDataFolder $fitFolder
String expName = StringFromList(i,expNXFS)
Wave nxfs = $expName
AppendToGraph/W=ModelvsExpPlot nxfs vs enWave
Variable x = numpnts(nxfs)
String resName = "res" + num2str(i)
Make/O/N=(x) $resName
Wave res = $resName
SetDataFolder $iniFolder
if(!fit)
String dftName = StringFromList(i,DFTNXFS)
Wave dft = $dftName
AppendToGraph/W=ModelvsExpPlot dft vs enWave
ModifyGraph lstyle($dftName)=3
res = ((nxfs - dft)/nxfs)*100
pDiff = calcPercentDiff(nxfs,dft)
ModifyGraph rgb($expName)=(r,g,b),rgb($dftName)=(r,g,b),lsize($expName)=3,lsize($dftName)=3
else
String fitName = StringFromList(i,fitNXFS)
Wave fitW = $fitName
AppendToGraph/W=ModelvsExpPlot fitW vs enWave
ModifyGraph lstyle($fitName)=3
res =(( nxfs - fitW)/nxfs)*100
pDiff = calcPercentDiff(nxfs,fitW)
ModifyGraph rgb($expName)=(r,g,b),rgb($fitName)=(r,g,b),lsize($expName)=3,lsize($fitName)=3
endif
AppendToGraph/W=ModelvsExpPlot/L=residuals res vs enWave
ModifyGraph rgb($resName)=(r,g,b)
percentDiff[i] = pDiff
endfor
SetDataFolder $iniFolder
//Append the DFT step edge onto graph
AppendToGraph/W=ModelvsExpPlot step vs enWave
ModifyGraph lsize($StringFromList(0,steps))=2,rgb($StringFromList(0,steps))=(0,0,0)
for(i=0;i<npks;i+=1)
String pkName = StringFromList(i,pks)
Wave pk = $pkName
AppendToGraph/W=ModelvsExpPlot/L=peaks pk
ModifyGraph rgb($pkName)=(0,0,0),lsize($pkName)=1.5
endfor
ModifyGraph grid=2,mirror=1,minor=1,fStyle=1,fSize=12,axisEnab(left)={0.2,0.8}
ModifyGraph lblPosMode(residuals)=1,axisEnab(residuals)={0.82,1},freePos(residuals)=0
ModifyGraph lblPosMode(peaks)=1,axisEnab(peaks)={0,0.18},freePos(peaks)=0,lblPosMode(left)=1
Label left "Mass Absorbance [cm\S2\M/g]\\U"
Label peaks "Peaks [a.u.]\\U"
Label residuals "Residuals[%]\\U"
Label bottom "Transition Energy[eV]"
SetAxis bottom 283,310
SetAxis residuals -100,100
SetAxis peaks *,70000
//Make the legend
String totalLegend = "θ[°] EXP DFT %Diff\r",legendPortion = "",whichList
if(fit)
whichList = fitNXFS
else
whichList = DFTNXFS
endif
for(i=0;i<n;i+=1)
String alpha = StringFromList(i,thetaList)
String dftSpec = StringFromList(i,whichList)
String expSpec = StringFromList(i,expNXFS)
if(i != (n-1))
legendPortion += alpha + "° \\s('"+ expSpec +"') \\s('" + dftSpec +"') " + num2str(percentDiff[i]) +"\r\n"
else
legendPortion += alpha + "° \\s('"+ expSpec +"') \\s('" + dftSpec +"') " + num2str(percentDiff[i])
endif
endfor
Legend/C/A=RT/N=text0/J totalLegend + legendPortion
else
for(i=0;i<n;i+=1)
SetDataFolder $fitFolder
expName = StringFromList(i,expNXFS)
Wave nxfs = $expName
x = numpnts(nxfs)
resName = "res" + num2str(i)
Make/O/N=(x) $resName
Wave res = $resName
SetDataFolder $iniFolder
if(!fit)
dftName = StringFromList(i,DFTNXFS)
Wave dft = $dftName
res = ((nxfs - dft)/nxfs)*100
pDiff = calcPercentDiff(nxfs,dft)
else
fitName = StringFromList(i,fitNXFS)
Wave fitW = $fitName
res =(( nxfs - fitW)/nxfs)*100
pDiff = calcPercentDiff(nxfs,fitW)
endif
percentDiff[i] = pDiff
endfor
totalLegend = "θ[°] EXP DFT %Diff\r"
legendPortion = ""
if(fit)
whichList = fitNXFS
else
whichList = DFTNXFS
endif
for(i=0;i<n;i+=1)
alpha = StringFromList(i,thetaList)
dftSpec = StringFromList(i,whichList)
expSpec = StringFromList(i,expNXFS)
if(i != (n-1))
legendPortion += alpha + "° \\s('"+ expSpec +"') \\s('" + dftSpec +"') " + num2str(percentDiff[i]) +"\r\n"
else
legendPortion += alpha + "° \\s('"+ expSpec +"') \\s('" + dftSpec +"') " + num2str(percentDiff[i])
endif
endfor
Legend/C/A=RT/N=text0/J/W=ModelvsExpPlot totalLegend + legendPortion
endif
SetDataFolder $iniFolder
End
Function gaugeChange(pwOri,pwNew)
Wave pwOri,pwNew
Variable nPeaks = (numpnts(pwOri)-pwOri[0]-4)/11,i,j=0
Make/O/N=(nPeaks) difPos,difWid,difAmp,difAmp2
for(i=pwOri[0]+4;i<numpnts(pwOri);i+=11)
Variable oriPos = pwOri[i+0]
Variable newPos = pwNew[i+0]
Variable oriWid = pwOri[i+1]
Variable newWid = pwNew[i+1]
Variable oriAmp = pwOri[i+2]
Variable newAmp = pwNew[i+2]
Variable oriAmp2 = pwOri[i+10]
Variable newAmp2 = pwNew[i+10]
//Use log to track change
//log(new/old)
difPos[j] = (newPos - oriPos)///oriPos)*100
difWid[j] = ((newWid - oriWid)/oriWid)*100
difAmp[j] = ((newAmp - oriAmp)/oriAmp)*100
difAmp2[j] = ((newAmp2 - oriAmp2)/oriAmp2)*100
j+=1
endfor
DoWindow ParameterChanges
if(!V_Flag)
NewFreeAxis/L ampchange
NewFreeAxis/L modampchange
Display/N=ParameterChanges/K=1 difPos
AppendToGraph/L=ampchange difAmp
AppendToGraph/L=modampchange difAmp2
ModifyGraph grid=2,mirror=1,nticks=10,fStyle=1,fSize=12
Label left "Position Diff [eV]"
Label ampchange "Amplitude Diff"
Label modampchange "Ratio Diff"
Label bottom "Peak ID"
ModifyGraph mode=4,marker=19,lsize=1.5
ModifyGraph lblPosMode(left)=1,lblPosMode(ampchange)=1,lblPosMode(modampchange)=1
ModifyGraph axisEnab(left)={0,0.3},axisEnab(ampchange)={0.34,0.64},axisEnab(modampchange)={0.68,1}
ModifyGraph freePos(ampchange)=0,freePos(modampchange)=0
endif
End
Function DFTfitNew(pw,hw,tw,xw,sw,ew,epsw)
Wave pw,hw,tw,xw,sw,ew,epsw //parameter,hold,theta,energy,step,experimental,and epsilon waves
//Wave makeSingleConstraintWave(holdAmps,holdWidths,holdPos,holdAlpha,holdSecAmp,pWave1D,pkID)
String H = holdWaveToStr(hw)
Duplicate/O ew,fitRes,results
Duplicate/O pw,refineFitpw
Variable V_FitError = 0.000001
FuncFit/H=H/M=2/Q simDFTfit2,refineFitpw, ew /X={xw,tw,sw} /R=fitRes /E=epsw /D=results// /C=constraint
Wave totalNEXAFS
splitSpec(totalNEXAFS,4,"fitResult")
plotModel("40;55;70;90",fit=1)
End
Function/S holdWaveToStr(hw)
Wave hw
Variable n = numpnts(hw),i
String H =""
for(i=0;i<n;i+=1)
H += num2str(hw[i])
endfor
// print H
return H
End
Function cleanUpTensorWaves2()
String resonanceList = WaveList("resonance_*",";","")
String normResonanceList = WaveList("norm_resonance_*",";","")
String pWaveList = SortList(WaveList("pWave_*",";",""))
Variable nResonances = ItemsInList(resonanceList)
Variable nPwaves = ItemsInList(pWaveList)
Variable k
//Place the tensors for each step into a 3D wave. Each layer corresponds to a resonance tensor
Make/O/N=(3,3,nResonances) oritensor3D,normTensor3D
Concatenate/NP=2/O resonanceList,oritensor3D
Concatenate/NP=2/O normResonanceList,normTensor3D
//Remove the 2D tensor waves that clutter the workspace
for(k=0;k<=nResonances-1;k+=1)
String currentResWave = StringFromList(k,resonanceList)
String currentNormResWave = StringFromList(k,normResonanceList)
Wave w = $currentResWave
Wave z = $currentNormResWave
KillWaves/Z $currentResWave,$currentNormResWave
endfor
for(k=0;k<=nPwaves-1;k+=1)
String currentPwave = StringFromList(k,pWaveList)
Wave b = $currentPwave
KillWaves/Z $currentPwave
endfor
KillWaves/Z rotMatAlignX,rotMatAlignY,rotMatAlignZ,rotXY,rotYX
KillWaves/Z totAzi,tensor3D,TransitionInstances
End
Function/WAVE makePolarWave2(thetaList,nPnts)
String thetaList
Variable nPnts
Make/O/D/N=(nPnts) valuesPolar
Variable nThetas = ItemsInList(thetaList)
Variable pointsPerTheta = nPnts/nThetas
Variable i,j=0
for(i=0;i<nPnts;i+=1)
valuesPolar[i] =str2num(StringFromList(j,thetaList))
if(i==(j+1)*pointsPerTheta-1)
j+=1
endif
endfor
return valuesPolar
End
Function splitSpec(w,n,name,[alpha,reScale])
Wave w //Wave containing concatenated spectra
Variable n //How many spectra are there in the concatenated wave?
String name //What should be the base names of the split spectra?
Variable alpha //What's the alpha value for the generated spectra?
Variable reScale //SetScale of wave?
Variable pnts = numpnts(w)/n
String cSpec
Variable i,j=0,k=0
for(i=1;i<=n;i+=1)
if(ParamIsDefault(alpha))
cSpec = name + num2str(i)// + "_alpha" + num2str(alpha)
else
cSpec = name + num2str(i) + "_alpha" + num2str(alpha)
endif
Make/O/N=(pnts) $cSpec
Wave y = $cSpec
if(reScale)
SetScale/i x,280,360,y //Update this so that the x scale is obtained from the panel
endif
for(j=j;j<=i*pnts-1;j+=1)
if(n==1)
y[k] = w[j]
else
y[k] = w[j]
endif
k+=1
endfor
k=0
endfor
End
Function plotPeaks(nSpec,nPeaks,alpha,tval,ovpVal)
Variable nSpec,nPeaks,alpha,tval,ovpVal
Variable i,j
for(j=1;j<=nSpec;j+=1)
String graphName = "Spec_" + num2str(j) +"_Alpha" + replaceString(".",num2str(alpha),"p") + "_OS" + replaceString(".",num2str(tval),"p") + "_OVP" + replaceString(".",num2str(ovpVal),"p")
DoWindow $graphName
if(!V_Flag)
Display/N=$graphName
for(i=0;i<nPeaks;i+=1)
String cPeakName = "pk" + num2str(i) + "_spec" + num2str(j)
Wave z = $cPeakName
AppendToGraph/W=$graphName z
endfor
Label left "Mass Absorbance [cm2/g] \\U";DelayUpdate
Label bottom "Transition Energy[eV]";DelayUpdate
ModifyGraph grid=2,mirror=1,nticks=10,minor=1,fStyle=1,lsize=2
ApplyColorTableToTopGraph("ColdWarm")
endif
endfor
End
Function plotResults(baseNameList,alpha,eName,thetaList,tval,ovpVal)
String baseNameList
Variable alpha
String eName
String thetaList
Variable tval
Variable ovpVal
Variable nItems = ItemsInList(baseNameList,";")
Variable i,j,k
for(i=0;i<nItems;i+=1)
String currentWaveList = StringFromList(i,baseNameList,";")
String currentSetList = WaveList(currentWaveList+"*alpha"+num2str(alpha),";","")
String energyList = WaveList(eName +"*alpha"+num2str(alpha),";","")
Variable nSet = ItemsInList(currentSetList)
String plotName = currentWaveList +"_Alpha" + replaceString(".",num2str(alpha),"p") + "_OS" + replaceString(".",num2str(tval),"p") + "_OVP" + replaceString(".",num2str(ovpVal),"p")
DoWindow $plotName
if(!V_Flag)
String totalLegend = ""
for(j=0;j<nSet;j+=1)
String currentWave = StringFromList(j,currentSetList)
String currentEnergy = StringFromList(j,energyList)
Wave w = $currentWave
Wave x = $currentEnergy
if(j==0)
Display/N=$plotName/K=1 w vs x
elseif(j<nSet)
AppendToGraph/W=$plotName w vs x
endif
String currentTheta = StringFromList(j,thetaList)
String legendPortion
if(StringMatch(currentWaveList,"dftSpec"))
if(j<nSet-1)
legendPortion = "\\s(" + currentWave + ") " + currentTheta + "\r"
else
legendPortion = "\\s(" + currentWave + ") " + currentTheta
endif
elseif(StringMatch(currentWaveList,"dftStep"))
if(j<nSet-1)
legendPortion = "\\s(" + currentWave + ") " + currentTheta + "\r"
else
legendPortion = "\\s(" + currentWave + ") " + currentTheta
endif
elseif(StringMatch(currentWaveList,"expSpec"))
if(j<nSet-1)
legendPortion = "\\s(" + currentWave + ") " + currentTheta + "\r"
else
legendPortion = "\\s(" + currentWave + ") " + currentTheta
endif
endif
totalLegend += legendPortion
endfor
if(StringMatch(currentWaveList,"dftSpec"))
Legend/C/N=text0/J "DFT \r \\JCθ[°]\r \\JL" + totalLegend
elseif(StringMatch(currentWaveList,"dftStep"))
Legend/C/N=text0/J "Step \r \\JCθ[°]\r \\JL" + totalLegend
elseif(StringMatch(currentWaveList,"expSpec"))
Legend/C/N=text0/J "Experiment \r\\JCθ[°]\r \\JL" + totalLegend
endif
Label left "Mass Absorbance [cm\\S2\\M/g] \\U";DelayUpdate
Label bottom "Transition Energy [eV]";DelayUpdate
ModifyGraph grid=2,mirror=1,nticks=10,minor=1,fStyle=1,fSize=16,lsize=1.5
SetAxis bottom 280,320
ApplyColorTableToTopGraph("ColdWarm")
endif
endfor
End
Function plotResultsFit2(baseNameList,alpha,eName,thetaList,tval,ovpMax,nPeaks,NEXAFStype)
String baseNameList
Variable alpha
String eName
String thetaList
Variable tval
Variable ovpMax
Variable nPeaks
String NEXAFStype
Variable nItems = ItemsInList(baseNameList,";")
Variable i,j
alpha = round(alpha)
for(i=0;i<nItems;i+=1)
String currentWaveList = StringFromList(i,baseNameList,";")
String currentSetList = WaveList(currentWaveList+"*alpha"+num2str(alpha),";","")
String energyList = WaveList(eName +"*alpha"+num2str(alpha),";","")
Variable nSet = ItemsInList(currentSetList)
endfor
String summaryPlot = "Final_Comparison" + replaceString(".",num2str(alpha),"p") + "_OS" + replaceString(".",num2str(tval),"p") + "_OVP" + replaceString(".",num2str(ovpMax),"p") + "_" + NEXAFStype
DoWindow $summaryPlot
if(!V_Flag)
Display/N=$summaryPlot/K=1
for(i=0;i<nSet;i+=1)
String currentExp = StringFromList(0,baseNameList,";")
String currentDFT = StringFromList(1,baseNameList,";")
String currentExpList = WaveList(currentExp +"*alpha"+num2str(alpha),";","")
String currentDFTList = WaveList(currentDFT +"*alpha"+num2str(alpha),";","")
String enList = WaveList(eName +"*alpha"+num2str(alpha),";","")
String currentTheta = StringFromList(i,thetaList)
String currentExpWave = StringFromList(i,currentExpList ,";")
String currentDFTWave = StringFromList(i,currentDFTList ,";")
String currentEnerWave = StringFromList(i,enList,";")
Wave w = $currentExpWave
Wave y = $currentDFTWave
Wave x = $currentEnerWave
AppendToGraph w,y vs x
ModifyGraph lstyle($currentDFTWave)=3
endfor
ApplyColorTableToTopGraph("ColdWarm")
//Append Step
String currentStepWave = "dftStep1_alpha" + num2str(alpha)
Wave z = $currentStepWave
AppendToGraph z vs x
ModifyGraph rgb($currentStepWave)=(39321,39321,39321)
Variable magicAngleSpec = findMagicAngle(thetaList)
NewFreeAxis/L BBPeaks
//Append BB peaks to plot
for(i=0;i<nPeaks;i+=1)
String cPeakName = "pk" + num2str(i) + "_spec" + num2str(magicAngleSpec)
Wave pk = $cPeakName
AppendToGraph/L=BBPeaks/W=$summaryPlot pk
ModifyGraph rgb($cPeakName)=(0,0,0)
endfor
Label left "Mass Absorbance [cm\\S2\\M/g] \\U";DelayUpdate
Label bottom "Transition Energy [eV]";DelayUpdate
ModifyGraph grid=2,mirror=1,nticks=20,minor=1,fStyle=1,fSize=16,lsize=1.5
ModifyGraph axisEnab(left)={0.35,1},axisEnab(BBPeaks)={0,0.3},freePos(BBPeaks)=0,lblPosMode=1
SetAxis bottom 283,320
SetAxis BBPeaks 0,100000//*
Label BBPeaks "BB Peaks\\u"
String legendText = "\\s(" + currentExpWave +") Experiment \\s(" + currentDFTWave + ") DFT\r\\s(" + currentStepWave +") Step"
Legend/C/N=text0/J "\\JCα = " + num2str(alpha) + "°\r" + legendText
endif
End
Function/WAVE getParams(tval,ovpVal)
Variable tval,ovpVal
String iniFolder = GetDataFolder(1)
String dftFitFolder = "All"
//Look for folder containing results from amplitude fitting DFT clusters of each component
String iniPwaveName
Variable fit = 0
if(DataFolderExists(dftFitFolder))
SetDataFolder $dftFitFolder
if(fit)
iniPwaveName = "combClusterPWAll"//Use this if using the pwave before fitting to dft
else
iniPwaveName = "pw2DFit"//"pw2dOriginal"//Use this using pwave after fitting to dft
endif
Wave pWave = $iniPwaveName
SetDataFolder iniFolder
Duplicate/O pWave, $iniPwaveName
else
print "Data folder for " + dftFitFolder + " not found."
endif
Wave pw2D = $iniPwaveName
return pw2d
End
Function/WAVE make2Dfrom1DPwave(pw1d)
Wave pw1d
Variable i=0,j,nClusters = (numpnts(pw1d)-4-pw1d[0])/11
Make/O/N=(nClusters,3) pw2D
for(j=4+pw1d[0];j<4+pw1d[0]+11*nClusters;j+=11)
pw2D[i][0] = pw1D[j] //Energy
pw2D[i][1] = pw1D[j+1]//Width
pw2D[i][2] = pw1D[j+2]//Amp
i+=1
endfor
return pw2d
End
//This should be at the end of the clustering process.
Function makeTensor(pWave)
Wave pWave
Variable nClusters = DimSize(pWave,0),i=0
Variable tol = 1/100 //What is the minimum threshold of values to consider for the TDM tensor? If component is less than the V_max*tol then make it 0
Variable targetDP = 10
for(i=0;i<nClusters;i+=1)
String tensorName = "resonance_" + num2str(i)
Make/O/N=(3,3) $tensorName
Wave w = $tensorName
w = 0
w[0][0] = pWave[i][8] ; w[0][1] = pWave[i][11]; w[0][2] = pWave[i][12]
w[1][0] = pWave[i][11]; w[1][1] = pWave[i][9] ; w[1][2] = pWave[i][13]
w[2][0] = pWave[i][12]; w[2][1] = pWave[i][13]; w[2][2] = pWave[i][10]
truncateSym(w,targetDP,tol)
endfor
End
Function normalizeTensor()
String resonanceList = WaveList("resonance_*",";","")
Variable nResonances = ItemsInList(resonanceList)
Variable k
//Add a wave that will contain the max amplitudes
Make/O/N=(nResonances) maxAmplitudes
for(k=0;k<=nResonances-1;k+=1)
String currentTensorName = StringFromList(k,resonanceList)
Wave currentTensor = $currentTensorName
WaveStats/Q $currentTensorName
String normTensorName = "norm_resonance_" + num2str(k)
Duplicate/O currentTensor,$normTensorName
Wave normTensor = $normTensorName
//normTensor = normTensor/V_max
maxAmplitudes[k] = V_max
endfor
End
Function getAmpEnFromFit(pwFit,pwOri,alpha,tval,ovpVal,pwMolAdj,[d])
Wave pwFit
Wave pwOri
Wave pwMolAdj
Variable alpha
Variable tval
Variable ovpVal
Variable d
Variable nPeaks = (numpnts(pwOri) - pwOri[0] - 4)/11
Variable i,j=0,k=0
Variable i0dIF = pwFit[1]
Make/o/n=(nPeaks) iniAmps,fitAmps,iniEns,fitEns,iniTheta,fitTheta
Make/O/N=(nPeaks) ampChange,enChange,modThetaChange,tdmThetaChange,widChange
Make/O/N=(nPeaks) iniTDMTheta,fitTDMTheta,iniWidth,fitWidth
//Get the fitted and original Peak Amplitudes,Widths, and Positions
for(i=pwOri[0] + 4;i<11*nPeaks+pwOri[0]+4;i+=11)
fitEns[j] = pwFit[i]
fitAmps[j] = pwFit[i+2]
fitTheta[j] = pwFit[i+10]
// ------------------------------------------------------------
// Calculate the azamuthal angle by computing the planar and
// vector components
// ------------------------------------------------------------
variable planar_ini = sqrt(pwMolAdj[i+6]^2 + pwMolAdj[i+3]^2)
variable planar_fit = sqrt(pwOri[i+6]^2 + pwOri[i+3]^2)
fitTDMTheta[j] = atan(planar_ini/pwMolAdj[i+8])*(180/pi)
fitWidth[j] = pwFit[i+1]*2.355
iniEns[j] = pwOri[i]
iniAmps[j] = pwOri[i+2]
iniTheta[j] = pwOri[i+10]
iniTDMTheta[j] = atan(planar_fit/pwOri[i+8])*(180/pi)
iniWidth[j] = pwOri[i+1]*2.355
Variable wid = pwFit[i+1]*2.355
enChange[j] = (fitEns[j] - iniEns[j])/(wid) //Relative energy change
modThetaChange[j] = fitTDMTheta[j] - iniTDMTheta[j]//Change in modTheta
ampChange[j] = log(fitAmps[j]/iniAmps[j])//Log Ratio of fit/original amplitudes
tdmThetaChange[j] = fitTDMTheta[j] - iniTDMTheta[j]
widChange[j] = (fitWidth[j] - iniWidth[j])/iniWidth[j]//Relative change in width
j+=1
endfor
if(d)
String gName = "FitParamChange_OS" +num2str(tval) + "_OVP" + num2str(ovpval)
DoWindow $gName
if(!V_Flag)
Display/N=$gName/W=(0,0,300,500)/K=1 ampChange
NewFreeAxis/L deltaEn
NewFreeAxis/L deltaTh
NewFreeAxis/L deltaTDM
AppendToGraph/W=$gName/L=deltaEn enChange
AppendToGraph/W=$gName/L=deltaTh modThetaChange
AppendToGraph/W=$gName/L=deltaTDM fitTDMTheta,iniTDMTheta//tdmThetaChange
ModifyGraph mirror=1,minor=1,fStyle=1,fSize=14,lblPosMode(left)=1,lblPosMode(deltaEn)=1,lblPosMode(deltaTh)=1,lblPosMode(deltaTDM)=1
ModifyGraph axisEnab(left)={0,0.22},axisEnab(deltaEn)={0.25,0.47},axisEnab(deltaTh)={0.5,0.72},axisEnab(deltaTDM)={0.75,1},freePos(deltaEn)=0,freePos(deltaTh)=0,freePos(deltaTDM)=0
ModifyGraph mode=4,marker=19,rgb(enChange)=(1,34817,52428),rgb(modThetaChange)=(1,39321,19939)//,rgb(tdmThetaChange)=(19729,1,39321)
Label left "log(A\\BF\\M/A\\BI\\M)"
Label deltaEn "∆E/FWHM"
Label deltaTh "∆θ[°]"
Label deltaTDM "Final,Initial[°]"
Label bottom "Cluster ID"
SetAxis deltaEn -1,1
SetAxis deltaTh -90,90
ModifyGraph manTick(deltaTh)={0,45,0,0},manMinor(deltaTh)={2,0}
SetAxis deltaTDM 0,90
ModifyGraph manTick(deltaTDM)={0,45,0,0},manMinor(deltaTDM)={2,0}
SetAxis left -1,1
ModifyGraph zero(left)=1,zero(deltaEn)=1,zero(deltaTh)=1,zero(deltaTDM)=1,zeroThick(left)=2,zeroThick(deltaEn)=2,zeroThick(deltaTh)=2,zeroThick(deltaTDM)=2
ModifyGraph rgb(fitTDMTheta)=(19729,1,39321),rgb(iniTDMTheta)=(0,0,0)
endif
endif
// String gName2 = "FitAmplitudes_Alpha_" + replaceString(".",num2str(alpha),"p") + "OS_" + replaceString(".",num2str(tval),"p") + "OVP_" + replaceString(".",num2str(ovpVal),"p")
// DoWindow $gName2
// if(!V_Flag)
// Display/N=$gName2/K=1 fitAmps,iniAmplitudes VS fitEnergies
// Label left "Transition Amplitude [a.u.] \U"
// Label bottom "Peak Energy[eV]"
// ModifyGraph grid=2,zero(left)=1,mirror=1,nticks(bottom)=nPeaks,nTicks(left)=10,minor=1,fStyle=1,zeroThick(left)=2
// ModifyGraph lsize=1.5
// ModifyGraph marker=16,mode(fitAmps)=8,toMode(fitAmps)=1,mode(iniAmplitudes)=3
// ModifyGraph rgb(iniAmplitudes)=(0,0,65535)
// ModifyGraph useNegRGB(fitAmps)=1,usePlusRGB(fitAmps)=1,plusRGB(fitAmps)=(65535,43690,0),negRGB(fitAmps)=(29524,1,58982)
// Legend/C/N=text0/J/A=MC "\\JCAmplitudes\r\\s(fitAmps) Fit\r\\s(iniAmplitudes) Orignal"
// endif
End
//This function fits the molecular tilt angle to a given energy range defined by E1-E2. The pi-manifold is a good choice.
Function/WAVE fitAlpha(E1,E2,pw,xw,ew,tw,sw,nSpec,os,ovp)
Wave pw,xw,ew,sw,tw //Parameter wave, concatenated energy wave,concatenated experimental NEXAFS,concatenated sample theta wave
Variable E1,E2 //Energy range that we want to fit alpha in
Variable nSpec,os,ovp//How many spectra are we fitting?
Wave mw = makeMaskWave(E1,E2,xw)
String H = makeHoldStrAlphaFit(pw,E2)
Wave eps = makeEpsiltonWaveAlphaFit(pw,E2)
Wave con = makeConstraintAlphaFit(pw,E2)
Duplicate/O ew,alphaFitResults,res
Duplicate/O pw, pwAlphaFit
Variable V_FitError=0
FuncFit/H=H simDFTfit2,pwAlphaFit, ew /X={xw,tw,sw} /R=res /E=eps /D=alphaFitResults /M=mw /C=con
splitSpec(alphaFitResults,nSpec,"alphaFit",alpha=pwAlphaFit[2])
Variable alpha = pwAlphaFit[2],i0 = pwAlphaFit[1]
// plotFitResults("alphaFit",alpha,i0,os,ovp)
return pwAlphaFit
End
Function/WAVE fitAlpha2(E1,E2,pw,xw,ew,nSpec,tl,alpha,i0,os,ovp,sw)
Wave pw,xw,ew,sw //Parameter wave, concatenated energy wave,concatenated experimental NEXAFS,concatenated sample theta wave
Variable E1,E2 //Energy range that we want to fit alpha in
Variable nSpec //How many spectra are we fitting?
Variable alpha,i0 //Tilt angle guess
Variable os,ovp
String tl
Duplicate/O pw, pwAlphaFit
Variable nEnergies = detEnPnts(xw,E1,E2),i
Make/O/N=(nEnergies,(nSpec+1)) alphaFitVals
Make/O/N=(nEnergies) energies,alphas
Duplicate/O ew,ew_Sub
ew_Sub = ew - sw
//Variable newAlpha = popAlphaPWave(xw,E1,E2,ew_Sub,alphaFitVals,nSpec,tl,alpha,i0,os,ovp)
//pwAlphaFit[2] = newAlpha
return pwAlphaFit
End
Function detEnPnts(w,E1,E2)
Wave w
Variable E1,E2
Variable p1 = round(BinarySearchInterp(w,E1))
Variable p2 = round(BinarySearchInterp(w,E2))
Variable dif = p2-p1
//print p1,p2,dif
return dif
End
Function popAlphaPWave(xw,E1,E2,ew,pw,nSpec,tl,alpha,i0,os,ovp)
Wave xw//Energy wave
Wave ew//Experiment wave
Wave pw//2D wave that will be populated with energies and intensities to fit
String tl//List containing sample theta values
Variable E1,E2,nSpec,alpha,i0,os,ovp
Variable i,j,pps=numpnts(xw)/nSpec//,n = DimSize(pw,0)
//Variable p1 = round(BinarySearchInterp(xw,E1))
//Variable p2 = round(BinarySearchInterp(xw,E2))
FindLevel/Q/R=[0,pps-1] xw,E1
Variable p1 = round(V_levelX)
FindLevel/Q/R=[0,pps-1] xw,E2
Variable p2 = round(V_levelX)
Variable n = p2-p1
Make/O/N=(nSpec) thetas
Make/O/N=(n) alphas,energies,sigmas,avgAlpha
//This loop will populate the energies for desired energy range
for(i=0;i<n;i+=1)
pw[i][0] = xw[p1 + i]
energies[i] = xw[p1 + i]
endfor
//This loop will populate the intensities for desired energy range for each sample theta into pw
for(j=0;j<nSpec;j+=1)
for(i=0;i<n;i+=1)
pw[i][j] = ew[p1 + j*pps + i]
endfor
endfor
//This loop will populate the theta wave based on the theta list
for(i=0;i<nSpec;i+=1)
thetas[i] = str2num(StringFromList(i,tl))
endfor
//This loop will make and populate the 1d waves containing:
//1. the intensites for each sample theta for each energy
//2. The pw for the alpha fits
//3. The result waves of the fits
for(i=0;i<n;i+=1)
String name = "aFit_" + num2str(i)
String name2 = "aval_" + num2str(i)
String name3 = "alphaResultFit_" + num2str(i)
String name4 = "alphaEpsFit_" + num2str(i)
String name5 = "alphaResiFit_" + num2str(i)
String name6 = "alphaConsFit_" + num2str(i)
Make/O/N=(nSpec) $name,$name3,$name5
Make/D/O/N=(3) $name2,$name4
Make/O/T/N=1 $name6
Wave w = $name
Wave fitpw = $name2
Wave w3 = $name3
Wave eps = $name4
eps[0] = 1e-4
eps[1] = 1e-6
Wave res = $name5
Wave/T con = $name6
con[0] = {"K0>=0","K0<=90","K1>=0"}
fitpw[0] = alpha
fitpw[1] = i0
fitpw[2] = 0 //Only fit Pi Range
for(j=0;j<nSpec;j+=1)
w[j] = pw[i][j]
endfor
//Fit alpha
FuncFit/Q fitStohrAlpha , fitpw, w /X=thetas /D=w3 /R=res /E=eps /C=con
Wave W_Sigma
alphas[i] = fitpw[0]
sigmas[i] = W_sigma[0]
KillWaves $name,$name3,$name2,$name4,$name5,$name6
endfor
WaveStats/Q alphas
avgAlpha = V_avg
Variable alphaMin = V_min
WaveStats/Q sigmas
Variable avgError = V_avg
print avgAlpha
//Display the results of the alpha fit
// String gName = "alphaFit_OS" + num2str(os) + "_OVP" + num2str(ovp)
// DoWindow $gName
// if(!V_Flag)
// Display/N=$gName/K=1 alphas,avgAlpha vs energies
// ErrorBars/W=$gName alphas Y,wave=(sigmas,sigmas)
// ModifyGraph mirror=1,minor=1,fStyle=1,fSize=14
// ModifyGraph mode(alphas)=4,marker(alphas)=19,lstyle(avgAlpha)=3,lsize(avgAlpha)=2,rgb(avgAlpha)=(0,0,0)
// Label left "α[°]"
// Label bottom "Transition Energy[eV]"
// Legend/C/N=text0/J/A=MC "\\s(alphas) alphas\r\\s(avgAlpha) avgAlpha\rAVG α = "+num2str(avgAlpha[0])+" ± "+num2str(avgError)+"°"
// Legend/C/N=text0/J/A=MC "\\s(alphas) alphas\r\\s(avgAlpha) avgAlpha\rAVG α = "+num2str(alphaMin)+" ± "+num2str(avgError)+"°"
// endif
return alphaMin//avgAlpha[0]//
End
Function fitStohrAlpha(pw,yw,xw):FitFunc
Wave pw //This parameter wave contains the value of alpha to be fitted
Wave yw//This is the intensity wave at a given energy
Wave xw//This is the theta wave
pw[0] *= (pi/180)
xw *= (pi/180)
Variable i,n=numpnts(xw)
//if(pw[0] > 55)
// Debugger
//endif
for(i=0;i<n;i+=1)
if(pw[2]==0)//Vector Orbital
yw[i] = pw[1]*(1/3)*(1+0.50*(3*cos(pw[0])^2-1)*(3*cos(xw[i])^2-1))//Vector Orbital
elseif(pw[2]==1)//Planar Orbital
yw[i] = pw[1]*(2/3)*(1-0.25*(3*cos(pw[0])^2-1)*(3*cos(xw[i])^2-1))//Planar Orbital
endif
endfor
pw[0] *= (180/pi)//Convert alpha back to degrees
xw *= (180/pi)
End
Function fitStohrAlpha2(pw,yw,xw)
Wave pw //This parameter wave contains the value of alpha to be fitted
Wave yw//This is the intensity wave at a given energy
Wave xw//This is the theta wave
pw[0] *= (pi/180)
xw *= (pi/180)
Variable i,n=numpnts(xw)
Duplicate/O yw,test
for(i=0;i<n;i+=1)
test[i] = pw[1]*(1/3)*(1+0.5*(3*cos(pw[0])^2-1)*(3*cos(xw[i])^2-1))
endfor
pw[0] *= (180/pi)
xw *= (180/pi)
End
Function plotFitResults(fitStage,alpha,i0,os,ovp)
String fitStage
Variable alpha
Variable i0,os,ovp
Variable i,j=0
Wave M_colors = makeColorWave(0.5)
Variable nColors = DimSize(M_colors,0)
String wList = WaveList(fitStage+"*alpha"+num2str(round(alpha)),";","")
String xList = WaveList("energy*",";","")
String eList = WaveList("exp*",";","")
Variable n = itemsInList(wList)
String pltName = fitStage + "_Results" + "OS" +num2str(os) + "_OVP" + num2str(ovp)
DoWindow $pltName
if(!V_Flag)
Display/N=$pltName/K=1
for(i=0;i<n;i+=1)
String cwn = StringFromList(i,wList)
String xwn = StringFromList(i,xList)
String ewn = StringFromList(i,eList)
Wave w = $cwn, e = $ewn ,x = $xwn
AppendToGraph/W=$pltName w,e vs x
ModifyGraph lstyle($cwn)=3,lsize($ewn)=1.5
ModifyGraph rgb($cwn)=(M_colors[j][0],M_colors[j][1],M_colors[j][2],M_colors[j][3])
ModifyGraph rgb($ewn)=(M_colors[j][0],M_colors[j][1],M_colors[j][2],M_colors[j][3])
j+=1
if(j>=nColors)
j = 0
endif
endfor
Label left "Mass Absorbance [cm\S2\M/g] \U"
Label bottom "Transition Energy [eV]"
ModifyGraph mirror=1,nticks=10,minor=1,fStyle=1,fSize=14
if(StringMatch(fitStage,"alphaFit"))
TextBox/C/N=text0/A=MC "α="+num2str(alpha)+"°"
elseif(StringMatch(fitStage,"i0Fit"))
TextBox/C/N=text0/A=MC "i0="+num2str(i0)
endif
endif
End
Function/WAVE fitI0(E1,E2,pw,xw,ew,tw,sw,nSpec,tval,ovpval)
Wave pw,xw,ew,sw,tw //Parameter wave, concatenated energy wave,concatenated experimental NEXAFS,concatenated sample theta wave
Variable E1,E2 //Energy range that we want to fit alpha in
Variable nSpec //How many spectra are we fitting?
Variable tval,ovpval
Wave mw = makeMaskWave(E1,E2,xw)
String H = makeHoldStrI0Fit(pw)
Wave eps = makeEpsiltonWaveI0Fit(pw)
Duplicate/O ew,i0FitResults,res
Duplicate/O pw, pwi0Fit
Variable V_FitError=0
FuncFit/Q/H=H simDFTfit2,pwi0Fit, ew /X={xw,tw,sw} /R=res /E=eps /D=i0FitResults/M=mw
splitSpec(i0FitResults,nSpec,"i0Fit",alpha=round(pwi0Fit[2]))
splitSpec(xw,nSpec,"energy")
splitSpec(ew,nSpec,"exp")
Variable alpha = pwi0Fit[2],i0 = pwi0Fit[1]
//plotFitResults("i0Fit",alpha,i0,tval,ovpval)
return pwi0Fit
End
Function organizeTensorWaves(alpha,fit)
Variable alpha
String fit
String iniFolder = GetDataFolder(1)
Variable i,j
NewDataFolder/O TensorMisc
String misc = WaveList("!totalNEXAFS*",";","")
Variable nMisc = ItemsInList(misc)
for(j=0;j<nMisc;j+=1)
String currentWave = StringFromList(j,misc)
Wave w = $currentWave
String destFolder = iniFolder + "TensorMisc:"
MoveWave w,$destFolder
endfor
String finalFolderName = "Alpha_" + replaceString(".",num2str(alpha),"p")
NewDataFolder/O $finalFolderName
MoveDataFolder/O=3 TensorMisc,$finalFolderName
if(StringMatch(fit,"no"))
MoveDataFolder/O=3 $finalFolderName,Modeling
endif
End
Function howManySpec(w)
Wave w
Variable dim = WaveDims(w)
Variable n,i,j=1,val
if(dim == 1)
n = numpnts(w)
else
n = DimSize(w,0)
endif
for(i=1;i<n;i+=1)
if(dim == 1)
val = w[i]
if(val != w[i-1])
j+=1
endif
else
val = w[i][1]
if(val != w[i-1][1])
j+=1
endif
endif
endfor
return j
End
Function/S makeThetaList(w)
Wave w
Variable dim = WaveDims(w)
Variable n,i,val
String thetaList = ""
if(dim == 1)
n = numpnts(w)
else
n = DimSize(w,0)
endif
for(i=1;i<n;i+=1)
if(dim == 1)
val = w[i]
if((i-1)==0)
thetaList = AddListItem(num2str(val),thetaList)
elseif(val != w[i-1])
thetaList = AddListItem(num2str(val),thetaList)
endif
else
val = w[i][1]
if((i-1)==0)
thetaList = AddListItem(num2str(val),thetaList)
elseif(val != w[i-1][1])
thetaList = AddListItem(num2str(val),thetaList)
endif
endif
endfor
thetaList = SortList(thetaList,";",2)
return thetaList
End
Function makeCoVar(pw,cvMat,sd,pNames,alpha,[d])
Wave pw,cvMat,sd,pNames
Variable alpha,d
Variable i,j=0
Variable n=numpnts(pw)
Variable nPeaks = (numpnts(pw) - 4 - pw[0])/11
Duplicate/O cvMat,cvMadAdj,corrMat
Duplicate/O pw,pw2
Duplicate/O pNames,pNames2
for(i=0;i<n;i+=1)
Variable sdev = sd[i]
Variable corr = cvMadAdj[i][j]/sdev
if(numtype(corr) != 0 )
corrMat[i][j] = 0
else
corrMat[i][j] = corr
endif
if(j>=n-1)
break
endif
if(i==n-1)
i=0
j+=1
endif
endfor
//Remove Normalized Values of Oscillator Strength. Not used for fitting.
for(i=11*nPeaks+4+pw[0]-6;i>4 + pw[0];i-=11)
DeletePoints i,6,cvMadAdj,corrMat
DeletePoints/M=1 i,6,cvMadAdj,corrMat
DeletePoints i,6,pw2,pNames2
endfor
//Remove Ionization Potentials. Not used for fitting.
for(i=pw[0] + 3;i>3;i-=1)
DeletePoints i,1,cvMadAdj,corrMat
DeletePoints/M=1 i,1,cvMadAdj,corrMat
DeletePoints i,1,pw2,pNames2
endfor
////Remove phi and number of Atoms. Not used for fitting.
if(d)
String corrGName = "CORRELATION_" + replaceString(".",num2str(alpha),"p")
DoWindow $corrGName//CORRELATION
if(!V_Flag)
WaveStats/Q corrMat
NewImage/N=$corrGName/K=1 corrMat
ModifyImage corrMat ctab= {*,*,RedWhiteBlue256,0}
ModifyGraph nticks=10,fStyle=1,gridStyle=2,gridRGB=(0,0,0),margin(left)=25,margin(top)=25,margin(right)=90,fsize=10
Label left "Fit Parameters";DelayUpdate
Label top "Fit Parameters"
ColorScale/C/N=text0/A=RC/E ctab={-0.2,0.2,RedWhiteBlue256,0},axisRange={V_min,V_max}
ColorScale/C/N=text0 "Correlation \\U"
endif
endif
End
Function FitPoly3(yw,xw,StartX, EndX)
WAVE yw, xw
Variable startX, EndX
FindLevel/P/Q xw, startX
Variable startP=floor(V_LevelX)
Findlevel/P/Q xw, endX
Variable endP=floor(V_LevelX)
CurveFit/W=2/Q poly 3, yw[startP,endP]/X=xw[startP,endP]
end
Function Lstep(x, x0,width)
Variable x, x0, width
return 1/2 + 1/pi * atan((x-x0)/(width/2))
end
Function Gstep(x,x0,width)
Variable x, x0, width
Variable c=2*sqrt(2)
return 1/2 + 1/2*erf((x-x0)/(width/c))
end
Function/S makeHoldString(holdAmps,holdWidths,holdPos,pWave1D,holdModTheta,holdAlpha,step)
Variable holdAmps,holdWidths,holdPos,holdModTheta,holdAlpha,step
Wave pWave1D
Variable i,nPeaks = (numpnts(pwave1d)-pwave1d[0]-4)/11
//Make Hold String for fit. Open amplitudes, hold position and width constant
if(holdAlpha)
String H = "1111" //H1 = Number of atoms, i0, alpha, phi
else
H = "1101"
endif
for(i=1;i<=pWave1D[0];i+=1)
H +="1" //For Ionization Potentials from DFT. Used to build the Step Edge. Hold them constant.
endfor
for(i=0;i<=nPeaks-1;i+=1)
//Hold string for peak parameters. Position, Width, Max Amplitude, xxNoRM, xyNorm,xzNorm,yyNorm,yzNorm,zzNorm
//Hold cases:
if(!holdPos && !holdWidths && !holdAmps && !holdModTheta)
H +="00011111110"//"00011111110"
elseif(holdPos && !holdWidths && holdAmps && !holdModTheta)
H +="10111111110"
elseif(holdPos && !holdWidths && !holdAmps && !holdModTheta)
H +="10011111110"//"10011111110"
elseif(holdPos && holdWidths && !holdAmps && !holdModTheta)
H +="11011111110"//"11011111110"
elseif(!holdPos && holdWidths && !holdAmps && !holdModTheta)
H +="01011111110"
elseif(!holdPos && !holdWidths && holdAmps && !holdModTheta)
H +="00111111110"
elseif(!holdPos && holdWidths && holdAmps && !holdModTheta)
H +="01111111110"
elseif(holdAmps && holdWidths && holdAmps && !holdModTheta)
H +="11111111110"
elseif(!holdPos && !holdWidths && !holdAmps && holdModTheta)
H +="00011111111"//"00011111110"
elseif(holdPos && !holdWidths && holdAmps && holdModTheta)
H +="10111111111"
elseif(holdPos && !holdWidths && !holdAmps && holdModTheta)
H +="10011111111"//"10011111110"
elseif(holdPos && holdWidths && !holdAmps && holdModTheta)
H +="11011111111"//"11011111110"
elseif(!holdPos && holdWidths && !holdAmps && holdModTheta)
H +="01011111111"
elseif(!holdPos && !holdWidths && holdAmps && holdModTheta)
H +="00111111111"
elseif(!holdPos && holdWidths && holdAmps && holdModTheta)
H +="01111111111"
elseif(holdAmps && holdWidths && holdAmps && holdModTheta)
H +="11111111111"
endif
endfor
String hName = "holdWave" + num2str(step)
Make/O/N=(numpnts(pWave1D)) $hName
Wave holdWave = $hName
for(i=0;i<numpnts(pWave1D);i+=1)
holdWave[i] = str2num(H[i,i])
endfor
//print H
return H
End
Function/S makeHoldStrAlphaFit(pw,Emax)
Wave pw
Variable Emax
Variable i,nPeaks = (numpnts(pw)-pw[0]-4)/11
//Make Hold String for fit. Open amplitudes, hold position and width constant
String H = "1101" //H1 = Number of atoms, i0, alpha, phi
for(i=1;i<=pw[0];i+=1)
H +="1" //For Ionization Potentials from DFT. Used to build the Step Edge. Hold them constant.
endfor
for(i=0;i<=nPeaks-1;i+=1)
Variable E = pw[i*11+4+pw[0]]
if( E < Emax)
H +="11011111111"//If peak position is less than max mask energy then open amplitudes
else
H +="11111111111"//If peak position is greater than max mask energy then close amplitudes
endif
endfor
Make/O/N=(numpnts(pw)) holdWave_alphaFit
for(i=0;i<numpnts(pw);i+=1)
holdWave_alphaFit[i] = str2num(H[i,i])
endfor
return H
End
Function/S makeHoldStrI0Fit(pw)
Wave pw
Variable i,nPeaks = (numpnts(pw)-pw[0]-4)/11
//Make Hold String for fit. Open amplitudes, hold position and width constant
String H = "1011" //Number of atoms, i0, alpha, phi. Open only i0
for(i=1;i<=pw[0];i+=1)
H +="1" //For Ionization Potentials from DFT. Used to build the Step Edge. Hold them constant.
endfor
for(i=0;i<=nPeaks-1;i+=1)
H +="11111111111"
endfor
Make/O/N=(numpnts(pw)) holdWave_I0Fit
for(i=0;i<numpnts(pw);i+=1)
holdWave_I0Fit[i] = str2num(H[i,i])
endfor
return H
End
Function/WAVE makeConstraintAlphaFit(pw,Emax)
Wave pw
Variable Emax
Variable i,nPeaks = (numpnts(pw)-pw[0]-4)/11,pos,j=0
String c
Make/O/T/N=2 constraintAlpha
constraintAlpha[0] = {"K2 >= 0","K2 <= 90"}
for(i=4 + pw[0];i < 4 + pw[0] + 11*(nPeaks);i+=11)
pos = pw[i+0]
if(pos <= Emax)
c = "K" + num2str(i+2) + " >= 0"
Redimension/N=(2+j) constraintAlpha
constraintAlpha[j+1] = c
j+=1
else
break
endif
endfor
return constraintAlpha
End
Function/WAVE makeEpsiltonWave(pWave1D,holdAmps,holdWidths,holdPos,holdModTheta,holdAlpha,step,[tol])
Wave pWave1D
Variable holdAmps,holdWidths,holdPos,holdModTheta,holdAlpha,step,tol
Variable i,nPeaks = (numpnts(pwave1d)-pwave1d[0]-4)/11,epsPos,epsWid,epsAmp,epsMT
//Set up values for epsilon wave
String eName = "eps" +num2str(step)
Make/O/N=(numpnts(pWave1D)) $eName
Wave eps = $eName
if(ParamIsDefault(tol))
epsPos = 1e-3
epsWid = 1e-3
epsAmp = 1e-3
epsMT = 1e-3
else
epsPos = tol
epsWid = tol
epsAmp = tol
epsMT = tol
endif
eps[0] = 0
eps[1] = 0
if(holdAlpha)
eps[2] = 0
else
eps[2] = 1e-2
endif
eps[3] = 0
for(i=4;i<pWave1D[0] + 4;i+=1)
eps[i] = 0 //For Ionization Potentials from DFT. Used to build the Step Edge
endfor
for(i=4 + pWave1D[0];i<11*nPeaks+4+pWave1D[0];i+=11)
if(!holdPos && !holdWidths && !holdAmps && holdModTheta)
eps[i + 0] = epsPos
eps[i + 1] = epsWid
eps[i + 2] = epsAmp
eps[i + 10] = 0
elseif(holdPos && !holdWidths && holdAmps && holdModTheta)
eps[i + 0] = 0
eps[i + 1] = epsWid
eps[i + 2] = 0
eps[i + 10] = 0
elseif(holdPos && !holdWidths && !holdAmps && holdModTheta)
eps[i + 0] = 0
eps[i + 1] = epsWid
eps[i + 2] = epsAmp
eps[i + 10] = 0
elseif(holdPos && holdWidths && !holdAmps && holdModTheta)
eps[i + 0] = 0
eps[i + 1] = 0
eps[i + 2] = epsAmp
eps[i + 10] = 0
elseif(!holdPos && holdWidths && !holdAmps && holdModTheta)
eps[i + 0] = epsPos
eps[i + 1] = 0
eps[i + 2] = epsAmp
eps[i + 10] = 0
elseif(!holdPos && !holdWidths && holdAmps && holdModTheta)
eps[i + 0] = epsPos
eps[i + 1] = epsWid
eps[i + 2] = 0
eps[i + 10] = 0
elseif(!holdPos && holdWidths && holdAmps && holdModTheta)
eps[i + 0] = epsPos
eps[i + 1] = 0
eps[i + 2] = 0
eps[i + 10] = 0
elseif(holdAmps && holdWidths && holdAmps && holdModTheta)
eps[i + 0] = 0
eps[i + 1] = 0
eps[i + 2] = 0
eps[i + 10] = 0
elseif(!holdPos && !holdWidths && !holdAmps && !holdModTheta) //
eps[i + 0] = epsPos
eps[i + 1] = epsWid
eps[i + 2] = epsAmp
eps[i + 10] = epsMT
elseif(holdPos && !holdWidths && holdAmps && !holdModTheta)
eps[i + 0] = 0
eps[i + 1] = epsWid
eps[i + 2] = 0
eps[i + 10] = epsMT
elseif(holdPos && !holdWidths && !holdAmps && !holdModTheta)
eps[i + 0] = 0
eps[i + 1] = epsWid
eps[i + 2] = epsAmp
eps[i + 10] = epsMT
elseif(holdPos && holdWidths && !holdAmps && !holdModTheta)
eps[i + 0] = 0
eps[i + 1] = 0
eps[i + 2] = epsAmp
eps[i + 10] = epsMT
elseif(!holdPos && holdWidths && !holdAmps && !holdModTheta)
eps[i + 0] = epsPos
eps[i + 1] = 0
eps[i + 2] = epsAmp
eps[i + 10] = epsMT
elseif(!holdPos && !holdWidths && holdAmps && !holdModTheta)
eps[i + 0] = epsPos
eps[i + 1] = epsWid
eps[i + 2] = 0
eps[i + 10] = epsMT
elseif(!holdPos && holdWidths && holdAmps && !holdModTheta)
eps[i + 0] = epsPos
eps[i + 1] = 0
eps[i + 2] = 0
eps[i + 10] = epsMT
elseif(holdAmps && holdWidths && holdAmps && !holdModTheta)
eps[i + 0] = 0
eps[i + 1] = 0
eps[i + 2] = 0
eps[i + 10] = epsMT
endif
eps[i + 3] = 0
eps[i + 4] = 0
eps[i + 5] = 0
eps[i + 6] = 0
eps[i + 7] = 0
eps[i + 8] = 0
eps[i + 9] = 0
endfor
return eps
End
Function/WAVE makeEpsiltonWaveAlphaFit(pw,Emax)
Wave pw
Variable Emax
Variable i,nPeaks = (numpnts(pw)-pw[0]-4)/11
//Set up values for epsilon wave
Make/O/N=(numpnts(pw)) eps_alphaFit
Wave eps = eps_alphaFit
Variable epsAmp = 1e-4
Variable epsAmp2 = 1e-4
eps[0] = 0
eps[1] = 0//5e-9
eps[2] = 1e-2
eps[3] = 0
for(i=4;i<pw[0] + 4;i+=1)
eps[i] = 0 //For Ionization Potentials from DFT. Used to build the Step Edge
endfor
for(i=4 + pw[0];i<11*nPeaks+4+pw[0];i+=11)
eps[i + 0] = 0
eps[i + 1] = 0
if(pw[i] < Emax)
eps[i + 2] = epsAmp
else
eps[i + 2] = 0
endif
eps[i + 3] = 0
eps[i + 4] = 0
eps[i + 5] = 0
eps[i + 6] = 0
eps[i + 7] = 0
eps[i + 8] = 0
eps[i + 9] = 0
eps[i + 10] = 0
endfor
return eps
End
Function/WAVE makeEpsiltonWaveI0Fit(pw)
Wave pw
Variable i,nPeaks = (numpnts(pw)-pw[0]-4)/11
//Set up values for epsilon wave
Make/O/N=(numpnts(pw)) eps_I0Fit
Wave eps = eps_I0Fit
eps[0] = 0
eps[1] = 1e-2
eps[2] = 0
eps[3] = 0
for(i=4;i<pw[0] + 4;i+=1)
eps[i] = 0 //For Ionization Potentials from DFT. Used to build the Step Edge
endfor
for(i=4 + pw[0];i<11*nPeaks+4+pw[0];i+=11)
eps[i + 0] = 0
eps[i + 1] = 0
eps[i + 2] = 0
eps[i + 3] = 0
eps[i + 4] = 0
eps[i + 5] = 0
eps[i + 6] = 0
eps[i + 7] = 0
eps[i + 8] = 0
eps[i + 9] = 0
eps[i + 10] = 0
endfor
return eps
End
Function/WAVE makeConstraintWave(holdAmps,holdWidths,holdPos,nPeaks,pWave1D,holdModTheta,holdAlpha,step)
Variable holdAmps,holdWidths,holdPos,holdModTheta,holdAlpha,step
Variable nPeaks
Wave pWave1D
Variable i,j,pos,pLow,pHigh,wHigh,wid,n=2,emax=360,aMod,wMult=2
// if(nPeaks>14)
// n=1
// wMult=1.5
// else
//
// endif
//Variable openParams = holdAmps + holdWidths + holdPos
String cName = "constraints" + num2str(step)
if(!holdAlpha)
j=2
aMod=2
String alphaLo = "K2 >= 0"
String alphaHi = "K2 <= 90"
else
j=0
aMod=0
endif
if(!holdAlpha)
if(nPeaks == 1)
Make/O/T/N=(2) $cName
Wave/T constraints = $cName
else
Make/O/T/N=(nPeaks) $cName
Wave/T constraints = $cName
endif
constraints[0] = alphaLo
constraints[1] = alphaHi
else
Make/O/T/N=(nPeaks) $cName
Wave/T constraints = $cName
endif
String lcp,hcp,lcp2,hcp2//Constraint strings for position
String lcw,hcw//Constraint strings for width
String lca //Constraint strings for amplitude
String lcm,hcm //Constraint strings for modTheta
if(!holdPos && !holdWidths && !holdAmps &&holdModTheta)
Redimension/N=(5*nPeaks+aMod) constraints
for(i=4 + pWave1D[0];i<11*nPeaks + 4 + pWave1D[0];i+=11)
pos = pWave1D[i+0]
wid = pWave1D[i+1]
pLow = pos - n*wid
pHigh = pos + n*wid
wHigh = wMult*wid
// lcp = "K" + num2str(i+0) + " >=" + num2str(pLow)
// hcp = "K" + num2str(i+0) + " <=" + num2str(pHigh)
lcw = "K" + num2str(i+1) + " > 0"
hcw = "K" + num2str(i+1) + " <=" + num2str(wHigh)
lca = "K" + num2str(i+2) + " > 0"
if(i==4 + pWave1D[0])
lcp = "K" + num2str(i+0) + " >" + num2str(pLow)
hcp = "K" + num2str(i+0) + " <" + num2str(pHigh)
elseif(i == 11*(nPeaks-1) + 4 + pWave1D[0])
lcp = "K" + num2str(i+0) + " >" + num2str(pWave1D[i-11])
hcp = "K" + num2str(i+0) + " <" + num2str(pHigh)
else
lcp = "K" + num2str(i+0) + " >" + num2str(pWave1D[i-11])
hcp = "K" + num2str(i+0) + " <" + num2str(pWave1D[i+11])
endif
hcp2 = "K" + num2str(i+0) + " <=" + num2str(emax)
constraints[j+0] = lcp
constraints[j+1] = hcp
constraints[j+2] = lcw
constraints[j+3] = hcw
constraints[j+4] = lca
j+=5
endfor
elseif(holdPos && !holdWidths && holdAmps &&holdModTheta)
Redimension/N=(2*nPeaks+aMod) constraints
for(i=4 + pWave1D[0];i<11*nPeaks + 4 + pWave1D[0];i+=11)
wid = pWave1D[i+1]
wHigh = wMult*wid
lcw = "K" + num2str(i+1) + " > 0"
hcw = "K" + num2str(i+1) + " <=" + num2str(wHigh)
constraints[j+0] = lcw
constraints[j+1] = hcw
j+=2
endfor
elseif(holdPos && !holdWidths && !holdAmps &&holdModTheta)
Redimension/N=(3*nPeaks+aMod) constraints
for(i=4 + pWave1D[0];i<11*nPeaks + 4 + pWave1D[0];i+=11)
wid = pWave1D[i+1]
wHigh = wMult*wid
lcw = "K" + num2str(i+1) + " > 0"
hcw = "K" + num2str(i+1) + " <=" + num2str(wHigh)
lca = "K" + num2str(i+2) + " > 0"
constraints[j+0] = lcw
constraints[j+1] = hcw
constraints[j+2] = lca
j+=3
endfor
elseif(holdPos && holdWidths && !holdAmps &&holdModTheta)
Redimension/N=(1*nPeaks+aMod) constraints
for(i=4 + pWave1D[0];i<11*nPeaks + 4 + pWave1D[0];i+=11)
lca = "K" + num2str(i+2) + " > 0"
constraints[j+0] = lca
j+=1
endfor
elseif(!holdPos && holdWidths && !holdAmps &&holdModTheta)
Redimension/N=(3*nPeaks+aMod) constraints
for(i=4 + pWave1D[0];i<11*nPeaks + 4 + pWave1D[0];i+=11)
pos = pWave1D[i+0]
wid = pWave1D[i+1]
pLow = pos - n*wid
pHigh = pos + n*wid
// lcp = "K" + num2str(i+0) + " >=" + num2str(pLow)
// hcp = "K" + num2str(i+0) + " <=" + num2str(pHigh)
lca = "K" + num2str(i+2) + " > 0"
if(i==4 + pWave1D[0])
lcp = "K" + num2str(i+0) + " >" + num2str(pLow)
hcp = "K" + num2str(i+0) + " <" + num2str(pHigh)
elseif(i == 11*(nPeaks-1) + 4 + pWave1D[0])
lcp = "K" + num2str(i+0) + " >" + num2str(pWave1D[i-11])
hcp = "K" + num2str(i+0) + " <" + num2str(pHigh)
else
lcp = "K" + num2str(i+0) + " >" + num2str(pWave1D[i-11])
hcp = "K" + num2str(i+0) + " <" + num2str(pWave1D[i+11])
endif
hcp2 = "K" + num2str(i+0) + " <=" + num2str(emax)
constraints[j+0] = lcp
constraints[j+1] = hcp
constraints[j+2] = lca
j+=3
endfor
elseif(!holdPos && !holdWidths && holdAmps &&holdModTheta)
Redimension/N=(5*nPeaks+aMod) constraints
for(i=4 + pWave1D[0];i<11*nPeaks + 4 + pWave1D[0];i+=11)
pos = pWave1D[i+0]
wid = pWave1D[i+1]
wHigh = wMult*wid
pLow = pos - n*wid
pHigh = pos + n*wid
// lcp = "K" + num2str(i+0) + " >=" + num2str(pLow)
// hcp = "K" + num2str(i+0) + " <=" + num2str(pHigh)
lcw = "K" + num2str(i+1) + " > 0"
hcw = "K" + num2str(i+1) + " <=" + num2str(wHigh)
lca = "K" + num2str(i+1) + " > 0"
if(i==4 + pWave1D[0])
lcp = "K" + num2str(i+0) + " >" + num2str(pLow)
hcp = "K" + num2str(i+0) + " <" + num2str(pHigh)
elseif(i == 11*(nPeaks-1) + 4 + pWave1D[0])
lcp = "K" + num2str(i+0) + " >" + num2str(pWave1D[i-11])
hcp = "K" + num2str(i+0) + " <" + num2str(pHigh)
else
lcp = "K" + num2str(i+0) + " >" + num2str(pWave1D[i-11])
hcp = "K" + num2str(i+0) + " <" + num2str(pWave1D[i+11])
endif
hcp2 = "K" + num2str(i+0) + " <=" + num2str(emax)
constraints[j+0] = lcp
constraints[j+1] = hcp
constraints[j+2] = lcw
constraints[j+3] = hcw
constraints[j+4] = lca
j+=5
endfor
elseif(!holdPos && holdWidths && holdAmps &&holdModTheta)
Redimension/N=(2*nPeaks+aMod) constraints
for(i=4 + pWave1D[0];i<11*nPeaks + 4 + pWave1D[0];i+=11)
pos = pWave1D[i+0]
wid = pWave1D[i+1]
pLow = pos - n*wid
pHigh = pos + n*wid
// lcp = "K" + num2str(i+0) + " >=" + num2str(pLow)
// hcp = "K" + num2str(i+0) + " <=" + num2str(pHigh)
if(i==4 + pWave1D[0])
lcp = "K" + num2str(i+0) + " >" + num2str(pLow)
hcp = "K" + num2str(i+0) + " <" + num2str(pHigh)
elseif(i == 11*(nPeaks-1) + 4 + pWave1D[0])
lcp = "K" + num2str(i+0) + " >" + num2str(pWave1D[i-11])
hcp = "K" + num2str(i+0) + " <" + num2str(pHigh)
else
lcp = "K" + num2str(i+0) + " >" + num2str(pWave1D[i-11])
hcp = "K" + num2str(i+0) + " <" + num2str(pWave1D[i+11])
endif
hcp2 = "K" + num2str(i+0) + " <=" + num2str(emax)
constraints[j+0] = lcp
constraints[j+1] = hcp
j+=2
endfor
////////////////////////////////////////////////////////
elseif(!holdPos && !holdWidths && !holdAmps &&!holdModTheta)
Redimension/N=(7*nPeaks+aMod) constraints//(5*nPeaks) constraints
for(i=4 + pWave1D[0];i<11*nPeaks + 4 + pWave1D[0];i+=11)
pos = pWave1D[i+0]
wid = pWave1D[i+1]
wHigh = wMult*wid
pLow = pos - n*wid
pHigh = pos + n*wid
// lcp = "K" + num2str(i+0) + " >=" + num2str(pLow)
// hcp = "K" + num2str(i+0) + " <=" + num2str(pHigh)
lcw = "K" + num2str(i+1) + " > 0"
hcw = "K" + num2str(i+1) + " <=" + num2str(wHigh)
lca = "K" + num2str(i+2) + " > 0"
lcm = "K" + num2str(i+10) + " >= -90"
hcm = "K" + num2str(i+10) + " <= 90"
if(i==4 + pWave1D[0])
lcp = "K" + num2str(i+0) + " >" + num2str(pLow)
hcp = "K" + num2str(i+0) + " <" + num2str(pHigh)
elseif(i == 11*(nPeaks-1) + 4 + pWave1D[0])
lcp = "K" + num2str(i+0) + " >" + num2str(pWave1D[i-11])
hcp = "K" + num2str(i+0) + " <" + num2str(pHigh)
else
lcp = "K" + num2str(i+0) + " >" + num2str(pWave1D[i-11])
hcp = "K" + num2str(i+0) + " <" + num2str(pWave1D[i+11])
endif
hcp2 = "K" + num2str(i+0) + " <=" + num2str(emax)
constraints[j+0] = lcp
constraints[j+1] = hcp
constraints[j+2] = lcw
constraints[j+3] = hcw
constraints[j+4] = lca
constraints[j+5] = lcm
constraints[j+6] = hcm
j+=7
endfor
elseif(holdPos && !holdWidths && holdAmps &&!holdModTheta)
Redimension/N=(4*nPeaks+aMod) constraints
for(i=4 + pWave1D[0];i<11*nPeaks + 4 + pWave1D[0];i+=11)
wid = pWave1D[i+1]
wHigh = wMult*wid
lcw = "K" + num2str(i+1) + " > 0"
hcw = "K" + num2str(i+1) + " <=" + num2str(wHigh)
lcm = "K" + num2str(i+10) + " >= -90"
hcm = "K" + num2str(i+10) + " <= 90"
constraints[j+0] = lcw
constraints[j+1] = hcw
constraints[j+2] = lcm
constraints[j+3] = hcm
j+=4
endfor
elseif(holdPos && !holdWidths && !holdAmps &&!holdModTheta)
Redimension/N=(5*nPeaks+aMod) constraints//(3*nPeaks) constraints
for(i=4 + pWave1D[0];i<11*nPeaks + 4 + pWave1D[0];i+=11)
wid = pWave1D[i+1]
wHigh = wMult*wid
lcw = "K" + num2str(i+1) + " > 0"
hcw = "K" + num2str(i+1) + " <=" + num2str(wHigh)
lca = "K" + num2str(i+2) + " > 0"
lcm = "K" + num2str(i+10) + " >= -90"
hcm = "K" + num2str(i+10) + " <= 90"
constraints[j+0] = lcw
constraints[j+1] = hcw
constraints[j+2] = lca
constraints[j+3] = lcm
constraints[j+4] = hcm
j+=5
endfor
elseif(holdPos && holdWidths && !holdAmps &&!holdModTheta)
Redimension/N=(3*nPeaks+aMod) constraints//(2*nPeaks) constraints
for(i=4 + pWave1D[0];i<11*nPeaks + 4 + pWave1D[0];i+=11)
lca = "K" + num2str(i+2) + " > 0"
lcm = "K" + num2str(i+10) + " >= -90"
hcm = "K" + num2str(i+10) + " <= 90"
constraints[j+0] = lca
constraints[j+1] = lcm
constraints[j+2] = hcm
j+=3
endfor
elseif(!holdPos && holdWidths && !holdAmps &&!holdModTheta)
Redimension/N=(5*nPeaks+aMod) constraints//(4*nPeaks) constraints
for(i=4 + pWave1D[0];i<11*nPeaks + 4 + pWave1D[0];i+=11)
pos = pWave1D[i+0]
wid = pWave1D[i+1]
pLow = pos - n*wid
pHigh = pos + n*wid
// lcp = "K" + num2str(i+0) + " >=" + num2str(pLow)
// hcp = "K" + num2str(i+0) + " <=" + num2str(pHigh)
lca = "K" + num2str(i+2) + " > 0"
lcm = "K" + num2str(i+10) + " >= -90"
hcm = "K" + num2str(i+10) + " <= 90"
if(i==4 + pWave1D[0])
lcp = "K" + num2str(i+0) + " >" + num2str(pLow)
hcp = "K" + num2str(i+0) + " <" + num2str(pHigh)
elseif(i == 11*(nPeaks-1) + 4 + pWave1D[0])
lcp = "K" + num2str(i+0) + " >" + num2str(pWave1D[i-11])
hcp = "K" + num2str(i+0) + " <" + num2str(pHigh)
else
lcp = "K" + num2str(i+0) + " >" + num2str(pWave1D[i-11])
hcp = "K" + num2str(i+0) + " <" + num2str(pWave1D[i+11])
endif
hcp2 = "K" + num2str(i+0) + " <=" + num2str(emax)
constraints[j+0] = lcp
constraints[j+1] = hcp
constraints[j+2] = lca
constraints[j+3] = lcm
constraints[j+4] = hcm
j+=5
endfor
elseif(!holdPos && !holdWidths && holdAmps &&!holdModTheta)
Redimension/N=(6*nPeaks+aMod) constraints
for(i=4 + pWave1D[0];i<11*nPeaks + 4 + pWave1D[0];i+=11)
pos = pWave1D[i+0]
wid = pWave1D[i+1]
wHigh = wMult*wid
pLow = pos - n*wid
pHigh = pos + n*wid
// lcp = "K" + num2str(i+0) + " >=" + num2str(pLow)
// hcp = "K" + num2str(i+0) + " <=" + num2str(pHigh)
lcw = "K" + num2str(i+1) + " > 0"
hcw = "K" + num2str(i+1) + " <=" + num2str(wHigh)
lcm = "K" + num2str(i+10) + " >= -90"
hcm = "K" + num2str(i+10) + " <= 90"
if(i==4 + pWave1D[0])
lcp = "K" + num2str(i+0) + " >" + num2str(pLow)
hcp = "K" + num2str(i+0) + " <" + num2str(pHigh)
elseif(i == 11*(nPeaks-1) + 4 + pWave1D[0])
lcp = "K" + num2str(i+0) + " >" + num2str(pWave1D[i-11])
hcp = "K" + num2str(i+0) + " <" + num2str(pHigh)
else
lcp = "K" + num2str(i+0) + " >" + num2str(pWave1D[i-11])
hcp = "K" + num2str(i+0) + " <" + num2str(pWave1D[i+11])
endif
hcp2 = "K" + num2str(i+0) + " <=" + num2str(emax)
constraints[j+0] = lcp
constraints[j+1] = hcp
constraints[j+2] = lcw
constraints[j+3] = lcw
constraints[j+4] = lcm
constraints[j+5] = hcm
j+=6
endfor
elseif(!holdPos && holdWidths && holdAmps &&!holdModTheta)
Redimension/N=(4*nPeaks+aMod) constraints
for(i=4 + pWave1D[0];i<11*nPeaks + 4 + pWave1D[0];i+=11)
pos = pWave1D[i+0]
wid = pWave1D[i+1]
pLow = pos - n*wid
pHigh = pos + n*wid
// lcp = "K" + num2str(i+0) + " >=" + num2str(pLow)
// hcp = "K" + num2str(i+0) + " <=" + num2str(pHigh)
lcm = "K" + num2str(i+10) + " >= -90"
hcm = "K" + num2str(i+10) + " <= 90"
if(i==4 + pWave1D[0])
lcp = "K" + num2str(i+0) + " >" + num2str(pLow)
hcp = "K" + num2str(i+0) + " <" + num2str(pHigh)
elseif(i == 11*(nPeaks-1) + 4 + pWave1D[0])
lcp = "K" + num2str(i+0) + " >" + num2str(pWave1D[i-11])
hcp = "K" + num2str(i+0) + " <" + num2str(pHigh)
else
lcp = "K" + num2str(i+0) + " >" + num2str(pWave1D[i-11])
hcp = "K" + num2str(i+0) + " <" + num2str(pWave1D[i+11])
endif
hcp2 = "K" + num2str(i+0) + " <=" + num2str(emax)
constraints[j+0] = lcp
constraints[j+1] = hcp
constraints[j+2] = lcm
constraints[j+3] = hcm
j+=4
endfor
elseif(holdAmps && holdWidths && holdAmps &&holdModTheta)
print "Constraint wave not built due to all parameters being held constant"
endif
return constraints
End
Function/WAVE makeConstraintWave2(holdAmps,holdWidths,holdPos,nPeaks,pWave1D,holdModTheta,holdAlpha,step)
Variable holdAmps,holdWidths,holdPos,holdModTheta,holdAlpha,step
Variable nPeaks
Wave pWave1D
Variable i,j,pos,pLow,pHigh,wHigh,wid,n=1,emax=360,aMod,wMult=1.5
// if(nPeaks>14)
// n=1
// wMult=1.5
// else
//
// endif
//Variable openParams = holdAmps + holdWidths + holdPos
String cName = "constraints" + num2str(step)
if(!holdAlpha)
j=2
aMod=2
String alphaLo = "K2 >= 0"
String alphaHi = "K2 <= 90"
else
j=0
aMod=0
endif
if(!holdAlpha)
if(nPeaks == 1)
Make/O/T/N=(2) $cName
Wave/T constraints = $cName
else
Make/O/T/N=(nPeaks) $cName
Wave/T constraints = $cName
endif
constraints[0] = alphaLo
constraints[1] = alphaHi
else
Make/O/T/N=(nPeaks) $cName
Wave/T constraints = $cName
endif
String lcp,hcp,lcp2,hcp2//Constraint strings for position
String lcw,hcw//Constraint strings for width
String lca //Constraint strings for amplitude
String lcm,hcm //Constraint strings for modTheta
if(!holdPos && !holdWidths && !holdAmps &&holdModTheta)
Redimension/N=(2*nPeaks+aMod) constraints
for(i=4 + pWave1D[0];i<11*nPeaks + 4 + pWave1D[0];i+=11)
pos = pWave1D[i+0]
wid = pWave1D[i+1]
pLow = pos - n*wid
pHigh = pos + n*wid
wHigh = wMult*wid
lcw = "K" + num2str(i+1) + " > 0"
lca = "K" + num2str(i+2) + " > 0"
constraints[j+0] = lcw
constraints[j+1] = lca
j+=2
endfor
elseif(holdPos && !holdWidths && holdAmps &&holdModTheta)
Redimension/N=(1*nPeaks+aMod) constraints
for(i=4 + pWave1D[0];i<11*nPeaks + 4 + pWave1D[0];i+=11)
wid = pWave1D[i+1]
wHigh = wMult*wid
lcw = "K" + num2str(i+1) + " > 0"
constraints[j+0] = lcw
j+=1
endfor
elseif(holdPos && !holdWidths && !holdAmps &&holdModTheta)
Redimension/N=(2*nPeaks+aMod) constraints
for(i=4 + pWave1D[0];i<11*nPeaks + 4 + pWave1D[0];i+=11)
wid = pWave1D[i+1]
wHigh = wMult*wid
lcw = "K" + num2str(i+1) + " > 0"
lca = "K" + num2str(i+2) + " > 0"
constraints[j+0] = lcw
constraints[j+2] = lca
j+=2
endfor
elseif(holdPos && holdWidths && !holdAmps &&holdModTheta)
Redimension/N=(1*nPeaks+aMod) constraints
for(i=4 + pWave1D[0];i<11*nPeaks + 4 + pWave1D[0];i+=11)
lca = "K" + num2str(i+2) + " > 0"
constraints[j+0] = lca
j+=1
endfor
elseif(!holdPos && holdWidths && !holdAmps &&holdModTheta)
Redimension/N=(1*nPeaks+aMod) constraints
for(i=4 + pWave1D[0];i<11*nPeaks + 4 + pWave1D[0];i+=11)
pos = pWave1D[i+0]
wid = pWave1D[i+1]
pLow = pos - n*wid
pHigh = pos + n*wid
lca = "K" + num2str(i+2) + " > 0"
constraints[j+0] = lca
j+=1
endfor
elseif(!holdPos && !holdWidths && holdAmps &&holdModTheta)
Redimension/N=(2*nPeaks+aMod) constraints
for(i=4 + pWave1D[0];i<11*nPeaks + 4 + pWave1D[0];i+=11)
pos = pWave1D[i+0]
wid = pWave1D[i+1]
wHigh = wMult*wid
pLow = pos - n*wid
pHigh = pos + n*wid
lcw = "K" + num2str(i+1) + " > 0"
lca = "K" + num2str(i+1) + " > 0"
constraints[j+2] = lcw
constraints[j+4] = lca
j+=2
endfor
elseif(!holdPos && holdWidths && holdAmps &&holdModTheta)
Redimension/N=(0*nPeaks+aMod) constraints
for(i=4 + pWave1D[0];i<11*nPeaks + 4 + pWave1D[0];i+=11)
pos = pWave1D[i+0]
wid = pWave1D[i+1]
pLow = pos - n*wid
pHigh = pos + n*wid
j+=0
endfor
////////////////////////////////////////////////////////
elseif(!holdPos && !holdWidths && !holdAmps &&!holdModTheta)
Redimension/N=(4*nPeaks+aMod) constraints//(5*nPeaks) constraints
for(i=4 + pWave1D[0];i<11*nPeaks + 4 + pWave1D[0];i+=11)
pos = pWave1D[i+0]
wid = pWave1D[i+1]
wHigh = wMult*wid
pLow = pos - n*wid
pHigh = pos + n*wid
lcw = "K" + num2str(i+1) + " > 0"
lca = "K" + num2str(i+2) + " > 0"
lcm = "K" + num2str(i+10) + " >= -90"
hcm = "K" + num2str(i+10) + " <= 90"
constraints[j+0] = lcw
constraints[j+1] = lca
constraints[j+2] = lcm
constraints[j+3] = hcm
j+=4
endfor
elseif(holdPos && !holdWidths && holdAmps &&!holdModTheta)
Redimension/N=(3*nPeaks+aMod) constraints
for(i=4 + pWave1D[0];i<11*nPeaks + 4 + pWave1D[0];i+=11)
wid = pWave1D[i+1]
wHigh = wMult*wid
lcw = "K" + num2str(i+1) + " > 0"
lcm = "K" + num2str(i+10) + " >= -90"
hcm = "K" + num2str(i+10) + " <= 90"
constraints[j+0] = lcw
constraints[j+1] = lcm
constraints[j+2] = hcm
j+=3
endfor
elseif(holdPos && !holdWidths && !holdAmps &&!holdModTheta)
Redimension/N=(4*nPeaks+aMod) constraints//(3*nPeaks) constraints
for(i=4 + pWave1D[0];i<11*nPeaks + 4 + pWave1D[0];i+=11)
wid = pWave1D[i+1]
wHigh = wMult*wid
lcw = "K" + num2str(i+1) + " > 0"
lca = "K" + num2str(i+2) + " > 0"
lcm = "K" + num2str(i+10) + " >= -90"
hcm = "K" + num2str(i+10) + " <= 90"
constraints[j+0] = lcw
constraints[j+1] = lca
constraints[j+2] = lcm
constraints[j+3] = hcm
j+=4
endfor
elseif(holdPos && holdWidths && !holdAmps &&!holdModTheta)
Redimension/N=(3*nPeaks+aMod) constraints//(2*nPeaks) constraints
for(i=4 + pWave1D[0];i<11*nPeaks + 4 + pWave1D[0];i+=11)
lca = "K" + num2str(i+2) + " > 0"
lcm = "K" + num2str(i+10) + " >= -90"
hcm = "K" + num2str(i+10) + " <= 90"
constraints[j+0] = lca
constraints[j+1] = lcm
constraints[j+2] = hcm
j+=3
endfor
elseif(!holdPos && holdWidths && !holdAmps &&!holdModTheta)
Redimension/N=(3*nPeaks+aMod) constraints//(4*nPeaks) constraints
for(i=4 + pWave1D[0];i<11*nPeaks + 4 + pWave1D[0];i+=11)
pos = pWave1D[i+0]
wid = pWave1D[i+1]
pLow = pos - n*wid
pHigh = pos + n*wid
lca = "K" + num2str(i+2) + " > 0"
lcm = "K" + num2str(i+10) + " >= -90"
hcm = "K" + num2str(i+10) + " <= 90"
constraints[j+0] = lca
constraints[j+1] = lcm
constraints[j+2] = hcm
j+=3
endfor
elseif(!holdPos && !holdWidths && holdAmps &&!holdModTheta)
Redimension/N=(3*nPeaks+aMod) constraints
for(i=4 + pWave1D[0];i<11*nPeaks + 4 + pWave1D[0];i+=11)
pos = pWave1D[i+0]
wid = pWave1D[i+1]
wHigh = wMult*wid
pLow = pos - n*wid
pHigh = pos + n*wid
lcw = "K" + num2str(i+1) + " > 0"
lcm = "K" + num2str(i+10) + " >= -90"
hcm = "K" + num2str(i+10) + " <= 90"
constraints[j+0] = lcw
constraints[j+1] = lcm
constraints[j+2] = hcm
j+=3
endfor
elseif(!holdPos && holdWidths && holdAmps &&!holdModTheta)
Redimension/N=(2*nPeaks+aMod) constraints
for(i=4 + pWave1D[0];i<11*nPeaks + 4 + pWave1D[0];i+=11)
pos = pWave1D[i+0]
wid = pWave1D[i+1]
pLow = pos - n*wid
pHigh = pos + n*wid
lcm = "K" + num2str(i+10) + " >= -90"
hcm = "K" + num2str(i+10) + " <= 90"
constraints[j+0] = lcm
constraints[j+1] = hcm
j+=2
endfor
elseif(holdAmps && holdWidths && holdAmps &&holdModTheta)
print "Constraint wave not built due to all parameters being held constant"
endif
return constraints
End
Function alphaModelPlotting(fit,allExpEnergy,allExpSpec,allStepEnergy,allDFTSteps,results,totalNEXAFS,nSpec,nPeaks,pwCopy,tval,ovpVal,thetaList,d,NEXAFStype,[alpha])
String fit,thetaList,NEXAFStype
Wave allExpEnergy,allExpSpec,allStepEnergy,allDFTSteps,results,totalNEXAFS,pwCopy
Variable nSpec,nPeaks,tval,ovpVal,d,alpha
if(StringMatch(fit,"yes"))
splitSpec(allExpEnergy ,nSpec,"expEnergy" ,alpha=round(pwCopy[2]))
splitSpec(allExpSpec ,nSpec,"expSpec" ,alpha=round(pwCopy[2]))
splitSpec(allStepEnergy,nSpec,"stepEnergy",alpha=round(pwCopy[2]))
splitSpec(allDFTSteps ,nSpec,"dftStep" ,alpha=round(pwCopy[2]))
splitSpec(results ,nSpec,"fitresults" ,alpha=round(pwCopy[2]))
// if(d)
// print "Generating comparison plots from fits."
// plotResultsFit2("expSpec;fitresults;dftStep;",pwCopy[2],"expEnergy",thetaList,tval,ovpVal,nPeaks,NEXAFStype)
// endif
elseif(StringMatch(fit,"no"))
splitSpec(allExpEnergy ,nSpec,"expEnergy" ,alpha=alpha)
splitSpec(allExpSpec ,nSpec,"expSpec" ,alpha=alpha)
splitSpec(allStepEnergy,nSpec,"stepEnergy",alpha=alpha)
splitSpec(allDFTSteps ,nSpec,"dftStep" ,alpha=alpha)//,reScale=1)
splitSpec(totalNEXAFS ,nSpec,"dftSpec" ,alpha=alpha)
if(d)
print "Generating comparison plots from modeling."
// plotPeaks(nSpec,nPeaks,pwCopy[2],tval,ovpVal)
plotResults("dftSpec;",alpha,"expEnergy",thetaList,tval,ovpVal)
endif
endif
End
Function findMagicAngle(thetaList)
String thetaList
Variable nThetas = ItemsInList(thetaList),i
for(i=0;i<nThetas;i+=1)
Variable thetaVal = str2num(StringFromList(i,thetaList))
if((54 <= thetaVal) && (thetaVal <=55))
break
endif
endfor
return i+1
End
Function/WAVE makeMaskWave(E1,E2,xw)
Variable E1,E2 //Energies defining region to be fit. Energies less/greater than E1/E2 will be masked
Wave xw //Energy wave
//Fit only region between energy 1 and energy 2
//If maskwave point equals 0 then point won't be fitted.
Duplicate/O xw,maskWave
Variable i,x=numpnts(xw)
for(i=0;i<x;i+=1)
Variable en = xw[i]
if(en >= E1 && en <= E2)
maskWave[i] = 1
else
maskWave[i] = 0
endif
endfor
return maskWave
End
// bare fit function for simDFT
Function simpleDFTModel(pw,norm3D,thetaValues)
Wave pw //1D Parameter wave. Has peak positions,widths, and amplitudes. has initial guess for alpha and IPs required to build step edge
Wave norm3D //Absorption tensor
Wave thetaValues
Variable i,j=0,k,m
//Make the absorption tensor for each transition, normalize it, and place each transition into a layer of a 3D wave
Variable nTransitions = DimSize(norm3D,2)
Variable pos,wid,amp,alpha,i0,phi
Variable p0,pf,nSpec=numpnts(thetaValues),cSpec=1,thetaVal
Variable nAtoms = pw[0]
Variable targetDP = 10
Make/O/D/N=(3,3) currentTensor = 0
//This is the wave that will contain the DFT tensor model NEXAFS
Variable specpnts = 300*nSpec
Variable ini = 280,fin=290,res=2000
Wave xWave = makeX(ini,fin,specpnts,nSpec)
Wave thw = makeThetaWave(ini,fin,specpnts,nSpec,thetaValues)
Variable nPnts = specpnts/nSpec
Make/O/D/N=(nTransitions) MA = 0
//Make rotation matrices for rotation of 90,180,and 270 degrees around z-axis
Make/O/D/N=(3,3) rotMat0 = {{cos(0*(Pi/180)) ,sin(0*(Pi/180)),0} ,{-sin(0*(Pi/180)) ,cos(0*(Pi/180)),0} ,{0,0,1}}
Make/O/D/N=(3,3) rotMat90 = {{cos(90*(Pi/180)) ,sin(90*(Pi/180)),0} ,{-sin(90*(Pi/180)) ,cos(90*(Pi/180)),0} ,{0,0,1}}
Make/O/D/N=(3,3) rotMat180 = {{cos(180*(Pi/180)),sin(180*(Pi/180)),0},{-sin(180*(Pi/180)),cos(180*(Pi/180)),0},{0,0,1}}
Make/O/D/N=(3,3) rotMat270 = {{cos(270*(Pi/180)),sin(270*(Pi/180)),0},{-sin(270*(Pi/180)),cos(270*(Pi/180)),0},{0,0,1}}
for(i=3;i<3+3*nTransitions;i+=3)
i0 = pw[0]
alpha = pw[1]//90-pw[i+9]
phi = pw[2]
pos = pw[i + 0]
wid = pw[i + 1]
amp = pw[i + 2]
currentTensor = i0 * amp * norm3D[p][q][j]
Make/O/D/N=(3,3) rotMatAlignX = {{1,0,0},{0,cos(alpha*(Pi/180)),sin(alpha*(Pi/180))},{0,-sin(alpha*(Pi/180)),cos(alpha*(Pi/180))}}
MatrixOP/O tiltedTensor = rotMatAlignX x currentTensor x rotMatAlignX^t
MatrixOP/O RotTensor0 = rotMat0 x tiltedTensor x rotMat0^t
MatrixOP/O RotTensor90 = rotMat90 x tiltedTensor x rotMat90^t
MatrixOP/O RotTensor180 = rotMat180 x tiltedTensor x rotMat180^t
MatrixOP/O RotTensor270 = rotMat270 x tiltedTensor x rotMat270^t
MatrixOP/O filmTensor = RotTensor0 + RotTensor90 + RotTensor180 + RotTensor270
for(k=0;k<=2;k+=1)
for(m=0;m<=2;m+=1)
Variable currComp = filmTensor[k][m]
targetDP = round(targetDP)
currComp = round(currComp * (10^targetDP)) / (10^targetDP)
if(currComp == -0)
currComp = 0
endif
filmTensor[k][m] = currComp
endfor
endfor
if(j<nTransitions)
if(cSpec == 1)
p0 = 0
pf = nPnts-1
thetaVal = thw[p0]
elseif(cSpec == nSpec)
p0 = (cSpec-1)*nPnts
pf = cSpec*nPnts-1
thetaVal = thw[p0]
else
p0 = (cSpec-1)*nPnts
pf = cSpec*nPnts-1
thetaVal = thw[p0]
endif
endif
String eName = "eField_" + num2str(thetaVal)
Make/O/D/N=(3) $eName = {sin(thetaVal*(Pi/180))*cos(phi*(Pi/180)),sin(thetaVal*(Pi/180))*sin(phi*(Pi/180)),cos(thetaVal*(Pi/180))}
Wave eField = $eName
MatrixOP/O tempMA = amp * (eField^t x filmTensor x eField)
if(numtype(tempMA[0]) !=0)
MA[j] = 0
else
MA[j] = tempMA[0]
endif
//Make totalNEXAFS for current Theta
String tNXFSname = "totalNEXAFS_" + num2str(thetaVal)
Make/O/N=(specpnts) $tNXFSname
Wave totalNEXAFS = $tNXFSname
//Make peaks associated with current theta
String pkName = "pk" + num2str(j) + "_spec" + num2str(cSpec) + "_Alpha" + num2str(alpha) + "_Theta" + num2str(thetaVal)
Make/O/N=(res) $pkName
Wave z = $pkName
SetScale/i x,ini,fin,z
z = MA[j] * gauss(x,pos,wid)
totalNEXAFS += MA[j] * gauss(xWave,pos,wid)
j+=1
if(j<=nTransitions)
if(cSpec == 1)
if(j==(nTransitions) && cSpec < nSpec)
i=0
cSpec+=1
j=0
endif
else
if(j==(nTransitions) && cSpec < nSpec)
i=0
cSpec+=1
j=0
endif
endif
endif
endfor
KillWaves rotMat0,rotMat90,rotMat180,rotMat270,rotTensor0,rotTensor90,rotTensor180,rotTensor270,rotMatAlignX
organizeSimpleModel(alpha)
plotSimpleTensor(pw)
Wave enWave = makeX2(ini,fin,res)
plotAlphaIntensities(pw,thetaValues,enWave)
concatenateEField()
End
Function organizeSimpleModel(alpha)
Variable alpha
String iniFolder = GetDataFolder(1)
String fName = "Alpha_" + num2str(alpha)
NewDataFolder/O $fName
String pkWaves = WaveList("pk*",";","")
Variable npks = ItemsInList(pkWaves),i
for(i=0;i<npks;i+=1)
String name = StringFromList(i,pkWaves)
Wave w = $name
String nName = iniFolder + fName + ":" + name
Duplicate/O w,$nName
KillWaves w
endfor
End
Function plotSimpleTensor(pWave)
Wave pWave
Variable alpha = pWave[1]
Variable energy = pWave[3],width = pWave[4],i
String iniFolder = GetDataFolder(1)
String fName = "Alpha_" + num2str(alpha)
SetDataFolder $fName
String wList = WaveList("pk*",";","")
Variable n = ItemsInList(wList)
String plotName = "Theta_Peaks"//"Alpha_" + num2str(alpha) + "_PLOT"
DoWindow $plotName
if(!V_Flag)
Display/N=$plotName/K=1
for(i=0;i<n;i+=1)
String wName = StringFromList(i,wList)
Wave w = $wName
AppendToGraph/W=$plotName w
endfor
SetAxis bottom energy-3*width,energy+3*width
ModifyGraph grid=2,mirror=1,nticks(left)=10,minor=1,fStyle=1,fSize=14,lsize=1.5
Label left "Transition Intensity [a.u.]"
Label bottom "Transition Energy [eV]"
ApplyColorTableToTopGraph("ColdWarm")
TextBox/C/N=text0 "Alpha " + num2str(alpha)
endif
SetDataFolder $iniFolder
End
Function plotAlphaIntensities(pWave,tw,ew)
Wave pWave,tw,ew
Variable pt = BinarySearch(ew,pWave[3])
Variable alpha = pWave[1]
String iniFolder = GetDataFolder(1)
String fName = "Alpha_" + num2str(alpha)
SetDataFolder $fName
String wList = WaveList("pk*",";","")
Variable n = ItemsInList(wList),i
String intName = "intensity_Alpha" + num2str(alpha)
Make/O/N=(n) $intName
Wave intensity = $intName
for(i=0;i<n;i+=1)
String name = StringFromList(i,wList)
Wave w = $name
intensity[i] = w[pt]
endfor
String plotName = "Theta_Intensities"//"alphaIntensities_" + num2str(alpha)
DoWindow $plotName
if(!V_Flag)
Display/N=$plotName/K=1 intensity vs tw
ModifyGraph grid=2,mirror=1,nticks(left)=10,minor=1,fStyle=1,fSize=14,lsize=1.5,mode=4,marker=19,msize=3
Label left "Transition Intensity [a.u.]"
Label bottom "Sample θ [°]"
endif
SetDataFolder $iniFolder
End
Function plotAlphaIntensities2(en,ew,nxname,nSpec,thetaList)
Wave ew
Variable en,nSpec
String nxName,thetaList
Variable pt = BinarySearch(ew,en),i
Make/O/N=(nSpec) intensity,tw
String nxList = WaveList(nxname+"*",";","")
for(i=0;i<nSpec;i+=1)
String name = StringFromList(i,nxList)
Wave w = $name
intensity[i] = w[pt]
tw[i] = str2num(StringFromList(i,thetaList))
endfor
String plotName = "Theta_Intensities"//"alphaIntensities_" + num2str(alpha)
DoWindow $plotName
if(!V_Flag)
Display/N=$plotName/K=1 intensity vs tw
ModifyGraph grid=2,mirror=1,nticks(left)=10,minor=1,fStyle=1,fSize=14,lsize=1.5,mode=4,marker=19,msize=3
Label left "Transition Intensity [a.u.]"
Label bottom "Sample θ [°]"
endif
End
Function/WAVE makeX(ini,fin,res,nSpec)
Variable ini,fin,res,nSpec
Make/O/N=(res) xWave = 0
Variable i,j=1,c=1
for(i=0;i<res;i+=1)
xWave[i] = ini + j*(fin-ini)/(res/nSpec)
j+=1
if(mod(i+1,(res/nSpec))==0 && i!=0)
j=0
c+=1
if(c<=nSpec)
continue
else
break
endif
endif
endfor
return xWave
End
Function/WAVE makeThetaWave(ini,fin,res,nSpec,thetaValues)
Variable ini,fin,res,nSpec
Wave thetaValues
Make/O/N=(res) thetaWave = 0
Variable i,c=0
for(i=0;i<res;i+=1)
Variable thetaVal = thetaValues[c]
thetaWave[i] = thetaVal
if(mod(i+1,(res/nSpec))==0 && i!=0)
c+=1
if(c<=nSpec)
continue
else
break
endif
endif
endfor
return thetaWave
End
Function/WAVE makeX2(ini,fin,res)
Variable ini,fin,res
Make/O/N=(res) enWave = 0
Variable i
for(i=0;i<res;i+=1)
enWave[i] = ini + i*(fin-ini)/res
endfor
return enWave
End
Function concatenateEField()
String eFieldList = WaveList("eField*",";","")
Concatenate eFieldList,AllEFIelds
Variable i,n=ItemsInList(eFieldList)
for(i=0;i<n;i+=1)
String name = StringFromList(i,eFieldList)
Wave w = $name
KillWaves w
endfor
End
Function fitSinglePeak(pw,pkID,holdPos,holdWidths,holdAmps,holdSecAmp,tval,ovpMax,alpha,mol)
Wave pw
Variable pkId
Variable holdPos,holdWidths,holdAmps,holdSecAmp
Variable tval,ovpMax
Variable alpha
String mol
String baseFolder = "root:Packages:DFTClustering:PolarAngles_"+mol+":TransitionFiltering_"+ replaceString(".",num2str(tval),"p") + "OS_" + replaceString(".",num2str(ovpMax),"p") +"OVP:AmplitudeFitting1:"
String iniFolder = baseFolder + "Alpha_" + replaceString(".",num2str(alpha),"p")
String tensorFolder = iniFolder + ":TensorMisc:"
SetDataFolder $tensorFolder
//TO DO:
//1. Find the parameter wave for the fits
String newpwName = "refine_pwCopy_pk" + num2str(pkID)
Duplicate/O pw,$newpwName
Wave newpw = $newpwName
//2. Find the experimental NEXAFS to be fit
String specName = tensorFolder + "allExpSpec"
Wave spec = $specName
String resultsName = "refine_results_pk" + num2str(pkID)
String residualName = "refine_res_pk" + num2str(pkID)
Duplicate/O spec,$resultsName,$residualName
Wave results = $resultsName
Wave res = $residualName
//3. Find the experimental energies
String enName = tensorFolder + "allExpEnergy"
Wave en = $enName
//4.Get wave with sample theta values
Wave valuesPolar
//5.Get wave with DFT step edge
Wave allDFTSteps
//6. Modify hold string ,constraint wave and epsilon wave so that only the parameters of the current peak are modified
Wave constraints = makeSingleConstraintWave(holdAmps,holdWidths,holdPos,holdSecAmp,pw,pkID)
Wave epsilon = makeSingleEpsiltonWave(pw,pkID,holdAmps,holdWidths,holdPos,holdSecAmp)
String H = makeSingleHoldString(holdAmps,holdWidths,holdPos,holdSecAmp,pw,pkID)
//Variable V_FitError = 0
Variable V_FitTol = 0.00001
if(holdAmps && holdWidths && holdPos)
FuncFit/H=H/M=2 simDFTfit2,newpw, spec /X={en,valuesPolar,allDFTSteps} /R=res /E=epsilon /D=results
else
FuncFit/H=H/M=2 simDFTfit2,newpw, spec /X={en,valuesPolar,allDFTSteps} /R=res /E=epsilon /C=constraints /D=results
endif
splitSpec(results,4,"refine_results_pk" + num2str(pkID) +"_",alpha=alpha)
End
//This function makes the constraint wave for the fit refinement.
//The amplitudes of all peaks remain open but the position,width, amplitude, local alpha, and tensor element ratio can be opened for a desired peak.
Function/WAVE makeSingleConstraintWave(holdAmps,holdWidths,holdPos,holdSecAmp,pWave1D,pkID)
Variable holdAmps,holdWidths,holdPos,holdSecAmp
Variable pkID
Wave pWave1D
Variable i=4 + pWave1D[0] + pkID*11,j=2,pos,pLow,pHigh,wid,n=2
Variable nPeaks = ((numpnts(pWave1D) - 4 - pWave1D[0])/11)-1,cpk=0
Variable totalConstraints = 0
if(!holdAmps)
totalConstraints +=1
endif
if(!holdWidths)
totalConstraints +=1
endif
if(!holdPos)
totalConstraints +=2
endif
if(!holdSecAmp)
totalConstraints +=1
endif
String constraintWName = "constraints_Pk" + num2str(pkID)
Make/O/T/N=(nPeaks + totalConstraints) $constraintWName
Wave/T constraints = $constraintWName
//Change amplitude such that it's the absolute value.
String lc0,lc1,lc2,lc3,hc0
//lc0 --> Controls the lower bound for the peak position
//hc0 --> Controls the upper bound for the peak position
//lc1 --> Controls the lower bound for the peak width (always be greater than 0)
//lc2 --> Controls the lower bound on the peak amplitude (Always greater than 0)
//lc3 --> Controls the lower bound for the ratio between the tensor elements (always greater than zero)
//lc4 --> Controls the lower bound for the tilt angle (always greater than or equal to 0 degrees)
//lc5 --> Controls the upper bound on the tilt angle (always less than or equal to 90 degrees)
if(!holdPos && !holdWidths && !holdAmps && !holdSecAmp)
Redimension/N=(nPeaks + totalConstraints) constraints//(5*nPeaks) constraints
j=0
for(i=4 + pWave1D[0];i < 4 + pWave1D[0] + 11*(nPeaks+1);i+=11)
if(cpk == pkID)
pos = pWave1D[i+0]
wid = pWave1D[i+1]
pLow = pos - n*wid
pHigh = pos + n*wid
lc0 = "K" + num2str(i+0) + " >=" + num2str(pLow)
hc0 = "K" + num2str(i+0) + " <=" + num2str(pHigh)
lc1 = "K" + num2str(i+1) + " >= 0"
lc2 = "K" + num2str(i+2) + " >= 0"
lc3 = "K" + num2str(i+10) + " >= 0"
constraints[j+0] = lc0
constraints[j+1] = hc0
constraints[j+2] = lc1
constraints[j+3] = lc2
constraints[j+4] = lc3
j+=5
cpk+=1
else
lc2 = "K" + num2str(i+2) + " >= 0"
constraints[j+0] = lc2
j+=1
cpk+=1
endif
endfor
elseif(holdPos && !holdWidths && holdAmps && !holdSecAmp)
Redimension/N=(nPeaks + totalConstraints) constraints
j=0
for(i=4 + pWave1D[0];i < 4 + pWave1D[0] + 11*(nPeaks+1);i+=11)
if(cpk == pkID)
lc1 = "K" + num2str(i+1) + " >= 0"
constraints[j+0] = lc1
j+=1
cpk+=1
else
lc2 = "K" + num2str(i+2) + " >= 0"
// lc3 = "K" + num2str(i+10) + " >= 0"
constraints[j+0] = lc2
// constraints[j+1] = lc3
j+=1
cpk+=1
endif
endfor
elseif(holdPos && !holdWidths && !holdAmps && !holdSecAmp)
Redimension/N=(nPeaks + totalConstraints) constraints//(3*nPeaks) constraints
j=0
for(i=4 + pWave1D[0];i < 4 + pWave1D[0] + 11*(nPeaks+1);i+=11)
if(cpk == pkID)
lc1 = "K" + num2str(i+1) + " >= 0"
lc2 = "K" + num2str(i+2) + " >= 0"
lc3 = "K" + num2str(i+10) + " >= 0"
constraints[j+0] = lc1
constraints[j+1] = lc2
// constraints[j+2] = lc3
j+=2
cpk+=1
else
lc2 = "K" + num2str(i+2) + " >= 0"
// lc3 = "K" + num2str(i+10) + " >= 0"
constraints[j+0] = lc2
// constraints[j+1] = lc3
j+=1
cpk+=1
endif
endfor
elseif(holdPos && holdWidths && !holdAmps && !holdSecAmp)
Redimension/N=(nPeaks + totalConstraints) constraints//(2*nPeaks) constraints
j=0
for(i=4 + pWave1D[0];i < 4 + pWave1D[0] + 11*(nPeaks+1);i+=11)
if(cpk == pkID)
lc2 = "K" + num2str(i+2) + " >= 0"
lc3 = "K" + num2str(i+10) + " >= 0"
constraints[j+0] = lc2
// constraints[j+1] = lc3
j+=1
cpk+=1
else
lc2 = "K" + num2str(i+2) + " >= 0"
// lc3 = "K" + num2str(i+10) + " >= 0"
constraints[j+0] = lc2
// constraints[j+1] = lc3
j+=1
cpk+=1
endif
endfor
elseif(!holdPos && holdWidths && !holdAmps && !holdSecAmp)
Redimension/N=(nPeaks + totalConstraints) constraints//(4*nPeaks) constraints
j=0
for(i=4 + pWave1D[0];i < 4 + pWave1D[0] + 11*(nPeaks+1);i+=11)
if(cpk == pkID)
pos = pWave1D[i+0]
wid = pWave1D[i+1]
pLow = pos - n*wid
pHigh = pos + n*wid
lc0 = "K" + num2str(i+0) + " >=" + num2str(pLow)
hc0 = "K" + num2str(i+0) + " <=" + num2str(pHigh)
lc2 = "K" + num2str(i+2) + " >= 0"
lc3 = "K" + num2str(i+10) + " >= 0"
constraints[j+0] = lc0
constraints[j+1] = hc0
constraints[j+2] = lc2
constraints[j+3] = lc3
j+=4
cpk+=1
else
lc2 = "K" + num2str(i+2) + " >= 0"
// lc3 = "K" + num2str(i+10) + " >= 0"
constraints[j+0] = lc2
// constraints[j+1] = lc3
j+=1
cpk+=1
endif
endfor
elseif(!holdPos && !holdWidths && holdAmps && !holdSecAmp)
Redimension/N=(nPeaks + totalConstraints) constraints
j=0
for(i=4 + pWave1D[0];i < 4 + pWave1D[0] + 11*(nPeaks+1);i+=11)
if(cpk == pkID)
pos = pWave1D[i+0]
wid = pWave1D[i+1]
pLow = pos - n*wid
pHigh = pos + n*wid
lc0 = "K" + num2str(i+0) + " >=" + num2str(pLow)
hc0 = "K" + num2str(i+0) + " <=" + num2str(pHigh)
lc1 = "K" + num2str(i+1) + " >= 0"
lc3 = "K" + num2str(i+10) + " >= 0"
constraints[j+0] = lc0
constraints[j+1] = hc0
constraints[j+2] = lc1
constraints[j+3] = lc3
j+=4
cpk+=1
else
lc2 = "K" + num2str(i+2) + " >= 0"
// lc3 = "K" + num2str(i+10) + " >= 0"
constraints[j+0] = lc2
// constraints[j+1] = lc3
j+=1
cpk+=1
endif
endfor
elseif(!holdPos && holdWidths && holdAmps && !holdSecAmp)
Redimension/N=(nPeaks + totalConstraints) constraints
j=0
for(i=4 + pWave1D[0];i < 4 + pWave1D[0] + 11*(nPeaks+1);i+=11)
if(cpk == pkID)
pos = pWave1D[i+0]
wid = pWave1D[i+1]
pLow = pos - n*wid
pHigh = pos + n*wid
lc0 = "K" + num2str(i+0) + " >=" + num2str(pLow)
hc0 = "K" + num2str(i+0) + " <=" + num2str(pHigh)
lc3 = "K" + num2str(i+10) + " >= 0"
constraints[j+0] = lc0
constraints[j+1] = hc0
constraints[j+2] = lc3
j+=3
cpk+=1
else
lc2 = "K" + num2str(i+2) + " >= 0"
// lc3 = "K" + num2str(i+10) + " >= 0"
constraints[j+0] = lc2
// constraints[j+1] = lc3
j+=1
cpk+=1
endif
endfor
elseif(!holdPos && !holdWidths && !holdAmps && holdSecAmp)
Redimension/N=(nPeaks + totalConstraints) constraints//(5*nPeaks) constraints
j=0
for(i=4 + pWave1D[0];i < 4 + pWave1D[0] + 11*(nPeaks+1);i+=11)
if(cpk == pkID)
pos = pWave1D[i+0]
wid = pWave1D[i+1]
pLow = pos - n*wid
pHigh = pos + n*wid
lc0 = "K" + num2str(i+0) + " >=" + num2str(pLow)
hc0 = "K" + num2str(i+0) + " <=" + num2str(pHigh)
lc1 = "K" + num2str(i+1) + " >= 0"
lc2 = "K" + num2str(i+2) + " >= 0"
lc3 = "K" + num2str(i+10) + " >= 0"
constraints[j+0] = lc0
constraints[j+1] = hc0
constraints[j+2] = lc1
constraints[j+3] = lc2
// constraints[j+4] = lc3
j+=4
cpk+=1
else
lc2 = "K" + num2str(i+2) + " >= 0"
// lc3 = "K" + num2str(i+10) + " >= 0"
constraints[j+0] = lc2
// constraints[j+1] = lc3
j+=1
cpk+=1
endif
endfor
elseif(holdPos && !holdWidths && holdAmps && holdSecAmp)
Redimension/N=(nPeaks + totalConstraints) constraints
j=0
for(i=4 + pWave1D[0];i < 4 + pWave1D[0] + 11*(nPeaks+1);i+=11)
if(cpk == pkID)
lc1 = "K" + num2str(i+1) + " >= 0"
constraints[j+0] = lc1
j+=1
cpk+=1
else
lc2 = "K" + num2str(i+2) + " >= 0"
// lc3 = "K" + num2str(i+10) + " >= 0"
constraints[j+0] = lc2
// constraints[j+1] = lc3
j+=1
cpk+=1
endif
endfor
elseif(holdPos && !holdWidths && !holdAmps && holdSecAmp)
Redimension/N=(nPeaks + totalConstraints) constraints//(3*nPeaks) constraints
j=0
for(i=4 + pWave1D[0];i < 4 + pWave1D[0] + 11*(nPeaks+1);i+=11)
if(cpk == pkID)
lc1 = "K" + num2str(i+1) + " >= 0"
lc2 = "K" + num2str(i+2) + " >= 0"
lc3 = "K" + num2str(i+10) + " >= 0"
constraints[j+0] = lc1
constraints[j+1] = lc2
// constraints[j+2] = lc3
j+=2
cpk+=1
else
lc2 = "K" + num2str(i+2) + " >= 0"
// lc3 = "K" + num2str(i+10) + " >= 0"
constraints[j+0] = lc2
// constraints[j+1] = lc3
j+=1
cpk+=1
endif
endfor
elseif(holdPos && holdWidths && !holdAmps && holdSecAmp)
Redimension/N=(nPeaks + totalConstraints) constraints//(2*nPeaks) constraints
j=0
for(i=4 + pWave1D[0];i < 4 + pWave1D[0] + 11*(nPeaks+1);i+=11)
if(cpk == pkID)
lc2 = "K" + num2str(i+2) + " >= 0"
lc3 = "K" + num2str(i+10) + " >= 0"
constraints[j+0] = lc2
// constraints[j+1] = lc3
j+=1
cpk+=1
else
lc2 = "K" + num2str(i+2) + " >= 0"
// lc3 = "K" + num2str(i+10) + " >= 0"
constraints[j+0] = lc2
// constraints[j+1] = lc3
j+=1
cpk+=1
endif
endfor
elseif(!holdPos && holdWidths && !holdAmps && holdSecAmp)
Redimension/N=(nPeaks + totalConstraints) constraints//(4*nPeaks) constraints
j=0
for(i=4 + pWave1D[0];i < 4 + pWave1D[0] + 11*(nPeaks+1);i+=11)
if(cpk == pkID)
pos = pWave1D[i+0]
wid = pWave1D[i+1]
pLow = pos - n*wid
pHigh = pos + n*wid
lc0 = "K" + num2str(i+0) + " >=" + num2str(pLow)
hc0 = "K" + num2str(i+0) + " <=" + num2str(pHigh)
lc2 = "K" + num2str(i+2) + " >= 0"
lc3 = "K" + num2str(i+10) + " >= 0"
constraints[j+0] = lc0
constraints[j+1] = hc0
constraints[j+2] = lc2
// constraints[j+3] = lc3
j+=3
cpk+=1
else
lc2 = "K" + num2str(i+2) + " >= 0"
// lc3 = "K" + num2str(i+10) + " >= 0"
constraints[j+0] = lc2
// constraints[j+1] = lc3
j+=1
cpk+=1
endif
endfor
elseif(!holdPos && !holdWidths && holdAmps && holdSecAmp)
Redimension/N=(nPeaks + totalConstraints) constraints
j=0
for(i=4 + pWave1D[0];i < 4 + pWave1D[0] + 11*(nPeaks+1);i+=11)
if(cpk == pkID)
pos = pWave1D[i+0]
wid = pWave1D[i+1]
pLow = pos - n*wid
pHigh = pos + n*wid
lc0 = "K" + num2str(i+0) + " >=" + num2str(pLow)
hc0 = "K" + num2str(i+0) + " <=" + num2str(pHigh)
lc1 = "K" + num2str(i+1) + " >= 0"
constraints[j+0] = lc0
constraints[j+1] = hc0
constraints[j+2] = lc1
j+=3
cpk+=1
else
lc2 = "K" + num2str(i+2) + " >= 0"
// lc3 = "K" + num2str(i+10) + " >= 0"
constraints[j+0] = lc2
// constraints[j+1] = lc3
j+=1
cpk+=1
endif
endfor
elseif(!holdPos && holdWidths && holdAmps && holdSecAmp)
Redimension/N=(nPeaks + totalConstraints) constraints
j=0
for(i=4 + pWave1D[0];i < 4 + pWave1D[0] + 11*(nPeaks+1);i+=11)
if(cpk == pkID)
pos = pWave1D[i+0]
wid = pWave1D[i+1]
pLow = pos - n*wid
pHigh = pos + n*wid
lc0 = "K" + num2str(i+0) + " >=" + num2str(pLow)
hc0 = "K" + num2str(i+0) + " <=" + num2str(pHigh)
constraints[j+0] = lc0
constraints[j+1] = hc0
j+=2
cpk+=1
else
lc2 = "K" + num2str(i+2) + " >= 0"
// lc3 = "K" + num2str(i+10) + " >= 0"
constraints[j+0] = lc2
// constraints[j+1] = lc3
j+=1
cpk+=1
endif
endfor
elseif(holdAmps && holdWidths && holdAmps && holdSecAmp)
print "Constraint wave not built due to all parameters being held constant"
endif
return constraints
End
Function/WAVE makeSingleEpsiltonWave(pWave1D,pkID,holdAmps,holdWidths,holdPos,holdSecAmp)
Wave pWave1D
Variable pkID
Variable holdAmps,holdWidths,holdPos,holdSecAmp
Variable nPeaks = (numpnts(pWave1D) - 4 - pWave1D[0])/11,cPk=0
Variable i
//Set up values for epsilon wave
String epsWaveName = "eps_Pk" + num2str(pkID)
Make/O/N=(numpnts(pWave1D)) $epsWaveName
Wave eps = $epsWaveName
Variable epsPos = 1e-7
Variable epsWid = 1e-7
Variable epsAmp = 1e-4
Variable epsProp = 1e-4
eps[0] = 0
eps[1] = 0//5e-9
eps[3] = 0
for(i=4;i<pWave1D[0] + 4;i+=1)
eps[i] = 0 //For Ionization Potentials from DFT. Used to build the Step Edge
endfor
for(i=4 + pWave1D[0];i<11*nPeaks+4+pWave1D[0];i+=11)
if(cPk == pkID)//i==(11*pkID + 4 + pWave1D[0]))
if(!holdPos && !holdWidths && !holdAmps && holdSecAmp)
eps[i + 0] = epsPos
eps[i + 1] = epsWid
eps[i + 2] = epsAmp
eps[i + 10] = 0
elseif(holdPos && !holdWidths && holdAmps && holdSecAmp)
eps[i + 0] = 0
eps[i + 1] = epsWid
eps[i + 2] = 0
eps[i + 10] = 0
elseif(holdPos && !holdWidths && !holdAmps && holdSecAmp)
eps[i + 0] = 0
eps[i + 1] = epsWid
eps[i + 2] = epsAmp
eps[i + 10] = 0
elseif(holdPos && holdWidths && !holdAmps && holdSecAmp)
eps[i + 0] = 0
eps[i + 1] = 0
eps[i + 2] = epsAmp
eps[i + 10] = 0
elseif(!holdPos && holdWidths && !holdAmps && holdSecAmp)
eps[i + 0] = epsPos
eps[i + 1] = 0
eps[i + 2] = epsAmp
eps[i + 10] = 0
elseif(!holdPos && !holdWidths && holdAmps && holdSecAmp)
eps[i + 0] = epsPos
eps[i + 1] = epsWid
eps[i + 2] = 0
eps[i + 10] = 0
elseif(!holdPos && holdWidths && holdAmps && holdSecAmp)
eps[i + 0] = epsPos
eps[i + 1] = 0
eps[i + 2] = 0
eps[i + 10] = 0
elseif(holdPos && holdWidths && holdAmps && holdSecAmp)
eps[i + 0] = 0
eps[i + 1] = 0
eps[i + 2] = 0
eps[i + 10] = 0
elseif(!holdPos && !holdWidths && !holdAmps && !holdSecAmp)
eps[i + 0] = epsPos
eps[i + 1] = epsWid
eps[i + 2] = epsAmp
eps[i + 10] = epsProp
elseif(holdPos && !holdWidths && holdAmps && !holdSecAmp)
eps[i + 0] = 0
eps[i + 1] = epsWid
eps[i + 2] = 0
eps[i + 10] = epsProp
elseif(holdPos && !holdWidths && !holdAmps && !holdSecAmp)
eps[i + 0] = 0
eps[i + 1] = epsWid
eps[i + 2] = epsAmp
eps[i + 10] = epsProp
elseif(holdPos && holdWidths && !holdAmps && !holdSecAmp)
eps[i + 0] = 0
eps[i + 1] = 0
eps[i + 2] = epsAmp
eps[i + 10] = epsProp
elseif(!holdPos && holdWidths && !holdAmps && !holdSecAmp)
eps[i + 0] = epsPos
eps[i + 1] = 0
eps[i + 2] = epsAmp
eps[i + 10] = epsProp
elseif(!holdPos && !holdWidths && holdAmps && !holdSecAmp)
eps[i + 0] = epsPos
eps[i + 1] = epsWid
eps[i + 2] = 0
eps[i + 10] = epsProp
elseif(!holdPos && holdWidths && holdAmps && !holdSecAmp)
eps[i + 0] = epsPos
eps[i + 1] = 0
eps[i + 2] = 0
eps[i + 10] = epsProp
elseif(holdPos && holdWidths && holdAmps && !holdSecAmp)
eps[i + 0] = 0
eps[i + 1] = 0
eps[i + 2] = 0
eps[i + 10] = epsProp
endif
eps[i + 3] = 0
eps[i + 4] = 0
eps[i + 5] = 0
eps[i + 6] = 0
eps[i + 7] = 0
eps[i + 8] = 0
eps[i + 9] = 0
else
eps[i + 0] = 0
eps[i + 1] = 0
eps[i + 2] = 0//epsAmp
eps[i + 3] = 0
eps[i + 4] = 0
eps[i + 5] = 0
eps[i + 6] = 0
eps[i + 7] = 0
eps[i + 8] = 0
eps[i + 9] = 0
eps[i + 10] = 0
endif
cPk+=1
endfor
return eps
End
Function/S makeSingleHoldString(holdAmps,holdWidths,holdPos,holdSecAmp,pWave1D,pkID)
Variable holdAmps,holdWidths,holdPos,holdSecAmp
Wave pWave1D
Variable pkID
Variable i
Variable nPeaks = (numpnts(pWave1D) - 4 - pWave1D[0])/11
//Make Hold String for fit. Open amplitudes, hold position and width constant
String H = "1111"//H1 = Number of atoms, i0, alpha, phi
for(i=1;i<=pWave1D[0];i+=1)
H +="1" //For Ionization Potentials from DFT. Used to build the Step Edge. Hold them constant.
endfor
for(i=0;i<=nPeaks-1;i+=1)
//Hold string for peak parameters. Position, Width, Max Amplitude, xxNoRM, xyNorm,xzNorm,yyNorm,yzNorm,zzNorm
//Hold cases:
if(i==pkID)
if(!holdPos && !holdWidths && !holdAmps && holdSecAmp)
H +="00011111111"
elseif(holdPos && !holdWidths && holdAmps && holdSecAmp)
H +="10111111111"
elseif(holdPos && !holdWidths && !holdAmps && holdSecAmp)
H +="10011111111"
elseif(holdPos && holdWidths && !holdAmps && holdSecAmp)
H +="11011111111"
elseif(!holdPos && holdWidths && !holdAmps && holdSecAmp)
H +="01011111111"
elseif(!holdPos && !holdWidths && holdAmps && holdSecAmp)
H +="00111111111"
elseif(!holdPos && holdWidths && holdAmps && holdSecAmp)
H +="01111111111"
elseif(holdAmps && holdWidths && holdAmps && holdSecAmp)
H +="11111111111"
//
elseif(!holdPos && !holdWidths && !holdAmps && !holdSecAmp)
H +="00011111110"
elseif(holdPos && !holdWidths && holdAmps && !holdSecAmp)
H +="10111111110"
elseif(holdPos && !holdWidths && !holdAmps && !holdSecAmp)
H +="10011111110"
elseif(holdPos && holdWidths && !holdAmps && !holdSecAmp)
H +="11011111110"
elseif(!holdPos && holdWidths && !holdAmps && !holdSecAmp)
H +="01011111110"
elseif(!holdPos && !holdWidths && holdAmps && !holdSecAmp)
H +="00111111110"
elseif(!holdPos && holdWidths && holdAmps && !holdSecAmp)
H +="01111111110"
elseif(holdAmps && holdWidths && holdAmps && !holdSecAmp)
H +="11111111110"
//
endif
else
H +="11111111111"//"11011111111"
endif
endfor
String holdWaveName = "holdWave_pk" + num2str(pkID)
Make/O/N=(numpnts(pWave1D)) $holdWaveName
Wave holdWave = $holdWaveName
for(i=0;i<numpnts(pWave1D);i+=1)
holdWave[i] = str2num(H[i,i])
endfor
print H
return H
End
Function compareTransitionPositions(pw1,pw2)
Wave pw1,pw2
Variable i,nPeaks = (numpnts(pw1)-4-pw1[0])/11,en1,en2,amp1,amp2,j=0
Make/O/N=(nPeaks) iniEnergy,finEnergy,diffEnergy,iniAmp,finAmp,diffAmp
print nPeaks
for(i=4+pw1[0];i<11*nPeaks+4+pw1[0];i+=11)
en1 = pw1[i]
en2 = pw2[i]
amp1 = pw1[i+2]
amp2 = pw2[i+2]
iniEnergy[j] = en1
finEnergy[j] = en2
iniAmp[j] = amp1
finAmp[j] = amp2
diffEnergy[j] = en2-en1
diffAmp[j] = amp2 - amp1
j+=1
endfor
End
Function/WAVE modelVectorOrbital(tw,a)
Wave tw
Variable a
Variable i,x=numpnts(tw),alphaR = a * (Pi/180)
Make/O/N=(x) vecOrb,vecParaInt,vecPerpInt
Variable para,perp
for(i=0;i<x;i+=1)
Variable t_angle = tw[i] * (Pi/180)
print "Tdm planar orbital", t_angle
para = (1/3) * (1 + (1/2)*((3 * cos( t_angle)^2 - 1) * (3 * cos(alphaR)^2 - 1)))
perp = (1/2) * sin(alphaR)^2
vecParaInt[i] = para
vecPerpInt[i] = perp
vecOrb[i] = para + perp
endfor
return vecOrb
End
Function/WAVE modelPlanarOrbital(tw,a)
Wave tw
Variable a
Variable i,x=numpnts(tw),alphaR = a * (Pi/180)
Make/O/N=(x) plOrb,plParaInt,plPerpInt
Variable para,perp
for(i=0;i<x;i+=1)
Variable t_angle = tw[i] * (Pi/180)
print "Tdm planar orbital", t_angle
para = (2/3) * (1 - (1/4)*((3 * cos( t_angle)^2 - 1) * (3 * cos(alphaR)^2 - 1)))
perp = (1/2) * ( 1 + cos(alphaR)^2)
plParaInt[i] = para
plPerpInt[i] = perp
plOrb[i] = para + perp
endfor
return plOrb
End
Function orbitalWrapper(tw,a)
Wave tw
Variable a
Wave vecOrb = modelVectorOrbital(tw,a)
Wave plOrb = modelPlanarOrbital(tw,a)
Wave plParaInt,vecParaInt,plPerpInt,vecPerpInt
WaveStats/Q plParaInt
Variable plPaMin = V_min,plPaMax = V_max
WaveStats/Q vecParaInt
Variable vPaMin = V_min,vPaMax = V_max
WaveStats/Q plPerpInt
Variable plPeMin = V_min,plPeMax = V_max
WaveStats/Q vecPerpInt
Variable vPeMin = V_min,vPeMax = V_max
Variable perpMin,perpMax,paraMin,paraMax
if(plPaMin < vPaMin)
paraMin = plPaMin
else
paraMin = vPaMin
endif
if(plPaMax > vPaMax)
paraMax = plPaMax
else
paraMax = vPaMax
endif
if(plPeMin < vPeMin)
perpMin = plPeMin
else
perpMin = vPeMin
endif
if(plPeMax > vPeMax)
perpMax = plPeMax
else
perpMax = vPeMax
endif
//Compare Total intensities of vector and planar orbitals
DoWindow plotVecvsPlanarOrbs
if(!V_Flag)
Display/N=plotVecvsPlanarOrbs/K=1 vecOrb,plOrb vs tw
NewFreeAxis/L para
NewFreeAxis/L perp
AppendToGraph/W=plotVecvsPlanarOrbs/L=para plParaInt,vecParaInt vs tw
AppendToGraph/W=plotVecvsPlanarOrbs/L=perp plPerpInt,vecPerpInt vs tw
ModifyGraph mode=4,marker=19,lsize=1.5, freePos(para)=0,freePos(perp)=0
Label left "Total Intensity[a.u.]"
Label bottom "θ[°]"
Label para "Para Intensity[a.u.]"
Label perp "Perp Intensity[a.u.]"
SetAxis para paraMin,paraMax
SetAxis perp perpMin,perpMax
ModifyGraph grid=2,mirror=1,minor=1
ModifyGraph rgb(plOrb)=(1,4,52428),rgb(plParaInt)=(1,4,52428),rgb(plPerpInt)=(1,4,52428)
ModifyGraph lblPosMode(left)=1,axisEnab(left)={0.69,1}
ModifyGraph lblPosMode(para)=1,axisEnab(para)={0.34,0.66}
ModifyGraph lblPosMode(perp)=1,axisEnab(perp)={0,0.32}
Legend/C/N=text0/J/A=RB "\\JCα="+num2str(a)+"°\r\\s(plOrb) Planar\r\\s(vecOrb) Vector"
else
Legend/C/N=text0/J/W=plotVecvsPlanarOrbs "\\JCα="+num2str(a)+"°\r\\s(plOrb) Planar\r\\s(vecOrb) Vector"
endif
End
Function/S detOrbType(tensor)
Wave tensor
String type
if((tensor[0][0]==tensor[1][1]==tensor[2][2]))
type = "I"
elseif((tensor[0][0]==0) && (tensor[1][1]==0) && (tensor[2][2]!=0))
type = "V"
elseif((tensor[0][0]!=0) && (tensor[1][1]!=0) && (tensor[2][2]==0))
type = "P"
elseif((tensor[0][0]!=0) && (tensor[1][1]!=0) && (tensor[2][2]!=0))
type = "M"
endif
print type
return type
End
Function modelTensorInt(pw,thw,tensor)
Wave pw //1D Parameter wave. Has peak positions,widths, and amplitudes. has initial guess for alpha and IPs required to build step edge
Wave thw //Wave containing the various values of theta
Wave tensor
Variable i,j=0,k,m,targetDP = 10,n=numpnts(thw)
Variable pos,wid,amp,alpha,i0,phi,localalpha,amp2
Duplicate/O tensor,currentTensor
Duplicate/O pw,npw
Make/O/N=(n) tensorInt,tempMA
//Make rotation matrices for rotation of 90,180,and 270 degrees around z-axis
Make/O/D/N=(3,3) rotMat0 = {{cos(0*(Pi/180)) ,sin(0*(Pi/180)),0} ,{-sin(0*(Pi/180)) ,cos(0*(Pi/180)),0} ,{0,0,1}}
Make/O/D/N=(3,3) rotMat90 = {{cos(90*(Pi/180)) ,sin(90*(Pi/180)),0} ,{-sin(90*(Pi/180)) ,cos(90*(Pi/180)),0} ,{0,0,1}}
Make/O/D/N=(3,3) rotMat180 = {{cos(180*(Pi/180)),sin(180*(Pi/180)),0},{-sin(180*(Pi/180)),cos(180*(Pi/180)),0},{0,0,1}}
Make/O/D/N=(3,3) rotMat270 = {{cos(270*(Pi/180)),sin(270*(Pi/180)),0},{-sin(270*(Pi/180)),cos(270*(Pi/180)),0},{0,0,1}}
String vecType = detOrbType(tensor)
//*****POTENTIALLY CHANGE CLUSTERING ALGORITHM****
//Generate clusters based on overall/total OS instead of component OS
//How to open up individual tensor elements for fitting:
//1. Ratio of in-plane vs out-of-plane components?
//2. Need a second parameter to describe amplitude? Possibly related to a local alpha?
//*********Will need to change pWave from 10 parameters per peak to 11!*******
//3. Visualize tensor elements for each cluster (Tensor Element vs Cluster ID) -->Log plot
//4. Additive oscillator strength... How to accomplish this programatically???
alpha = npw[0]*(Pi/180)
phi = npw[1]*(Pi/180)
pos = npw[2]
wid = ABS(npw[3])
amp = ABS(npw[4])
amp2 = npw[5]
currentTensor = amp * tensor[p][q]
Make/O/N=2 vector
vector[0] = sqrt(tensor[0][0])
vector[1] = sqrt(0.5*tensor[2][2])
//vector[2] = tensor[2][2]
Wave rv = vecOpsWrap(vector,amp2,"Z")
currentTensor[0][0] = abs(rv[0])^2
currentTensor[1][1] = abs(rv[0])^2
currentTensor[2][2] = 2*abs(rv[1])^2
Make/O/N=(3,3) modMolTensor = 0
modMolTensor[0][0] = abs(rv[0])^2
modMolTensor[1][1] = abs(rv[0])^2
modMolTensor[2][2] = 2*abs(rv[1])^2
//print sqrt(currentTensor[0][0]^2+currentTensor[1][1]^2+currentTensor[2][2]^2)
Make/O/D/N=(3,3) rotMatAlignX = {{1,0,0},{0,cos(alpha),sin(alpha)},{0,-sin(alpha),cos(alpha)}}
//Tilt the tensor by angle alpha
MatrixOP/O tiltedTensorX = rotMatAlignX x currentTensor x rotMatAlignX^t
//Construct the film tensor by adding the azimuthal rotations
MatrixOP/O RotTensor0X = rotMat0 x tiltedTensorX x rotMat0^t
MatrixOP/O RotTensor90X = rotMat90 x tiltedTensorX x rotMat90^t
MatrixOP/O RotTensor180X = rotMat180 x tiltedTensorX x rotMat180^t
MatrixOP/O RotTensor270X = rotMat270 x tiltedTensorX x rotMat270^t
MatrixOP/O filmTensor = RotTensor0X + RotTensor90X + RotTensor180X + RotTensor270X
Wave filmTensorTrunc = truncateMatrix(targetDP,filmTensor)
//print sqrt(filmTensorTrunc[0][0]^2+filmTensorTrunc[1][1]^2+filmTensorTrunc[2][2]^2)
//Apply electric field to current tensor to obtain the mass absorbance
for(i=0;i<n;i+=1)
Variable thetaVal = thw[i]*(Pi/180)
Make/O/D/N=(3) eField = {sin(thetaVal)*cos(phi),sin(thetaVal)*sin(phi),cos(thetaVal)}
MatrixOP/O tempMA = (eField^t x filmTensorTrunc x eField)//Check if this is correct!
tensorInt[i] = tempMA[0]
String pkName = "t_pk"+ num2str(thw[i])
Make/O/N=2000 $pkName
Wave z = $pkName
SetScale/i x,280,360,z
z = 0
z = (tensorInt[i]) * gauss(x,pos,wid)
endfor
KillWaves/Z rotMat0,rotMat90,rotMat180,rotMat270,RotTensor0,RotTensor90,RotTensor180,RotTensor270,TEMPma
DoWindow plotTensorInt
if(!V_Flag)
Display/N=plotTensorInt/K=1 tensorInt vs thw
ModifyGraph mode=4,marker=19,lsize=1.5,grid=2,mirror=1,minor=1
Label left "Tensor Intensity[a.u.]"
Label bottom "θ[°]"
TextBox/C/N=text1/A=RB "\\JCα="+num2str(npw[0])+"° \rModAmp = "+num2str(npw[5])
else
TextBox/C/N=text1/A=RB/W=plotTensorInt "\\JCα="+num2str(npw[0])+"° \rModAmp = "+num2str(npw[5])
endif
End
Function/WAVE truncateMatrix(targetDP,mat)
Variable targetDP
Wave mat
Variable k,m
for(k=0;k<=2;k+=1)
for(m=0;m<=2;m+=1)
Variable currComp = mat[k][m]
targetDP = round(targetDP)
currComp = round(currComp * (10^targetDP)) / (10^targetDP)
if(currComp == -0)
currComp = 0
endif
mat[k][m] = currComp
endfor
endfor
return mat
End
Function calcVectorRatio(v)
Wave v
Variable ratio
//Ratio is defined in terms of z component(v[1]) to xy-component(v[0])
//What to do when z or xy- component is 0??
if((v[0] == 0) || (v[1] == 0))
ratio = 1
else
ratio = v[1]/v[0]
endif
return ratio
End
Function/WAVE truncateVector(targetDP,vec)
Variable targetDP
Wave vec
Variable n = numpnts(vec)
Variable k
for(k=0;k<n;k+=1)
Variable currComp = vec[k]
targetDP = round(targetDP)
currComp = round(currComp * (10^targetDP)) / (10^targetDP)
if(currComp == -0)
currComp = 0
endif
vec[k] = currComp
endfor
return vec
End
Function calcVecNorm(v)
Wave v
Variable n = numpnts(v),i,mag=0
for(i=0;i<n;i+=1)
mag += v[i]^2
endfor
mag = sqrt(mag)
//print mag
return mag
End
Function/WAVE normVec(v)
Wave v
Duplicate/O v,nv
Variable mag = calcVecNorm(v)
nv = v/mag
Variable mag2 = calcVecNorm(nv)
return nv
End
Function/WAVE rotVector(v,deg,axis)
Wave v
Variable deg
String axis
Variable n = DimSize(v,0),ndeg
Duplicate/O v,rv
ndeg = deg * (Pi/180)
if(n == 3)
if(StringMatch(axis,"Z"))
Make/O/N=(3,3) rotMat = {{cos(ndeg),sin(ndeg),0},{-sin(ndeg),cos(ndeg),0},{0,0,1}}
elseif(StringMatch(axis,"X"))
Make/O/N=(3,3) rotMat = {{1,0,0},{0,cos(ndeg),sin(ndeg)},{0,-sin(ndeg),cos(ndeg)}}
elseif(StringMatch(axis,"Y"))
Make/O/N=(3,3) rotMat = {{cos(ndeg),0,-sin(ndeg)},{0,1,0},{sin(ndeg),0,cos(ndeg)}}
endif
else
Make/O/N=(2,2) rotMat = {{cos(ndeg),sin(ndeg)},{-sin(ndeg),cos(ndeg)}}
endif
MatrixOP/O rv = rotMat x v
Wave rv2 = truncateVector(10,rv)
Variable mag = calcVecNorm(rv)
return rv2
End
Function modelTensorvsVector(tensorpw,theta,tensor,alpha,modAmp)
Wave tensorpw,theta,tensor
Variable alpha,modAmp
tensorpw[0] = alpha
tensorpw[5] = modAmp
modelTensorInt(tensorpw,theta,tensor)
orbitalWrapper(theta,alpha)
End
Function/WAVE vecOpsWrap(v,deg,axis)
Wave v
Variable deg
String axis
//Determine magnitude of initial vector and normalize it (creates nv)
Variable mag = calcVecNorm(v)
Wave nv = normVec(v)
Variable mag2 = calcVecNorm(nv)
//Rotate normalized 2D vector by some degree
Wave rv = rotVector(nv,deg,"x")//axis)
Variable mag3 = calcVecNorm(rv)
//Calculate the ratio between the rotated vector components --> ModAmp(amp2)
//print mag,mag2,mag3
return rv
End
Function calcDeterminant(tensor,rotAngle)
Wave tensor
Variable rotAngle
Variable detIni,detFin,As,Bs,Cs,Ds,Es,Fs,Gs,Hs,Is,Ae,Be,Ce,De,Ee,Fe,Ge,He,Ie
rotAngle = rotAngle * (Pi/180)
Make/O/D/N=(3,3) rotMat = {{cos(rotAngle) ,sin(rotAngle),0} ,{-sin(rotAngle) ,cos(rotAngle),0} ,{0,0,1}}
MatrixOP/O newTensor = rotMat x tensor x rotMat^t
As = tensor[0][0];Bs = tensor[0][1];Cs = tensor[0][2]
Ds = tensor[1][0];Es = tensor[1][1];Fs = tensor[1][2]
Gs = tensor[2][0];Hs = tensor[2][1];Is = tensor[2][2]
detIni = As * (Es*Is - Fs*Hs) - Bs * (Ds*Is - Fs*Gs) + Cs * (Ds*Hs - Es*Gs)
Ae = newtensor[0][0];Be = newtensor[0][1];Ce = newtensor[0][2]
De = newtensor[1][0];Ee = newtensor[1][1];Fe = newtensor[1][2]
Ge = newtensor[2][0];He = newtensor[2][1];Ie = newtensor[2][2]
detFin = Ae * (Ee*Ie - Fe*He) - Be * (De*Ie - Fe*Ge) + Ce * (De*He - Ee*Ge)
print detIni
print detFin
End
Function calcNormTensor(tensor)
Wave tensor
Variable i,j
for(i=0;i<3;i+=1)
Variable normT = (tensor[i][j])^2
if(j==2)
break
elseif(i<2)
j+=1
else
i=0
endif
endfor
print normT
End
Function/WAVE truncate2D(w,targetDP)
Wave w
Variable targetDP
WaveStats/Q w
Variable k,m
//If the value of a component is less than tol times the maximum tensor component then set it to 0
for(k=0;k<=2;k+=1)
for(m=0;m<=2;m+=1)
Variable currComp = w[k][m]
targetDP = round(targetDP)
currComp = round(currComp * (10^targetDP)) / (10^targetDP)
if(currComp == -0)
currComp = 0
endif
w[k][m] = currComp
endfor
endfor
return w
End
Function calcRedChiSq(ori,chiSq,nPeaks,openParams,openAlpha)
Wave ORI
Variable chiSq,nPeaks,openParams,openAlpha
Variable n=numpnts(ori),redChiSq=0
redChiSq = chiSq/(n-nPeaks*openParams - openAlpha*1)
return redChiSq
End
Function/WAVE scaleExptoBA(expSpec,expEn,anchorStep1,anchorStep2,mol)
Wave expSpec,expEn
Variable anchorStep1,anchorStep2
String mol
//Find the bare atom waves
Wave mu_energy = findBAenergy()
Wave mu = findBAMA(mol)
//Find energies in mu
Variable lo = BinarySearch(mu_energy,anchorStep1)
Variable hi = BinarySearch(mu_energy,anchorStep2)
WaveStats/R=[lo,hi]/Q mu
Variable mins = V_min
Duplicate/O expSpec,test
//Find the experimental energies used for scaling
Variable exp280 = findWaveValAtEergy(expEn,expSpec,anchorStep1)
Variable exp360 = findWaveValAtEergy(expEn,expSpec,anchorStep2)
//Find the bare atom energies used for scaling
Variable bareStepLo = findWaveValAtEergy(mu_energy,mu,anchorStep1)
Variable bareStepHi = findWaveValAtEergy(mu_energy,mu,anchorStep2)
Variable expScale = (exp360-exp280) / (bareStepHi-bareStepLo)
test = test/ expScale + V_min
return test
End
Function MAtoF2F1(maw,ew,rho,mol)
Wave maw,ew //Mass absorbance and energy waves
Variable rho //Density of molecule
String mol//Name of molecule
Variable Na=6.0221415e23 //Avogadro's number [at/d.mol]
Variable re=2.81794e-13 //classical electron radius [cm]
Variable hc=1.97263e-05//eV*cm //1.23984e-4//Product of speed of light and Planck's constant
Wave mu = findBAMA(mol)
Variable Mw=NumberByKey("Mw",Note(mu))//Molecular weight of molecule
Variable zstar=NumberByKey("Zstar",Note(mu))//Zstar for molecule
String betaWaveStr=removeending(nameofwave(maw),"_ma")+"_beta"
String f2WaveStr=removeending(betaWaveStr,"_beta")+"_f2"
Duplicate/O maw,$betaWaveStr,$f2WaveStr
Wave betas = $betaWaveStr
Wave F2 = $f2WaveStr
//Convert mass absorbance to beta and then to f2
betas = maw*hc/(4*pi*ew)
F2=(Mw*maw*ew)/(2*re*hc*Na)
//Calculate f1 from f2 wave
//Wave f1 = NXA_KK_FFT2(ew, F2, zstar)
Wave f1 = BAC_KK_FFT(ew, F2, zstar,19)//
String deltaWaveStr=removeending(nameofwave(f1),"_f1")+"_delta"
Duplicate/O/D f1,$deltaWaveStr
Wave delta = $deltaWaveStr
Variable n=numpnts(ew),i
for(i=0;i<n;i+=1)
Variable lambda = hc/ew[i]
delta[i] = (F1[i]*rho*Na*re*lambda^2)/(2*Pi*Mw)
endfor
End
Function/WAVE BAC_KK_FFT(EnergyWave, f2Wave, Z_star,pad)
wave EnergyWave, f2Wave
variable Z_star//sum of effective number of protons of repeating unit
//Check Z* calculation
variable pad
string f2WaveStr
redimension/D EnergyWave, f2Wave//, EnergyWave_ori
f2WaveStr=removeending(nameofwave(f2Wave),"_f2")+"_F1"
make/D/O/N=(2^pad) tempF2
setscale/I x, 0, 30000, "eV", tempf2//30000eV is max energy
Interpolate2/T=1/I=3/Y=tempf2 EnergyWave, f2Wave
redimension/C/D tempf2
Insertpoints 2^pad, 2^pad, tempf2
Duplicate/d/c/o tempf2, isign
isign[0,2^pad]=cmplx(0,-1)
isign[2^pad,2^(pad+1)-1]=cmplx(0,1)
Variable t0=startMStimer
If( 0)
MatrixOp/O outWave=real(IFFT(cmplx(real(FFT(tempf2,0)*isign),0),0))
SetScale/i x, 0, 60000, outwave
Interpolate2/T=1/I=3/Y=tempf1/X=EnergyWave outwave
else
FFT tempf2
MatrixOp/O tempf2=tempf2*isign
redimension/R tempf2
redimension/C tempf2
IFFT tempf2
Redimension/R tempf2
Interpolate2/T=1/I=3/Y=tempf1/X=EnergyWave tempf2
endif
print stopMStimer(t0)/1e6
tempf1=tempf1*2+Z_star
duplicate/O tempf1 $(f2WaveStr)
Wave w = $(f2WaveStr)
return w
End
Function/WAVE NXA_KK_FFT2(EnergyWave_ori, f2Wave_ori, Z_star)
wave EnergyWave_ori, f2Wave_ori
variable Z_star//sum of effective number of protons of repeating unit
string f2WaveStr
duplicate/O EnergyWave_ori EnergyWave
duplicate/O f2Wave_ori f2Wave
redimension/D EnergyWave, f2Wave, EnergyWave_ori
f2WaveStr=removeending(nameofwave(f2Wave_ori),"_f2")+"_F1"
make/D/O/N=(2^21) sampleEn
//1
sampleEn=x*30000/(2^21-1)
InsertPoints 0,2, EnergyWave
EnergyWave[0]=0
EnergyWave[1]=10-1e-10
InsertPoints 0,2, f2Wave
//f2wave[0,1]=f2wave[3]*5
Interpolate2/T=1/N=2000/I=3/Y=tempf2intp/X=sampleEn EnergyWave, f2Wave
//2
killwaves sampleEn
redimension/C/D tempf2intp
setscale/I x, 0, 30000, "eV", tempf2intp
FFT/PAD={(2^22)}/DEST=tempf2intpFFT/OUT=1 tempf2intp
//3
killwaves tempf2intp
duplicate/O tempf2intpFFT tempf2intpFFTimag
redimension/R tempf2intpFFTimag
tempf2intpFFTimag=imag(tempf2intpFFT)
killwaves tempf2intpFFT
tempf2intpFFTimag[(2^21), (2^22)]*=-1
redimension/C tempf2intpFFTimag
IFFT/DEST=tempf2intpIFFT tempf2intpFFTimag
//4
killwaves tempf2intpFFTimag
Redimension/R tempf2intpIFFT
DeletePoints (2^21),(2^22), tempf2intpIFFT
make/D/O/N=(2^21) sampleEn
//5
sampleEn=x*30000/(2^21-1)
Interpolate2/T=1/N=2000/I=3/Y=tempf1/X=EnergyWave_ori sampleEn, tempf2intpIFFT
//6
tempf1=tempf1*2+Z_star
duplicate/O tempf1 $(f2WaveStr)
Wave w = $(f2WaveStr)
killwaves tempf2intpIFFT, sampleEn, EnergyWave, f2wave//,tempf1
return w
End
Function MAtoF2(maw,ew,rho,mol)
Wave maw,ew //Mass absorbance and energy waves
Variable rho //Density of molecule
String mol//Name of molecule
Variable Na=6.0221415e23 //Avogadro's number [at/d.mol]
Variable re=2.81794e-13 //classical electron radius [cm]
Variable hc=1.97263e-05//eV*cm //1.23984e-4//Product of speed of light and Planck's constant
Wave mu = findBAMA(mol)
Variable Mw=NumberByKey("Mw",Note(mu))//Molecular weight of molecule
Variable zstar=NumberByKey("Zstar",Note(mu))//Zstar for molecule
String betaWaveStr=removeending(nameofwave(maw),"_ma")+"_beta"
String f2WaveStr=removeending(betaWaveStr,"_beta")+"_f2"
Duplicate/O maw,$betaWaveStr,$f2WaveStr
Wave betas = $betaWaveStr
Wave F2 = $f2WaveStr
//Convert mass absorbance to beta and then to f2
betas = maw*hc/(4*pi*ew)
F2=(Mw*maw*ew)/(2*re*hc*Na)
End
Function makeTensorSpecsOCs(pw,yw,ew,thw,sw)
Wave pw //1D Parameter wave. Has peak positions,widths, and amplitudes. has initial guess for alpha and IPs required to build step edge
Wave yw //Wave containing the different spectra to be fit
Wave ew //Wave containing the energies of the various spectra to be fit (i.e. the x wave)
Wave thw //Wave containing the various values of theta
Wave sw //Wave containing the concatenated steps from the DFT IPs
Variable i,j=0,k,m
Variable targetDP = 10
//Make the absorption tensor for each transition, normalize it, and place each transition into a layer of a 3D wave
makeTensor1D(pw)
normalizeTensor()
Wave norm3D = make3DnormWave()
Wave tensor3D = make3DResonance()
//Add the step edge
yw = sw
Duplicate/O yw,output
//Make waves that will contain tensor element NEXAFS
Duplicate/O yw,xxSpec,yySpec,zzSpec,xySpec,xzSpec,yzSpec
//Reference hold Wave. To be used to determine how the peak amplitudes will be defined
Wave holdWave
Variable nTransitions = DimSize(norm3D,2)
Variable pos,wid,amp,alpha,i0,phi,localalpha,amp2
Variable p0,pf,nSpec=howManySpec(thw),cSpec=1,thetaVal
Make/O/N=(3,3,nTransitions) filmTensor3D,r0x3D,r90x3D,r180x3D,r270x3D,tilt3D,correctedMolTensor3D
Variable nAtoms = pw[0]
Make/O/D/N=(3,3) currentTensor = 0
Variable nPnts = numpnts(yw)/nSpec
Make/O/N=(nTransitions) MA = 0,vecAngle = 0,vecAngle2 = 0
//Wave that will populate the XX/YY and ZZ tensor elements into 2D vector
Make/O/N=2 vector
//Make rotation matrices for rotation of 90,180,and 270 degrees around z-axis
Make/O/D/N=(3,3) rotMat0 = {{cos(0*(Pi/180)) ,sin(0*(Pi/180)),0} ,{-sin(0*(Pi/180)) ,cos(0*(Pi/180)),0} ,{0,0,1}}
Make/O/D/N=(3,3) rotMat90 = {{cos(90*(Pi/180)) ,sin(90*(Pi/180)),0} ,{-sin(90*(Pi/180)) ,cos(90*(Pi/180)),0} ,{0,0,1}}
Make/O/D/N=(3,3) rotMat180 = {{cos(180*(Pi/180)),sin(180*(Pi/180)),0},{-sin(180*(Pi/180)),cos(180*(Pi/180)),0},{0,0,1}}
Make/O/D/N=(3,3) rotMat270 = {{cos(270*(Pi/180)),sin(270*(Pi/180)),0},{-sin(270*(Pi/180)),cos(270*(Pi/180)),0},{0,0,1}}
//Duplicated parameter wave that will contain the results of rotating the molecular tensor
Duplicate/O pw,pwMolAdj,pwFilm
Wave pwMolAdj,pwFilm
i0 = pw[1]
alpha = pw[2] * (Pi/180)
phi = pw[3] * (Pi/180)
Variable count = 0
for(i=nAtoms + 4 ;i<11*nTransitions + nAtoms;i+=11)
pos = pw[i + 0]
wid = ABS(pw[i + 1])
amp = ABS(pw[i + 2])
localalpha = pw[i + 9]
amp2 = pw[i + 10]
currentTensor = tensor3D[p][q][j]// norm3D[p][q][j]
vector[0] = currentTensor[0][0]
vector[1] = currentTensor[2][2]
Wave rv = vecOpsWrap(vector,amp2,"Z")
currentTensor[0][0] = abs(rv[0])
currentTensor[1][1] = abs(rv[0])
currentTensor[2][2] = abs(rv[1])
if(WaveExists(pwMolAdj))
pwMolAdj[i+3] = currentTensor[0][0] // xx
pwMolAdj[i+4] = currentTensor[0][1] // xy
pwMolAdj[i+5] = currentTensor[0][2] // xz
pwMolAdj[i+6] = currentTensor[1][1] // yy
pwMolAdj[i+7] = currentTensor[1][2] // yz
pwMolAdj[i+8] = currentTensor[2][2] // zz - symmetric!
endif
Variable ang2 = atan(0.5*(tensor3D[2][2][j]/tensor3D[0][0][j])) * (180/pi)
Variable ang3 = atan((0.5*rv[1])/rv[0]) * (180/pi)
vecAngle[j] = ang2
vecAngle2[j] = ang3
currentTensor *= i0 * amp
Make/O/D/N=(3,3) rotMatAlignX = {{1,0,0},{0,cos(alpha),sin(alpha)},{0,-sin(alpha),cos(alpha)}}
//Tilt the tensor by angle alpha
MatrixOP/O tiltedTensorX = rotMatAlignX x currentTensor x rotMatAlignX^t
//Construct the film tensor by adding the azimuthal rotations
MatrixOP/O RotTensor0X = rotMat0 x tiltedTensorX x rotMat0^t
MatrixOP/O RotTensor90X = rotMat90 x tiltedTensorX x rotMat90^t
MatrixOP/O RotTensor180X = rotMat180 x tiltedTensorX x rotMat180^t
MatrixOP/O RotTensor270X = rotMat270 x tiltedTensorX x rotMat270^t
MatrixOP/O filmTensor = RotTensor0X + RotTensor90X + RotTensor180X + RotTensor270X
Wave filmTensorT = truncate2D(filmTensor,targetDP)
if(WaveExists(pwFilm))
pwFilm[i+3] = filmTensorT[0][0]
pwFilm[i+4] = filmTensorT[0][1]
pwFilm[i+5] = filmTensorT[0][2]
pwFilm[i+6] = filmTensorT[1][1]
pwFilm[i+7] = filmTensorT[1][2]
pwFilm[i+8] = filmTensorT[2][2]
endif
correctedMolTensor3D[][][j] = currentTensor[p][q] //Molecular tensor after rotating ZZ/XX elements by ModTheta
filmTensor3D[][][j] = filmTensorT[p][q] //Film Tensor after tilting molecular tensor by alpha and 4-fold addition
r0x3D[][][j] = RotTensor0X[p][q]
r90x3D[][][j] = RotTensor90X[p][q]
r180x3D[][][j] = RotTensor180X[p][q]
r270x3D[][][j] = RotTensor270X[p][q]
tilt3D[][][j] = tiltedTensorX[p][q]
if(j<nTransitions)
if(cSpec == 1)
p0 = 0
pf = nPnts-1
thetaVal = thw[p0] * (Pi/180)
elseif(cSpec == nSpec)
p0 = (cSpec-1)*nPnts
pf = cSpec*nPnts-1
thetaVal = thw[p0] * (Pi/180)
else
p0 = (cSpec-1)*nPnts
pf = cSpec*nPnts-1
thetaVal = thw[p0] * (Pi/180)
endif
endif
//Apply electric field to current tensor to obtain the mass absorbance
Make/O/D/N=(3) eField = {sin(thetaVal)*cos(phi),sin(thetaVal)*sin(phi),cos(thetaVal)}
MatrixOP/O tempMA = eField^t x filmTensor x eField
if(numtype(tempMA[0]) !=0)
print "Transition " + num2str(j) + " with a theta value of " + num2str(thetaVal) + " has a problem"
//MA[j] = 0
else
MA[j] = tempMA[0] //abs(tempMA[0])
endif
//Make the BB peaks for display
String pkName = "pk" + num2str(j) + "_spec" + num2str(cSpec)
Make/O/N=2000 $pkName
Wave z = $pkName
SetScale/i x,280,360,z
z = 0
z = MA[j] * gauss(x,pos,wid)
//yw[p0,pf] += sqrt(2*Pi) * wid * MA[j] * gauss(ew,pos,wid)
output[p0,pf] += MA[j] * gauss(ew,pos,wid)
xxSpec[p0,pf] += currentTensor[0][0] * gauss(ew,pos,wid)
yySpec[p0,pf] += currentTensor[1][1] * gauss(ew,pos,wid)
zzSpec[p0,pf] += currentTensor[2][2] * gauss(ew,pos,wid)
xySpec[p0,pf] += currentTensor[0][1] * gauss(ew,pos,wid)
xzSpec[p0,pf] += currentTensor[0][2] * gauss(ew,pos,wid)
yzSpec[p0,pf] += currentTensor[1][2] * gauss(ew,pos,wid)
j+=1
if(j<=nTransitions)
if(cSpec == 1)
if(j==(nTransitions) && cSpec < nSpec)
i=nAtoms + 4 - 11
cSpec+=1
j=0
endif
else
if(j==(nTransitions) && cSpec < nSpec)
i=nAtoms + 4 - 11
cSpec+=1
j=0
endif
endif
endif
endfor
KillWaves/Z rotMat0,rotMat90,rotMat180,rotMat270,RotTensor0,RotTensor90,RotTensor180,RotTensor270,TEMPma
splitSpec(ew,4,"en")
splitSpec(xxSpec,4,"NXFS_XX")
splitSpec(yySpec,4,"NXFS_YY")
splitSpec(zzSpec,4,"NXFS_ZZ")
splitSpec(xySpec,4,"NXFS_XY")
splitSpec(xzSpec,4,"NXFS_XZ")
splitSpec(yzSpec,4,"NXFS_YZ")
Wave NXFS_XX1,NXFS_XX2,NXFS_XX3,NXFS_XX4,NXFS_YY1,NXFS_YY2,NXFS_YY3,NXFS_YY4,NXFS_ZZ1,NXFS_ZZ2,NXFS_ZZ3,NXFS_ZZ4,en1,en2,en3,en4
MAtoF2(NXFS_XX1,en2,1.6,"ZnPc")
MAtoF2(NXFS_XX2,en2,1.6,"ZnPc")
MAtoF2(NXFS_XX3,en3,1.6,"ZnPc")
MAtoF2(NXFS_XX4,en4,1.6,"ZnPc")
MAtoF2(NXFS_YY1,en2,1.6,"ZnPc")
MAtoF2(NXFS_YY2,en2,1.6,"ZnPc")
MAtoF2(NXFS_YY3,en3,1.6,"ZnPc")
MAtoF2(NXFS_YY4,en4,1.6,"ZnPc")
MAtoF2(NXFS_ZZ1,en2,1.6,"ZnPc")
MAtoF2(NXFS_ZZ2,en2,1.6,"ZnPc")
MAtoF2(NXFS_ZZ3,en3,1.6,"ZnPc")
MAtoF2(NXFS_ZZ4,en4,1.6,"ZnPc")
End
Function i0CostFunction()
// Optimize/A=0
End
Function/Wave logAmpRatio(pw,yw,xw)
Wave pw,yw,xw
Variable i,n=numpnts(pw),i0 = pw[0],aIni,aFin,j=0
for(i=1;i<n;i+=2)
aIni = pw[i]
aFin = pw[i+1]
yw[j] = i0 * log(aFin/aIni)
j+=1
endfor
return yw
End
Function logAmpRatioCost(pw0,pw1,ar)
Wave pw0,pw1,ar
Variable nPeaks = (numpnts(pw0) - 4 - pw0[0])/11,n=numpnts(pw0),i,i0=pw1[1],j=0
Make/O/N=(nPeaks) AMPS1,AMPS2,AMPS3
Duplicate/O pw1,pw2
Duplicate/O ar,ar2
WaveStats/Q ar
Variable avgAmp = V_avg
Variable multiplier = abs(avgAmp) * 10 * i0
Variable amp1,amp2,amp3
for(i=4 + pw1[0];i<n;i+=11)
amp1 = pw0[i+2]
amp2 = pw1[i+2]
amp3 = pw1[i+2]/multiplier
pw2[i+2] = amp3
AMPS1[j] = amp1
AMPS2[j] = amp2
AMPS3[j] = amp3
ar2[j] = log(amp3/amp1)
j+=1
endfor
End
Function/WAVE scaleExptoDFTStep2(stepSum,anchor1,anchor2,pi1,pi2,sig1,sig2,mol,method,nSpec,tl,alpha1,alpha2,i0,expSpecName,expEnName,eta,etadel,etaFin)
Wave stepSum //Concatenated wave containing the step edge built from DFT
Variable anchor1,anchor2 //Energies for experimental data used for scaling
Variable pi1,pi2 //Energies that define pi range
Variable sig1,sig2 //Energies that define sigma range
Variable method //Use 1 point or 2 point scaling for spectra
Variable nSpec //How many different experimental spectra are we fitting (i.e. how many different sample alignments)
Variable alpha1,alpha2 //Initial alpha guess for pi and sigma range respectively
Variable i0 //Scale factor for alpha fits
Variable eta //This parameter controls how the scaling factor will be adjusted for experiment to step will be changed. Smaller value wil increase exp intensity, larger value will decrease exp intensity. Set to 1 for default.
Variable etadel //By how much should eta be decreased each iteration?
Variable etaFin //What should be the stopping value for eta? Should be greater than 0.
String mol //Name of the molecule. Used to look up bare atom absorption wave in NXA folder
String tl //Semi colon separated list containing the theta values for each spectrum
String expSpecName //Base name of experimental spectra waves (i.e. if spectra set are named SP1,SP2,SP3 --> expSpecName is "SP"
String expEnName //Base name for experimental energy waves. Same instruction as expSpecName
//Ensure that there is at least one layer for the 3D waves
Variable etaDim = abs((eta - etaFin)/etaDel)
if(etaDim==0)
etaDim = 1
endif
//Make the concatenated NEXAFS wave
Wave allExpSpec = makeLongSpecWave(expSpecName)
Wave allExpEnergy = makeLongEnWave(expEnName)
Variable tol = 1e-3,expScale,pps=round(numpnts(allExpEnergy)/nSpec),k=0
//Find the bare atom waves
//Wave mu_energy = findBAenergy()
//Wave mu = findBAMA(mol)
WaveStats/Q stepSum
//Find the bare atom intensity values at the energies used for scaling
Variable bareStepLo = findWaveValAtEergy(allExpEnergy,stepSum,anchor1)
Variable bareStepHi = findWaveValAtEergy(allExpEnergy,stepSum,anchor2)
Duplicate/O allExpSpec,allExpSpec2
//Find the experimental intensity values at the energies used for scaling
Variable expLo = findWaveValAtEergy(allExpEnergy,allExpSpec2,anchor1)
Variable expHi = findWaveValAtEergy(allExpEnergy,allExpSpec2,anchor2)
//Scale the experimental data to the bare atom absorption
Variable equalAlpha = 0
//Find points in experiment wave that define pi and sigma manifold energy ranges
FindLevel/Q/R=[0,pps-1] allExpEnergy,pi1
Variable piPnt1 = round(V_levelX)
FindLevel/Q/R=[0,pps-1] allExpEnergy,pi2
Variable piPnt2 = round(V_levelX)
FindLevel/Q/R=[0,pps-1] allExpEnergy,sig1
Variable sigPnt1 = round(V_levelX)
FindLevel/Q/R=[0,pps-1] allExpEnergy,sig2
Variable sigPnt2 = round(V_levelX)
//Wave that will contain NEXAFS scaling results
Make/O/N=(pps,nSpec,etaDim) ScaledEtaNEXAFS = 0
//Make waves that will contain the intensities,energies,and fit uncertainties at pi and sigma manifold
Variable nPi = piPnt2-piPnt1, nSig = sigPnt2-sigPnt1,i,j
Make/O/N=(nPi,nSpec+1) piIntsAlpha = 0
Make/O/N=(nSig,nSpec+1) sigIntsAlpha = 0
Make/O/N=(nSpec) thetas = 0
Make/O/N=(nPi) alphasPi,energiesPi = 0,sigmasPi = 0,avgAlphaPi = 0
Make/O/N=(nSig) alphasSig = 0,energiesSig = 0,sigmasSig = 0,avgAlphaSig = 0
//3D waves for fit results
Make/O/N=(nSpec,nPi,etaDim) piFitResults2D = 0,piExp2D = 0,piResiduals2D = 0
Make/O/N=(3,nPi,etaDim) piPW2D = 0
Make/O/N=(nSpec,nSig,etaDim) SigFitResults2D = 0,SigExp2D = 0,SigResiduals2D = 0
Make/O/N=(3,nSig,etaDim) sigPW2D = 0
Make/O/N=(etaDim) etaWave
do
//Scale the experimental NEXAFS to the bare atom absorption generated from DFT
//----------------------------------------------------------------------------------------
if(method == 1)
expScale = expLo/bareStepLo //Try anchoring at just preedge
print expLo,bareStepLo,expScale
elseif(method == 2)
expScale = (expHi-expLo) / (bareStepHi-bareStepLo)//Anchor at post and preedge
endif
allExpSpec2 = allExpSpec / (eta *expScale)
Variable expLo_2 = findWaveValAtEergy(allExpEnergy,allExpSpec2,anchor1)
Variable dif = expLo_2 - bareStepLo
if(abs(dif) > tol)
//print "Difference between experiment and step is larger than tolerance. Check."
if(dif > 0)
allExpSpec2 -= dif
elseif(dif < 0)
allExpSpec2 += dif
endif
expLo_2 = findWaveValAtEergy(allExpEnergy,allExpSpec2,anchor1)
if ((expLo_2 - bareStepLo) > tol)
Debugger
endif
//print dif
endif
//-----------------------------------------------------------------------------------------
if(eta==1)
break
endif
//This loop will populate the energies for desired energy pi range
for(i=0;i<nPi;i+=1)
piIntsAlpha[i][0] = allExpSpec2[piPnt1 + i]
energiesPi[i] = allExpEnergy[piPnt1 + i]
endfor
//This loop will populate the intensities for desired pi energy range for each sample theta into pw
for(j=0;j<nSpec;j+=1)
for(i=0;i<nPi;i+=1)
piIntsAlpha[i][j] = allExpSpec2[piPnt1 + j*pps + i]
endfor
endfor
//This loop will populate the energies for desired energy pi range
for(i=0;i<nSig;i+=1)
sigIntsAlpha[i][0] = allExpSpec2[sigPnt1 + i]
energiesSig[i] = allExpEnergy[sigPnt2 + i]
endfor
//This loop will populate the intensities for desired pi energy range for each sample theta into pw
for(j=0;j<nSpec;j+=1)
for(i=0;i<nSig;i+=1)
sigIntsAlpha[i][j] = allExpSpec2[sigPnt1 + j*pps + i]
endfor
endfor
//This loop will populate the theta wave based on the theta list
for(i=0;i<nSpec;i+=1)
thetas[i] = str2num(StringFromList(i,tl))
endfor
//Fit alpha in Pi Range
//This loop will fit alpha at each energy within the pi range
for(i=0;i<nPi;i+=1)
String namePi1 = "aPiFit_" + num2str(i)//Wave containing experimental intensities
String namePi2 = "aPiVal_" + num2str(i)//Parameter wave for alpha fit
String namePi3 = "alphaPiResultFit_" + num2str(i)//Destination wave for alpha fit
String namePi4 = "alphaPiEpsFit_" + num2str(i)//Epsilon wave
String namePi5 = "alphaPiResiFit_" + num2str(i)//Residual Wave
String namePi6 = "alphaPiConsFit_" + num2str(i)//Constraint wave
Make/O/N=(nSpec) $namePi1,$namePi3,$namePi5
Make/D/O/N=(3) $namePi2,$namePi4
Make/O/T/N=1 $namePi6
Wave w = $namePi1
Wave fitpw = $namePi2
Wave w3 = $namePi3
Wave eps = $namePi4
eps[0] = 1e-6
eps[1] = 1e-6
eps[2] = 0
Wave res = $namePi5
Wave/T con = $namePi6
con[0] = {"K0>=0","K0<=90","K1>=0"}
fitpw[0] = alpha1
fitpw[1] = i0
fitpw[2] = 0 //Only fit Pi Range
//Populate this wave with the intensities for each spectrum at current energy
for(j=0;j<nSpec;j+=1)
w[j] = piIntsAlpha[i][j]
endfor
String H = "001"
Variable V_FitTol = 0.00001
FuncFit/Q/H=H fitStohrAlpha , fitpw, w /X=thetas /D=w3 /R=res /E=eps /C=con
Wave W_Sigma
alphasPi[i] = fitpw[0]
sigmasPi[i] = W_sigma[0]
piFitResults2D[][i][k] = w3[p]
piExp2D[][i][k] = w[p]
piResiduals2D[][i][k] = res[p]
piPW2D[][i][k] = fitpw[p]
KillWaves $namePi1,$namePi3,$namePi2,$namePi4,$namePi5,$namePi6
endfor
WaveStats/Q/RMD=[0,0][][k,k] piPW2D
Variable avgPiAlpha = V_avg
//Fit alpha in Sigma Range
//This loop will fit alpha at each energy within the sigma range
for(i=0;i<nSig;i+=1)
String nameSig1 = "aSigFit_" + num2str(i)
String nameSig2 = "aSigVal_" + num2str(i)
String nameSig3 = "alphaSigResultFit_" + num2str(i)
String nameSig4 = "alphaSigEpsFit_" + num2str(i)
String nameSig5 = "alphaSigResiFit_" + num2str(i)
String nameSig6 = "alphaSigConsFit_" + num2str(i)
Make/O/N=(nSpec) $nameSig1,$nameSig3,$nameSig5
Make/D/O/N=(3) $nameSig2,$nameSig4
Make/O/T/N=1 $nameSig6
Wave w = $nameSig1
Wave fitpw = $nameSig2
Wave w3 = $nameSig3
Wave eps = $nameSig4
eps[0] = 1e-6
eps[1] = 1e-6
eps[2] = 0
Wave res = $nameSig5
Wave/T con = $nameSig6
con[0] = {"K0>=0","K0<=90","K1>=0"}
//Populate this wave with the intensities for each spectrum at current energy
for(j=0;j<nSpec;j+=1)
w[j] = sigIntsAlpha[i][j]
endfor
fitpw[0] = alpha2
fitpw[1] = i0
fitpw[2] = 1 //Only fit Sigma Range
FuncFit/Q/H=H fitStohrAlpha , fitpw, w /X=thetas /D=w3 /R=res /E=eps /C=con
Wave W_Sigma
alphasSig[i] = fitpw[0]
sigmasSig[i] = W_sigma[0]
SigFitResults2D[][i][k] = w3[p]
SigExp2D[][i][k] = w[p]
SigResiduals2D[][i][k] = res[p]
sigPW2D[][i][k] = fitpw[p]
KillWaves $nameSig1,$nameSig3,$nameSig2,$nameSig4,$nameSig5,$nameSig6
endfor
WaveStats/Q/RMD=[0,0][][k,k] sigPW2D
Variable avgSigAlpha = V_avg
Variable difPiSigAlpha = abs(avgSigAlpha-avgPiAlpha)
if(difPiSigAlpha <= 0.25)
print "Alphas in both regions are within 0.25 degrees of one another. Finishing."
print avgPiAlpha,avgSigAlpha,eta, difPiSigAlpha,k
splitSpec(allExpSpec2,nSpec,"SCALESPEC_ETA"+num2str(eta)+"_")
String wList = WaveList("SCALESPEC_ETA"+num2str(eta)+"_*",";","")
for(i=0;i<nSpec;i+=1)
String cWave = StringFromList(i,wList)
Wave w = $cWave
ScaledEtaNEXAFS[][i][k]= w[p]
KillWaves w
endfor
etaWave[k] = eta
//Wave that will contain NEXAFS scaling results
Redimension/N=(pps,nSpec,k+1) ScaledEtaNEXAFS
//3D waves for fit results
Redimension/N=(nSpec,nPi,k+1) piFitResults2D,piExp2D,piResiduals2D
Redimension/N=(3,nPi,k+1) piPW2D
Redimension/N=(nSpec,nSig,k+1) SigFitResults2D,SigExp2D,SigResiduals2D
Redimension/N=(3,nSig,k+1) sigPW2D
Redimension/N=(k+1) etaWave
equalAlpha = 1
else
print avgPiAlpha,avgSigAlpha,eta, difPiSigAlpha,k
equalAlpha = 0
splitSpec(allExpSpec2,nSpec,"SCALESPEC_ETA"+num2str(eta)+"_")
wList = WaveList("SCALESPEC_ETA"+num2str(eta)+"_*",";","")
for(i=0;i<nSpec;i+=1)
cWave = StringFromList(i,wList)
Wave w = $cWave
ScaledEtaNEXAFS[][i][k]= w[p]
KillWaves w
endfor
etaWave[k] = eta
eta -= etaDel
k+=1
endif
if(k >= etaDim)
break
endif
while(equalAlpha == 0 && eta > etaFin)
splitSpec(stepSum,nSpec,"STEPWAVE_")
//print avgPiAlpha,avgSigAlpha,eta
return allExpSpec2
End