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

pearl-anglescan-process.ipf
Go to the documentation of this file.
1 #pragma rtGlobals=3 // Use modern global access method and strict wave access.
2 #pragma version = 1.8
3 #pragma IgorVersion = 6.2
4 #pragma ModuleName = PearlAnglescanProcess
5 #include "pearl-vector-operations"
6 #include "pearl-polar-coordinates"
7 #include <New Polar Graphs>
8
9 // copyright (c) 2013-17 Paul Scherrer Institut
10 //
11 // Licensed under the Apache License, Version 2.0 (the "License");
12 // you may not use this file except in compliance with the License.
13 // You may obtain a copy of the License at
14 // http:///www.apache.org/licenses/LICENSE-2.0
15 //
16 // Please acknowledge the use of this code.
17
76
81
82
105 function strip_delete_frames(strip, qlo, qhi, theta, tilt, phi)
106 wave strip // 2D data, X-axis = analyser angle, Y-axis = arbitrary manipulator scan
107 variable qlo
108 variable qhi
109 wave theta
110 wave tilt
111 wave phi
112
113 if (qlo > qhi)
114 return -1
115 endif
116
117 // source indices
118 variable snx = dimsize(strip, 0)
119 variable sny = dimsize(strip, 1)
120 variable sq1lo = 0
121 variable sq1hi = max(qlo-1, 0)
122 variable sq2lo = min(qhi+1, sny - 1)
123 variable sq2hi = dimsize(strip, 1) - 1
124
125 // dest indices
126 variable dnx = snx
127 variable dny = sny - (sq2lo - sq1hi + 1)
128 variable dq1lo = 0
129 variable dq1hi = sq1hi
130 variable dq2lo = dq1hi + 1
131 variable dq2hi = dny - 1
132 variable q1ofs = sq1lo - dq1lo
133 variable q2ofs = sq2lo - dq2lo
134
135 duplicate /free strip, strip_copy
136 redimension /n=(dnx,dny) strip
137 strip[][dq1lo,dq1hi] = strip_copy[p][q + q1ofs]
138 strip[][dq2lo,dq2hi] = strip_copy[p][q + q2ofs]
139
140 duplicate /free theta, theta_copy
141 redimension /n=(dny) theta
142 theta[dq1lo,dq1hi] = theta_copy[p + q1ofs]
143 theta[dq2lo,dq2hi] = theta_copy[p + q2ofs]
144
145 duplicate /free tilt, tilt_copy
146 redimension /n=(dny) tilt
147 tilt[dq1lo,dq1hi] = tilt_copy[p + q1ofs]
148 tilt[dq2lo,dq2hi] = tilt_copy[p + q2ofs]
149
150 duplicate /free phi, phi_copy
151 redimension /n=(dny) phi
152 phi[dq1lo,dq1hi] = phi_copy[p + q1ofs]
153 phi[dq2lo,dq2hi] = phi_copy[p + q2ofs]
154
155 return 0
156 end
157
187 function normalize_strip_x(strip, [smooth_method, smooth_factor, check])
188 wave strip
189 variable smooth_method
190 variable smooth_factor
191 variable check
192
193 if (ParamIsDefault(smooth_method))
194 smooth_method = 4
195 endif
196 if (ParamIsDefault(smooth_factor))
197 switch(smooth_method)
198 case 4:
199 smooth_factor = 0.5
200 break
201 default:
202 smooth_factor = 2
203 endswitch
204 endif
205 if (ParamIsDefault(check))
206 check = 0
207 endif
208
209 // average over all scan positions
210 wave raw_dist = ad_profile_x(strip, -inf, inf, "")
211
212 // remove nans
213 extract /free /indx raw_dist, clean_index, numtype(raw_dist) == 0
214 duplicate /free raw_dist, dist, dist_x
215 redimension /n=(numpnts(clean_index)) dist, dist_x
216 dist = raw_dist[clean_index[p]]
217 dist_x = pnt2x(raw_dist, clean_index[p])
218 variable div = mean(dist)
219 dist /= div
220
221 if (check)
222 duplicate /o raw_dist, check_dist
223 check_dist = numtype(raw_dist) == 0 ? interp(x, dist_x, dist) : nan
224 endif
225
226 // smooth distribution function
227 switch(smooth_method)
228 case 1:
229 Smooth /B /E=3 smooth_factor, dist
230 break
231 case 2:
232 Smooth /E=3 smooth_factor, dist
233 break
234 case 3:
235 make /n=1 /d /free fit_params
236 fit_scienta_ang_transm(raw_dist, fit_params)
237 duplicate /free raw_dist, dist, dist_x
238 dist_x = x
239 dist = scienta_ang_transm(fit_params, x)
240 break
241 case 4:
242 loess /smth=(smooth_factor) srcWave=dist, factors={dist_x}
243 break
244 endswitch
245
246 if (check)
247 duplicate /o raw_dist, check_smoo
248 check_smoo = interp(x, dist_x, dist)
249 endif
250
251 // divide
252 if (check != 2)
253 strip /= interp(x, dist_x, dist)
254 endif
255 end
256
283 function normalize_strip_phi(strip, theta, phi, [theta_offset, theta_range, check])
284 wave strip
285 wave theta
286 wave phi
287 variable theta_offset
288 variable theta_range
289 variable check
290
291 if (ParamIsDefault(check))
292 check = 0
293 endif
294 if (ParamIsDefault(theta_offset))
295 theta_offset = 0
296 endif
297 if (ParamIsDefault(theta_range))
298 theta_offset = 10
299 endif
300
301 // average over analyser angles
302 wave dist = ad_profile_y(strip, -inf, inf, "")
303
304 // smooth distribution function
305 duplicate /free dist, dist_smoo
306 duplicate /free theta, theta_int
307 theta_int = theta - theta_offset
308 duplicate /free phi, phi_int
309 setscale /p x phi_int[0], phi_int[1] - phi_int[0], waveunits(phi, -1), dist, dist_smoo
310
311 extract /free /indx dist, red_idx, theta_int < theta_range
312 duplicate /free red_idx, red_dist, red_phi
313 red_dist = dist[red_idx]
314 red_phi = phi_int[red_idx]
315
316 variable wavg = mean(red_dist)
317 make /n=4 /d /free coef
318 coef[0] = {wavg, wavg/100, pi/180, 0}
319 CurveFit /q /h="0010" /g /w=2 sin, kwcWave=coef, red_dist /x=red_phi
320 dist_smoo = coef[0] + coef[1] * sin(coef[2] * phi_int[p] + coef[3])
321
322 // divide
323 if (check != 2)
324 strip = strip / dist_smoo[q] * coef[0]
325 endif
326
327 // check
328 if (check)
329 duplicate /o dist, check_dist
330 duplicate /o dist_smoo, check_smoo
331 setscale /p x dimoffset(dist,0), dimdelta(dist,0), waveunits(dist,0), check_dist, check_smoo
332 endif
333 end
334
366 function normalize_strip_theta(strip, theta, [theta_offset, smooth_method, smooth_factor, check])
367 wave strip
368 wave theta
369 variable theta_offset
370 variable smooth_method
371 variable smooth_factor
372 variable check
373
374 if (ParamIsDefault(check))
375 check = 0
376 endif
377 if (ParamIsDefault(theta_offset))
378 theta_offset = 0
379 endif
380 if (ParamIsDefault(smooth_method))
381 smooth_method = 4
382 endif
383 if (ParamIsDefault(smooth_factor))
384 smooth_factor = 0.5
385 endif
386
387 // average over analyser angles
388 wave dist = ad_profile_y(strip, -inf, inf, "")
389
390 // smooth distribution function
391 duplicate /free dist, dist_smoo
392 duplicate /free theta, theta_int
393 theta_int = theta - theta_offset
394 setscale /p x theta_int[0], theta_int[1] - theta_int[0], waveunits(theta,-1), dist, dist_smoo
395 variable nx = dimsize(strip, 0)
396 variable ix
397
398 switch(smooth_method)
399 case 1:
400 Smooth /B /E=3 smooth_factor, dist_smoo
401 break
402 case 2:
403 Smooth /E=3 smooth_factor, dist_smoo
404 break
405 case 4:
406 loess /dest=dist_smoo /smth=(smooth_factor) srcWave=dist, factors={theta_int}
407 break
408 case 3:
409 for (ix = 0; ix < nx; ix += 1)
410 dist = strip[ix][p]
411 if (smooth_factor > 1)
412 CurveFit /nthr=0 /q /w=2 poly smooth_factor+1, dist /x=theta_int /d=dist_smoo
413 else
414 CurveFit /nthr=0 /q /w=2 line, dist /x=theta_int /d=dist_smoo
415 endif
416 strip[ix,ix][] /= dist_smoo[q]
417 endfor
418 dist_smoo = 1
419 break
420 endswitch
421
422 // divide
423 if (check != 2)
424 strip /= dist_smoo[q]
425 endif
426
427 // check
428 if (check)
429 duplicate /o dist, check_dist
430 duplicate /o dist_smoo, check_smoo
431 setscale /p x dimoffset(dist,0), dimdelta(dist,0), waveunits(dist,0), check_dist, check_smoo
432 endif
433 end
434
464 function normalize_strip_thetaphi(strip, theta, phi, [theta_offset, smooth_method, smooth_factor, check])
465 wave strip
466 wave theta
467 wave phi
468 variable theta_offset
469 variable smooth_method
470 variable smooth_factor
471 variable check
472
473 if (ParamIsDefault(check))
474 check = 0
475 endif
476 if (ParamIsDefault(theta_offset))
477 theta_offset = 0
478 endif
479 if (ParamIsDefault(smooth_method))
480 smooth_method = 4
481 endif
482 if (ParamIsDefault(smooth_factor))
483 smooth_factor = 0.5
484 endif
485
486 // average over analyser angles
487 wave dist = ad_profile_y(strip, -inf, inf, "")
488
489 // smooth distribution function
490 duplicate /free dist, dist_smoo
491 duplicate /free theta, theta_int
492 theta_int = theta - theta_offset
493 setscale /p x theta_int[0], theta_int[1] - theta_int[0], waveunits(theta,-1), dist, dist_smoo
494 variable nx = dimsize(strip, 0)
495 variable ix
496
497 switch(smooth_method)
498 case 4:
499 loess /dest=dist_smoo /smth=(smooth_factor) srcWave=dist, factors={theta_int, phi}
500 break
501 default:
502 abort "smooth method not supported"
503 endswitch
504
505 // divide
506 if (check != 2)
507 strip /= dist_smoo[q]
508 endif
509
510 // check
511 if (check)
512 duplicate /o dist, check_dist
513 duplicate /o dist_smoo, check_smoo
514 setscale /p x dimoffset(dist,0), dimdelta(dist,0), waveunits(dist,0), check_dist, check_smoo
515 endif
516 end
517
523 function normalize_strip_theta_scans(strip, theta, [theta_offset, smooth_method, smooth_factor, check])
524 wave strip
525 wave theta
526 variable theta_offset
527 variable smooth_method
528 variable smooth_factor
529 variable check
530
531 if (ParamIsDefault(check))
532 check = 0
533 endif
534 if (ParamIsDefault(theta_offset))
535 theta_offset = 0
536 endif
537 if (ParamIsDefault(smooth_method))
538 smooth_method = 4
539 endif
540 if (ParamIsDefault(smooth_factor))
541 smooth_factor = 0.5
542 endif
543
544 // average over analyser angles
545 wave dist = ad_profile_y(strip, -inf, inf, "")
546
547 // smooth distribution function
548 duplicate /free dist, dist_smoo
549 duplicate /free theta, theta_int
550 theta_int = theta - theta_offset
551 setscale /p x theta_int[0], theta_int[1] - theta_int[0], waveunits(theta,-1), dist, dist_smoo
552
553 // analyse scanning scheme
554 duplicate /free theta_int, d1_theta, d2_theta
555 Differentiate /METH=2 theta_int /D=d1_theta
556 Differentiate /METH=2 d1_theta /D=d2_theta
557 d2_theta = abs(d2_theta)
558 make /free w_levels
559 FindLevels /edge=1 /p /q /d=w_levels d2_theta, 0.1
560 if (v_flag != 1)
561 abort "unrecognized scanning scheme"
562 endif
563 w_levels = ceil(w_levels)
564 InsertPoints 0, 1, w_levels
565 w_levels[0] = 0
566 InsertPoints numpnts(w_levels), 1, w_levels
567 w_levels[numpnts(w_levels)-1] = numpnts(theta_int)
568
569 variable n_scans = numpnts(w_levels) - 1
570 variable i_scan
571 variable p1, p2
572 for (i_scan = 0; i_scan < n_scans; i_scan += 1)
573 p1 = w_levels[i_scan]
574 p2 = w_levels[i_scan+1] - 1
575 duplicate /free /r=[p1, p2] dist, dist_piece, smooth_piece
576 duplicate /free /r=[p1, p2] theta_int, theta_piece
577 switch(smooth_method)
578 case 4:
579 loess /dest=smooth_piece /smth=(smooth_factor) srcWave=dist_piece, factors={theta_piece}
580 break
581 default:
582 abort "smooth method not supported"
583 endswitch
584 dist_smoo[p1, p2] = smooth_piece[p - p1]
585 endfor
586
587 // divide
588 if (check != 2)
589 strip /= dist_smoo[q]
590 endif
591
592 // check
593 if (check)
594 duplicate /o dist, check_dist
595 duplicate /o dist_smoo, check_smoo
596 setscale /p x dimoffset(dist,0), dimdelta(dist,0), waveunits(dist,0), check_dist, check_smoo
597 endif
598 end
599
613 function normalize_strip_2d(strip, theta, [theta_offset, smooth_method, smooth_factor, check])
614 wave strip
615 wave theta
616 variable theta_offset
617 variable smooth_method
618 variable smooth_factor
619 variable check
620
621 if (ParamIsDefault(check))
622 check = 0
623 endif
624 if (ParamIsDefault(theta_offset))
625 theta_offset = 0
626 endif
627 if (ParamIsDefault(smooth_method))
628 smooth_method = 4
629 endif
630 if (ParamIsDefault(smooth_factor))
631 smooth_factor = 0.5
632 endif
633
634 variable nx = dimsize(strip, 0)
635 variable ny = dimsize(strip, 1)
636
637 duplicate /free strip, dist, alpha_int, theta_int
638 theta_int = theta[q] - theta_offset
639 alpha_int = dimoffset(strip, 0) + p * dimdelta(strip, 0)
640 redimension /n=(nx * ny) dist, alpha_int, theta_int
641
642 switch(smooth_method)
643 case 4:
644 loess /dest=dist_smoo /smth=(smooth_factor) srcWave=dist, factors={alpha_int, theta_int}
645 redimension /n=(nx, ny) dist_smoo
646 break
647 default:
648 Abort "undefined smooth method"
649 break
650 endswitch
651
652 // divide
653 if (check != 2)
654 strip /= dist_smoo
655 endif
656
657 // check
658 if (check)
659 //duplicate /o dist, check_dist
660 duplicate /o dist_smoo, check_smoo
661 endif
662 end
663
673 function crop_strip(strip, xlo, xhi)
674 wave strip
675 variable xlo
676 variable xhi
677
678 variable plo = round((xlo - dimoffset(strip, 0)) / dimdelta(strip, 0))
679 variable phi = round((xhi - dimoffset(strip, 0)) / dimdelta(strip, 0))
680 xlo = plo * dimdelta(strip, 0) + dimoffset(strip, 0)
681 xhi = phi * dimdelta(strip, 0) + dimoffset(strip, 0)
682 variable nx = phi - plo + 1
683 variable ny = dimsize(strip, 1)
684
685 duplicate /free strip, strip_copy
686 redimension /n=(nx,ny) strip
687 strip = strip_copy[p + plo][q]
688 setscale /i x xlo, xhi, waveunits(strip, 0), strip
689 end
690
705 function crop_strip_theta(strip, theta_lo, theta_hi, theta, tilt, phi)
706 wave strip
707 variable theta_lo
708 variable theta_hi
709 wave theta
710 wave tilt
711 wave phi
712
713 extract /indx /free theta, idx, (theta >= theta_lo) && (theta <= theta_hi)
714 variable nx = dimsize(strip, 0)
715 variable ny = numpnts(idx)
716
717 theta[0, ny-1] = theta[idx]
718 tilt[0, ny-1] = tilt[idx]
719 phi[0, ny-1] = phi[idx]
720 redimension /n=(ny) theta, tilt, phi
721
722 duplicate /free strip, strip_copy
723 redimension /n=(nx,ny) strip
724 strip = strip_copy[p][idx[q]]
725 end
726
769 function pizza_service(data, nickname, theta_offset, tilt_offset, phi_offset, [npolar, nograph, folding, xpdplot])
770 wave data
771 string nickname
772 variable theta_offset
773 variable tilt_offset
774 variable phi_offset
775 variable npolar
776 variable nograph
777 variable folding
778 variable xpdplot
779
780 if (ParamIsDefault(npolar))
781 npolar = 91
782 endif
783 if (ParamIsDefault(nograph))
784 nograph = 0
785 endif
786 if (ParamIsDefault(folding))
787 folding = 1
788 endif
789 if (ParamIsDefault(xpdplot))
790 xpdplot = 0
791 endif
792
793 // sort out data folder structure
794 dfref saveDF = GetDataFolderDFR()
795 dfref dataDF = GetWavesDataFolderDFR(data)
796 setdatafolder dataDF
797 if (DataFolderExists(":attr"))
798 setdatafolder :attr
799 endif
800 dfref attrDF = GetDataFolderDFR()
801
802 wave /sdfr=attrDF ManipulatorTheta
803 wave /sdfr=attrDF ManipulatorTilt
804 wave /sdfr=attrDF ManipulatorPhi
805
806 if ((dimsize(ManipulatorTheta, 0) != dimsize(data, 1)) || (dimsize(ManipulatorTilt, 0) != dimsize(data, 1)) || (dimsize(ManipulatorPhi, 0) != dimsize(data, 1)))
807 Abort "Warning: The dimension size of the manipulator waves does not match the Y dimension of the data wave!\rIf you restructured the data wave, please use pizza_service_2 with properly scaled manipulator waves."
808 endif
809
810 duplicate /free ManipulatorTheta, m_theta
811 duplicate /free ManipulatorTilt, m_tilt
812 duplicate /free ManipulatorPhi, m_phi
813
814 m_theta -= theta_offset
815 m_tilt -= tilt_offset
816 m_phi -= phi_offset
817
818 pizza_service_2(data, nickname, m_theta, m_tilt, m_phi, npolar=npolar, nograph=nograph, folding=folding, xpdplot=xpdplot)
819
820 setdatafolder saveDF
821 end
822
862 function pizza_service_2(data, nickname, m_theta, m_tilt, m_phi, [npolar, nograph, folding, xpdplot])
863 wave data
864 string nickname
865 wave m_theta
866 wave m_tilt
867 wave m_phi
868 variable npolar
869 variable nograph
870 variable folding
871 variable xpdplot
872
873 if (ParamIsDefault(npolar))
874 npolar = 91
875 endif
876 if (ParamIsDefault(nograph))
877 nograph = 0
878 endif
879 if (ParamIsDefault(folding))
880 folding = 1
881 endif
882 if (ParamIsDefault(xpdplot))
883 xpdplot = 0
884 endif
885
886 if ((dimsize(m_theta, 0) != dimsize(data, 1)) || (dimsize(m_tilt, 0) != dimsize(data, 1)) || (dimsize(m_phi, 0) != dimsize(data, 1)))
887 Abort "Warning: The dimension size of the manipulator waves does not match the Y dimension of the data wave!"
888 endif
889
890 string graphname = "graph_" + nickname
891 string outprefix = nickname
892
893 // sort out data folder structure
894 dfref saveDF = GetDataFolderDFR()
895 dfref dataDF = GetWavesDataFolderDFR(data)
896 setdatafolder dataDF
897
898 if (xpdplot)
899 setdatafolder root:
900 outprefix = nickname
901 else
902 setdatafolder dataDF
903 newdatafolder /s/o $nickname
904 outprefix = ""
905 endif
906 dfref destDF = GetDataFolderDFR()
907
908 // performance monitoring
909 variable timerRefNum
910 variable /g pol_perf_secs
911 timerRefNum = startMSTimer
912
913 duplicate /free m_tilt, corr_tilt
914 duplicate /free m_phi, corr_phi
915 corr_tilt = -m_tilt // checked 140702
916 corr_phi = m_phi // checked 140702
917
918 make /n=1/d/free d_polar, d_azi
919
920 convert_angles_ttpd2polar(m_theta, corr_tilt, corr_phi, data, d_polar, d_azi)
921 d_azi += 180 // changed 151030 (v1.6)
922 make_hemi_grid(npolar, outprefix, xpdplot=xpdplot)
923 variable ifold
924 for (ifold = 0; ifold < folding; ifold += 1)
925 d_azi = d_azi >= 360 ? d_azi - 360 : d_azi
926 hemi_add_anglescan(outprefix, data, d_polar, d_azi)
927 d_azi += 360 / folding
928 endfor
929
930 // normalize folding
931 if (strlen(outprefix))
932 string s_prefix = outprefix + "_"
933 string s_int = s_prefix + "i"
934 else
935 s_prefix = ""
936 s_int = "values"
937 endif
938 if (folding > 1)
939 wave values = $s_int
940 values /= folding
941 endif
942
943 if (!nograph)
944 display_hemi_scan(outprefix, graphname = graphname)
945 endif
946
947 if (timerRefNum >= 0)
948 pol_perf_secs = stopMSTimer(timerRefNum) / 1e6
949 endif
950
951 setdatafolder saveDF
952 end
953
979 function show_analyser_line(theta, tilt, phi, theta_offset, tilt_offset, phi_offset, [npolar, nograph, xpdplot])
980 variable theta
981 variable tilt
982 variable phi
983 variable theta_offset
984 variable tilt_offset
985 variable phi_offset
986 variable npolar
987 variable nograph
988 variable xpdplot
989
990 string nickname = "analyser"
991
992 if (ParamIsDefault(npolar))
993 npolar = 91
994 endif
995 if (ParamIsDefault(nograph))
996 nograph = 0
997 endif
998 if (ParamIsDefault(xpdplot))
999 xpdplot = 0
1000 endif
1001 string graphname = "graph_" + nickname
1002 string outprefix = nickname
1003
1004 // sort out data folder structure
1005 dfref saveDF = GetDataFolderDFR()
1006 dfref dataDF = saveDF
1007 if (xpdplot)
1008 setdatafolder root:
1009 outprefix = nickname
1010 else
1011 setdatafolder dataDF
1012 newdatafolder /s/o $nickname
1013 outprefix = ""
1014 endif
1015 dfref destDF = GetDataFolderDFR()
1016
1017 make /n=1 /free m_theta
1018 make /n=1 /free m_tilt
1019 make /n=1 /free m_phi
1020 m_theta = theta - theta_offset
1021 m_tilt = tilt - tilt_offset
1022 m_tilt *= -1 // checked 140702
1023 m_phi = phi - phi_offset
1024 //m_phi *= -1 // checked 140702
1025
1026 make /n=60 /free data
1027 setscale /i x -30, 30, data
1028 data = x
1029 make /n=1/d/free d_polar, d_azi
1030
1031 convert_angles_ttpa2polar(m_theta, m_tilt, m_phi, data, d_polar, d_azi)
1032 d_azi += 180 // changed 151030 (v1.6)
1033 d_azi = d_azi >= 360 ? d_azi - 360 : d_azi
1034 make_hemi_grid(npolar, outprefix, xpdplot=xpdplot)
1035 hemi_add_anglescan(outprefix, data, d_polar, d_azi)
1036
1037 if (!nograph)
1038 display_hemi_scan(outprefix, graphname = graphname)
1039 endif
1040
1041 setdatafolder saveDF
1042 end
1043
1048
1049 function convert_angles_ttpd2polar(theta, tilt, phi, data, polar, azi)
1050 wave theta, tilt, phi // see convert_angles_ttpa2polar
1051 wave data // in, 1D or 2D
1052 // X-scale must be set to analyser angle scale
1053 wave polar, azi // see convert_angles_ttpa2polar
1054
1055 make /n=(dimsize(data, 0)) /d /free ana
1056 setscale /p x dimoffset(data, 0), dimdelta(data, 0), waveunits(data, 0), ana
1057 ana = x
1058 convert_angles_ttpa2polar(theta, tilt, phi, ana, polar, azi)
1059 end
1060
1088 function convert_angles_ttpa2polar(theta, tilt, phi, analyser, polar, azi)
1089 wave theta
1090 wave tilt
1091 wave phi
1092 wave analyser
1093 wave polar, azi
1094
1095 variable nn = numpnts(theta)
1096 variable na = numpnts(analyser)
1097 redimension /n=(na, nn) polar, azi
1098
1099 variable radius = 1 // don't need to specify - everything is scalable
1100
1101 // step 1: calculate cartesian detection vectors at normal emission
1102 // this is simply a polar-cartesian mapping, independent of the manipulator
1103 // phi=0 is in the polar rotation plane
1104 make /n=(3,na) /d /free w_orig_polar, w_orig_cart, w_rot_cart, w_rot_polar
1105 w_orig_polar[0][] = radius
1106 w_orig_polar[1][] = analyser[q]
1107 w_orig_polar[2][] = 0
1108 polar2cart_wave(w_orig_polar, w_orig_cart)
1109 // if the angle-dispersive axis was horizontal, we'd need to rotate the detector
1110 //rotate_z_wave(w_orig_cart, 90)
1111
1112 variable ii
1113 for (ii = 0; ii < nn; ii += 1)
1114 // step 2: rotate the detection vectors according to the manipulator angles
1115 // the order of rotations is important because we rotate about fixed axes
1116 // y-axis = tilt rotation axis
1117 // x-axis = polar rotation axis
1118 // z-axis = normal emission = azimuthal rotation axis
1119 w_rot_cart = w_orig_cart
1120 rotate_y_wave(w_rot_cart, -tilt[ii])
1121 rotate_x_wave(w_rot_cart, -theta[ii])
1122 rotate_z_wave(w_rot_cart, -phi[ii] - 90)
1123 // map the vectors back to the sample coordinate system
1124 cart2polar_wave(w_rot_cart, w_rot_polar)
1125 // copy to output
1126 polar[][ii] = w_rot_polar[1][p]
1127 azi[][ii] = w_rot_polar[2][p]
1128 endfor
1129 end
1130
1131 static function line_average(source, dest)
1132 // is this function used?
1133 wave source
1134 wave dest
1135
1136 variable ii
1137 variable nn = dimsize(source, 1)
1138 make /n=(dimsize(source, 0))/d/free line
1139 for (ii = 0; ii < nn; ii += 1)
1140 line = source[p][ii]
1141 wavestats /q line
1142 dest[][ii] = line[p] / v_max
1143 endfor
1144 end
1145
1149 static function calc_nth(Theta_st, Theta_in, th, Phi_ran, Phi_ref, Holomode)
1150 Variable Theta_st, Theta_in, th, Phi_ran, Phi_ref
1151 String Holomode
1152 Variable The_step
1153 Variable deg2rad=0.01745329
1154
1155 if ( cmpstr(Holomode, "Stereographic") == 0)
1156 The_step =trunc( Phi_ran*sin(th*deg2rad)*Phi_ref/Theta_st )
1157 if(th==90)
1158 The_step =trunc( Phi_ran*sin(th*pi/180)*Phi_ref/Theta_st )
1159 endif
1160 else
1161 if (cmpstr(Holomode, "Parallel") == 0)
1162 The_step=trunc( Phi_ran*tan(th*deg2rad)*Phi_ref/Theta_st )
1163 else
1164 if ( cmpstr(Holomode, "h") == 0)
1165 The_step=trunc( th/Theta_in*Phi_ran/Theta_st )
1166 else
1167 //altro
1168 endif
1169 endif
1170 endif
1171
1172 return(The_step)
1173 end
1174
1178 static function calc_phi_step(Theta_in, th, Theta_st, Phi_ran, Phi_ref, Holomode)
1179 Variable Theta_in, th, Theta_st, Phi_ran, Phi_ref
1180 String Holomode
1181
1182 Variable Phi_st
1183 Variable deg2rad=0.01745329
1184
1185 if ( cmpstr(Holomode, "Stereographic") == 0 )
1186 if ((th < 0.5) || (trunc(Phi_ran*sin(th*deg2rad)*Phi_ref/Theta_st) == 0))
1187 Phi_st=0.0
1188 else
1189 Phi_st=Phi_ran/(trunc(Phi_ran*sin(th*deg2rad)*Phi_ref/Theta_st))
1190 endif
1191 if(th==90)
1192 Phi_st=2.0
1193 endif
1194 endif
1195
1196 if ( cmpstr(Holomode, "Parallel") == 0 )
1197 if((th < 0.5) || (trunc(Phi_ran*tan(th*deg2rad)*Phi_ref/Theta_st) == 0))
1198 Phi_st=0.0
1199 else
1200 Phi_st=Phi_ran/(trunc(Phi_ran*tan(th*deg2rad)*Phi_ref/Theta_st))
1201 endif
1202 endif
1203
1204 if ( cmpstr(Holomode, "h") == 0 )
1205 if((th < 0.5) || (trunc(Phi_ran*sin(th*deg2rad)*Phi_ref/Theta_st) == 0))
1206 Phi_st=0.0
1207 else
1208 Phi_st=Phi_ran/trunc(th/Theta_in*Phi_ran/Theta_st)
1209 endif
1210 endif
1211
1212 if (Phi_st==0)
1213 Phi_st=360
1214 endif
1215
1216 return(Phi_st)
1217 end
1218
1222 static function Calc_The_step(th, Theta_st, Holomode)
1223 String Holomode
1224 Variable th, Theta_st
1225
1226 Variable deg2rad=0.01745329, dt_loc,The_step
1227
1228 if ( (cmpstr(Holomode, "Stereographic")) ==0 )
1229 The_step=Theta_st
1230 endif
1231
1232 if ( (cmpstr(Holomode, "h")) ==0 )
1233 The_step=Theta_st
1234 endif
1235
1236 if ( cmpstr(Holomode, "Parallel") == 0 )
1237 if(th < 89.5)
1238 dt_loc = Theta_st/cos(th*deg2rad)
1239 if(dt_loc > 10)
1240 dt_loc=10
1241 endif
1242 The_step=dt_loc
1243 else
1244 The_step=10
1245 endif
1246 endif
1247 return(The_step)
1248 end
1249
1253 static function CalcN_Theta(HoloMode,Theta_in,Theta_ran,Theta_st)
1254 String HoloMode
1255 Variable Theta_in,Theta_ran,Theta_st
1256 Variable n_theta, aux, aux1,ii
1257
1258 aux = Theta_in
1259 aux1= Theta_in - Theta_ran
1260 ii = 0
1261 do
1262 aux = aux - Calc_The_step(aux, Theta_st, HoloMode)
1263 if(aux<=Theta_in-Theta_ran)
1264 aux=Theta_in-Theta_ran
1265 endif
1266 ii = ii+1
1267 while((aux>aux1)%&(Theta_in-aux<=Theta_ran)) //
1268 n_theta=ii+1
1269 Return(n_theta)
1270 end
1271
1291 function make_hemi_grid(npol, nickname, [xpdplot])
1292 variable npol
1293 string nickname
1294 variable xpdplot
1295
1296 if (ParamIsDefault(xpdplot))
1297 xpdplot = 0
1298 endif
1299
1300 string HoloMode = "h"
1301 variable Theta_in = 90
1302 variable Theta_ran = 90
1303 variable Theta_st = 90 / (npol - 1)
1304 variable Phi_ran = 360
1305 variable Phi_ref = 1
1306 variable Phi_in = 0
1307
1308 variable n_theta = CalcN_Theta(HoloMode, Theta_in, Theta_ran, Theta_st)
1309
1310 // wave names
1311 if (strlen(nickname))
1312 string s_prefix = nickname + "_"
1313 string s_int = s_prefix + "i" // Intensity wave (counts/sec)
1314 else
1315 s_prefix = ""
1316 s_int = "values" // "i" is not a valid wave name
1317 endif
1318 string s_polar = s_prefix + "pol" // thetas for each int-point of the holo
1319 string s_azim = s_prefix + "az" // phis for each int-point of the holo
1320
1321 string s_index = s_prefix + "index" // starting index for each theta
1322 string s_theta = s_prefix + "th" // theta values
1323 string s_dphi = s_prefix + "dphi" // delta phis at each theta
1324 string s_nphis = s_prefix + "nphis" // number of phis at each theta
1325
1326 string s_HoloData = s_prefix + "data" // All holo exp.- parameter information
1327 string s_HoloInfo = s_prefix + "info"
1328
1329 // the following two waves are used by the pearl-anglescan procedures but not by XPDplot
1330 string s_tot = s_prefix + "tot" // accumulated counts at each point
1331 string s_weight = s_prefix + "wt" // total accumulation time at each point (arb. units)
1332
1333 make /O/D/n=(n_theta) $s_index /wave=index
1334 make /O/D/n=(n_theta) $s_theta /wave=theta
1335 make /O/D/n=(n_theta) $s_dphi /wave=dphi
1336 make /O/D/n=(n_theta) $s_nphis /wave=nphis
1337
1338 //---------- calculate phi-step-size for this theta:
1339 variable aux = Calc_The_step(Theta_in, Theta_st, HoloMode)
1340 dphi[0] = calc_phi_step(Theta_in, Theta_in, aux, Phi_ran, Phi_ref, HoloMode)
1341 Theta[0] = Theta_in
1342 nphis[0] = calc_nth(aux, Theta_in, Theta_in, Phi_ran, Phi_ref, HoloMode)
1343 Index[0] = nphis[0]
1344
1345 //---------- calculate number of phis, phi-step, and starting-index for each theta:
1346 variable ii = 1
1347 do
1348 Theta[ii] = Theta[ii-1] - aux
1349 if(Theta[ii] <= Theta_in-Theta_ran)
1350 Theta[ii] = Theta_in-Theta_ran
1351 endif
1352 aux = Calc_The_step(Theta[ii], Theta_st, HoloMode)
1353 dphi[ii] = calc_phi_step(Theta_in, Theta[ii], aux, Phi_ran, Phi_ref, HoloMode)
1354 nphis[ii] = calc_nth(aux, Theta_in, Theta[ii], Phi_ran, Phi_ref, HoloMode)
1355 Index[ii] = Index[ii-1] + nphis[ii]
1356 ii=ii+1
1357 while(ii < n_theta)
1358
1359 if (Index[n_theta-1]==Index[n_theta-2])
1360 Index[n_theta-1]=Index[n_theta-2]+1
1361 nphis[n_theta-1]=1
1362 endif
1363
1364 variable NumPoints = sum(nphis, 0, numpnts(nphis))
1365
1366 //---------- calculate theta and phi for each data point:
1367 make /O/D/N=(NumPoints) $s_polar /wave=polar, $s_azim /wave=azim
1368 note azim, "version=1.6"
1369
1370 ii = 0
1371 variable StartIndex = 0
1372 variable EndIndex
1373 do
1374 EndIndex=Index[ii]
1375 Polar[StartIndex, EndIndex-1]=Theta[ii]
1376 Azim[StartIndex, EndIndex-1]= mod(Phi_ran+(x-StartIndex)*dphi[ii]+Phi_in,Phi_ran)
1377 ii = ii + 1
1378 StartIndex = EndIndex
1379 while(ii < n_theta)
1380
1381 duplicate /o azim, $s_int /wave=values
1382 duplicate /o azim, $s_tot /wave=totals
1383 duplicate /o azim, $s_weight /wave=weights
1384 values = nan
1385 totals = 0
1386 weights = 0
1387
1388 // XPDplot metadata
1389 if (xpdplot)
1390 string s_FileName = ""
1391 string s_Comment = "created by pearl-anglescan-process.ipf"
1392 string s_HoloMode = "Stereographic"
1393 variable /g gb_SpectraFile = 0
1394
1395 Make/O/D/n=22 $s_HoloData /wave=HoloData
1396 HoloData[0] = NaN // v_StartKE
1397 HoloData[1] = NaN // v_StoppKE
1398 HoloData[6] = NumPoints
1399 HoloData[7] = Theta_in
1400 HoloData[8] = Theta_ran
1401 HoloData[9] = Theta_st
1402 HoloData[11] = Phi_in
1403 HoloData[12] = Phi_ran
1404 HoloData[13] = Theta_st
1405 HoloData[15] = Phi_ref
1406 HoloData[16] = Phi_ran
1407 HoloData[17] = 0 // v_HoloBit (stereographic)
1408
1409 Make/O/T/n=22 $s_HoloInfo /wave=HoloInfo
1410 HoloInfo[0] = s_FileName
1411 HoloInfo[1] = s_Comment
1412 HoloInfo[10] = s_HoloMode
1413 HoloInfo[11] = "" // s_MeasuringMode
1414
1415 // notebook for XPDplot
1416 if (WinType(NickName) == 5)
1417 Notebook $NickName selection={startOfFile, endOfFile}
1418 Notebook $NickName text=""
1419 else
1420 NewNotebook /F=0 /K=1 /N=$NickName /W=(5,40,341,260)
1421 Notebook $NickName defaultTab=140
1422 Notebook $NickName statusWidth=300
1423 Notebook $NickName backRGB=(56797,56797,56797)
1424 Notebook $NickName pageMargins={80,80,80,80}
1425 Notebook $NickName fSize=10
1426 Notebook $NickName fStyle=0,textRGB=(65535,0,26214)
1427 Notebook $NickName textRGB=(65535,0,26214)
1428 endif
1429 Notebook $NickName text = "File:\t" + s_FileName + "\r"
1430 Notebook $NickName text = "*** " + s_Comment + " ***\r\r"
1431 Notebook $NickName text = "Angle-Mode:\t" + s_HoloMode + "\r"
1432 Notebook $NickName text = "XPDplot Nickname:\t" + NickName + "\r"
1433 endif
1434 end
1435
1442 function /s get_hemi_nickname(w)
1443 wave w
1444
1445 string prefix = get_hemi_prefix(w)
1446 string wname = nameofwave(w)
1447 string nickname
1448
1449 if (strlen(prefix))
1450 nickname = prefix
1451 else
1452 string s_wave_df = GetWavesDataFolder(w, 1)
1453 dfref parent_df = $(s_wave_df + "::")
1454 nickname = GetDataFolder(0, parent_df)
1455 endif
1456
1457 return nickname
1458 end
1459
1467 function /s get_hemi_prefix(w)
1468 wave w
1469
1470 string wname = nameofwave(w)
1471 string prefix
1472 if (ItemsInList(wname, "_") >= 2)
1473 prefix = StringFromList(0, wname, "_")
1474 else
1475 prefix = ""
1476 endif
1477
1478 return prefix
1479 end
1480
1498 function /df find_hemi_data(nickname, prefix, intwave)
1499 string nickname
1500 string &prefix
1501 string &intwave
1502
1503 dfref datadf
1504 prefix = ""
1505 intwave = "values"
1506 if (strlen(nickname))
1507 if (DataFolderExists(nickname))
1508 datadf = $nickname
1509 else
1510 datadf = getdatafolderdfr()
1511 prefix = nickname + "_"
1512 intwave = prefix + "i"
1513 if (exists(intwave) != 1)
1514 datadf = root:
1515 endif
1516 endif
1517 else
1518 datadf = getdatafolderdfr()
1519 prefix = ""
1520 intwave = "values"
1521 endif
1522 return datadf
1523 end
1524
1532 function clear_hemi_grid(nickname)
1533 string nickname
1534
1535 dfref datadf
1536 string s_prefix
1537 string s_int
1538 datadf = find_hemi_data(nickname, s_prefix, s_int)
1539
1540 string s_totals = s_prefix + "tot"
1541 string s_weights = s_prefix + "wt"
1542
1543 wave /sdfr=datadf /z w_values = $s_int
1544 wave /sdfr=datadf /z w_totals = $s_totals
1545 wave /sdfr=datadf /z w_weights = $s_weights
1546
1547 if (waveexists(w_totals))
1548 w_totals = 0
1549 endif
1550 if (waveexists(w_weights))
1551 w_weights = 0
1552 endif
1553 if (waveexists(w_values))
1554 w_values = nan
1555 endif
1556 end
1557
1579 function duplicate_hemi_scan(source_nickname, dest_folder, dest_nickname, [xpdplot])
1580 string source_nickname
1581 dfref dest_folder
1582 string dest_nickname
1583 variable xpdplot
1584
1585 if (ParamIsDefault(xpdplot))
1586 xpdplot = 0
1587 endif
1588
1589 dfref savedf = getdatafolderdfr()
1590
1591 // source data
1592 string s_prefix = ""
1593 string s_int = "values"
1594 dfref source_df = find_hemi_data(source_nickname, s_prefix, s_int)
1595 string s_polar = s_prefix + "pol"
1596 string s_azim = s_prefix + "az"
1597 string s_theta = s_prefix + "th"
1598 string s_tot = s_prefix + "tot"
1599 string s_weight = s_prefix + "wt"
1600 string s_matrix = s_prefix + "matrix"
1601
1602 wave /sdfr=source_df theta1 = $s_theta
1603 wave /sdfr=source_df polar1 = $s_polar
1604 wave /sdfr=source_df azim1 = $s_azim
1605 wave /sdfr=source_df tot1 = $s_tot
1606 wave /sdfr=source_df weight1 = $s_weight
1607 wave /sdfr=source_df values1 = $s_int
1608 wave /sdfr=source_df /z matrix1 = $s_matrix
1609
1610 variable npol = numpnts(theta1)
1611
1612 setdatafolder dest_folder
1613 make_hemi_grid(npol, dest_nickname, xpdplot=xpdplot)
1614
1615 // dest data
1616 dfref dest_df = find_hemi_data(dest_nickname, s_prefix, s_int)
1617 s_polar = s_prefix + "pol"
1618 s_azim = s_prefix + "az"
1619 s_theta = s_prefix + "th"
1620 s_tot = s_prefix + "tot"
1621 s_weight = s_prefix + "wt"
1622 s_matrix = s_prefix + "matrix"
1623
1624 wave /sdfr=dest_df theta2 = $s_theta
1625 wave /sdfr=dest_df polar2 = $s_polar
1626 wave /sdfr=dest_df azim2 = $s_azim
1627 wave /sdfr=dest_df tot2 = $s_tot
1628 wave /sdfr=dest_df weight2 = $s_weight
1629 wave /sdfr=dest_df values2 = $s_int
1630
1631 tot2 = tot1
1632 weight2 = weight1
1633 values2 = values1
1634 if (waveexists(matrix1))
1635 setdatafolder dest_df
1636 duplicate /o matrix1, $s_matrix
1637 endif
1638
1639 if (!(NumberByKey("version", note(azim1), "=", "\r") >= 1.6))
1640 azim2 += 180 // changed 151030 (v1.6)
1641 azim2 = azim2 >= 360 ? azim2 - 360 : azim2
1642 endif
1643
1644 setdatafolder saveDF
1645 end
1646
1654 function rotate_hemi_scan(nickname, angle)
1655 string nickname
1656 variable angle
1657
1658 dfref savedf = getdatafolderdfr()
1659
1660 string s_prefix = ""
1661 string s_int = "values"
1662 dfref df = find_hemi_data(nickname, s_prefix, s_int)
1663
1664 string s_polar = s_prefix + "pol"
1665 string s_azim = s_prefix + "az"
1666 string s_tot = s_prefix + "tot"
1667 string s_weight = s_prefix + "wt"
1668
1669 wave /sdfr=df polar = $s_polar
1670 wave /sdfr=df azim = $s_azim
1671 wave /sdfr=df tot = $s_tot
1672 wave /sdfr=df weight = $s_weight
1673 wave /sdfr=df values = $s_int
1674
1675 azim += angle
1676 azim = azim < 0 ? azim + 360 : azim
1677 azim = azim >= 360 ? azim - 360 : azim
1678
1679 duplicate /free polar, neg_polar
1680 neg_polar = -polar
1681 sort {neg_polar, azim}, polar, azim, tot, weight, values
1682
1683 setdatafolder saveDF
1684 end
1685
1702 function /s prepare_hemi_scan_display(nickname, [projection])
1703 string nickname
1704 variable projection
1705
1706 dfref savedf = getdatafolderdfr()
1707
1708 if (ParamIsDefault(projection))
1709 projection = 1
1710 endif
1711
1712 // hemi grid waves
1713 string s_prefix = ""
1714 string s_int = "values"
1715 dfref df = find_hemi_data(nickname, s_prefix, s_int)
1716
1717 string s_polar = s_prefix + "pol"
1718 string s_azim = s_prefix + "az"
1719
1720 wave /sdfr=df /z values = $s_int
1721 wave /sdfr=df /z azim = $s_azim
1722 wave /sdfr=df /z polar = $s_polar
1723
1724 setdatafolder df
1725 string s_ster_rad = s_prefix + "ster_rad"
1726 duplicate /o polar, $s_ster_rad /wave=ster_rad
1727 ster_rad = calc_graph_radius(polar, projection=projection)
1728
1729 string s_ster_x = s_prefix + "ster_x"
1730 string s_ster_y = s_prefix + "ster_y"
1731 duplicate /o azim, $s_ster_x /wave=ster_x, $s_ster_y /wave=ster_y
1732 ster_x = ster_rad * cos(azim * pi / 180)
1733 ster_y = ster_rad * sin(azim * pi / 180)
1734
1735 setdatafolder savedf
1736 end
1737
1784 function /s display_hemi_scan(nickname, [projection, graphtype, do_ticks, do_grids, graphname])
1785 string nickname
1786 variable projection
1787 variable graphtype
1788 variable do_ticks
1789 variable do_grids
1790 string graphname
1791
1792 dfref savedf = getdatafolderdfr()
1793
1794 if (ParamIsDefault(projection))
1795 projection = 1
1796 endif
1797 if (ParamIsDefault(graphtype))
1798 graphtype = 1
1799 endif
1800 if (ParamIsDefault(do_ticks))
1801 do_ticks = 3
1802 endif
1803 if (ParamIsDefault(do_grids))
1804 do_grids = 3
1805 endif
1806 if (ParamIsDefault(graphname))
1807 if (strlen(nickname) > 0)
1808 graphname = nickname
1809 else
1810 graphname = GetDataFolder(0)
1811 endif
1812 endif
1813
1814 prepare_hemi_scan_display(nickname, projection=projection)
1815
1816 // hemi grid waves
1817 string s_prefix = ""
1818 string s_int = "values"
1819 dfref df = find_hemi_data(nickname, s_prefix, s_int)
1820
1821 string s_polar = s_prefix + "pol"
1822 string s_azim = s_prefix + "az"
1823 string s_matrix = s_prefix + "matrix"
1824 string s_ster_rad = s_prefix + "ster_rad"
1825
1826 wave /sdfr=df /z values = $s_int
1827 wave /sdfr=df /z azim = $s_azim
1828 wave /sdfr=df /z polar = $s_polar
1829 wave /sdfr=df /z ster_rad = $s_ster_rad
1830 wave /sdfr=df /z matrix = $s_matrix
1831
1832 setdatafolder df
1833 variable azim_offset = 0
1834 if (!(NumberByKey("version", note(azim), "=", "\r") >= 1.6))
1835 DoAlert /T="display hemi scan" 0, "your dataset doesn't include the version 1.6 flag. if it was created with an earlier version that might be okay. please check that the orientation is correct!"
1836 azim_offset = 180 // changed 151030 (v1.6)
1837 endif
1838
1839 string s_trace
1840 DoWindow $graphname
1841 if (v_flag)
1842 if (str2num(GetUserData(graphname, "", "graphtype")) == graphtype)
1843 // graph exists and will update automatically - do not recreate
1844 graphtype = 0
1845 else
1846 // graph exists - but needs recreating
1847 killwindow $graphname
1848 endif
1849 endif
1850
1851 switch(graphtype)
1852 case 1:
1853 graphname = display_polar_graph(graphname, angle_offset=azim_offset, do_ticks=do_ticks)
1854
1855 s_trace = WMPolarAppendTrace(graphname, ster_rad, azim, 360)
1856 ModifyGraph /W=$graphname mode($s_trace)=2, lsize($s_trace)=2
1857 ModifyGraph /W=$graphname zColor($s_trace)={values,*,*,BlueGreenOrange,0}
1858
1859 ColorScale /W=$graphname /C /N=text0 /E=2 /F=0 /B=1 /A=RB /X=0.00 /Y=0.00 trace=polarY0
1860 ColorScale /W=$graphname /C /N=text0 side=2, width=5, heightPct=40, frame=0.50, lblMargin=0
1861 ColorScale /W=$graphname /C /N=text0 nticks=2, minor=1, tickLen=4.00, tickThick=0.50
1862
1863 SetWindow $graphname, userdata(projection)=num2str(projection)
1864 SetWindow $graphname, userdata(graphtype)=num2str(graphtype)
1865 draw_hemi_axes(graphname, do_grids=do_grids)
1866 break
1867 case 3:
1868 graphname = display_polar_graph(graphname, angle_offset=azim_offset, do_ticks=do_ticks)
1869
1870 s_trace = WMPolarAppendTrace(graphname, ster_rad, azim, 360)
1871 ModifyGraph /W=$graphname mode($s_trace)=0, lsize($s_trace)=0
1872 AppendImage /L=VertCrossing /B=HorizCrossing matrix
1873
1874 ColorScale /W=$graphname /C /N=text0 /E=2 /F=0 /B=1 /A=RB /X=0.00 /Y=0.00 image=$s_matrix
1875 ColorScale /W=$graphname /C /N=text0 side=2, width=5, heightPct=40, frame=0.50, lblMargin=0
1876 ColorScale /W=$graphname /C /N=text0 nticks=2, minor=1, tickLen=4.00, tickThick=0.50
1877
1878 SetWindow $graphname, userdata(projection)=num2str(projection)
1879 SetWindow $graphname, userdata(graphtype)=num2str(graphtype)
1880 draw_hemi_axes(graphname, do_grids=do_grids)
1881 break
1882 endswitch
1883
1884 setdatafolder savedf
1885 return graphname
1886 end
1887
1929 static function /s display_polar_graph(graphname, [angle_offset, do_ticks])
1930
1931 string graphname
1932 variable angle_offset
1933 variable do_ticks
1934
1935 dfref savedf = GetDataFolderDFR()
1936
1937 if (ParamIsDefault(angle_offset))
1938 angle_offset = 0
1939 endif
1940 if (ParamIsDefault(do_ticks))
1941 do_ticks = 3
1942 endif
1943
1944 if ((strlen(graphname) == 0) || (wintype(graphname) == 0))
1945 Display /k=1 /W=(10,45,360,345)
1946 DoWindow /C $graphname
1947 graphname = WMNewPolarGraph("", graphname)
1948 WMPolarGraphSetVar(graphname, "zeroAngleWhere", angle_offset)
1949
1950 WMPolarGraphSetVar(graphname, "angleAxisThick", 0.5)
1951 WMPolarGraphSetStr(graphname, "doMajorAngleTicks", "manual")
1952 WMPolarGraphSetVar(graphname, "majorAngleInc", 30) // major ticks in 30 deg steps
1953 WMPolarGraphSetVar(graphname, "minorAngleTicks", 2) // minor ticks in 10 deg steps
1954 WMPolarGraphSetStr(graphname, "angleTicksLocation", "Outside")
1955 WMPolarGraphSetVar(graphname, "doAngleTickLabelSubRange", 1)
1956 WMPolarGraphSetVar(graphname, "angleTickLabelRangeStart", 0)
1957 WMPolarGraphSetVar(graphname, "angleTickLabelRangeExtent", 90)
1958 WMPolarGraphSetStr(graphname, "angleTickLabelNotation", "%g°")
1959
1960 WMPolarGraphSetVar(graphname, "doPolarGrids", 0)
1961 WMPolarGraphSetVar(graphname, "doRadiusTickLabels", 0)
1962 WMPolarGraphSetStr(graphname, "radiusAxesWhere", " Off") // note the leading spaces, cf. WMPolarAnglesForRadiusAxes
1963 WMPolarGraphSetStr(graphname, "radiusTicksLocation", "Off")
1964
1965 WMPolarGraphSetVar(graphname, "majorTickLength", 2)
1966 WMPolarGraphSetVar(graphname, "majorTickThick", 0.5)
1967 WMPolarGraphSetVar(graphname, "minorTickLength", 1)
1968 WMPolarGraphSetVar(graphname, "minorTickThick", 0.5)
1969 WMPolarGraphSetVar(graphname, "tickLabelOpaque", 0)
1970 WMPolarGraphSetVar(graphname, "tickLabelFontSize", 7)
1971
1972 // changes
1973 if (do_ticks & 1)
1974 WMPolarGraphSetStr(graphname, "angleTicksLocation", "Outside")
1975 else
1976 WMPolarGraphSetStr(graphname, "angleTicksLocation", "Off")
1977 endif
1978 if (do_ticks & 2)
1979 WMPolarGraphSetVar(graphname, "doMinorAngleTicks", 1)
1980 else
1981 WMPolarGraphSetVar(graphname, "doMinorAngleTicks", 0)
1982 endif
1983
1984 DoWindow /T $graphname, graphname
1985
1986 // cursor info in angles
1987 string graphdf = "root:packages:WMPolarGraphs:" + graphname
1988 setdatafolder graphdf
1989 // current theta, phi coordinates are stored in global variables in the package folder of the graph
1990 variable /g csrA_theta
1991 variable /g csrA_phi
1992 variable /g csrB_theta
1993 variable /g csrB_phi
1994 // the text box is hidden initially. it shows up and hides with the cursor info box.
1995 string tb
1996 tb = "\\{"
1997 tb = tb + "\"A = (%.1f, %.1f)\","
1998 tb = tb + graphdf + ":csrA_theta,"
1999 tb = tb + graphdf + ":csrA_phi"
2000 tb = tb + "}"
2001 TextBox /W=$graphname /A=LT /B=1 /E=2 /F=0 /N=tb_angles /X=1 /Y=1 /V=0 tb
2002 tb = "\\{"
2003 tb = tb + "\"B = (%.1f, %.1f)\","
2004 tb = tb + graphdf + ":csrB_theta,"
2005 tb = tb + graphdf + ":csrB_phi"
2006 tb = tb + "}"
2007 AppendText /W=$graphname /N=tb_angles tb
2008 // updates are triggered by a window hook
2009 SetWindow $graphname, hook(polar_graph_hook)=PearlAnglescanProcess#polar_graph_hook
2010 else
2011 // graph window exists
2012 DoWindow /F $graphname
2013 endif
2014
2015 setdatafolder savedf
2016 return graphname
2017 end
2018
2044 static function /s draw_hemi_axes(graphname, [do_grids])
2045 string graphname
2046 variable do_grids
2047
2048 if (ParamIsDefault(do_grids))
2049 do_grids = 3
2050 endif
2051
2052 dfref savedf = GetDataFolderDFR()
2053
2054 string sproj = GetUserData(graphname, "", "projection")
2055 variable projection = str2num("0" + sproj)
2056
2057 SetDrawLayer /W=$graphname ProgFront
2058
2059 // polar axis
2060 SetDrawEnv /W=$graphname xcoord=HorizCrossing, ycoord=VertCrossing
2061 SetDrawEnv /W=$graphname linethick= 0.5
2062 SetDrawEnv /W=$graphname dash=2
2063 SetDrawEnv /W=$graphname fillpat=0
2064 SetDrawEnv /W=$graphname fname="default", fsize=7
2065 SetDrawEnv /W=$graphname textxjust=1, textyjust=1
2066 //SetDrawEnv /W=$graphname linefgc=(65535,65535,65535)
2067 SetDrawEnv /W=$graphname save
2068
2069 if (do_grids & 1)
2070 DrawLine /W=$graphname 0, -2, 0, 2
2071 DrawLine /W=$graphname -2, 0, 2, 0
2072 endif
2073
2074 variable radi
2075 if (do_grids & 2)
2076 radi = calc_graph_radius(0.5, projection=projection)
2077 DrawOval /W=$graphname -radi, radi, radi, -radi
2078 radi = calc_graph_radius(30, projection=projection)
2079 DrawOval /W=$graphname -radi, radi, radi, -radi
2080 radi = calc_graph_radius(60, projection=projection)
2081 DrawOval /W=$graphname -radi, radi, radi, -radi
2082
2083 SetDrawEnv /W=$graphname textxjust= 1,textyjust= 2
2084 SetDrawEnv /W=$graphname save
2085 radi = calc_graph_radius(30, projection=projection)
2086 DrawText /W=$graphname radi, -0.1, "30°"
2087 radi = calc_graph_radius(60, projection=projection)
2088 DrawText /W=$graphname radi, -0.1, "60°"
2089 endif
2090
2091 setdatafolder savedf
2092 end
2093
2116 function draw_diffraction_cone(graphname, groupname, theta_axis, theta_inner, phi)
2117 string graphname
2118 string groupname
2119
2120 variable theta_axis
2121 variable theta_inner
2122 variable phi
2123
2124 variable r_axis = calc_graph_radius(theta_axis)
2125 variable r_inner = calc_graph_radius(theta_inner)
2126 variable r_outer = calc_graph_radius(2 * theta_axis - theta_inner)
2127
2128 SetDrawEnv push
2129 SetDrawLayer UserFront
2130 DrawAction getgroup=$groupname, delete
2131 SetDrawEnv gstart, gname=$groupname
2132 variable xc, yc, xr, yr
2133
2134 // cone periphery
2135 variable r_center = (r_outer + r_inner) / 2
2136 variable r_radius = (r_outer - r_inner) / 2
2137 xc = r_center * cos(phi * pi / 180)
2138 yc = r_center * sin(phi * pi / 180)
2139 xr = r_radius
2140 yr = r_radius
2141 SetDrawEnv xcoord=HorizCrossing, ycoord=VertCrossing
2142 SetDrawEnv dash=11, fillpat=0
2143 DrawOval xc - xr, yc - yr, xc + xr, yc + yr
2144
2145 // cone axis
2146 xc = r_axis * cos(phi * pi / 180)
2147 yc = r_axis * sin(phi * pi / 180)
2148 r_radius = calc_graph_radius(2)
2149 xr = r_radius
2150 yr = r_radius
2151 SetDrawEnv xcoord=HorizCrossing, ycoord=VertCrossing
2152 SetDrawEnv fillfgc=(0,0,0)
2153 DrawOval xc - xr, yc - yr, xc + xr, yc + yr
2154
2155 SetDrawEnv gstop
2156 SetDrawEnv pop
2157 end
2158
2180 function /s display_scanlines(nickname, alpha_lo, alpha_hi, m_theta, m_tilt, m_phi, [folding, projection])
2181 string nickname
2182 variable alpha_lo
2183 variable alpha_hi
2184 wave m_theta
2185 wave m_tilt
2186 wave m_phi
2187 variable folding
2188 variable projection
2189
2190 if (ParamIsDefault(folding))
2191 folding = 1
2192 endif
2193 if (ParamIsDefault(projection))
2194 projection = 1
2195 endif
2196
2197 // sort out data folder structure
2198 dfref saveDF = GetDataFolderDFR()
2199 newdatafolder /s/o $nickname
2200 string graphname = "graph_" + nickname
2201
2202 duplicate /free m_tilt, loc_m_tilt
2203 loc_m_tilt = -m_tilt
2204
2205 make /n=1 /d /free d_polar, d_azi
2206 variable n_alpha = round(alpha_hi - alpha_lo) + 1
2207 make /n=(n_alpha) /d /free analyser
2208 setscale /i x alpha_lo, alpha_hi, "°", analyser
2209 analyser = x
2210
2211 convert_angles_ttpa2polar(m_theta, loc_m_tilt, m_phi, analyser, d_polar, d_azi)
2212 duplicate /free d_polar, d_radius
2213 d_radius = calc_graph_radius(d_polar, projection=projection)
2214 d_azi += 180 // changed 151030 (v1.6)
2215
2216 graphname = display_polar_graph(graphname)
2217 SetWindow $graphname, userdata(projection)=num2str(projection)
2218
2219 variable ifold
2220 variable iang
2221 variable nang = numpnts(m_theta)
2222 string s_rad
2223 string s_azi
2224 string s_trace
2225 for (ifold = 0; ifold < folding; ifold += 1)
2226 d_azi = d_azi >= 360 ? d_azi - 360 : d_azi
2227 for (iang = 0; iang < nang; iang += 1)
2228 sprintf s_rad, "rad_%d_%d", ifold, iang
2229 duplicate /o analyser, $s_rad
2230 wave w_rad = $s_rad
2231 w_rad = d_radius[p][iang]
2232
2233 sprintf s_azi, "azi_%d_%d", ifold, iang
2234 duplicate /o analyser, $s_azi
2235 wave w_azi = $s_azi
2236 w_azi = d_azi[p][iang]
2237
2238 if (numtype(sum(w_rad)) == 0)
2239 s_trace = WMPolarAppendTrace(graphname, w_rad, w_azi, 360)
2240 ModifyGraph /w=$graphname mode($s_trace)=0, lsize($s_trace)=0.5
2241 endif
2242 endfor
2243 d_azi += 360 / folding
2244 endfor
2245
2246 draw_hemi_axes(graphname)
2247
2248 setdatafolder saveDF
2249 return graphname
2250 end
2251
2268 constant kProjDist = 0
2269 constant kProjStereo = 1
2270 constant kProjArea = 2
2271 constant kProjGnom = 3
2272 constant kProjOrtho = 4
2273
2274 static constant kProjScaleDist = 2
2275 static constant kProjScaleStereo = 2
2276 static constant kProjScaleArea = 2
2277 // scaled so that radius(gnom) = radius(stereo) for polar = 88
2278 static constant kProjScaleGnom = 0.06744519021
2279 static constant kProjScaleOrtho = 2
2280
2295 threadsafe function calc_graph_radius(polar, [projection])
2296 variable polar
2297 variable projection
2298
2299 if (ParamIsDefault(projection))
2300 projection = 1
2301 endif
2302
2303 variable radius
2304 switch(projection)
2305 case kProjStereo: // stereographic
2306 radius = kProjScaleStereo * tan(polar / 2 * pi / 180)
2307 break
2308 case kProjArea: // equal area
2309 radius = kProjScaleArea * sin(polar / 2 * pi / 180)
2310 break
2311 case kProjGnom: // gnomonic
2312 radius = polar < 90 ? kProjScaleGnom * tan(polar * pi / 180) : inf
2313 break
2314 case kProjOrtho: // orthographic
2315 radius = kProjScaleOrtho * sin(polar * pi / 180)
2316 break
2317 default: // equidistant
2318 radius = kProjScaleDist * polar / 90
2319 endswitch
2320
2321 return radius
2322 end
2323
2340 threadsafe function calc_graph_polar(x, y, [projection])
2341 variable x
2342 variable y
2343 variable projection
2344
2345 if (ParamIsDefault(projection))
2346 projection = 1
2347 endif
2348
2349 variable radius
2350 variable polar
2351
2352 radius = sqrt(x^2 + y^2)
2353 switch(projection)
2354 case kProjStereo: // stereographic
2355 polar = 2 * atan(radius / kProjScaleStereo) * 180 / pi
2356 break
2357 case kProjArea: // equal area
2358 polar = 2 * asin(radius / kProjScaleArea) * 180 / pi
2359 break
2360 case kProjGnom: // gnomonic
2361 polar = atan(radius / kProjScaleGnom) * 180 / pi
2362 break
2363 case kProjOrtho: // orthographic
2364 polar = asin(radius / kProjScaleOrtho) * 180 / pi
2365 break
2366 default: // equidistant
2367 polar = 90 * radius / kProjScaleDist
2368 endswitch
2369
2370 return polar
2371 end
2372
2393 threadsafe function calc_graph_azi(x, y, [projection,zeroAngle])
2394 variable x
2395 variable y
2396 variable projection
2397 variable zeroAngle
2398
2399 if (ParamIsDefault(projection))
2400 projection = 1
2401 endif
2402 if (ParamIsDefault(zeroAngle))
2403 zeroAngle = 0
2404 endif
2405
2406 variable azi
2407 if (x > 0)
2408 azi = atan(y / x) * 180 / pi
2409 else
2410 azi = atan(y / x) * 180 / pi + 180
2411 endif
2412
2413 azi += zeroAngle
2414 if (azi < 0)
2415 azi += 360
2416 endif
2417 if (azi >= 360)
2418 azi -= 360
2419 endif
2420 if (numtype(azi) != 0)
2421 azi = 0
2422 endif
2423
2424 return azi
2425 end
2426
2438 static function update_polar_info(graphname)
2439 string graphname
2440
2441 dfref savedf = GetDataFolderDFR()
2442
2443 string graphdf = "root:packages:WMPolarGraphs:" + graphname
2444 setdatafolder graphdf
2445
2446 nvar csrA_theta
2447 nvar csrA_phi
2448 nvar csrB_theta
2449 nvar csrB_phi
2450
2451 string sproj = GetUserData(graphname, "", "projection")
2452 variable projection = str2num("0" + sproj)
2453 nvar zeroAngleWhere
2454
2455 variable x = hcsr(A, graphname)
2456 variable y = vcsr(A, graphname)
2457 csrA_theta = calc_graph_polar(x, y, projection=projection)
2458 csrA_phi = calc_graph_azi(x, y, projection=projection, zeroAngle=zeroAngleWhere)
2459
2460 x = hcsr(B, graphname)
2461 y = vcsr(B, graphname)
2462 csrB_theta = calc_graph_polar(x, y, projection=projection)
2463 csrB_phi = calc_graph_azi(x, y, projection=projection, zeroAngle=zeroAngleWhere)
2464
2465 setdatafolder savedf
2466 end
2467
2473 static function polar_graph_hook(s)
2474 STRUCT WMWinHookStruct &s
2475
2476 Variable hookResult = 0
2477
2478 switch(s.eventCode)
2479 case 7: // cursor moved
2480 update_polar_info(s.winname)
2481 break
2482 case 20: // show info
2483 TextBox /W=$s.winname /N=tb_angles /C /V=1
2484 break
2485 case 21: // hide info
2486 TextBox /W=$s.winname /N=tb_angles /C /V=0
2487 break
2488 endswitch
2489
2490 return hookResult // 0 if nothing done, else 1
2491 end
2492
2493 function set_polar_graph_cursor(nickname, cursorname, polar_angle, azim_angle, [graphname])
2494 string nickname
2495 string cursorname
2496 variable polar_angle
2497 variable azim_angle
2498 string graphname
2499
2500 if (ParamIsDefault(graphname))
2501 if (strlen(nickname) > 0)
2502 graphname = nickname
2503 else
2504 graphname = GetDataFolder(0)
2505 endif
2506 endif
2507
2508 string s_prefix = ""
2509 string s_int = "values"
2510 dfref df = find_hemi_data(nickname, s_prefix, s_int)
2511
2512 string s_polar = s_prefix + "pol"
2513 string s_azim = s_prefix + "az"
2514 wave /sdfr=df /z azim = $s_azim
2515 wave /sdfr=df /z polar = $s_polar
2516
2517 FindLevel /P /Q polar, polar_angle
2518 if (v_flag == 0)
2519 variable polar_level = floor(v_levelx)
2520 FindLevel /P /Q /R=[polar_level] azim, azim_angle
2521 if (v_flag == 0)
2522 variable azim_level = round(v_levelx)
2523 string tracename = "polarY0"
2524 Cursor /W=$graphname /P $cursorname $traceName azim_level
2525 endif
2526 endif
2527 end
2528
2538 function hemi_add_anglescan(nickname, values, polar, azi, [weights])
2539 string nickname // name prefix of holo waves.
2540 // may be empty.
2541 wave values // intensity values
2542 // the wave can be one- or two-dimensional.
2543 // no specific order required, the function sorts the arrays internally
2544 wave polar // polar coordinates. allowed range 0 <= theta <= 90
2545 // dimensions corresponding to value.
2546 wave azi // azimuthal coordinates. allowed range -360 <= phi < +360
2547 // dimensions corresponding to value.
2548 wave weights // total accumulation time of each point of values. default = 1
2549
2550 if (ParamIsDefault(weights))
2551 duplicate /free values, weights
2552 weights = 1
2553 endif
2554
2555 // quick check whether hemi grid is existing
2556 string s_prefix = ""
2557 string s_int = "values"
2558 dfref df = find_hemi_data(nickname, s_prefix, s_int)
2559
2560 string s_polar = s_prefix + "pol"
2561 string s_azim = s_prefix + "az"
2562 string s_theta = s_prefix + "th"
2563
2564 wave /sdfr=df /z w_values = $s_int
2565 wave /sdfr=df /z w_azim = $s_azim
2566 wave /sdfr=df /z w_polar = $s_polar
2567 wave /sdfr=df /z w_theta = $s_theta
2568 if (!waveexists(w_values) || !waveexists(w_azim) || !waveexists(w_polar))
2569 abort "Missing hemispherical scan grid. Please call make_hemi_grid() first."
2570 endif
2571
2572 // make internal copies, one-dimensional, ordered in theta
2573 duplicate /free values, values_copy
2574 duplicate /free polar, polar_copy
2575 duplicate /free azi, azi_copy
2576 duplicate /free weights, weights_copy
2577 variable nn = dimsize(values, 0) * max(dimsize(values, 1), 1)
2578 redimension /n=(nn) values_copy, polar_copy, azi_copy, weights_copy
2579 sort /r polar_copy, polar_copy, azi_copy, values_copy, weights_copy
2580
2581 variable pol
2582 variable pol_st = abs(w_theta[1] - w_theta[0])
2583 variable pol1, pol2
2584
2585 duplicate /free azi_copy, azi_slice
2586 duplicate /free values_copy, values_slice
2587 duplicate /free weights_copy, weights_slice
2588 for (pol = 90; pol >= 0; pol -= pol_st)
2589 pol1 = pol - pol_st / 2
2590 pol2 = pol + pol_st / 2
2591 extract /free /indx polar_copy, sel, (pol1 < polar_copy) && (polar_copy <= pol2)
2592 if (numpnts(sel) > 0)
2593 redimension /n=(numpnts(sel)) azi_slice, values_slice, weights_slice
2594 azi_slice = azi_copy[sel]
2595 values_slice = values_copy[sel]
2596 weights_slice = weights_copy[sel]
2597 hemi_add_aziscan(nickname, values_slice, pol, azi_slice, weights=weights_slice)
2598 endif
2599 endfor
2600 end
2601
2608 function hemi_add_aziscan(nickname, values, polar, azi, [weights])
2609 string nickname // name prefix of holo waves.
2610 // may be empty.
2611 wave values // intensity values of the azimuthal scan at the positions given in the azi parameter
2612 variable polar // polar angle where to add the azi scan
2613 wave azi // angle positions of the azimuthal scan
2614 // acceptable range: >= -360 and < +360
2615 // no specific order required, the function sorts the array internally
2616 wave weights // total accumulation time of each point of values. default = 1
2617
2618 if (ParamIsDefault(weights))
2619 duplicate /free values, weights
2620 weights = 1
2621 endif
2622
2623 // hemi grid waves
2624 string s_prefix = ""
2625 string s_int = "values"
2626 dfref df = find_hemi_data(nickname, s_prefix, s_int)
2627
2628 string s_totals = s_prefix + "tot"
2629 string s_weights = s_prefix + "wt"
2630 string s_polar = s_prefix + "pol"
2631 string s_azim = s_prefix + "az"
2632 string s_index = s_prefix + "index"
2633 string s_theta = s_prefix + "th"
2634 string s_dphi = s_prefix + "dphi"
2635 string s_nphis = s_prefix + "nphis"
2636
2637 wave /sdfr=df w_polar = $s_polar
2638 wave /sdfr=df w_azim = $s_azim
2639 wave /sdfr=df w_values = $s_int
2640 wave /sdfr=df w_totals = $s_totals
2641 wave /sdfr=df w_weights = $s_weights
2642 wave /sdfr=df w_index = $s_index
2643 wave /sdfr=df w_theta = $s_theta
2644 wave /sdfr=df w_dphi = $s_dphi
2645 wave /sdfr=df w_nphis = $s_nphis
2646
2647 // destination slice coordinates
2648 //polar = round(polar)
2649 //variable ipol = 90 - polar
2650 variable ipol = BinarySearch(w_theta, polar)
2651 if (ipol < 0)
2652 abort "assertion failed in hemi_add_aziscan(): polar angle not found in grid."
2653 endif
2654
2655 variable d1, d2
2656 if (ipol >= 1)
2657 d1 = w_index[ipol - 1]
2658 else
2659 d1 = 0
2660 endif
2661 d2 = w_index[ipol] - 1
2662 variable nd = d2 - d1 + 1
2663 variable dphi = w_dphi[ipol]
2664 variable az1, az2
2665
2666 // source slice coordinates
2667 // order the slice from -dphi/2 to 360-dphi/2
2668 azi = azi < 0 ? azi + 360 : azi
2669 azi = azi >= 360 - dphi/2 ? azi - 360 : azi
2670 duplicate /free values, sel_values
2671 duplicate /free weights, sel_weights
2672
2673 // loop over destination
2674 variable id
2675 variable v1, v2, w1, w2
2676 for (id = 0; id < nd; id += 1)
2677 az1 = (id - 0.5) * dphi
2678 az2 = (id + 0.5) * dphi
2679 extract /free /indx azi, sel, (az1 <= azi) && (azi < az2)
2680 if (numpnts(sel) > 0)
2681 redimension /n=(numpnts(sel)) sel_values, sel_weights
2682 sel_values = values[sel]
2683 sel_weights = weights[sel]
2684 v1 = w_totals[d1 + id]
2685 w1 = w_weights[d1 + id]
2686 if ((numtype(v1) == 2) || (w1 <= 0))
2687 v1 = 0
2688 w1 = 0
2689 endif
2690 v2 = sum(sel_values)
2691 w2 = sum(sel_weights)
2692 w_totals[d1 + id] = v1 + v2
2693 w_weights[d1 + id] = w1 + w2
2694 endif
2695 endfor
2696 w_values[d1, d1 + nd - 1] = w_totals[p] / w_weights[p]
2697 end
2698
2726 function interpolate_hemi_scan(nickname, [projection])
2727 string nickname
2728 variable projection
2729
2730 dfref savedf = GetDataFolderDFR()
2731
2732 if (ParamIsDefault(projection))
2733 projection = 1
2734 endif
2735
2736 string s_prefix = ""
2737 string s_int = "values"
2738 dfref df = find_hemi_data(nickname, s_prefix, s_int)
2739 prepare_hemi_scan_display(nickname, projection=projection)
2740
2741 string s_polar = s_prefix + "pol"
2742 string s_azim = s_prefix + "az"
2743 string s_matrix = s_prefix + "matrix"
2744 string s_ster_rad = s_prefix + "ster_rad"
2745 string s_ster_x = s_prefix + "ster_x"
2746 string s_ster_y = s_prefix + "ster_y"
2747
2748 wave /sdfr=df /z values = $s_int
2749 wave /sdfr=df /z azim = $s_azim
2750 wave /sdfr=df /z polar = $s_polar
2751 wave /sdfr=df /z ster_rad = $s_ster_rad
2752 wave /sdfr=df /z ster_x = $s_ster_x
2753 wave /sdfr=df /z ster_y = $s_ster_y
2754
2755 variable min_ster_x = wavemin(ster_x)
2756 variable max_ster_x = wavemax(ster_x)
2757 variable x0 = min_ster_x
2758 variable xn = 181
2759 variable dx = (max_ster_x - min_ster_x) / (xn - 1)
2760 make /n=(numpnts(ster_x), 3) /free triplet
2761 triplet[][0] = ster_x[p]
2762 triplet[][1] = ster_y[p]
2763 triplet[][2] = values[p]
2764
2765 variable size = 181
2766 setdatafolder df
2767 make /n=(size, size) /d /o $(s_prefix + "matrix") /wave=matrix
2768 make /n=(size, size) /free mnorm
2769 ImageFromXYZ /as {ster_x, ster_y, values}, matrix, mnorm
2770 matrix /= mnorm
2771 matrixfilter NanZapMedian, matrix
2772 matrixfilter gauss, matrix
2773
2774 duplicate /free values, ster_finite
2775 ster_finite = (numtype(values) == 0) * (ster_x^2 + ster_y^2)
2776 variable ster_max = wavemax(ster_finite)
2777 matrix = (x^2 + y^2) <= ster_max ? matrix : nan
2778
2779 setdatafolder savedf
2780 end
2781
2792 function quick_pizza_image(data, nickname, theta_offset, tilt_offset, phi_offset, [npolar, nograph, folding])
2793 wave data // 2D intensity wave, see requirements above
2794 string nickname // nick name for output data
2795 // in default mode, this will be the name of a child folder containing the output
2796 // in XPDplot mode, this will be a prefix of the generated data in the root folder
2797 variable theta_offset // manipulator theta angle corresponding to normal emission
2798 variable tilt_offset // manipulator tilt angle corresponding to normal emission
2799 variable phi_offset // manipulator phi angle corresponding to phi_result = 0
2800 variable npolar // number of polar angles, determines polar and azimuthal step size
2801 // default = 91 (1 degree steps)
2802 variable nograph // 0 (default) = display a new polar graph
2803 // 1 = don't display a new graph (if a graph is existing from a previous call, it will update)
2804 variable folding // rotational averaging, default = 1
2805
2806 if (ParamIsDefault(npolar))
2807 npolar = 91
2808 endif
2809 if (ParamIsDefault(nograph))
2810 nograph = 0
2811 endif
2812 if (ParamIsDefault(folding))
2813 folding = 1
2814 endif
2815 string graphname = "graph_" + nickname
2816 string s_prefix = ""
2817
2818 // sort out data folder structure
2819 dfref saveDF = GetDataFolderDFR()
2820 dfref dataDF = GetWavesDataFolderDFR(data)
2821 setdatafolder dataDF
2822 if (DataFolderExists(":attr"))
2823 setdatafolder :attr
2824 endif
2825 dfref attrDF = GetDataFolderDFR()
2826 setdatafolder dataDF
2827 newdatafolder /s/o $nickname
2828 dfref destDF = GetDataFolderDFR()
2829
2830 // performance monitoring
2831 variable timerRefNum
2832 variable /g xyz_perf_secs
2833 timerRefNum = startMSTimer
2834
2835 wave /sdfr=attrDF ManipulatorTheta
2836 wave /sdfr=attrDF ManipulatorTilt
2837 wave /sdfr=attrDF ManipulatorPhi
2838 duplicate /free ManipulatorTheta, m_theta
2839 duplicate /free ManipulatorTilt, m_tilt
2840 duplicate /free ManipulatorPhi, m_phi
2841 m_theta -= theta_offset
2842 m_tilt -= tilt_offset
2843 m_tilt *= -1 // checked 140702
2844 m_phi -= phi_offset
2845 //m_phi *= -1 // checked 140702
2846
2847 make /n=1/d/free d_polar, d_azi
2848 convert_angles_ttpd2polar(m_theta, m_tilt, m_phi, data, d_polar, d_azi)
2849 d_azi += 180 // changed 151030 (v1.6)
2850 d_azi = d_azi >= 360 ? d_azi - 360 : d_azi
2851
2852 duplicate /free data, values
2853 variable nn = dimsize(values, 0) * max(dimsize(values, 1), 1)
2854 redimension /n=(nn) values, d_polar, d_azi
2855 duplicate /o d_polar, ster_rad, ster_x, ster_y
2856
2857 variable projection = 1
2858 switch(projection)
2859 case 1: // stereographic
2860 ster_rad = 2 * tan(d_polar / 2 * pi / 180)
2861 break
2862 case 2: // azimuthal
2863 ster_rad = 2 * cos((180 - d_polar) / 2 * pi / 180)
2864 break
2865 endswitch
2866 string s_ster_x = s_prefix + "ster_x"
2867 string s_ster_y = s_prefix + "ster_y"
2868
2869 nn = 401
2870 make /n=(nn, nn) /d /o matrix
2871 make /n=(nn, nn) /free mnorm
2872 setscale /i x -2, +2, matrix, mnorm
2873 setscale /i y -2, +2, matrix, mnorm
2874 matrix = 0
2875 mnorm = 0
2876
2877 variable ifold
2878 for (ifold = 0; ifold < folding; ifold += 1)
2879 ster_x = ster_rad * cos(d_azi * pi / 180)
2880 ster_y = ster_rad * sin(d_azi * pi / 180)
2881 ImageFromXYZ {ster_x, ster_y, values}, matrix, mnorm
2882 d_azi = d_azi >= 180 ? d_azi + 360 / folding - 180 : d_azi + 360 / folding
2883 endfor
2884
2885 matrix /= mnorm
2886 matrixfilter /n=5 NanZapMedian matrix
2887 matrixfilter /n=3 gauss matrix
2888
2889 if (!nograph)
2890 display /k=1
2891 appendimage matrix
2892 modifygraph width={Plan,1,bottom,left}
2893 endif
2894
2895 if (timerRefNum >= 0)
2896 xyz_perf_secs = stopMSTimer(timerRefNum) / 1e6
2897 endif
2898
2899 setdatafolder saveDF
2900 end
2901
2903 function save_hemi_scan(nickname, pathname, filename)
2904 string nickname
2905 string pathname
2906 string filename
2907
2908 dfref savedf = getdatafolderdfr()
2909
2910 // source data
2911 string s_prefix = ""
2912 string s_int = "values"
2913 dfref df = find_hemi_data(nickname, s_prefix, s_int)
2914
2915 string s_polar = s_prefix + "pol"
2916 string s_azim = s_prefix + "az"
2917 string s_theta = s_prefix + "th"
2918 string s_tot = s_prefix + "tot"
2919 string s_weight = s_prefix + "wt"
2920
2921 wave /sdfr=df theta1 = $s_theta
2922 wave /sdfr=df polar1 = $s_polar
2923 wave /sdfr=df azim1 = $s_azim
2924 wave /sdfr=df tot1 = $s_tot
2925 wave /sdfr=df weight1 = $s_weight
2926 wave /sdfr=df values1 = $s_int
2927
2928 save /m="\r\n" /o /p=$pathname /t theta1, polar1, azim1, tot1, weight1, values1 as filename
2929
2930 setdatafolder saveDF
2931 end
2932
2936 function load_hemi_scan(nickname, pathname, filename)
2937 string nickname
2938 string pathname
2939 string filename
2940
2941 dfref savedf = getdatafolderdfr()
2942
2943 //loadwave /p=$pathname /t theta1, polar1, azim1, tot1, weight1, values1 as filename
2944 //LoadWave /t/p=pearl_explorer_filepath/q filename
2945 //svar waves = s_wavenames
2946 //if (v_flag > 0)
2947 // string /g pearl_explorer_import = "load_itx_file"
2948 //endif
2949
2950 setdatafolder saveDF
2951 end
2952
2985 function import_tpi_scan(nickname, theta, phi, intensity, [folding, npolar, nograph, xpdplot])
2986 string nickname
2987 wave theta
2988 wave phi
2989 wave intensity
2990
2991 variable folding
2992 variable npolar
2993 variable nograph
2994 variable xpdplot
2995
2996 if (ParamIsDefault(npolar))
2997 npolar = 91
2998 endif
2999 if (ParamIsDefault(nograph))
3000 nograph = 0
3001 endif
3002 if (ParamIsDefault(folding))
3003 folding = 1
3004 endif
3005 if (ParamIsDefault(xpdplot))
3006 xpdplot = 0
3007 endif
3008
3009 make_hemi_grid(npolar, nickname, xpdplot=xpdplot)
3010
3011 variable ifold
3012 duplicate /free phi, fold_phi
3013 for (ifold = 0; ifold < folding; ifold += 1)
3014 hemi_add_anglescan(nickname, intensity, theta, fold_phi)
3015 fold_phi = fold_phi >= 180 ? fold_phi + 360 / folding - fold_phi : fold_phi + 360 / folding
3016 endfor
3017
3018 if (nograph==0)
3019 display_hemi_scan(nickname)
3020 endif
3021 end
3022
3034 function trim_hemi_scan(nickname, theta_max)
3035 string nickname
3036 variable theta_max
3037
3038 string s_prefix = ""
3039 string s_int = "values"
3040 dfref df = find_hemi_data(nickname, s_prefix, s_int)
3041
3042 string s_totals = s_prefix + "tot"
3043 string s_weights = s_prefix + "wt"
3044 string s_polar = s_prefix + "pol"
3045
3046 wave /sdfr=df w_polar = $s_polar
3047 wave /sdfr=df w_values = $s_int
3048 wave /sdfr=df w_totals = $s_totals
3049 wave /sdfr=df w_weights = $s_weights
3050
3051 w_values = w_polar <= theta_max ? w_totals / w_weights : nan
3052 end
3053
3073 function /wave hemi_polar_cut(nickname, azim)
3074 string nickname
3075 variable azim
3076
3077 dfref savedf = getdatafolderdfr()
3078 string s_prefix = ""
3079 string s_int = "values"
3080 dfref df = find_hemi_data(nickname, s_prefix, s_int)
3081
3082 string s_totals = s_prefix + "tot"
3083 string s_weights = s_prefix + "wt"
3084 string s_polar = s_prefix + "pol"
3085 string s_azim = s_prefix + "az"
3086 string s_index = s_prefix + "index"
3087 string s_theta = s_prefix + "th"
3088 string s_dphi = s_prefix + "dphi"
3089 string s_nphis = s_prefix + "nphis"
3090 string s_cut
3091 sprintf s_cut, "%s_azi%03u", s_int, round(azim)
3092
3093 wave /sdfr=df w_polar = $s_polar
3094 wave /sdfr=df w_azim = $s_azim
3095 wave /sdfr=df w_values = $s_int
3096 wave /sdfr=df w_totals = $s_totals
3097 wave /sdfr=df w_weights = $s_weights
3098 wave /sdfr=df w_index = $s_index
3099 wave /sdfr=df w_theta = $s_theta
3100 wave /sdfr=df w_dphi = $s_dphi
3101 wave /sdfr=df w_nphis = $s_nphis
3102
3103 variable npol = numpnts(w_theta)
3104 variable ipol
3105 variable pol_st = abs(w_theta[1] - w_theta[0])
3106 variable pol
3107 variable pol1, pol2
3108 variable nsel
3109
3110 setdatafolder df
3111 make /n=(npol) /o $s_cut
3112 wave w_cut = $s_cut
3113 setscale /i x w_theta[0], w_theta[numpnts(w_theta)-1], "deg", w_cut
3114 make /n=1 /free azi_slice
3115 make /n=1 /free values_slice
3116
3117 for (ipol = 0; ipol < npol; ipol += 1)
3118 pol = w_theta[ipol]
3119 pol1 = pol - pol_st / 2
3120 pol2 = pol + pol_st / 2
3121 extract /free /indx w_polar, sel, (pol1 < w_polar) && (w_polar <= pol2)
3122 nsel = numpnts(sel)
3123 if (nsel > 0)
3124 redimension /n=(nsel+2) azi_slice, values_slice
3125 azi_slice[1, nsel] = w_azim[sel[p-1]]
3126 azi_slice[0] = azi_slice[nsel] - 360
3127 azi_slice[nsel+1] = azi_slice[1] + 360
3128 values_slice[1, nsel] = w_values[sel[p-1]]
3129 values_slice[0] = values_slice[nsel]
3130 values_slice[nsel+1] = values_slice[1]
3131 w_cut[ipol] = interp(azim, azi_slice, values_slice)
3132 else
3133 w_cut[ipol] = nan
3134 endif
3135 endfor
3136
3137 setdatafolder savedf
3138 return w_cut
3139 end
3140
3159 function /wave hemi_azi_cut(nickname, pol)
3160 string nickname
3161 variable pol
3162
3163 dfref savedf = getdatafolderdfr()
3164 string s_prefix = ""
3165 string s_int = "values"
3166 dfref df = find_hemi_data(nickname, s_prefix, s_int)
3167
3168 string s_totals = s_prefix + "tot"
3169 string s_weights = s_prefix + "wt"
3170 string s_polar = s_prefix + "pol"
3171 string s_azim = s_prefix + "az"
3172 string s_index = s_prefix + "index"
3173 string s_theta = s_prefix + "th"
3174 string s_dphi = s_prefix + "dphi"
3175 string s_nphis = s_prefix + "nphis"
3176 string s_cut
3177 sprintf s_cut, "%s_pol%03u", s_int, round(pol)
3178
3179 wave /sdfr=df w_polar = $s_polar
3180 wave /sdfr=df w_azim = $s_azim
3181 wave /sdfr=df w_values = $s_int
3182 wave /sdfr=df w_totals = $s_totals
3183 wave /sdfr=df w_weights = $s_weights
3184 wave /sdfr=df w_index = $s_index
3185 wave /sdfr=df w_theta = $s_theta
3186 wave /sdfr=df w_dphi = $s_dphi
3187 wave /sdfr=df w_nphis = $s_nphis
3188
3189 variable pol_st = abs(w_theta[1] - w_theta[0])
3190 variable pol1, pol2
3191 variable nsel
3192
3193 pol1 = pol - pol_st / 2
3194 pol2 = pol + pol_st / 2
3195 extract /free /indx w_polar, sel, (pol1 < w_polar) && (w_polar <= pol2)
3196 nsel = numpnts(sel)
3197 if (nsel > 0)
3198 setdatafolder df
3199 make /n=(nsel) /o $s_cut
3200 wave w_cut = $s_cut
3201 w_cut = w_values[sel]
3202 setscale /i x w_azim[sel[0]], w_azim[sel[nsel-1]], "°", w_cut
3203 setdatafolder savedf
3204 return w_cut
3205 else
3206 setdatafolder savedf
3207 return $""
3208 endif
3209 setdatafolder savedf
3210 end
3211
3212 static function check_contrast(values, pcmin, pcmax, vmin, vmax)
3213 wave values
3214 variable pcmin
3215 variable pcmax
3216 variable &vmin
3217 variable &vmax
3218
3219 dfref save_df = GetDataFolderDFR()
3220 dfref dfr = NewFreeDataFolder()
3221 setdatafolder dfr
3222 StatsQuantiles /inan /iw /q /z values
3223 wave index = w_quantilesindex
3224 variable imin = round(numpnts(index) * pcmin / 100)
3225 variable imax = round(numpnts(index) * (100 - pcmax) / 100)
3226 vmin = values[index[imin]]
3227 vmax = values[index[imax]]
3228 setdatafolder save_df
3229 end
3230
3247 function set_contrast(pcmin, pcmax, [graphname, colortable])
3248 variable pcmin
3249 variable pcmax
3250 string graphname
3251 string colortable
3252
3253 if (ParamIsDefault(graphname))
3254 graphname = ""
3255 endif
3256 if (ParamIsDefault(colortable))
3257 colortable = ""
3258 endif
3259
3260 dfref save_df = GetDataFolderDFR()
3261
3262 string objname
3263 string info
3264 string wname
3265 string ctab
3266 variable rev
3267 variable n
3268 variable i
3269 variable vmin
3270 variable vmax
3271
3272 string traces = TraceNameList(graphname, ";", 1+4)
3273 n = ItemsInList(traces, ";")
3274 for (i = 0; i < n; i += 1)
3275 objname = StringFromList(i, traces, ";")
3276 info = TraceInfo(graphname, objname, 0)
3277 if (strlen(info) > 0)
3278 info = StringByKey("RECREATION", info, ":", ";")
3279 info = StringByKey("zColor(x)", info, "=", ";")
3280 if (strlen(info) > 2)
3281 info = info[1,strlen(info)-2]
3282 wname = StringFromList(0, info, ",")
3283 wave w = $wname
3284 ctab = StringFromList(3, info, ",")
3285 rev = str2num("0" + StringFromList(4, info, ","))
3286 if (strlen(colortable) > 0)
3287 ctab = colortable
3288 endif
3289 check_contrast(w, pcmin, pcmax, vmin, vmax)
3290 ModifyGraph /w=$graphname zColor($objname)={w, vmin, vmax, $ctab, rev}
3291 endif
3292 endif
3293 endfor
3294
3295 string images = ImageNameList(graphname, ";")
3296 n = ItemsInList(images, ";")
3297 for (i = 0; i < n; i += 1)
3298 objname = StringFromList(i, images, ";")
3299 wave w = ImageNameToWaveRef(graphname, objname)
3300 info = ImageInfo(graphname, objname, 0)
3301 if (strlen(info) > 0)
3302 info = StringByKey("RECREATION", info, ":", ";")
3303 info = StringByKey("ctab", info, "=", ";")
3304 if (strlen(info) > 2)
3305 info = info[1,strlen(info)-2]
3306 ctab = StringFromList(2, info, ",")
3307 rev = str2num("0" + StringFromList(3, info, ","))
3308 if (strlen(colortable) > 0)
3309 ctab = colortable
3310 endif
3311 check_contrast(w, pcmin, pcmax, vmin, vmax)
3312 ModifyImage /w=$graphname $objname ctab={vmin, vmax, $ctab, rev}
3313 endif
3314 endif
3315 endfor
3316
3317 setdatafolder save_df
3318 end
3319
3332 Function AngleToK(inwave)
3333 Wave inwave
3334 String newname = NameofWave(inwave)+"_k"
3335 Duplicate/O inwave, $newname
3336 Wave outwave = $newname
3337 Variable rows,columns,xdelta,xoffset,ydelta,yoffset,kmin,kmax,Emax
3338 // inwave parameters
3339 rows = DimSize(inwave,0)
3340 columns = DimSize(inwave,1)
3341 xdelta = DimDelta(inwave,0)
3342 xoffset = DimOffset(inwave,0)
3343 ydelta = DimDelta(inwave,1)
3344 yoffset = DimOffset(inwave,1)
3345 Emax= xoffset + xdelta*(rows-1)
3346 kmin = 0.5123*sqrt(Emax)*sin(pi/180*(yoffset)) // calculate the k boundaries
3347 kmax = 0.5123*sqrt(Emax)*sin(pi/180*(yoffset+(columns-1)*ydelta))
3348 SetScale/I y kmin,kmax,"Ang^-1", outwave
3349 // scale the y axis
3350 outwave = interp2D(inwave, x, 180/pi*asin(y/ (0.5123*sqrt(x)))) // recalculate to k
3351 outwave = (NumType(outwave)==2) ? 0 : outwave // replace NaNs (optional)
3352 End
hemi_polar_cut
wave hemi_polar_cut(string nickname, variable azim)
extract a polar cut from a hemispherical scan.
Definition: pearl-anglescan-process.ipf:3073
trim_hemi_scan
variable trim_hemi_scan(string nickname, variable theta_max)
trim a hemispherical scan at grazing angle
Definition: pearl-anglescan-process.ipf:3034
prepare_hemi_scan_display
string prepare_hemi_scan_display(string nickname, variable projection=defaultValue)
create waves for plotting a hemispherical angle scan.
Definition: pearl-anglescan-process.ipf:1702
pizza_service_2
variable pizza_service_2(wave data, string nickname, wave m_theta, wave m_tilt, wave m_phi, variable npolar=defaultValue, variable nograph=defaultValue, variable folding=defaultValue, variable xpdplot=defaultValue)
create a pizza plot from a measured (energy-integrated) data strip
Definition: pearl-anglescan-process.ipf:862
AngleToK
variable AngleToK(wave inwave)
k-space mapping of 2D angle-energy distribution (scienta image)
Definition: pearl-anglescan-process.ipf:3332
kProjScaleOrtho
static const variable kProjScaleOrtho
Definition: pearl-anglescan-process.ipf:2279
polar2cart_wave
variable polar2cart_wave(wave in, wave out)
Definition: pearl-polar-coordinates.ipf:58
normalize_strip_theta
variable normalize_strip_theta(wave strip, wave theta, variable theta_offset=defaultValue, variable smooth_method=defaultValue, variable smooth_factor=defaultValue, variable check=defaultValue)
divide the strip by the average polar distribution.
Definition: pearl-anglescan-process.ipf:366
normalize_strip_2d
variable normalize_strip_2d(wave strip, wave theta, variable theta_offset=defaultValue, variable smooth_method=defaultValue, variable smooth_factor=defaultValue, variable check=defaultValue)
divide the strip by a two-dimensional normalization function.
Definition: pearl-anglescan-process.ipf:613
crop_strip
variable crop_strip(wave strip, variable xlo, variable xhi)
crop a strip at the sides.
Definition: pearl-anglescan-process.ipf:673
kProjGnom
const variable kProjGnom
Definition: pearl-anglescan-process.ipf:2271
ad_profile_y
threadsafe wave ad_profile_y(wave dataset, variable p1, variable p2, string destname, variable noavg=defaultValue)
1D cut through 2D dataset along Y dimension, new destination wave.
Definition: pearl-area-profiles.ipf:542
make_hemi_grid
variable make_hemi_grid(variable npol, string nickname, variable xpdplot=defaultValue)
create a hemispherical, constant solid angle grid
Definition: pearl-anglescan-process.ipf:1291
hemi_add_anglescan
variable hemi_add_anglescan(string nickname, wave values, wave polar, wave azi, wave weights=defaultValue)
add an arbitrary angle scan to a hemispherical scan grid.
Definition: pearl-anglescan-process.ipf:2538
get_hemi_nickname
string get_hemi_nickname(wave w)
finds the nick name given any hemi wave
Definition: pearl-anglescan-process.ipf:1442
get_hemi_prefix
string get_hemi_prefix(wave w)
finds the prefix given any hemi wave
Definition: pearl-anglescan-process.ipf:1467
display_hemi_scan
string display_hemi_scan(string nickname, variable projection=defaultValue, variable graphtype=defaultValue, variable do_ticks=defaultValue, variable do_grids=defaultValue, string graphname=defaultValue)
display a plot of a hemispherical angle scan.
Definition: pearl-anglescan-process.ipf:1784
CalcN_Theta
static variable CalcN_Theta(string HoloMode, variable Theta_in, variable Theta_ran, variable Theta_st)
calculate the number of thetas for a pattern
Definition: pearl-anglescan-process.ipf:1253
find_hemi_data
dfr find_hemi_data(string nickname, string *prefix, string *intwave)
finds the folder, prefix and name of holo waves given their nick name
Definition: pearl-anglescan-process.ipf:1498
convert_angles_ttpd2polar
variable convert_angles_ttpd2polar(wave theta, wave tilt, wave phi, wave data, wave polar, wave azi)
convert angles from TTPA (theta-tilt-phi-analyser) scheme to polar coordinates.
Definition: pearl-anglescan-process.ipf:1049
clear_hemi_grid
variable clear_hemi_grid(string nickname)
clear a hemispherical scan grid
Definition: pearl-anglescan-process.ipf:1532
kProjScaleDist
static const variable kProjScaleDist
Definition: pearl-anglescan-process.ipf:2274
calc_graph_polar
threadsafe variable calc_graph_polar(variable x, variable y, variable projection=defaultValue)
calculate polar angle from Cartesian coordinate
Definition: pearl-anglescan-process.ipf:2340
check_contrast
static variable check_contrast(wave values, variable pcmin, variable pcmax, variable *vmin, variable *vmax)
Definition: pearl-anglescan-process.ipf:3212
Calc_The_step
static variable Calc_The_step(variable th, variable Theta_st, string Holomode)
calculate delta-theta for a given theta
Definition: pearl-anglescan-process.ipf:1222
kProjArea
const variable kProjArea
Definition: pearl-anglescan-process.ipf:2270
line_average
static variable line_average(wave source, wave dest)
Definition: pearl-anglescan-process.ipf:1131
calc_graph_radius
threadsafe variable calc_graph_radius(variable polar, variable projection=defaultValue)
calculate the projected polar angle
Definition: pearl-anglescan-process.ipf:2295
pizza_service
variable pizza_service(wave data, string nickname, variable theta_offset, variable tilt_offset, variable phi_offset, variable npolar=defaultValue, variable nograph=defaultValue, variable folding=defaultValue, variable xpdplot=defaultValue)
create a pizza plot from a measured (energy-integrated) data strip
Definition: pearl-anglescan-process.ipf:769
rotate_x_wave
variable rotate_x_wave(wave inout, variable angle)
rotate a wave of 3-vectors about the x axis.
Definition: pearl-vector-operations.ipf:175
cart2polar_wave
variable cart2polar_wave(wave in, wave out)
Definition: pearl-polar-coordinates.ipf:36
crop_strip_theta
variable crop_strip_theta(wave strip, variable theta_lo, variable theta_hi, wave theta, wave tilt, wave phi)
crop a strip in theta.
Definition: pearl-anglescan-process.ipf:705
version
version
Definition: pearl-anglescan-tracker.ipf:5
display_scanlines
string display_scanlines(string nickname, variable alpha_lo, variable alpha_hi, wave m_theta, wave m_tilt, wave m_phi, variable folding=defaultValue, variable projection=defaultValue)
display a polar graph with lines indicating the angles covered by an angle scan.
Definition: pearl-anglescan-process.ipf:2180
hemi_azi_cut
wave hemi_azi_cut(string nickname, variable pol)
extract an azimuthal cut from a hemispherical scan
Definition: pearl-anglescan-process.ipf:3159
draw_diffraction_cone
variable draw_diffraction_cone(string graphname, string groupname, variable theta_axis, variable theta_inner, variable phi)
draw the circle of a diffraction cone in a stereographic polar graph.
Definition: pearl-anglescan-process.ipf:2116
interpolate_hemi_scan
variable interpolate_hemi_scan(string nickname, variable projection=defaultValue)
interpolate a hemispherical scan onto a rectangular grid
Definition: pearl-anglescan-process.ipf:2726
normalize_strip_theta_scans
variable normalize_strip_theta_scans(wave strip, wave theta, variable theta_offset=defaultValue, variable smooth_method=defaultValue, variable smooth_factor=defaultValue, variable check=defaultValue)
divide the strip piecewise by a smooth polar distribution.
Definition: pearl-anglescan-process.ipf:523
hemi_add_aziscan
variable hemi_add_aziscan(string nickname, wave values, variable polar, wave azi, wave weights=defaultValue)
add an azimuthal scan to a hemispherical scan grid.
Definition: pearl-anglescan-process.ipf:2608
kProjScaleGnom
static const variable kProjScaleGnom
Definition: pearl-anglescan-process.ipf:2278
rotate_y_wave
variable rotate_y_wave(wave inout, variable angle)
rotates a wave of 3-vectors about the y axis
Definition: pearl-vector-operations.ipf:203
rotate_hemi_scan
variable rotate_hemi_scan(string nickname, variable angle)
azimuthally rotate a hemispherical scan dataset.
Definition: pearl-anglescan-process.ipf:1654
kProjScaleStereo
static const variable kProjScaleStereo
Definition: pearl-anglescan-process.ipf:2275
PearlAnglescanProcess
processing and holographic mapping of angle scanned XPD data.
display_polar_graph
static string display_polar_graph(string graphname, variable angle_offset=defaultValue, variable do_ticks=defaultValue)
displays an empty polar graph
Definition: pearl-anglescan-process.ipf:1929
kProjOrtho
const variable kProjOrtho
Definition: pearl-anglescan-process.ipf:2272
save_hemi_scan
variable save_hemi_scan(string nickname, string pathname, string filename)
save a hemispherical scan to an Igor text file
Definition: pearl-anglescan-process.ipf:2903
normalize_strip_phi
variable normalize_strip_phi(wave strip, wave theta, wave phi, variable theta_offset=defaultValue, variable theta_range=defaultValue, variable check=defaultValue)
divide the strip by a sine function in phi (wobble correction).
Definition: pearl-anglescan-process.ipf:283
normalize_strip_thetaphi
variable normalize_strip_thetaphi(wave strip, wave theta, wave phi, variable theta_offset=defaultValue, variable smooth_method=defaultValue, variable smooth_factor=defaultValue, variable check=defaultValue)
divide the strip by a smooth polar-azimuthal distribution.
Definition: pearl-anglescan-process.ipf:464
kProjStereo
const variable kProjStereo
Definition: pearl-anglescan-process.ipf:2269
quick_pizza_image
variable quick_pizza_image(wave data, string nickname, variable theta_offset, variable tilt_offset, variable phi_offset, variable npolar=defaultValue, variable nograph=defaultValue, variable folding=defaultValue)
map angle scan data onto a rectangular grid in stereographic projection
Definition: pearl-anglescan-process.ipf:2792
polar_graph_hook
static variable polar_graph_hook(WMWinHookStruct *s)
polar graph window hook
Definition: pearl-anglescan-process.ipf:2473
kProjDist
const variable kProjDist
Definition: pearl-anglescan-process.ipf:2268
calc_graph_azi
threadsafe variable calc_graph_azi(variable x, variable y, variable projection=defaultValue, variable zeroAngle=defaultValue)
calculate azimuthal angle from Cartesian coordinate
Definition: pearl-anglescan-process.ipf:2393
set_contrast
variable set_contrast(variable pcmin, variable pcmax, string graphname=defaultValue, string colortable=defaultValue)
set the pseudocolor contrast by percentile.
Definition: pearl-anglescan-process.ipf:3247
strip_delete_frames
variable strip_delete_frames(wave strip, variable qlo, variable qhi, wave theta, wave tilt, wave phi)
delete a contiguous range of frames from a strip.
Definition: pearl-anglescan-process.ipf:105
rotate_z_wave
variable rotate_z_wave(wave inout, variable angle)
rotates a wave of 3-vectors about the z axis
Definition: pearl-vector-operations.ipf:231
calc_nth
static variable calc_nth(variable Theta_st, variable Theta_in, variable th, variable Phi_ran, variable Phi_ref, string Holomode)
calculate the number of phis for a given theta
Definition: pearl-anglescan-process.ipf:1149
kProjScaleArea
static const variable kProjScaleArea
Definition: pearl-anglescan-process.ipf:2276
show_analyser_line
variable show_analyser_line(variable theta, variable tilt, variable phi, variable theta_offset, variable tilt_offset, variable phi_offset, variable npolar=defaultValue, variable nograph=defaultValue, variable xpdplot=defaultValue)
calculate and display the line seen by the analyser for a specific emission angle ...
Definition: pearl-anglescan-process.ipf:979
convert_angles_ttpa2polar
variable convert_angles_ttpa2polar(wave theta, wave tilt, wave phi, wave analyser, wave polar, wave azi)
convert angles from TTPA (theta-tilt-phi-analyser) scheme to polar coordinates.
Definition: pearl-anglescan-process.ipf:1088
draw_hemi_axes
static string draw_hemi_axes(string graphname, variable do_grids=defaultValue)
draw polar and azimuthal grids in an existing polar graph.
Definition: pearl-anglescan-process.ipf:2044
duplicate_hemi_scan
variable duplicate_hemi_scan(string source_nickname, dfref dest_folder, string dest_nickname, variable xpdplot=defaultValue)
duplicate a hemispherical scan dataset.
Definition: pearl-anglescan-process.ipf:1579
set_polar_graph_cursor
variable set_polar_graph_cursor(string nickname, string cursorname, variable polar_angle, variable azim_angle, string graphname=defaultValue)
Definition: pearl-anglescan-process.ipf:2493
update_polar_info
static variable update_polar_info(string graphname)
update the angles info based on cursors A and B of a given polar graph window
Definition: pearl-anglescan-process.ipf:2438
import_tpi_scan
variable import_tpi_scan(string nickname, wave theta, wave phi, wave intensity, variable folding=defaultValue, variable npolar=defaultValue, variable nograph=defaultValue, variable xpdplot=defaultValue)
import a hemispherical scan from theta-phi-intensity waves and display it
Definition: pearl-anglescan-process.ipf:2985
load_hemi_scan
variable load_hemi_scan(string nickname, string pathname, string filename)
load a hemispherical scan from an Igor text file
Definition: pearl-anglescan-process.ipf:2936
ad_profile_x
threadsafe wave ad_profile_x(wave dataset, variable q1, variable q2, string destname, variable noavg=defaultValue)
1D cut through 2D dataset along X dimension, new destination wave.
Definition: pearl-area-profiles.ipf:480
calc_phi_step
static variable calc_phi_step(variable Theta_in, variable th, variable Theta_st, variable Phi_ran, variable Phi_ref, string Holomode)
calculate delta-phi for a given theta
Definition: pearl-anglescan-process.ipf:1178
normalize_strip_x
variable normalize_strip_x(wave strip, variable smooth_method=defaultValue, variable smooth_factor=defaultValue, variable check=defaultValue)
divide the strip by the average X distribution.
Definition: pearl-anglescan-process.ipf:187