PEARL Procedures  rev-distro-2.0.0-0-gfda49c3-dirty
Igor procedures for the analysis of PEARL data
pearl-fitfuncs.ipf
Go to the documentation of this file.
1 #pragma rtGlobals=3// Use modern global access method and strict wave access.
2 #pragma IgorVersion = 6.2
3 #pragma ModuleName = PearlFitFuncs
4 #pragma version = 1.02
5 #include "mm-physconst"
6 
20 
25 
26 
27 //------------------------------------------------------------------------------
28 // Gaussian shapes
29 //------------------------------------------------------------------------------
30 
44 threadsafe variable MultiGaussLinBG(wave w, variable x){
45  wave w
46  variable x
47 
48  variable np = numpnts(w)
49  variable ip
50 
51  variable v = w[0] + x * w[1]
52  for (ip = 2; ip < np; ip += 3)
53  v += w[ip] * exp( -( (x - w[ip+1]) / w[ip+2] )^2 )
54  endfor
55 
56  return v
57 };
58 
79 threadsafe variable MultiGaussLinBG_AO(wave pw, wave yw, wave xw){
80  wave pw
81  wave yw
82  wave xw
83 
84  variable np = numpnts(pw)
85  variable ip
86 
87  yw = pw[0] + xw[p] * pw[1]
88  for (ip = 2; ip < np; ip += 3)
89  yw += pw[ip] * exp( -( (xw[p] - pw[ip+1]) / pw[ip+2] )^2 )
90  endfor
91 };
92 
93 //------------------------------------------------------------------------------
94 // Voigt shapes
95 //------------------------------------------------------------------------------
96 
110 variable MultiVoigtLinBG(wave w, variable x){
111  wave w
112  variable x
113 
114  variable np = numpnts(w)
115  variable ip
116 
117  variable v = w[0] + x * w[1]
118  for (ip = 2; ip < np; ip += 4)
119  v += w[ip] * VoigtFunc((x - w[ip+1]) / w[ip+2], w[ip+3])
120  endfor
121 
122  return v
123 };
124 
125 
126 //------------------------------------------------------------------------------
127 // Doniach-Sunjic shapes
128 //------------------------------------------------------------------------------
129 
140 threadsafe variable DoniachSunjic(variable x, variable amp, variable pos, variable sing, variable fwhm){
141  variable x
142  variable amp
143  variable pos
144  variable sing
145  variable fwhm
146 
147  variable nom, denom
148  nom = cos(pi * sing / 2 + (1 - sing) * atan((x - pos) / fwhm * 2))
149  denom = ((x - pos)^2 + fwhm^2 / 4)^((1 - sing) / 2)
150 
151  return amp * nom / denom * fwhm / 2
152 };
153 
167 variable MultiDoniachSunjicLinBG(wave w, variable x){
168  wave w
169  variable x
170 
171  variable np = numpnts(w)
172  variable ip
173 
174  variable v = w[0] + x * w[1]
175  for (ip = 2; ip < np; ip += 4)
176  v += DoniachSunjic(x, w[ip], w[ip+1], w[ip+3], w[ip+2])
177  endfor
178 
179  return v
180 };
181 
182 
183 threadsafe variable ds1_bg(wave w, variable x){
184  // Doniach-Sunjic fit function
185  // 0 <= sing < 1
186  wave w// coefficients - see below
187  variable x// independent variable
188 
189  //CurveFitDialog/ These comments were created by the Curve Fitting dialog. Altering them will
190  //CurveFitDialog/ make the function less convenient to work with in the Curve Fitting dialog.
191  //CurveFitDialog/ Equation:
192  //CurveFitDialog/ f(x) = DoniachSunjic(x, amp, pos, sing, fwhm) + bg
193  //CurveFitDialog/ End of Equation
194  //CurveFitDialog/ Independent Variables 1
195  //CurveFitDialog/ x
196  //CurveFitDialog/ Coefficients 5
197  //CurveFitDialog/ w[0] = bg
198  //CurveFitDialog/ w[1] = amp
199  //CurveFitDialog/ w[2] = pos
200  //CurveFitDialog/ w[3] = sing
201  //CurveFitDialog/ w[4] = FWHM
202 
203  return DoniachSunjic(x, w[1], w[2], w[3], w[4]) + w[0]
204 };
205 
206 threadsafe variable ds2_bg(wave w, variable x){
207  Wave w
208  Variable x
209 
210  //CurveFitDialog/ These comments were created by the Curve Fitting dialog. Altering them will
211  //CurveFitDialog/ make the function less convenient to work with in the Curve Fitting dialog.
212  //CurveFitDialog/ Equation:
213  //CurveFitDialog/ f(x) = w_0+( w_1*cos(pi*w_3/2+(1-w_3)*atan((x-w_2)/w_4)))/(((x-w_2)^2+w_4^2)^((1-w_3)/2)) +(w_5*cos(pi*w_7/2+(1-w_7)*atan((x-(w_6))/w_8)))/(((x-w_6)^2+w_8^2)^((1-w_7)/2))
214  //CurveFitDialog/ End of Equation
215  //CurveFitDialog/ Independent Variables 1
216  //CurveFitDialog/ x
217  //CurveFitDialog/ Coefficients 9
218  //CurveFitDialog/ w[0] = bg
219  //CurveFitDialog/ w[1] = amp1
220  //CurveFitDialog/ w[2] = pos1
221  //CurveFitDialog/ w[3] = sing1
222  //CurveFitDialog/ w[4] = wid1
223  //CurveFitDialog/ w[5] = amp2
224  //CurveFitDialog/ w[6] = pos2
225  //CurveFitDialog/ w[7] = sing2
226  //CurveFitDialog/ w[8] = wid2
227 
228  variable ds1 = DoniachSunjic(x, w[1], w[2], w[3], w[4])
229  variable ds2 = DoniachSunjic(x, w[5], w[6], w[7], w[8])
230 
231  return w[0] + ds1 + ds2
232 };
233 
234 variable ds4_bg(wave w, variable x){
235  Wave w
236  Variable x
237 
238  //CurveFitDialog/ These comments were created by the Curve Fitting dialog. Altering them will
239  //CurveFitDialog/ make the function less convenient to work with in the Curve Fitting dialog.
240  //CurveFitDialog/ Equation:
241  //CurveFitDialog/ f(x) = w_0+( w_1*cos(pi*w_3/2+(1-w_3)*atan((x-w_2)/w_4)))/(((x-w_2)^2+w_4^2)^((1-w_3)/2)) +(w_5*cos(pi*w_7/2+(1-w_7)*atan((x-(w_6))/w_8)))/(((x-w_6)^2+w_8^2)^((1-w_7)/2)) +( w_9*cos(pi*w_11/2+(1-w_11)*atan((x-w_10)/w_12)))/(((x-w_10)^2+w_12^2)^((1-w_11)/2)) +( w_13*cos(pi*w_15/2+(1-w_15)*atan((x-w_14)/w_16)))/(((x-w_14)^2+w_16^2)^((1-w_15)/2))
242  //CurveFitDialog/ End of Equation
243  //CurveFitDialog/ Independent Variables 1
244  //CurveFitDialog/ x
245  //CurveFitDialog/ Coefficients 17
246  //CurveFitDialog/ w[0] = w_0
247  //CurveFitDialog/ w[1] = w_11
248  //CurveFitDialog/ w[2] = w_12
249  //CurveFitDialog/ w[3] = w_13
250  //CurveFitDialog/ w[4] = w_14
251  //CurveFitDialog/ w[5] = w_21
252  //CurveFitDialog/ w[6] = w_22
253  //CurveFitDialog/ w[7] = w_23
254  //CurveFitDialog/ w[8] = w_24
255  //CurveFitDialog/ w[9] = w_31
256  //CurveFitDialog/ w[10] = w_32
257  //CurveFitDialog/ w[11] = w_33
258  //CurveFitDialog/ w[12] = w_34
259  //CurveFitDialog/ w[13] = w_41
260  //CurveFitDialog/ w[14] = w_42
261  //CurveFitDialog/ w[15] = w_43
262  //CurveFitDialog/ w[16] = w_44
263  Variable ds1, ds2, ds3, ds4
264  ds1=( w[1]*cos(pi*w[3]/2+(1-w[3])*atan((x-w[2])/w[4])))/(((x-w[2])^2+w[4]^2)^((1-w[3])/2))
265  ds2=( w[5]*cos(pi*w[7]/2+(1-w[7])*atan((x-w[6])/w[8])))/(((x-w[6])^2+w[8]^2)^((1-w[7])/2))
266  ds3=( w[9]*cos(pi*w[11]/2+(1-w[11])*atan((x-w[10])/w[12])))/(((x-w[10])^2+w[12]^2)^((1-w[11])/2))
267  ds4=( w[13]*cos(pi*w[15]/2+(1-w[15])*atan((x-w[14])/w[16])))/(((x-w[14])^2+w[16]^2)^((1-w[15])/2))
268 
269 
270  return w[0]+ds1+ds2+ds3+ds4
271 
272 
273 };
274 
275 variable ds6_bg(wave w, variable x){
276  Wave w
277  Variable x
278 
279  //CurveFitDialog/ These comments were created by the Curve Fitting dialog. Altering them will
280  //CurveFitDialog/ make the function less convenient to work with in the Curve Fitting dialog.
281  //CurveFitDialog/ Equation:
282  //CurveFitDialog/
283  //CurveFitDialog/ Variable g, ds1, ds2, ds3, ds4, ds5, ds6
284  //CurveFitDialog/ ds1=( w_11*cos(pi*w_13/2+(1-w_13)*atan((x-w_12)/w_14)))/(((x-w_12)^2+w_14^2)^((1-w_13)/2))
285  //CurveFitDialog/ ds2=( w_21*cos(pi*w_23/2+(1-w_23)*atan((x-w_22)/w_24)))/(((x-w_22)^2+w_24^2)^((1-w_23)/2))
286  //CurveFitDialog/ ds3=( w_31*cos(pi*w_33/2+(1-w_33)*atan((x-w_32)/w_34)))/(((x-w_32)^2+w_34^2)^((1-w_33)/2))
287  //CurveFitDialog/ ds4=( w_41*cos(pi*w_43/2+(1-w_43)*atan((x-w_42)/w_44)))/(((x-w_42)^2+w_44^2)^((1-w_43)/2))
288  //CurveFitDialog/ ds5=( w_51*cos(pi*w_53/2+(1-w_53)*atan((x-w_52)/w_54)))/(((x-w_52)^2+w_54^2)^((1-w_53)/2))
289  //CurveFitDialog/ ds6=( w_61*cos(pi*w_63/2+(1-w_63)*atan((x-w_62)/w_64)))/(((x-w_62)^2+w_64^2)^((1-w_63)/2))
290  //CurveFitDialog/
291  //CurveFitDialog/ f(x) =w_0+ds1+ds2+ds3+ds4+ds5+ds6
292  //CurveFitDialog/
293  //CurveFitDialog/ End of Equation
294  //CurveFitDialog/ Independent Variables 1
295  //CurveFitDialog/ x
296  //CurveFitDialog/ Coefficients 25
297  //CurveFitDialog/ w[0] = w_0
298  //CurveFitDialog/ w[1] = w_11
299  //CurveFitDialog/ w[2] = w_12
300  //CurveFitDialog/ w[3] = w_13
301  //CurveFitDialog/ w[4] = w_14
302  //CurveFitDialog/ w[5] = w_21
303  //CurveFitDialog/ w[6] = w_22
304  //CurveFitDialog/ w[7] = w_23
305  //CurveFitDialog/ w[8] = w_24
306  //CurveFitDialog/ w[9] = w_31
307  //CurveFitDialog/ w[10] = w_32
308  //CurveFitDialog/ w[11] = w_33
309  //CurveFitDialog/ w[12] = w_34
310  //CurveFitDialog/ w[13] = w_41
311  //CurveFitDialog/ w[14] = w_42
312  //CurveFitDialog/ w[15] = w_43
313  //CurveFitDialog/ w[16] = w_44
314  //CurveFitDialog/ w[17] = w_51
315  //CurveFitDialog/ w[18] = w_52
316  //CurveFitDialog/ w[19] = w_53
317  //CurveFitDialog/ w[20] = w_54
318  //CurveFitDialog/ w[21] = w_61
319  //CurveFitDialog/ w[22] = w_62
320  //CurveFitDialog/ w[23] = w_63
321  //CurveFitDialog/ w[24] = w_64
322 
323 
324  Variable ds1, ds2, ds3, ds4, ds5, ds6
325  ds1=( w[1]*cos(pi*w[3]/2+(1-w[3])*atan((x-w[2])/w[4])))/(((x-w[2])^2+w[4]^2)^((1-w[3])/2))
326  ds2=( w[5]*cos(pi*w[7]/2+(1-w[7])*atan((x-w[6])/w[8])))/(((x-w[6])^2+w[8]^2)^((1-w[7])/2))
327  ds3=( w[9]*cos(pi*w[11]/2+(1-w[11])*atan((x-w[10])/w[12])))/(((x-w[10])^2+w[12]^2)^((1-w[11])/2))
328  ds4=( w[13]*cos(pi*w[15]/2+(1-w[15])*atan((x-w[14])/w[16])))/(((x-w[14])^2+w[16]^2)^((1-w[15])/2))
329  ds5=( w[17]*cos(pi*w[19]/2+(1-w[19])*atan((x-w[18])/w[20])))/(((x-w[18])^2+w[20]^2)^((1-w[19])/2))
330  ds6=( w[21]*cos(pi*w[23]/2+(1-w[23])*atan((x-w[22])/w[24])))/(((x-w[22])^2+w[24]^2)^((1-w[23])/2))
331 
332  return w[0]+ds1+ds2+ds3+ds4+ds5+ds6
333 
334 };
335 
337  // data structure for DoniachSunjicBroadS structural function fit
338 
339  // waves populated by the FuncFit operation
340  wave pw;
341  wave yw;
342  wave xw;
343 
344  // convolution parameters to be set upon creation of the structure
345  variable precision;
346  variable oversampling;
347 
348  // auxiliary fields used internally by DoniachSunjicBroadS
349  // do not touch these
350  wave xdw;
351  wave model;
354 };
355 
356 //------------------------------------------------------------------------------
357 threadsafe variable DoniachSunjicBroadS(DoniachSunjicStruct* s){
358 //------------------------------------------------------------------------------
359  // Two-peak (bulk + surface) Doniach-Sunjic line shape with Gaussian broadening (convolution).
360  // Hold parameter 5 at 0 to fit just one peak.
361 
362  // Structural fit function for efficient fitting in procedures.
363  // Calculating the convolution requires auxiliary waves and additional, non-fitting parameters.
364  // To eliminate the time-consuming overhead of creating and killing the auxiliary waves,
365  // these waves are held in the fitting structure.
366 
367  // Caution: The function on its own is thread-safe.
368  // However, since FuncFit uses the same structure in all threads, the fitting cannot run in parallel.
369  // Set /NTHR=1.
370 
371  // See also Fit_DoniachSunjicBroad (example), DoniachSunjicBroad (conventional fit function)
372  Struct DoniachSunjicStruct &s
373 
374  // pw[0] = bulk amplitude
375  // pw[1] = bulk position
376  // pw[2] = Lorentzian FWHM
377  // pw[3] = Donjach-Sunjic singularity index (0..1)
378  // pw[4] = surface shift
379  // pw[5] = surface/bulk ratio
380  // pw[6] = Gaussian FWHM
381  // pw[7] = constant background
382  // pw[8] = linear background
383 
384  wave xw = s.xw
385  wave yw = s.yw
386  wave pw = s.pw
387 
388  variable precision = s.precision
389  variable oversampling = s.oversampling
390 
391  if (WaveExists(s.xdw))
392  wave xdw = s.xdw
393  wave model = s.model
394  wave broadening = s.broadening
395  wave convolution = s.convolution
396  else
397  make /n=0 /free xdw, model, broadening, convolution
398  redimension /d xdw, model, broadening, convolution
399  wave fs.xdw = xdw
400  wave fs.model = model
401  wave fs.broadening = broadening
402  wave fs.convolution = convolution
403  endif
404 
405  // calculate wave spacing based on minimum spacing of desired x points
406  differentiate /p xw /d=xdw
407  xdw = abs(xdw)
408  variable xd = wavemin(xdw) / oversampling
409 
410  // calculate broadening wave size based on width and precision variable
411  variable x0b = pw[6] * precision
412  variable nb = 2 * floor(x0b / xd) + 1
413 
414  // calculate model size based on desired range for yw
415  variable x0m = max(abs(wavemax(xw) - pw[1]), abs(wavemin(xw) - pw[1])) + x0b
416  variable nm = 2 * floor(x0m / xd) + 1
417  nb = min(nb, nm * 10)// limit wave size to avoid runtime errors for unphysically large parameter
418 
419  // create and calculate initial waves, normalize exponential
420  redimension /n=(nb) broadening
421  redimension /n=(nm) model
422  setscale/i x -x0b, x0b, "", broadening
423  setscale/i x -x0m, x0m, "", model
424 
425  broadening = exp( - (x / pw[6])^2 * 4 * ln(2))
426  variable nrm = area(broadening)
427  broadening /= nrm
428  model = DoniachSunjic(x, 1, 0, pw[3], pw[2])// bulk
429  model += DoniachSunjic(x, pw[5], pw[4], pw[3], pw[2])// surface
430 
431  // calculate the convolution
432  Convolve /a broadening, model
433  variable scale = pw[0] / wavemax(model)
434  model *= scale
435 
436  // prepare output
437  nm = numpnts(model)
438  x0m = xd * (nm - 1) / 2
439  setscale/i x -x0m, x0m, "", model
440 
441  yw = model(xw[p] - pw[1]) + pw[7] + pw[8] * xw[p]
442  yw = numtype(yw) ? 0 : yw
443 };
444 
445 //------------------------------------------------------------------------------
446 variable DoniachSunjicBroad(wave pw, wave yw, wave xw){
447 //------------------------------------------------------------------------------
448  // Two-peak (bulk + surface) Doniach-Sunjic line shape with Gaussian broadening (convolution).
449  // Hold parameter 5 at 0 to fit just one peak.
450  // Conventional fit function for use with the curve-fitting dialog.
451  // Compared to DoniachSunjicBroadS this function incurs extra overhead
452  // because auxiliary waves are created and killed between function calls.
453  // See also DoniachSunjicBroadS (optimized structural fit function)
454  Wave pw
455  Wave yw
456  Wave xw
457 
458  // pw[0] = bulk amplitude
459  // pw[1] = bulk position
460  // pw[2] = Lorentzian FWHM
461  // pw[3] = Donjach-Sunjic singularity index (0..1)
462  // pw[4] = surface shift
463  // pw[5] = surface/bulk ratio
464  // pw[6] = Gaussian FWHM
465  // pw[7] = constant background
466  // pw[8] = linear background
467 
468  // set up data structure
469  struct DoniachSunjicStruct fs
470  fs.precision = 5
471  fs.oversampling = 4
472 
473  wave fs.pw = pw
474  wave fs.xw = xw
475  wave fs.yw = yw
476 
477  // create temporary calculation waves in a global folder
478  dfref df = root:packages:pearl_fitfuncs:doniach_sunjic
479  if (DataFolderRefStatus(df) == 0)
480  newdatafolder root:packages:pearl_fitfuncs:doniach_sunjic
481  dfref df = root:packages:pearl_fitfuncs:doniach_sunjic
482  endif
483 
484  wave /z /sdfr=df fs.xdw = xdw
485  wave /z /sdfr=df fs.model = model
486  wave /z /sdfr=df fs.broadening = broadening
487  wave /z /sdfr=df fs.convolution = convolution
488 
489  if (WaveExists(fs.xdw) == 0)
490  dfref savedf = GetDataFolderDFR()
491  setdatafolder df
492  make /n=0 /d xdw, model, broadening, convolution
493  wave fs.xdw = xdw
494  wave fs.model = model
495  wave fs.broadening = broadening
496  wave fs.convolution = convolution
497  setdatafolder savedf
498  endif
499 
500  // calculate
502 
503  yw = fs.yw
504 };
505 
506 //------------------------------------------------------------------------------
507 variable Calc_DoniachSunjicBroad(wave pw, wave yw){
508 //------------------------------------------------------------------------------
509  // Calculate the DoniachSunjicBroadS line shape
510  Wave pw// coefficient wave
511  Wave yw// output wave, correct x-scaling required on input
512 
513  struct DoniachSunjicStruct fs
514  fs.precision = 5
515  fs.oversampling = 4
516 
517  duplicate /free pw, fs.pw
518  duplicate /free yw, fs.xw
519  fs.xw = x
520  duplicate /free yw, fs.yw
521 
523 
524  yw = fs.yw
525 };
526 
527 //------------------------------------------------------------------------------
528 variable Fit_DoniachSunjicBroad(wave pw, wave yw, wave xw, wave ww){
529 //------------------------------------------------------------------------------
530  // Fit the DoniachSunjicBroadS line shape.
531  // The function applies constraints which assume that the energy scale is in eV.
532  // Returns chi^2.
533  wave pw// coefficient wave- pre-load it with initial guess
534  wave yw
535  wave /z xw
536  wave /z ww// weights (standard deviation)
537 
538  struct DoniachSunjicStruct fs
539  fs.precision = 5
540  fs.oversampling = 4
541 
542  duplicate /free pw, fs.pw
543  if (WaveExists(xw))
544  duplicate /free xw, fs.xw
545  else
546  duplicate /free yw, fs.xw
547  fs.xw = x
548  endif
549  duplicate /free yw, fs.yw
550 
551  variable v_chisq = nan
552  variable V_FitMaxIters = 100
553  make /n=1 /t /free constraints = {"K0 >= 0", "K2 > 0", "K2 < 10", "K3 >= 0", "K3 < 1", "K4 >= -10", "K4 <= 10", "K5 >= 0", "K5 <= 1", "K6 >= 0", "K6 < 10"}
554  // note: only single thread allowed
555  FuncFit /NTHR=1 DoniachSunjicBroadS, pw, yw /X=xw /D /STRC=fs /C=constraints /NWOK /I=1 /W=ww
556 
557  return v_chisq
558 };
559 
560 //------------------------------------------------------------------------------
561 // peak-specific fit functions
562 //------------------------------------------------------------------------------
563 
564 variable Au4f(wave w, variable x){
565  // fit function for a nitrogen 1s-pi* absorption spectrum
566  // modelled as multiple Voigt shapes on a constant background
567  // similar to the Igor VoigtFit function
568  // but with a constant gaussian width (instrumental broadening) for all peaks
569  // gaussian and lorentzian widths are specified as FWHM
570  wave w// parameters
571  // w[0] constant background
572  // w[1] linear background
573  // w[2] global gaussian FWHM
574  // w[3 + 0 + (n-1) * 3] peak n area
575  // w[3 + 1 + (n-1) * 3] peak n position
576  // w[3 + 2 + (n-1) * 3] peak n lorentzian FWHM
577  // length of wave defines number of peaks
578 
579  // for compatibility with older code the linear background term can be omitted.
580  // if the number of parameters divides by 3, the linear background term is added,
581  // otherwise only the constant background.
582  variable x
583 
584  variable np = 15
585  variable ip, ip0
586 
587  variable bg = w[0]
588  variable v = bg
589  if (mod(np, 3) == 0)
590  v += w[1] * x
591  ip0 = 3
592  else
593  ip0 = 2
594  endif
595 
596  variable vc1, vc2, vc3, vc4
597  vc2 = 2 * sqrt(ln(2)) / w[ip0-1]
598  for (ip = ip0; ip < np; ip += 3)
599  vc1 = w[ip] / sqrt(pi) * vc2
600  vc3 = w[ip+1]
601  vc4 = vc2 * w[ip+2] / 2
602  v += vc1 * VoigtFunc(vc2 * (x - vc3), vc4)
603  endfor
604 
605  return v
606 
607 };
608 
609 variable Au4f_2p2(wave w, variable x){
610  // Au 4f 5/2 and 7/2 2-component Voigt fit with a common gaussian width
611  // gaussian and lorentzian widths are specified as FWHM
612  wave w// parameters
613  // w[0] constant background
614  // w[1] linear background
615  // w[2] global gaussian FWHM
616  // w[3] 5/2 bulk area
617  // w[4] 5/2 bulk position
618  // w[5] 5/2 lorentzian FWHM
619  // w[6] 7/2 bulk area
620  // w[7] 7/2 bulk position
621  // w[8] 7/2 lorentzian FWHM
622  // w[9] surface/bulk area ratio
623  // w[10] surface core level shift
624  variable x
625 
626  variable bg = w[0] + w[1] * x
627  variable v = bg
628 
629  variable vc1// amplitude
630  variable vc2// width
631  variable vc3// position
632  variable vc4// shape
633  vc2 = 2 * sqrt(ln(2)) / w[2]
634 
635  // 5/2 bulk
636  vc1 = w[3] / sqrt(pi) * vc2
637  vc3 = w[4]
638  vc4 = vc2 * w[5] / 2
639  v += vc1 * VoigtFunc(vc2 * (x - vc3), vc4)
640 
641  // 5/2 surface
642  vc1 = w[3] / sqrt(pi) * vc2 * w[9]
643  vc3 = w[4] + w[10]
644  vc4 = vc2 * w[5] / 2
645  v += vc1 * VoigtFunc(vc2 * (x - vc3), vc4)
646 
647  // 7/2 bulk
648  vc1 = w[6] / sqrt(pi) * vc2
649  vc3 = w[7]
650  vc4 = vc2 * w[8] / 2
651  v += vc1 * VoigtFunc(vc2 * (x - vc3), vc4)
652 
653  // 7/2 surface
654  vc1 = w[6] / sqrt(pi) * vc2 * w[9]
655  vc3 = w[7] + w[10]
656  vc4 = vc2 * w[8] / 2
657  v += vc1 * VoigtFunc(vc2 * (x - vc3), vc4)
658 
659  return v
660 
661 };
662 
663 variable ShowComponents_Au4f_2p2(wave coef_wave, wave fit_wave){
664  wave coef_wave
665  wave fit_wave
666 
667  duplicate /free coef_wave, coef1, coef2
668  coef1[9] = 0
669  coef2[3] *= coef_wave[9]
670  coef2[4] += coef_wave[10]
671  coef2[6] *= coef_wave[9]
672  coef2[7] += coef_wave[10]
673  coef2[9] = 0
674 
675  string s_fit_wave = NameOfWave(fit_wave)
676  string s_fit_p1 = s_fit_wave + "_p1"
677  string s_fit_p2 = s_fit_wave + "_p2"
678  duplicate /o fit_wave, $(s_fit_p1) /wave=fit_p1
679  duplicate /o fit_wave, $(s_fit_p2) /wave=fit_p2
680 
681  fit_p1 = Au4f_2p2(coef1, x)
682  fit_p2 = Au4f_2p2(coef2, x)
683 
684  string traces = TraceNameList("", ";", 1)
685  if ((WhichListItem(s_fit_wave, traces, ";") >= 0) && (WhichListItem(s_fit_p1, traces, ";") < 0))
686  appendtograph fit_p1, fit_p2
687  ModifyGraph lstyle($s_fit_p1)=2
688  ModifyGraph lstyle($s_fit_p2)=2
689  ModifyGraph rgb($s_fit_p1)=(0,0,65280)
690  ModifyGraph rgb($s_fit_p2)=(0,0,65280)
691  endif
692 };
693 
694 variable Au4f_2p3(wave w, variable x){
695  // Au 4f 5/2 and 7/2 3-component Voigt fit with a common gaussian width
696  // gaussian and lorentzian widths are specified as FWHM
697  wave w// parameters
698  // w[0] constant background
699  // w[1] linear background
700  // w[2] global gaussian FWHM
701  // w[3] 5/2 bulk area
702  // w[4] 5/2 bulk position
703  // w[5] 5/2 lorentzian FWHM
704  // w[6] 7/2 bulk area
705  // w[7] 7/2 bulk position
706  // w[8] 7/2 lorentzian FWHM
707  // w[9] surface/bulk area ratio
708  // w[10] surface core level shift
709  // w[11] 2nd layer/bulk area ratio
710  // w[12] 2nd layer core level shift
711  variable x
712 
713  variable bg = w[0] + w[1] * x
714  variable v = bg
715 
716  variable vc1// amplitude
717  variable vc2// width
718  variable vc3// position
719  variable vc4// shape
720  vc2 = 2 * sqrt(ln(2)) / w[2]
721 
722  // 5/2 bulk
723  vc1 = w[3] / sqrt(pi) * vc2
724  vc3 = w[4]
725  vc4 = vc2 * w[5] / 2
726  v += vc1 * VoigtFunc(vc2 * (x - vc3), vc4)
727 
728  // 5/2 surface
729  vc1 = w[3] / sqrt(pi) * vc2 * w[9]
730  vc3 = w[4] + w[10]
731  vc4 = vc2 * w[5] / 2
732  v += vc1 * VoigtFunc(vc2 * (x - vc3), vc4)
733 
734  // 5/2 2nd layer
735  vc1 = w[3] / sqrt(pi) * vc2 * w[11]
736  vc3 = w[4] + w[12]
737  vc4 = vc2 * w[5] / 2
738  v += vc1 * VoigtFunc(vc2 * (x - vc3), vc4)
739 
740  // 7/2 bulk
741  vc1 = w[6] / sqrt(pi) * vc2
742  vc3 = w[7]
743  vc4 = vc2 * w[8] / 2
744  v += vc1 * VoigtFunc(vc2 * (x - vc3), vc4)
745 
746  // 7/2 surface
747  vc1 = w[6] / sqrt(pi) * vc2 * w[9]
748  vc3 = w[7] + w[10]
749  vc4 = vc2 * w[8] / 2
750  v += vc1 * VoigtFunc(vc2 * (x - vc3), vc4)
751 
752  // 7/2 2nd layer
753  vc1 = w[6] / sqrt(pi) * vc2 * w[11]
754  vc3 = w[7] + w[12]
755  vc4 = vc2 * w[8] / 2
756  v += vc1 * VoigtFunc(vc2 * (x - vc3), vc4)
757 
758  return v
759 
760 };
761 
762 variable ShowComponents_Au4f_2p3(wave coef_wave, wave fit_wave){
763  wave coef_wave
764  wave fit_wave
765 
766  duplicate /free coef_wave, coef1, coef2, coef3
767  coef1[9] = 0
768  coef1[11] = 0
769 
770  coef2[3] *= coef_wave[9]
771  coef2[4] += coef_wave[10]
772  coef2[6] *= coef_wave[9]
773  coef2[7] += coef_wave[10]
774  coef2[9] = 0
775  coef2[11] = 0
776 
777  coef3[3] *= coef_wave[11]
778  coef3[4] += coef_wave[12]
779  coef3[6] *= coef_wave[11]
780  coef3[7] += coef_wave[12]
781  coef3[9] = 0
782  coef3[11] = 0
783 
784  string s_fit_wave = NameOfWave(fit_wave)
785  string s_fit_p1 = s_fit_wave + "_p1"
786  string s_fit_p2 = s_fit_wave + "_p2"
787  string s_fit_p3 = s_fit_wave + "_p3"
788  duplicate /o fit_wave, $(s_fit_p1) /wave=fit_p1
789  duplicate /o fit_wave, $(s_fit_p2) /wave=fit_p2
790  duplicate /o fit_wave, $(s_fit_p3) /wave=fit_p3
791 
792  fit_p1 = Au4f_2p2(coef1, x)
793  fit_p2 = Au4f_2p2(coef2, x)
794  fit_p3 = Au4f_2p2(coef3, x)
795 
796  string traces = TraceNameList("", ";", 1)
797  if ((WhichListItem(s_fit_wave, traces, ";") >= 0) && (WhichListItem(s_fit_p1, traces, ";") < 0))
798  appendtograph fit_p1, fit_p2, fit_p3
799  ModifyGraph lstyle($s_fit_p1)=2
800  ModifyGraph lstyle($s_fit_p2)=2
801  ModifyGraph lstyle($s_fit_p3)=2
802  ModifyGraph rgb($s_fit_p1)=(0,0,65280)
803  ModifyGraph rgb($s_fit_p2)=(0,0,65280)
804  ModifyGraph rgb($s_fit_p3)=(0,0,65280)
805  endif
806 };
807 
817 variable FermiGaussConv(wave pw, wave yw, wave xw){
818  WAVE pw, yw, xw
819 
820  // half width of temporary gaussian wave is pw[5] multiplied by this factor (may be fractional)
821  variable precision_g = 5
822  variable oversampling = 4
823 
824  // calculate wave spacing based on minimum spacing of desired x points
825  duplicate /free xw, xdw
826  differentiate /p xw /d=xdw
827  xdw = abs(xdw)
828  variable xd = wavemin(xdw) / oversampling
829 
830  // calculate gausswave size based on pw[5] and precision variable
831  variable x0g = abs(pw[5]) * precision_g
832  variable ng = 2 * floor(x0g / xd) + 1
833 
834  // calculate fermiwave size based on desired range for yw
835  variable emax = wavemax(xw)
836  variable emin = wavemin(xw)
837  variable x0f = max(abs(emax - pw[3]), abs(emin - pw[3])) + x0g
838  variable ne = 2 * floor(x0f / xd) + 1
839 
840  // create and calculate initial waves, normalize exponential
841  make /d /n=(ng) /free gausswave
842  make /d /n=(ne) /free fermiwave
843  setscale/i x -x0g, x0g, "", gausswave
844  setscale/i x -x0f, x0f, "", fermiwave
845 
846  gausswave = exp( - (x / pw[5] )^2 )
847  fermiwave = 1 / (exp( x / (kBoltzmann * pw[4])) + 1.0 )
848 
849  // calculate the convolution
850  duplicate /free fermiwave, resultwave
851  Convolve /a gausswave, resultwave
852  variable rmax = wavemax(resultwave)
853  resultwave /= rmax
854 
855  // prepare output
856  ng = numpnts(resultwave)
857  x0g = xd * (ng - 1) / 2
858  setscale/i x -x0g, x0g, "", resultwave
859 
860  yw = pw[2] * resultwave(xw[p] - pw[3]) + pw[0] + pw[1] * xw[p]
861 };
862 
threadsafe variable MultiGaussLinBG(wave w, variable x)
multiple gaussian peaks on a linear background fit function.
variable DoniachSunjicBroad(wave pw, wave yw, wave xw)
threadsafe variable MultiGaussLinBG_AO(wave pw, wave yw, wave xw)
multiple gaussian peaks on a linear background fit function (all at once).
variable ds4_bg(wave w, variable x)
variable FermiGaussConv(wave pw, wave yw, wave xw)
convolution of Fermi-Dirac distribution and a Gaussian.
threadsafe variable DoniachSunjicBroadS(DoniachSunjicStruct *s)
threadsafe variable DoniachSunjic(variable x, variable amp, variable pos, variable sing, variable fwhm)
Doniach-Sunjic line shape.
variable Au4f(wave w, variable x)
variable Au4f_2p3(wave w, variable x)
variable Au4f_2p2(wave w, variable x)
variable ShowComponents_Au4f_2p2(wave coef_wave, wave fit_wave)
variable Calc_DoniachSunjicBroad(wave pw, wave yw)
variable ShowComponents_Au4f_2p3(wave coef_wave, wave fit_wave)
variable Fit_DoniachSunjicBroad(wave pw, wave yw, wave xw, wave ww)
threadsafe variable ds2_bg(wave w, variable x)
variable ds6_bg(wave w, variable x)
variable MultiDoniachSunjicLinBG(wave w, variable x)
multiple doniach-sunjic peaks on a linear background fit function.
threadsafe variable ds1_bg(wave w, variable x)
variable MultiVoigtLinBG(wave w, variable x)
multiple voigt peaks on a linear background fit function.