PEARL Procedures rev-distro-2.1.1-1-gf419e92-dirty Igor procedures for the analysis of PEARL data

pearl-scienta-preprocess.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.1
3 #pragma ModuleName = PearlScientaPreprocess
4 #include "pearl-fitfuncs"
5
6 // Copyright (c) 2013-18 Paul Scherrer Institut
7 //
8 // Licensed under the Apache License, Version 2.0 (the "License");
9 // you may not use this file except in compliance with the License.
10 // You may obtain a copy of the License at
11 // http://www.apache.org/licenses/LICENSE-2.0
12
27
32
35 function prompt_int_linbg_reduction(param)
36 string &param
37
38 variable Lcrop = NumberByKey("Lcrop", param, "=", ";")
39 variable Lsize = NumberByKey("Lsize", param, "=", ";")
40 variable Hcrop = NumberByKey("Hcrop", param, "=", ";")
41 variable Hsize = NumberByKey("Hsize", param, "=", ";")
42 variable Cpos = NumberByKey("Cpos", param, "=", ";")
43 variable Csize = NumberByKey("Csize", param, "=", ";")
44
45 prompt Lcrop, "Lower cropping region"
46 prompt Hcrop, "Upper cropping region"
47 prompt Lsize, "Lower background region"
48 prompt Hsize, "Upper background region"
49 prompt Cpos, "Center position"
50 prompt Csize, "Center integration region"
51
52 doprompt "int_linbg_reduction Parameters", lcrop, hcrop, lsize, hsize, cpos, csize
53 if (v_flag == 0)
54 param = ReplaceNumberByKey("Lcrop", param, Lcrop, "=", ";")
55 param = ReplaceNumberByKey("Lsize", param, Lsize, "=", ";")
56 param = ReplaceNumberByKey("Hcrop", param, Hcrop, "=", ";")
57 param = ReplaceNumberByKey("Hsize", param, Hsize, "=", ";")
58 param = ReplaceNumberByKey("Cpos", param, Cpos, "=", ";")
59 param = ReplaceNumberByKey("Csize", param, Csize, "=", ";")
60 endif
61
62 return v_flag
63 end
64
93 function /s capture_int_linbg_cursors()
94 string param = csr_int_linbg_reduction("")
95 svar /z global_params = root:packages:pearl_explorer:s_reduction_params
96 if (svar_exists(global_params))
97 global_params = param
98 endif
99 return param
100 end
101
133 function /s csr_int_linbg_reduction(win)
134 string win
135
136 // read all cursor positions
137 variable ic
138 string sc
139 variable nc = 10
140 make /n=(nc) /free positions
141 variable np = 0
142 wave /z image = $""
143 string imagename = ""
144 string tracename = ""
145 string info
146
147 for (ic = 0; ic < nc; ic += 1)
148 sc = num2char(char2num("A") + ic)
149 wave /z wc = CsrWaveRef($sc, win)
150 info = CsrInfo($sc, win)
151 tracename = StringByKey("TNAME", info, ":", ";")
152 if (waveexists(wc) && (wavedims(wc) == 2))
153 if (!waveexists(image))
154 wave image = wc
155 imagename = tracename
156 endif
157 if (cmpstr(tracename, imagename) == 0)
158 positions[np] = pcsr($sc, win)
159 np += 1
160 endif
161 endif
162 endfor
163
164 np = floor(np / 2) * 2 // ignore odd cursor
165 redimension /n=(np) positions
166 sort positions, positions
167 // shift upper positions by one so that the rightmost pixel becomes 1.0
168 positions = p >= np / 2 ? positions + 1 : positions
169 positions = positions / dimsize(image, 0)
170
171 // map innermost cursor pair to peak center and size
172 variable ip2 = np / 2
173 variable ip1 = ip2 - 1
174 variable Cpos
175 variable Csize
176 if (ip1 >= 0)
177 Cpos = (positions[ip1] + positions[ip2]) / 2
178 Csize = positions[ip2] - positions[ip1]
179 else
180 // default: a small region in the center
181 Cpos = 0.5
182 Csize = 0.2
183 endif
184
185 // background region
186 ip1 -= 1
187 ip2 += 1
188 variable Lsize
189 variable Hsize
190 if (ip1 >= 0)
191 Lsize = positions[ip1]
192 Hsize = 1 - positions[ip2]
193 else
194 // default: everything outside the peak region
195 Lsize = Cpos - Csize / 2
196 Hsize = 1 - (Cpos + Csize / 2)
197 endif
198
199 // crop region
200 ip1 -= 1
201 ip2 += 1
202 variable Lcrop = 0
203 variable Hcrop = 0
204 if (ip1 >= 0)
205 Lcrop = positions[ip1]
206 Hcrop = 1 - positions[ip2]
207 else
208 // default: in fixed mode: dark corners of the EW4000 at PEARL, 0 otherwise
209 if (dimsize(image, 0) >= 992)
210 Lcrop = 0.11
211 Hcrop = 0.11
212 endif
213 endif
214 Lsize = max(Lsize - Lcrop, 0)
215 Hsize = max(Hsize - Hcrop, 0)
216
217 string param = ""
218 param = ReplaceNumberByKey("Lcrop", param, Lcrop, "=", ";")
219 param = ReplaceNumberByKey("Lsize", param, Lsize, "=", ";")
220 param = ReplaceNumberByKey("Hcrop", param, Hcrop, "=", ";")
221 param = ReplaceNumberByKey("Hsize", param, Hsize, "=", ";")
222 param = ReplaceNumberByKey("Cpos", param, Cpos, "=", ";")
223 param = ReplaceNumberByKey("Csize", param, Csize, "=", ";")
224
225 return param
226 end
227
260 threadsafe function /wave int_linbg_reduction(source, param)
261 wave source
262 string &param
263
264 variable nx = dimsize(source, 0)
265 variable ny = dimsize(source, 1)
266
267 // read parameters
268 variable lcrop = NumberByKey("Lcrop", param, "=", ";")
269 variable lsize = NumberByKey("Lsize", param, "=", ";")
270 variable hcrop = NumberByKey("Hcrop", param, "=", ";")
271 variable hsize = NumberByKey("Hsize", param, "=", ";")
272 variable cpos = NumberByKey("Cpos", param, "=", ";")
273 variable csize = NumberByKey("Csize", param, "=", ";")
274
275 make /wave /free /n=2 result_waves
276 make /free /n=0 dest1, dest2
277 result_waves[0] = dest1
278 result_waves[1] = dest2
279 adh5_setup_profile(source, dest1, 1)
280 adh5_setup_profile(source, dest2, 1)
281
282 // validate parameters
283 // background parameters are optional, center parameter is required.
284 if (numtype(lcrop) != 0)
285 lcrop = 0
286 endif
287 if (numtype(lsize) != 0)
288 lsize = 0
289 endif
290 if (numtype(hcrop) != 0)
291 hcrop = 0
292 endif
293 if (numtype(hsize) != 0)
294 hsize = 0
295 endif
296 if (numtype(Cpos) != 0)
297 redimension /n=0 result_waves
298 return result_waves // Cpos parameter missing
299 endif
300 if (numtype(Csize) != 0)
301 redimension /n=0 result_waves
302 return result_waves // Csize parameter missing
303 endif
304
305 variable lpos = lcrop + lsize / 2
306 variable hpos = 1 - (hcrop + hsize / 2)
307
308 variable p0
309 variable p1
310
311 duplicate /free dest1, lbg, hbg
312 if (lsize > 0)
313 p0 = round(lcrop * nx)
314 p1 = round((lcrop + lsize) * nx)
315 ad_profile_y_w(source, p0, p1, lbg)
316 else
317 lbg = 0
318 endif
319 if (hsize > 0)
320 p0 = round((1 - hcrop - hsize) * nx)
321 p1 = round((1 - hcrop) * nx)
322 ad_profile_y_w(source, p0, p1, hbg)
323 else
324 hbg = 0
325 endif
326 if (csize > 0)
327 p0 = round((cpos - csize/2) * nx)
328 p1 = round((cpos + csize/2) * nx)
329 ad_profile_y_w(source, p0, p1, dest1)
330 else
331 dest1 = 0
332 endif
333
334 variable scale = (cpos - lpos) / (hpos - lpos)
335 dest2 = dest1
336 dest1 -= scale * (hbg - lbg) + lbg
337 dest2 = sqrt(dest2 + scale^2 * (hbg + lbg))
338
339 string s_note1
340 string s_note2
341 sprintf s_note1, "AxisLabelD=peak integral"
342 sprintf s_note2, "KineticEnergy=%.3f", cpos * nx * dimdelta(source, 0) + dimoffset(source, 0)
343 Note dest1, s_note1
344 Note dest1, s_note2
345 Note dest2, s_note1
346 Note dest2, s_note2
347
348 return result_waves
349 end
350
351 function prompt_int_quadbg_reduction(param)
352 string &param
353
354 variable Lcrop = NumberByKey("Lcrop", param, "=", ";")
355 variable Lsize = NumberByKey("Lsize", param, "=", ";")
356 variable Hcrop = NumberByKey("Hcrop", param, "=", ";")
357 variable Hsize = NumberByKey("Hsize", param, "=", ";")
358 variable Cpos = NumberByKey("Cpos", param, "=", ";")
359 variable Csize = NumberByKey("Csize", param, "=", ";")
360
361 prompt Lcrop, "Lower cropping region"
362 prompt Hcrop, "Upper cropping region"
363 prompt Lsize, "Lower background region"
364 prompt Hsize, "Upper background region"
365 prompt Cpos, "Center position"
366 prompt Csize, "Center integration region"
367
368 doprompt "int_quadbg_reduction Parameters", lcrop, hcrop, lsize, hsize, cpos, csize
369 if (v_flag == 0)
370 param = ReplaceNumberByKey("Lcrop", param, Lcrop, "=", ";")
371 param = ReplaceNumberByKey("Lsize", param, Lsize, "=", ";")
372 param = ReplaceNumberByKey("Hcrop", param, Hcrop, "=", ";")
373 param = ReplaceNumberByKey("Hsize", param, Hsize, "=", ";")
374 param = ReplaceNumberByKey("Cpos", param, Cpos, "=", ";")
375 param = ReplaceNumberByKey("Csize", param, Csize, "=", ";")
376 endif
377
378 return v_flag
379 end
380
413 threadsafe function /wave int_quadbg_reduction(source, param)
414 wave source
415 string &param
416
417 variable nx = dimsize(source, 0)
418 variable ny = dimsize(source, 1)
419
420 // read parameters
421 variable lcrop = NumberByKey("Lcrop", param, "=", ";")
422 variable lsize = NumberByKey("Lsize", param, "=", ";")
423 variable hcrop = NumberByKey("Hcrop", param, "=", ";")
424 variable hsize = NumberByKey("Hsize", param, "=", ";")
425 variable cpos = NumberByKey("Cpos", param, "=", ";")
426 variable csize = NumberByKey("Csize", param, "=", ";")
427
428 make /wave /free /n=2 result_waves
429 make /free /n=0 dest1, dest2
430 result_waves[0] = dest1
431 result_waves[1] = dest2
432 adh5_setup_profile(source, dest1, 1)
433 adh5_setup_profile(source, dest2, 1)
434
435 // validate parameters
436 // background parameters are optional, center parameter is required.
437 if (numtype(lcrop) != 0)
438 lcrop = 0
439 endif
440 if (numtype(lsize) != 0)
441 lsize = 0
442 endif
443 if (numtype(hcrop) != 0)
444 hcrop = 0
445 endif
446 if (numtype(hsize) != 0)
447 hsize = 0
448 endif
449 if (numtype(Cpos) != 0)
450 redimension /n=0 result_waves
451 return result_waves // Cpos parameter missing
452 endif
453 if (numtype(Csize) != 0)
454 redimension /n=0 result_waves
455 return result_waves // Csize parameter missing
456 endif
457
458 // crop boundaries
459 variable pcl = round(lcrop * nx)
460 variable pch = round((1 - hcrop) * nx)
461 // fit boundaries
462 variable pfl = round((lcrop + lsize) * nx)
463 variable pfh = round((1 - hcrop - hsize) * nx)
464 // integration boundaries
465 variable pil = round((cpos - csize/2) * nx)
466 variable pih = round((cpos + csize/2) * nx)
467
468 // prepare intermediate data buffer
469 make /n=(nx) /d /free profile, mask, fit
470 setscale /p x dimoffset(source,0), dimdelta(source,0), waveunits(source,0), profile, mask, fit
471 mask = ((p >= pcl) && (p < pfl)) || ((p >= pfh) && (p < pch))
472
473 variable qq
474 variable sp, sf
475 variable xil = x2pnt(profile, pil)
476 variable xih = x2pnt(profile, pih)
477
478 make /n=3 /free /d w_coef
479 for (qq = 0; qq < ny; qq += 1)
480 profile = source[p][qq]
481 curvefit /Q /NTHR=1 /W=2 poly 3, kwCWave=w_coef, profile /M=mask
482 fit = poly(w_coef, x)
483 sp = sum(profile, xil, xih)
484 sf = sum(fit, xil, xih)
485 dest1[qq] = sp - sf
486 dest2[qq] = sqrt(sp)
487 endfor
488
489 string s_note1
490 string s_note2
491 sprintf s_note1, "AxisLabelD=peak integral"
492 sprintf s_note2, "KineticEnergy=%.3f", cpos * nx * dimdelta(source, 0) + dimoffset(source, 0)
493 Note dest1, s_note1
494 Note dest1, s_note2
495 Note dest2, s_note1
496 Note dest2, s_note2
497
498 return result_waves
499 end
500
509 function prompt_redim_linbg_reduction(param)
510 string &param
511
512 variable Lcrop = NumberByKey("Lcrop", param, "=", ";")
513 variable Lsize = NumberByKey("Lsize", param, "=", ";")
514 variable Hcrop = NumberByKey("Hcrop", param, "=", ";")
515 variable Hsize = NumberByKey("Hsize", param, "=", ";")
516 variable Cpos = NumberByKey("Cpos", param, "=", ";")
517 variable Csize = NumberByKey("Csize", param, "=", ";")
518
519 prompt Lcrop, "Lower cropping region"
520 prompt Hcrop, "Upper cropping region"
521 prompt Lsize, "Lower background region"
522 prompt Hsize, "Upper background region"
523 prompt Cpos, "Center position"
524 prompt Csize, "Center integration region"
525
526 doprompt "redim_linbg_reduction Parameters", lcrop, hcrop, lsize, hsize, cpos, csize
527 if (v_flag == 0)
528 param = ReplaceNumberByKey("Lcrop", param, Lcrop, "=", ";")
529 param = ReplaceNumberByKey("Lsize", param, Lsize, "=", ";")
530 param = ReplaceNumberByKey("Hcrop", param, Hcrop, "=", ";")
531 param = ReplaceNumberByKey("Hsize", param, Hsize, "=", ";")
532 param = ReplaceNumberByKey("Cpos", param, Cpos, "=", ";")
533 param = ReplaceNumberByKey("Csize", param, Csize, "=", ";")
534 endif
535
536 return v_flag
537 end
538
572 threadsafe function /wave redim_linbg_reduction(source, param)
573 wave source
574 string &param
575
576 variable nx = dimsize(source, 0)
577 variable ny = dimsize(source, 1)
578
579 duplicate /free source, source_redim
580 redimension /n=(nx * ny) source_redim
581 nx += 1
582 redimension /n=(nx, ny) source_redim
583
584 return int_linbg_reduction(source_redim, param)
585 end
586
592 function test_gauss4_reduction(image)
593 wave image
594
595 string param = ""
596
597 param = ReplaceNumberByKey("rngl", param, -inf, "=", ";")
598 param = ReplaceNumberByKey("rngh", param, inf, "=", ";")
599 param = ReplaceNumberByKey("npeaks", param, 4, "=", ";")
600 param = ReplaceNumberByKey("ybox", param, 1, "=", ";")
601 param = ReplaceNumberByKey("pos1", param, 11, "=", ";")
602 param = ReplaceNumberByKey("wid1", param, 0.1, "=", ";")
603 param = ReplaceNumberByKey("pos2", param, 12, "=", ";")
604 param = ReplaceNumberByKey("wid2", param, 0.2, "=", ";")
605 param = ReplaceNumberByKey("pos3", param, 13, "=", ";")
606 param = ReplaceNumberByKey("wid3", param, 0.3, "=", ";")
607 param = ReplaceNumberByKey("pos4", param, 14, "=", ";")
608 param = ReplaceNumberByKey("wid4", param, 0.4, "=", ";")
609
610 wave /wave results = gauss4_reduction(image, param)
611
612 variable npk = numpnts(results) / 2
613 variable ipk
614 string sw
615 for (ipk = 0; ipk < npk; ipk += 1)
616 sw = "test_int_" + num2str(ipk + 1)
617 duplicate /o results[ipk], $sw
618 sw = "test_sig_" + num2str(ipk + 1)
619 duplicate /o results[ipk + npk], $sw
620 endfor
621 end
622
626 function prompt_gauss4_reduction(param)
627 string &param
628
629 variable rngl = NumberByKey("rngl", param, "=", ";")
630 variable rngh = NumberByKey("rngh", param, "=", ";")
631 variable pos1 = NumberByKey("pos1", param, "=", ";")
632 variable wid1 = NumberByKey("wid1", param, "=", ";")
633 variable pos2 = NumberByKey("pos2", param, "=", ";")
634 variable wid2 = NumberByKey("wid2", param, "=", ";")
635 variable pos3 = NumberByKey("pos3", param, "=", ";")
636 variable wid3 = NumberByKey("wid3", param, "=", ";")
637 variable pos4 = NumberByKey("pos4", param, "=", ";")
638 variable wid4 = NumberByKey("wid4", param, "=", ";")
639 variable npeaks = NumberByKey("npeaks", param, "=", ";")
640 variable ybox = NumberByKey("ybox", param, "=", ";")
641
642 prompt rngl, "range low"
643 prompt rngh, "range high"
644 prompt pos1, "position 1"
645 prompt wid1, "width 1"
646 prompt pos2, "position 2"
647 prompt wid2, "width 2"
648 prompt pos3, "position 3"
649 prompt wid3, "width 3"
650 prompt pos4, "position 4"
651 prompt wid4, "width 4"
652 prompt npeaks, "number of peaks"
653 prompt ybox, "ybox (1 or 3)"
654
655 doprompt "gauss4_reduction reduction parameters (1/2)", rngl, rngh, npeaks, ybox
656 if (v_flag == 0)
657 param = ReplaceNumberByKey("rngl", param, rngl, "=", ";")
658 param = ReplaceNumberByKey("rngh", param, rngh, "=", ";")
659 param = ReplaceNumberByKey("npeaks", param, npeaks, "=", ";")
660 param = ReplaceNumberByKey("ybox", param, ybox, "=", ";")
661
662 doprompt "gauss4_reduction reduction parameters (2/2)", pos1, wid1, pos2, wid2, pos3, wid3, pos4, wid4
663 if (v_flag == 0)
664 param = ReplaceNumberByKey("pos1", param, pos1, "=", ";")
665 param = ReplaceNumberByKey("wid1", param, wid1, "=", ";")
666 param = ReplaceNumberByKey("pos2", param, pos2, "=", ";")
667 param = ReplaceNumberByKey("wid2", param, wid2, "=", ";")
668 param = ReplaceNumberByKey("pos3", param, pos3, "=", ";")
669 param = ReplaceNumberByKey("wid3", param, wid3, "=", ";")
670 param = ReplaceNumberByKey("pos4", param, pos4, "=", ";")
671 param = ReplaceNumberByKey("wid4", param, wid4, "=", ";")
672 endif
673 endif
674
675 return v_flag
676 end
677
718 threadsafe function /wave gauss4_reduction(source, param)
719 wave source
720 string &param
721
722 variable nx = dimsize(source, 0)
723 variable ny = dimsize(source, 1)
724
725 // read parameters
726 variable rngl = NumberByKey("rngl", param, "=", ";")
727 variable rngh = NumberByKey("rngh", param, "=", ";")
728 variable pos1 = NumberByKey("pos1", param, "=", ";")
729 variable wid1 = NumberByKey("wid1", param, "=", ";")
730 variable pos2 = NumberByKey("pos2", param, "=", ";")
731 variable wid2 = NumberByKey("wid2", param, "=", ";")
732 variable pos3 = NumberByKey("pos3", param, "=", ";")
733 variable wid3 = NumberByKey("wid3", param, "=", ";")
734 variable pos4 = NumberByKey("pos4", param, "=", ";")
735 variable wid4 = NumberByKey("wid4", param, "=", ";")
736 variable npeaks = NumberByKey("npeaks", param, "=", ";")
737 variable ybox = NumberByKey("ybox", param, "=", ";")
738
739 // prepare curve fit
740 variable ipk
741 make /free xprof
742 adh5_setup_profile(source, xprof, 0)
743 duplicate /free xprof, xprof_sig
744 variable pl = max(x2pnt(xprof, rngl), 0)
745 variable ph = min(x2pnt(xprof, rngh), numpnts(xprof) - 1)
746
747 make /free /n=(npeaks) peak_coef
748 peak_coef = p * 3 + 2
749 variable n_coef = npeaks * 3 + 2
750 make /free /d /n=14 w_coef, W_sigma
751 w_coef[0] = {0, 0, 1, pos1, wid1, 1, pos2, wid2, 1, pos3, wid3, 1, pos4, wid4}
752 redimension /n=(n_coef) w_coef, w_sigma
753
754 // text constraints cannot be used in threadsafe functions.
755 // the following matrix-vector forumlation is equivalent to:
756 // make /free /T /N=6 constraints
757 // constraints[0] = {"K2 >= 0", "K5 >= 0", "K8 >= 0", "K11 >= 0", "K1 <= 0", "K0 => 0"}
758 make /free /n=(npeaks + 2, numpnts(w_coef)) cmat
759 make /free /n=(npeaks + 2) cvec
760 cmat = 0
761 cmat[0][0] = -1
762 cmat[1][1] = 1
763 cvec = 0
764
765 string hold = "00"
766 for (ipk=0; ipk < npeaks; ipk += 1)
767 hold += "011"
768 cmat[2 + ipk][2 + ipk*3] = -1
769 endfor
770
771 // prepare output
772 make /free /n=(npeaks * 2) /wave result_waves
773 string s_note
774 for (ipk = 0; ipk < npeaks; ipk += 1)
775 make /free /n=0 pk_int
776 adh5_setup_profile(source, pk_int, 1)
777 pk_int = nan
778 sprintf s_note, "AxisLabelD=peak %u integral", ipk+1
779 Note pk_int, s_note
780 sprintf s_note, "KineticEnergy=%.3f", w_coef[3 + ipk * 3]
781 Note pk_int, s_note
782 result_waves[ipk] = pk_int
783
784 make /free /n=0 pk_sig
785 adh5_setup_profile(source, pk_sig, 1)
786 pk_sig = nan
787 sprintf s_note, "AxisLabelD=peak %u sigma", ipk+1
788 Note pk_sig, s_note
789 sprintf s_note, "KineticEnergy=%.3f", w_coef[3 + ipk * 3]
790 Note pk_sig, s_note
791 result_waves[ipk + npeaks] = pk_sig
792
793 waveclear pk_int, pk_sig
794 endfor
795
796 // loop over angle scale
797 variable p0 = 0
798 variable p1 = dimsize(source, 1) - 1
799 variable pp
800 variable wmin
801 variable wmax
802 if (ybox > 1)
803 p0 += ceil((ybox - 1) / 2)
804 p1 -= ceil((ybox - 1) / 2)
805 endif
806 variable V_FitNumIters
807
808 for (pp = p0; pp <= p1; pp += 1)
809 // box average
810 xprof = source[p][pp]
811 if (ybox > 1)
812 xprof += source[p][pp-1] + source[p][pp+1]
813 endif
814 xprof_sig = max(sqrt(xprof), 1)
815 xprof /= ybox
816 xprof_sig /= ybox
817
818 // generate guess
819 wmin = wavemin(xprof)
820 wmax = wavemax(xprof)
821 w_coef[0] = wmin
822 w_coef[1] = 0
823
824 for (ipk=0; ipk < npeaks; ipk += 1)
825 w_coef[2 + ipk*3] = wmax - wmin
826 endfor
827 FuncFit /H=hold /Q /NTHR=1 /N /W=2 MultiGaussLinBG_AO w_coef xprof[pl,ph] /C={cmat, cvec} /I=1 /W=xprof_sig[pl,ph]
828 wave w_sigma
829
830 // retrieve results, leave them at nan if the fit did not converge
831 if (V_FitNumIters < 40)
832 for (ipk = 0; ipk < npeaks; ipk += 1)
833 wave val = result_waves[ipk]
834 wave sig = result_waves[ipk + npeaks]
835 val[pp] = max(w_coef[peak_coef[ipk]], 0)
836 sig[pp] = max(w_sigma[peak_coef[ipk]], 0)
837 endfor
838 endif
839 endfor
840
841 // calculate integral
842 for (ipk = 0; ipk < npeaks; ipk += 1)
843 wave val = result_waves[ipk]
844 wave sig = result_waves[ipk + npeaks]
845 val *= w_coef[peak_coef[ipk] + 2] * sqrt(pi)
846 sig *= w_coef[peak_coef[ipk] + 2] * sqrt(pi)
847 endfor
848
849 return result_waves
850 end
851
852
884 function /s find_gauss4_reduction_params(spectrum, peakpos)
885 wave spectrum
886 wave peakpos
887 string param = ""
888
889 variable wmin = wavemin(spectrum)
890 variable wmax = wavemax(spectrum)
891
892 // read parameters
893 variable rngl = dimoffset(spectrum, 0)
894 variable rngh = dimoffset(spectrum, 0) + dimdelta(spectrum, 0) * (dimsize(spectrum, 0) - 1)
895 make /n=4 /free positions, widths
896 variable npeaks = numpnts(peakpos)
897 variable ybox = 1
898 positions = 0
899 positions[0, npeaks-1] = peakpos[p]
900 widths = 0.2
901
902 variable n_coef = npeaks * 3 + 2
903 make /free /d /n=(n_coef) w_coef
904 w_coef = 0
905 w_coef[0] = wmin
906 w_coef[1] = 0
907
908 make /free /n=(2+npeaks, numpnts(w_coef)) cmat
909 make /free /n=(2+npeaks) cvec
910 cmat = 0
911 cmat[0][0] = -1
912 cmat[1][1] = 1
913 cvec = 0
914
915 variable ip
916 for (ip=0; ip < npeaks; ip += 1)
917 cmat[2 + ip][2 + ip*3] = -1
918 w_coef[2 + ip*3] = wmax - wmin
919 w_coef[3 + ip*3] = peakpos[ip]
920 w_coef[4 + ip*3] = widths[ip]
921 endfor
922
923 variable V_FitNumIters
924 FuncFit /Q /NTHR=1 /N MultiGaussLinBG w_coef spectrum /C={cmat, cvec}
925
926 for (ip=0; ip < npeaks; ip += 1)
927 positions[ip] = w_coef[3 + ip * 3]
928 widths[ip ] = abs(w_coef[4 + ip * 3])
929 endfor
930 for (ip=npeaks; ip < 4; ip += 1)
931 positions[ip] = 0
932 widths[ip] = 0.2
933 endfor
934
935 param = ReplaceNumberByKey("rngl", param, rngl, "=", ";")
936 param = ReplaceNumberByKey("rngh", param, rngh, "=", ";")
937 param = ReplaceNumberByKey("npeaks", param, npeaks, "=", ";")
938 param = ReplaceNumberByKey("ybox", param, ybox, "=", ";")
939 param = ReplaceNumberByKey("pos1", param, positions[0], "=", ";")
940 param = ReplaceNumberByKey("wid1", param, widths[0], "=", ";")
941 param = ReplaceNumberByKey("pos2", param, positions[1], "=", ";")
942 param = ReplaceNumberByKey("wid2", param, widths[1], "=", ";")
943 param = ReplaceNumberByKey("pos3", param, positions[2], "=", ";")
944 param = ReplaceNumberByKey("wid3", param, widths[2], "=", ";")
945 param = ReplaceNumberByKey("pos4", param, positions[3], "=", ";")
946 param = ReplaceNumberByKey("wid4", param, widths[3], "=", ";")
947
948 return param
949 end
950
958 function test_shockley_anglefit(image, branch)
959 wave image
960 variable branch
961
962 string param = ""
963 param = ReplaceStringByKey("branch", param, num2str(branch), "=", ";")
964
965 string s_branch
966 if (branch >= 0)
967 s_branch = "p"
968 else
969 s_branch = "n"
970 endif
971 string pkpos_name = "saf_pkpos_" + s_branch
972 string pkwid_name = "saf_pkwid_" + s_branch
973
974 wave /wave results = shockley_anglefit(image, param)
975 duplicate results[0], $pkpos_name
976 duplicate results[1], $pkwid_name
977 end
978
979 function prompt_Shockley_anglefit(param)
980 string &param
981
982 variable branch = NumberByKey("branch", param, "=", ";")
983
984 prompt branch, "Branch (-1 or +1)"
985
986 doprompt "Shockley_anglefit_reduction Parameters", branch
987 if (v_flag == 0)
988 param = ReplaceNumberByKey("branch", param, branch, "=", ";")
989 endif
990
991 return v_flag
992 end
993
1016 threadsafe function /wave Shockley_anglefit(source, param)
1017 wave source
1018 string &param
1019
1020 variable nx = dimsize(source, 0)
1021 variable ny = dimsize(source, 1)
1022
1023 // read parameters
1024 variable branch = NumberByKey("branch", param, "=", ";")
1025
1026 // validate parameters
1027 if (numtype(branch) != 0)
1028 branch = +1
1029 endif
1030
1031 // prepare output
1032 make /wave /free /n=2 result_waves
1033 make /free /n=0 dest1, dest2
1034 result_waves[0] = dest1
1035 result_waves[1] = dest2
1036 adh5_setup_profile(source, dest1, 0)
1037 adh5_setup_profile(source, dest2, 0)
1038 dest1 = nan
1039 dest2 = nan
1040
1041 // select angle range
1042 // hard-coded for a particular measurement series
1043 variable y0
1044 variable y1
1045 if (branch < 0)
1046 y0 = -5
1047 y1 = 0
1048 else
1049 y0 = 0
1050 y1 = 5
1051 endif
1052
1053 // select energy range
1054 // start at the point of highest intensity and go up 0.45 eV
1055 variable p0
1056 variable p1
1057 variable q0
1058 variable q1
1059 duplicate /free dest1, center
1060 q0 = round((y0 - dimoffset(source, 1)) / dimdelta(source, 1))
1061 q1 = round((y1 - dimoffset(source, 1)) / dimdelta(source, 1))
1062 ad_profile_x_w(source, q0, q1, center)
1063 wavestats /q/m=1 center
1064 p0 = round((v_maxloc - dimoffset(source, 0)) / dimdelta(source, 0))
1065 p1 = round((v_maxloc + 0.4 - dimoffset(source, 0)) / dimdelta(source, 0))
1066
1067 // prepare intermediate data buffer
1068 make /n=(ny)/d/free profile
1069 setscale /p x dimoffset(source,1), dimdelta(source,1), waveunits(source,1), profile
1070
1071 variable pp
1072 for (pp = p0; pp <= p1; pp += 1)
1073 profile = source[pp][p]
1074 curvefit /Q /NTHR=1 /W=2 gauss profile(y0,y1)
1075 wave w_coef
1076 dest1[pp] = w_coef[2]
1077 dest2[pp] = w_coef[3]
1078 endfor
1079
1080 return result_waves
1081 end
1082
1083 function scienta_norm(w, x): fitfunc
1084 wave w
1085 variable x
1086
1087 return w[0] * (x^2 - w[1]^2)
1088 end
1089
1090 function /wave fit_scienta_ang_transm(data, params)
1091 wave data // measured angular distribution (1D)
1092 wave /z params
1093
1094 if (!waveexists(params))
1095 make /n=12 /o params
1096 endif
1097 redimension /n=12/d params
1098
1099 variable h = wavemax(data) - wavemin(data)
1100 params[0] = h / 2
1101 params[1] = 0
1102 params[2] = 7
1103 params[3] = h / 4
1104 params[4] = -23
1105 params[5] = 4
1106 params[6] = h / 4
1107 params[7] = +23
1108 params[8] = 4
1109 params[9] = h / 2
1110 params[10] = 0
1111 params[11] = -0.001
1112 FuncFit /NTHR=0 /q scienta_ang_transm params data
1113
1114 return params
1115 end
1116
1117 threadsafe function scienta_ang_transm(w, x): fitfunc
1118 // parameterized angular transmission function of the analyser
1119 wave w // coefficients
1120 // w[0] = amplitude gauss 1
1121 // w[1] = position gauss 1
1122 // w[2] = width gauss 1
1123 // w[3] = amplitude gauss 2
1124 // w[4] = position gauss 2
1125 // w[5] = width gauss 2
1126 // w[6] = amplitude gauss 3
1127 // w[7] = position gauss 3
1128 // w[8] = width gauss 3
1129 // w[9] = constant background
1130 // w[10] = linear background
1131 // w[11] = quadratic background
1132 variable x
1133
1134 make /free /n=4 /d w_int
1135 w_int[0] = 0
1136 w_int[1,] = w[p - 1]
1137 variable pk1 = gauss1d(w_int, x)
1138 w_int[1,] = w[p + 2]
1139 variable pk2 = gauss1d(w_int, x)
1140 w_int[1,] = w[p + 5]
1141 variable pk3 = gauss1d(w_int, x)
1142 w_int[0,2] = w[9 + p]
1143 w_int[3] = 0
1144 variable bg = poly(w_int, x)
1145
1146 return bg + pk1 + pk2 + pk3
1147 end
1148
1149 function /wave fit_scienta_poly_bg(data, params, bgterms)
1150 wave data // measured distribution (2D)
1151 wave /z params // wave, will be redimensioned for the correct size
1152 variable bgterms // number of terms in the polynomial background: 2, 3, or 4
1153
1154 if (!waveexists(params))
1155 make /n=15 /o params
1156 endif
1157 redimension /n=15 /d params
1158
1159 variable wmax = wavemax(data)
1160 variable wmin = wavemin(data)
1161 params[0] = 0
1162 params[1] = 7
1163 params[2] = 1 / 2
1164 params[3] = -23
1165 params[4] = 4
1166 params[5] = 1 / 2
1167 params[6] = +23
1168 params[7] = 4
1169 params[8] = 1
1170 params[9] = 0
1171 params[10] = -0.001
1172 params[11] = wmin
1173 params[12] = (wmax - wmin) / dimdelta(data,1) / dimsize(data,1)
1174 params[13] = 0
1175 params[14] = 0
1176
1177 string h = "0000000000000"
1178 if (bgterms < 3)
1179 h = h + "1"
1180 else
1181 h = h + "0"
1182 endif
1183 if (bgterms < 4)
1184 h = h + "1"
1185 else
1186 h = h + "0"
1187 endif
1188 FuncFitMD /NTHR=1 /q /h=h scienta_poly_bg params data
1189
1190 return params
1191 end
1192
1193 function scienta_poly_bg(w, e, a): fitfunc
1194 // polynomial background with
1195 // parameterized angular transmission function of the analyser
1196 wave w // coefficients
1197 // angular transmission, varies with a
1198 // amplitude of gauss 1 = 1 constant
1199 // other peak amplitudes and linear terms are relative to gauss 1
1200 // w[0] = position gauss 1
1201 // w[1] = width gauss 1
1202 // w[2] = amplitude gauss 2, relative to gauss 1
1203 // w[3] = position gauss 2
1204 // w[4] = width gauss 2
1205 // w[5] = amplitude gauss 3, relative to gauss 1
1206 // w[6] = position gauss 3
1207 // w[7] = width gauss 3
1208 // w[8] = constant term
1209 // w[9] = linear term
1210 // w[10] = quadratic term
1211 // spectral background, varies with e
1212 // w[11] = constant term
1213 // w[12] = linear term
1214 // w[13] = quadratic term
1215 // w[14] = cubic term
1216 variable a // detection angle
1217 variable e // electron energy
1218
1219 make /free /n=4 /d w_int
1220 variable p0 = 0
1221
1222 w_int[0] = 0
1223 w_int[1] = 1
1224 w_int[2,] = w[p0 + p - 2]
1225 variable pk1 = gauss1d(w_int, a)
1226 p0 += 2
1227
1228 w_int[1,] = w[p0 + p - 1]
1229 variable pk2 = gauss1d(w_int, a)
1230 p0 += 3
1231
1232 w_int[1,] = w[p0 + p - 1]
1233 variable pk3 = gauss1d(w_int, a)
1234 p0 += 3
1235
1236 w_int[0,2] = w[p0 + p]
1237 w_int[3] = 0
1238 variable base = poly(w_int, a)
1239 p0 += 3
1240
1241 w_int[0,3] = w[p0 + p]
1242 variable bg = poly(w_int, e)
1243
1244 return bg * (base + pk1 + pk2 + pk3)
1245 end
MultiGaussLinBG
threadsafe variable MultiGaussLinBG(wave w, variable x)
multiple gaussian peaks on a linear background fit function.
Definition: pearl-fitfuncs.ipf:44
MultiGaussLinBG_AO
threadsafe variable MultiGaussLinBG_AO(wave pw, wave yw, wave xw)
multiple gaussian peaks on a linear background fit function (all at once).
Definition: pearl-fitfuncs.ipf:79
prompt_gauss4_reduction
variable prompt_gauss4_reduction(string *param)
prompt for the gauss4_reduction parameters
Definition: pearl-scienta-preprocess.ipf:626
redim_linbg_reduction
threadsafe wave redim_linbg_reduction(wave source, string *param)
linear background reduction function for incorrectly dimensioned scienta image
Definition: pearl-scienta-preprocess.ipf:572
test_gauss4_reduction
variable test_gauss4_reduction(wave image)
apply the gauss4_reduction function to a single image
Definition: pearl-scienta-preprocess.ipf:592
ad_profile_x_w
threadsafe wave ad_profile_x_w(wave dataset, variable q1, variable q2, wave destwave, variable noavg=defaultValue)
1D cut through 2D dataset along X dimension, existing destination wave.
Definition: pearl-area-profiles.ipf:504
adh5_setup_profile
threadsafe variable adh5_setup_profile(wave image, wave profile, variable dim)
set up a one-dimensional wave for a line profile based on a 2D original wave.
Definition: pearl-area-import.ipf:1134
prompt_int_quadbg_reduction
variable prompt_int_quadbg_reduction(string *param)
Definition: pearl-scienta-preprocess.ipf:351
int_linbg_reduction
threadsafe wave int_linbg_reduction(wave source, string *param)
linear-background subtracted integration reduction function.
Definition: pearl-scienta-preprocess.ipf:260
gauss4_reduction
threadsafe wave gauss4_reduction(wave source, string *param)
fit horizontal cuts of an image with up to four gaussian peaks on a linear background ...
Definition: pearl-scienta-preprocess.ipf:718
prompt_redim_linbg_reduction
variable prompt_redim_linbg_reduction(string *param)
parameter dialog for the redim_linbg_reduction() function
Definition: pearl-scienta-preprocess.ipf:509
ad_profile_y_w
threadsafe wave ad_profile_y_w(wave dataset, variable p1, variable p2, wave destwave, variable noavg=defaultValue)
1D cut through 2D dataset along X dimension, existing destination wave.
Definition: pearl-area-profiles.ipf:567
int_quadbg_reduction
threadsafe wave int_quadbg_reduction(wave source, string *param)
integrate peak area minus a quadratic background
Definition: pearl-scienta-preprocess.ipf:413
prompt_int_linbg_reduction
variable prompt_int_linbg_reduction(string *param)
prompt the user for integrate on linear background reduction parameters.
Definition: pearl-scienta-preprocess.ipf:35
csr_int_linbg_reduction
string csr_int_linbg_reduction(string win)
calculate linear background reduction parameters from cursors in a graph.
Definition: pearl-scienta-preprocess.ipf:133
capture_int_linbg_cursors
string capture_int_linbg_cursors()
capture linear background reduction parameters from cursors in a graph.
Definition: pearl-scienta-preprocess.ipf:93