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