PEARL Procedures rev-distro-3.1.0-0-gea838b3-dirty
Igor procedures for the analysis of PEARL data
Loading...
Searching...
No Matches
pearl-anglescan-process.ipf
Go to the documentation of this file.
1#pragma TextEncoding = "UTF-8"
2#pragma rtGlobals=3 // Use modern global access method and strict wave access.
3#pragma version = 1.9
4#pragma IgorVersion = 6.2
5#pragma ModuleName = PearlAnglescanProcess
6#include "pearl-vector-operations"
7#include "pearl-polar-coordinates"
8#include <New Polar Graphs>
9
10// copyright (c) 2013-21 Paul Scherrer Institut
11//
12// Licensed under the Apache License, Version 2.0 (the "License");
13// you may not use this file except in compliance with the License.
14// You may obtain a copy of the License at
15// http:///www.apache.org/licenses/LICENSE-2.0
16//
17// Please acknowledge the use of this code.
18
77
82
83
106function /s strip_append(strip1, strip2)
107 wave strip1
108 wave strip2
109
110 dfref df1 = GetWavesDataFolderDFR(strip1)
111 dfref df2 = GetWavesDataFolderDFR(strip2)
112 variable ny1 = dimsize(strip1, 1)
113 variable ny2 = dimsize(strip2, 1)
114
115 concatenate /np=1 {strip2}, strip1
116 string modified = AddListItem(NameOfWave(strip1), "")
117
118 variable idf = 0
119 do
120 variable iw = 0
121 do
122 wave /z w1 = WaveRefIndexedDFR(df1, iw)
123 if (!WaveExists(w1))
124 break
125 endif
126
127 wave /z w2 = df2:$(NameOfWave(w1))
128 if (WaveExists(w1) && WaveExists(w2))
129 if ((DimSize(w1, 0) == ny1) && (DimSize(w1, 1) == 0) && (DimSize(w2, 0) == ny2) && (DimSize(w2, 1) == 0))
130 concatenate /np=0 {w2}, w1
131 modified = AddListItem(NameOfWave(w1), modified, "", Inf)
132 endif
133 endif
134 iw += 1
135 while(1)
136
137 df1 = df1:attr
138 df2 = df2:attr
139 if ((DataFolderRefStatus(df1) != 1) || (DataFolderRefStatus(df2) != 1))
140 break
141 endif
142 idf += 1
143 while(idf < 2)
144
145 return modified
146end
147
170function strip_delete_frames(strip, qlo, qhi, theta, tilt, phi)
171 wave strip // 2D data, X-axis = analyser angle, Y-axis = arbitrary manipulator scan
172 variable qlo
173 variable qhi
174 wave theta
175 wave tilt
176 wave phi
177
178 if (qlo > qhi)
179 return -1
180 endif
181
182 // source indices
183 variable snx = dimsize(strip, 0)
184 variable sny = dimsize(strip, 1)
185 variable sq1lo = 0
186 variable sq1hi = max(qlo-1, 0)
187 variable sq2lo = min(qhi+1, sny - 1)
188 variable sq2hi = dimsize(strip, 1) - 1
189
190 // dest indices
191 variable dnx = snx
192 variable dny = sny - (sq2lo - sq1hi + 1)
193 variable dq1lo = 0
194 variable dq1hi = sq1hi
195 variable dq2lo = dq1hi + 1
196 variable dq2hi = dny - 1
197 variable q1ofs = sq1lo - dq1lo
198 variable q2ofs = sq2lo - dq2lo
199
200 duplicate /free strip, strip_copy
201 redimension /n=(dnx,dny) strip
202 strip[][dq1lo,dq1hi] = strip_copy[p][q + q1ofs]
203 strip[][dq2lo,dq2hi] = strip_copy[p][q + q2ofs]
204
205 duplicate /free theta, theta_copy
206 redimension /n=(dny) theta
207 theta[dq1lo,dq1hi] = theta_copy[p + q1ofs]
208 theta[dq2lo,dq2hi] = theta_copy[p + q2ofs]
209
210 duplicate /free tilt, tilt_copy
211 redimension /n=(dny) tilt
212 tilt[dq1lo,dq1hi] = tilt_copy[p + q1ofs]
213 tilt[dq2lo,dq2hi] = tilt_copy[p + q2ofs]
214
215 duplicate /free phi, phi_copy
216 redimension /n=(dny) phi
217 phi[dq1lo,dq1hi] = phi_copy[p + q1ofs]
218 phi[dq2lo,dq2hi] = phi_copy[p + q2ofs]
219
220 return 0
221end
222
252function normalize_strip_x(strip, [smooth_method, smooth_factor, check])
253 wave strip
254 variable smooth_method
255 variable smooth_factor
256 variable check
257
258 if (ParamIsDefault(smooth_method))
259 smooth_method = 4
260 endif
261 if (ParamIsDefault(smooth_factor))
262 switch(smooth_method)
263 case 4:
264 smooth_factor = 0.5
265 break
266 default:
267 smooth_factor = 2
268 endswitch
269 endif
270 if (ParamIsDefault(check))
271 check = 0
272 endif
273
274 // average over all scan positions
275 wave raw_dist = ad_profile_x(strip, -inf, inf, "")
276
277 // remove nans
278 extract /free /indx raw_dist, clean_index, numtype(raw_dist) == 0
279 duplicate /free raw_dist, dist, dist_x
280 redimension /n=(numpnts(clean_index)) dist, dist_x
281 dist = raw_dist[clean_index[p]]
282 dist_x = pnt2x(raw_dist, clean_index[p])
283 variable div = mean(dist)
284 dist /= div
285
286 if (check)
287 duplicate /o raw_dist, check_dist
288 check_dist = numtype(raw_dist) == 0 ? interp(x, dist_x, dist) : nan
289 endif
290
291 // smooth distribution function
292 switch(smooth_method)
293 case 1:
294 Smooth /B /E=3 smooth_factor, dist
295 break
296 case 2:
297 Smooth /E=3 smooth_factor, dist
298 break
299 case 3:
300 make /n=1 /d /free fit_params
301 fit_scienta_ang_transm(raw_dist, fit_params)
302 duplicate /free raw_dist, dist, dist_x
303 dist_x = x
304 dist = scienta_ang_transm(fit_params, x)
305 break
306 case 4:
307 loess /smth=(smooth_factor) srcWave=dist, factors={dist_x}
308 break
309 endswitch
310
311 if (check)
312 duplicate /o raw_dist, check_smoo
313 check_smoo = interp(x, dist_x, dist)
314 endif
315
316 // divide
317 if (check != 2)
318 strip /= interp(x, dist_x, dist)
319 endif
320end
321
348function normalize_strip_phi(strip, theta, phi, [theta_offset, theta_range, check])
349 wave strip
350 wave theta
351 wave phi
352 variable theta_offset
353 variable theta_range
354 variable check
355
356 if (ParamIsDefault(check))
357 check = 0
358 endif
359 if (ParamIsDefault(theta_offset))
360 theta_offset = 0
361 endif
362 if (ParamIsDefault(theta_range))
363 theta_offset = 10
364 endif
365
366 // average over analyser angles
367 duplicate /free strip, strip_copy
368 MatrixFilter NanZapMedian strip_copy
369 wave dist = ad_profile_y(strip_copy, -inf, inf, "")
370
371 // smooth distribution function
372 duplicate /free dist, dist_smoo
373 duplicate /free theta, theta_int
374 theta_int = theta - theta_offset
375 duplicate /free phi, phi_int
376 setscale /p x phi_int[0], phi_int[1] - phi_int[0], waveunits(phi, -1), dist, dist_smoo
377
378 extract /free /indx dist, red_idx, theta_int < theta_range
379 duplicate /free red_idx, red_dist, red_phi
380 red_dist = dist[red_idx]
381 red_phi = phi_int[red_idx]
382
383 variable wavg = mean(red_dist)
384 make /n=4 /d /free coef
385 coef[0] = {wavg, wavg/100, pi/180, 0}
386 CurveFit /q /h="0010" /g /w=2 sin, kwcWave=coef, red_dist /x=red_phi
387 dist_smoo = coef[0] + coef[1] * sin(coef[2] * phi_int[p] + coef[3])
388
389 // divide
390 if (check != 2)
391 strip = strip / dist_smoo[q] * coef[0]
392 endif
393
394 // check
395 if (check)
396 duplicate /o dist, check_dist
397 duplicate /o dist_smoo, check_smoo
398 setscale /p x dimoffset(dist,0), dimdelta(dist,0), waveunits(dist,0), check_dist, check_smoo
399 endif
400end
401
433function normalize_strip_theta(strip, theta, [theta_offset, smooth_method, smooth_factor, check])
434 wave strip
435 wave theta
436 variable theta_offset
437 variable smooth_method
438 variable smooth_factor
439 variable check
440
441 if (ParamIsDefault(check))
442 check = 0
443 endif
444 if (ParamIsDefault(theta_offset))
445 theta_offset = 0
446 endif
447 if (ParamIsDefault(smooth_method))
448 smooth_method = 4
449 endif
450 if (ParamIsDefault(smooth_factor))
451 smooth_factor = 0.5
452 endif
453
454 // average over analyser angles
455 duplicate /free strip, strip_copy
456 MatrixFilter NanZapMedian strip_copy
457 wave dist = ad_profile_y(strip_copy, -inf, inf, "")
458
459 // smooth distribution function
460 duplicate /free dist, dist_smoo
461 duplicate /free theta, theta_int
462 theta_int = theta - theta_offset
463 setscale /p x theta_int[0], theta_int[1] - theta_int[0], waveunits(theta,-1), dist, dist_smoo
464 variable nx = dimsize(strip, 0)
465 variable ix
466
467 switch(smooth_method)
468 case 1:
469 Smooth /B /E=3 smooth_factor, dist_smoo
470 break
471 case 2:
472 Smooth /E=3 smooth_factor, dist_smoo
473 break
474 case 4:
475 loess /dest=dist_smoo /smth=(smooth_factor) srcWave=dist, factors={theta_int}
476 break
477 case 3:
478 for (ix = 0; ix < nx; ix += 1)
479 dist = strip[ix][p]
480 if (smooth_factor > 1)
481 CurveFit /nthr=0 /q /w=2 poly smooth_factor+1, dist /x=theta_int /d=dist_smoo
482 else
483 CurveFit /nthr=0 /q /w=2 line, dist /x=theta_int /d=dist_smoo
484 endif
485 strip[ix,ix][] /= dist_smoo[q]
486 endfor
487 dist_smoo = 1
488 break
489 endswitch
490
491 // divide
492 if (check != 2)
493 strip /= dist_smoo[q]
494 endif
495
496 // check
497 if (check)
498 duplicate /o dist, check_dist
499 duplicate /o dist_smoo, check_smoo
500 setscale /p x dimoffset(dist,0), dimdelta(dist,0), waveunits(dist,0), check_dist, check_smoo
501 endif
502end
503
533function normalize_strip_thetaphi(strip, theta, phi, [theta_offset, smooth_method, smooth_factor, check])
534 wave strip
535 wave theta
536 wave phi
537 variable theta_offset
538 variable smooth_method
539 variable smooth_factor
540 variable check
541
542 if (ParamIsDefault(check))
543 check = 0
544 endif
545 if (ParamIsDefault(theta_offset))
546 theta_offset = 0
547 endif
548 if (ParamIsDefault(smooth_method))
549 smooth_method = 4
550 endif
551 if (ParamIsDefault(smooth_factor))
552 smooth_factor = 0.5
553 endif
554
555 // average over analyser angles
556 duplicate /free strip, strip_copy
557 MatrixFilter NanZapMedian strip_copy
558 wave dist = ad_profile_y(strip_copy, -inf, inf, "")
559
560 // smooth distribution function
561 duplicate /free dist, dist_smoo
562 duplicate /free theta, theta_int
563 theta_int = theta - theta_offset
564 setscale /p x theta_int[0], theta_int[1] - theta_int[0], waveunits(theta,-1), dist, dist_smoo
565 variable nx = dimsize(strip, 0)
566 variable ix
567
568 switch(smooth_method)
569 case 4:
570 loess /dest=dist_smoo /smth=(smooth_factor) srcWave=dist, factors={theta_int, phi}
571 break
572 default:
573 abort "smooth method not supported"
574 endswitch
575
576 // divide
577 if (check != 2)
578 strip /= dist_smoo[q]
579 endif
580
581 // check
582 if (check)
583 duplicate /o dist, check_dist
584 duplicate /o dist_smoo, check_smoo
585 setscale /p x dimoffset(dist,0), dimdelta(dist,0), waveunits(dist,0), check_dist, check_smoo
586 endif
587end
588
594function normalize_strip_theta_scans(strip, theta, [theta_offset, smooth_method, smooth_factor, check])
595 wave strip
596 wave theta
597 variable theta_offset
598 variable smooth_method
599 variable smooth_factor
600 variable check
601
602 if (ParamIsDefault(check))
603 check = 0
604 endif
605 if (ParamIsDefault(theta_offset))
606 theta_offset = 0
607 endif
608 if (ParamIsDefault(smooth_method))
609 smooth_method = 4
610 endif
611 if (ParamIsDefault(smooth_factor))
612 smooth_factor = 0.5
613 endif
614
615 // average over analyser angles
616 duplicate /free strip, strip_copy
617 MatrixFilter NanZapMedian strip_copy
618 wave dist = ad_profile_y(strip_copy, -inf, inf, "")
619
620 // smooth distribution function
621 duplicate /free dist, dist_smoo
622 duplicate /free theta, theta_int
623 theta_int = theta - theta_offset
624 setscale /p x theta_int[0], theta_int[1] - theta_int[0], waveunits(theta,-1), dist, dist_smoo
625
626 // analyse scanning scheme
627 duplicate /free theta_int, d1_theta, d2_theta
628 Differentiate /METH=2 theta_int /D=d1_theta
629 Differentiate /METH=2 d1_theta /D=d2_theta
630 d2_theta = abs(d2_theta)
631 make /free w_levels
632 FindLevels /edge=1 /p /q /d=w_levels d2_theta, 0.1
633 if (v_flag != 1)
634 abort "unrecognized scanning scheme"
635 endif
636 w_levels = ceil(w_levels)
637 InsertPoints 0, 1, w_levels
638 w_levels[0] = 0
639 InsertPoints numpnts(w_levels), 1, w_levels
640 w_levels[numpnts(w_levels)-1] = numpnts(theta_int)
641
642 variable n_scans = numpnts(w_levels) - 1
643 variable i_scan
644 variable p1, p2
645 for (i_scan = 0; i_scan < n_scans; i_scan += 1)
646 p1 = w_levels[i_scan]
647 p2 = w_levels[i_scan+1] - 1
648 duplicate /free /r=[p1, p2] dist, dist_piece, smooth_piece
649 duplicate /free /r=[p1, p2] theta_int, theta_piece
650 switch(smooth_method)
651 case 4:
652 loess /dest=smooth_piece /smth=(smooth_factor) srcWave=dist_piece, factors={theta_piece}
653 break
654 default:
655 abort "smooth method not supported"
656 endswitch
657 dist_smoo[p1, p2] = smooth_piece[p - p1]
658 endfor
659
660 // divide
661 if (check != 2)
662 strip /= dist_smoo[q]
663 endif
664
665 // check
666 if (check)
667 duplicate /o dist, check_dist
668 duplicate /o dist_smoo, check_smoo
669 setscale /p x dimoffset(dist,0), dimdelta(dist,0), waveunits(dist,0), check_dist, check_smoo
670 endif
671end
672
686function normalize_strip_2d(strip, theta, [theta_offset, smooth_method, smooth_factor, check])
687 wave strip
688 wave theta
689 variable theta_offset
690 variable smooth_method
691 variable smooth_factor
692 variable check
693
694 if (ParamIsDefault(check))
695 check = 0
696 endif
697 if (ParamIsDefault(theta_offset))
698 theta_offset = 0
699 endif
700 if (ParamIsDefault(smooth_method))
701 smooth_method = 4
702 endif
703 if (ParamIsDefault(smooth_factor))
704 smooth_factor = 0.5
705 endif
706
707 variable nx = dimsize(strip, 0)
708 variable ny = dimsize(strip, 1)
709
710 duplicate /free strip, dist, alpha_int, theta_int
711 MatrixFilter NanZapMedian dist
712 theta_int = theta[q] - theta_offset
713 alpha_int = dimoffset(strip, 0) + p * dimdelta(strip, 0)
714 redimension /n=(nx * ny) dist, alpha_int, theta_int
715
716 switch(smooth_method)
717 case 4:
718 loess /dest=dist_smoo /smth=(smooth_factor) srcWave=dist, factors={alpha_int, theta_int}
719 redimension /n=(nx, ny) dist_smoo
720 break
721 default:
722 Abort "undefined smooth method"
723 break
724 endswitch
725
726 // divide
727 if (check != 2)
728 strip /= dist_smoo
729 endif
730
731 // check
732 if (check)
733 //duplicate /o dist, check_dist
734 duplicate /o dist_smoo, check_smoo
735 endif
736end
737
747function crop_strip(strip, xlo, xhi)
748 wave strip
749 variable xlo
750 variable xhi
751
752 variable plo = round((xlo - dimoffset(strip, 0)) / dimdelta(strip, 0))
753 variable phi = round((xhi - dimoffset(strip, 0)) / dimdelta(strip, 0))
754 xlo = plo * dimdelta(strip, 0) + dimoffset(strip, 0)
755 xhi = phi * dimdelta(strip, 0) + dimoffset(strip, 0)
756 variable nx = phi - plo + 1
757 variable ny = dimsize(strip, 1)
758
759 duplicate /free strip, strip_copy
760 redimension /n=(nx,ny) strip
761 strip = strip_copy[p + plo][q]
762 setscale /i x xlo, xhi, waveunits(strip, 0), strip
763end
764
779function crop_strip_theta(strip, theta_lo, theta_hi, theta, tilt, phi)
780 wave strip
781 variable theta_lo
782 variable theta_hi
783 wave theta
784 wave tilt
785 wave phi
786
787 extract /indx /free theta, idx, (theta >= theta_lo) && (theta <= theta_hi)
788 variable nx = dimsize(strip, 0)
789 variable ny = numpnts(idx)
790
791 theta[0, ny-1] = theta[idx]
792 tilt[0, ny-1] = tilt[idx]
793 phi[0, ny-1] = phi[idx]
794 redimension /n=(ny) theta, tilt, phi
795
796 duplicate /free strip, strip_copy
797 redimension /n=(nx,ny) strip
798 strip = strip_copy[p][idx[q]]
799end
800
843function pizza_service(data, nickname, theta_offset, tilt_offset, phi_offset, [npolar, nograph, folding, xpdplot])
844 wave data
845 string nickname
846 variable theta_offset
847 variable tilt_offset
848 variable phi_offset
849 variable npolar
850 variable nograph
851 variable folding
852 variable xpdplot
853
854 if (ParamIsDefault(npolar))
855 npolar = 91
856 endif
857 if (ParamIsDefault(nograph))
858 nograph = 0
859 endif
860 if (ParamIsDefault(folding))
861 folding = 1
862 endif
863 if (ParamIsDefault(xpdplot))
864 xpdplot = 0
865 endif
866
867 // sort out data folder structure
868 dfref saveDF = GetDataFolderDFR()
869 dfref dataDF = GetWavesDataFolderDFR(data)
870 setdatafolder dataDF
871 if (DataFolderExists(":attr"))
872 setdatafolder :attr
873 endif
874 dfref attrDF = GetDataFolderDFR()
875
876 wave /sdfr=attrDF ManipulatorTheta
877 wave /sdfr=attrDF ManipulatorTilt
878 wave /sdfr=attrDF ManipulatorPhi
879
880 if ((dimsize(ManipulatorTheta, 0) != dimsize(data, 1)) || (dimsize(ManipulatorTilt, 0) != dimsize(data, 1)) || (dimsize(ManipulatorPhi, 0) != dimsize(data, 1)))
881 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."
882 endif
883
884 duplicate /free ManipulatorTheta, m_theta
885 duplicate /free ManipulatorTilt, m_tilt
886 duplicate /free ManipulatorPhi, m_phi
887
888 m_theta -= theta_offset
889 m_tilt -= tilt_offset
890 m_phi -= phi_offset
891
892 pizza_service_2(data, nickname, m_theta, m_tilt, m_phi, npolar=npolar, nograph=nograph, folding=folding, xpdplot=xpdplot)
893
894 setdatafolder saveDF
895end
896
936function pizza_service_2(data, nickname, m_theta, m_tilt, m_phi, [npolar, nograph, folding, xpdplot])
937 wave data
938 string nickname
939 wave m_theta
940 wave m_tilt
941 wave m_phi
942 variable npolar
943 variable nograph
944 variable folding
945 variable xpdplot
946
947 if (ParamIsDefault(npolar))
948 npolar = 91
949 endif
950 if (ParamIsDefault(nograph))
951 nograph = 0
952 endif
953 if (ParamIsDefault(folding))
954 folding = 1
955 endif
956 if (ParamIsDefault(xpdplot))
957 xpdplot = 0
958 endif
959
960 if ((dimsize(m_theta, 0) != dimsize(data, 1)) || (dimsize(m_tilt, 0) != dimsize(data, 1)) || (dimsize(m_phi, 0) != dimsize(data, 1)))
961 Abort "Warning: The dimension size of the manipulator waves does not match the Y dimension of the data wave!"
962 endif
963
964 string graphname = "graph_" + nickname
965 string outprefix = nickname
966
967 // sort out data folder structure
968 dfref saveDF = GetDataFolderDFR()
969 dfref dataDF = GetWavesDataFolderDFR(data)
970 setdatafolder dataDF
971
972 if (xpdplot)
973 setdatafolder root:
974 outprefix = nickname
975 else
976 setdatafolder dataDF
977 newdatafolder /s/o $nickname
978 outprefix = ""
979 endif
980 dfref destDF = GetDataFolderDFR()
981
982 // performance monitoring
983 variable timerRefNum
984 variable /g pol_perf_secs
985 timerRefNum = startMSTimer
986
987 duplicate /free m_tilt, corr_tilt
988 duplicate /free m_phi, corr_phi
989 corr_tilt = -m_tilt // checked 140702
990 corr_phi = m_phi // checked 140702
991
992 make /n=1/d/free d_polar, d_azi
993
994 convert_angles_ttpd2polar(m_theta, corr_tilt, corr_phi, data, d_polar, d_azi)
995 d_azi += 180 // changed 151030 (v1.6)
996 make_hemi_grid(npolar, outprefix, xpdplot=xpdplot)
997 variable ifold
998 for (ifold = 0; ifold < folding; ifold += 1)
999 d_azi = d_azi >= 360 ? d_azi - 360 : d_azi
1000 hemi_add_anglescan(outprefix, data, d_polar, d_azi)
1001 d_azi += 360 / folding
1002 endfor
1003
1004 // normalize folding
1005 if (strlen(outprefix))
1006 string s_prefix = outprefix + "_"
1007 string s_int = s_prefix + "i"
1008 else
1009 s_prefix = ""
1010 s_int = "values"
1011 endif
1012 if (folding > 1)
1013 wave values = $s_int
1014 values /= folding
1015 endif
1016
1017 if (!nograph)
1018 display_hemi_scan(outprefix, graphname = graphname)
1019 endif
1020
1021 if (timerRefNum >= 0)
1022 pol_perf_secs = stopMSTimer(timerRefNum) / 1e6
1023 endif
1024
1025 setdatafolder saveDF
1026end
1027
1053function show_analyser_line(theta, tilt, phi, theta_offset, tilt_offset, phi_offset, [npolar, nograph, xpdplot])
1054 variable theta
1055 variable tilt
1056 variable phi
1057 variable theta_offset
1058 variable tilt_offset
1059 variable phi_offset
1060 variable npolar
1061 variable nograph
1062 variable xpdplot
1063
1064 string nickname = "analyser"
1065
1066 if (ParamIsDefault(npolar))
1067 npolar = 91
1068 endif
1069 if (ParamIsDefault(nograph))
1070 nograph = 0
1071 endif
1072 if (ParamIsDefault(xpdplot))
1073 xpdplot = 0
1074 endif
1075 string graphname = "graph_" + nickname
1076 string outprefix = nickname
1077
1078 // sort out data folder structure
1079 dfref saveDF = GetDataFolderDFR()
1080 dfref dataDF = saveDF
1081 if (xpdplot)
1082 setdatafolder root:
1083 outprefix = nickname
1084 else
1085 setdatafolder dataDF
1086 newdatafolder /s/o $nickname
1087 outprefix = ""
1088 endif
1089 dfref destDF = GetDataFolderDFR()
1090
1091 make /n=1 /free m_theta
1092 make /n=1 /free m_tilt
1093 make /n=1 /free m_phi
1094 m_theta = theta - theta_offset
1095 m_tilt = tilt - tilt_offset
1096 m_tilt *= -1 // checked 140702
1097 m_phi = phi - phi_offset
1098 //m_phi *= -1 // checked 140702
1099
1100 make /n=60 /free data
1101 setscale /i x -30, 30, data
1102 data = x
1103 make /n=1/d/free d_polar, d_azi
1104
1105 convert_angles_ttpa2polar(m_theta, m_tilt, m_phi, data, d_polar, d_azi)
1106 d_azi += 180 // changed 151030 (v1.6)
1107 d_azi = d_azi >= 360 ? d_azi - 360 : d_azi
1108 make_hemi_grid(npolar, outprefix, xpdplot=xpdplot)
1109 hemi_add_anglescan(outprefix, data, d_polar, d_azi)
1110
1111 if (!nograph)
1112 display_hemi_scan(outprefix, graphname = graphname)
1113 endif
1114
1115 setdatafolder saveDF
1116end
1117
1122
1123function convert_angles_ttpd2polar(theta, tilt, phi, data, polar, azi)
1124 wave theta, tilt, phi // see convert_angles_ttpa2polar
1125 wave data // in, 1D or 2D
1126 // X-scale must be set to analyser angle scale
1127 wave polar, azi // see convert_angles_ttpa2polar
1128
1129 make /n=(dimsize(data, 0)) /d /free ana
1130 setscale /p x dimoffset(data, 0), dimdelta(data, 0), waveunits(data, 0), ana
1131 ana = x
1132 convert_angles_ttpa2polar(theta, tilt, phi, ana, polar, azi)
1133end
1134
1162function convert_angles_ttpa2polar(theta, tilt, phi, analyser, polar, azi)
1163 wave theta
1164 wave tilt
1165 wave phi
1166 wave analyser
1167 wave polar, azi
1168
1169 variable nn = numpnts(theta)
1170 variable na = numpnts(analyser)
1171 redimension /n=(na, nn) polar, azi
1172
1173 variable radius = 1 // don't need to specify - everything is scalable
1174
1175 // step 1: calculate cartesian detection vectors at normal emission
1176 // this is simply a polar-cartesian mapping, independent of the manipulator
1177 // phi=0 is in the polar rotation plane
1178 make /n=(3,na) /d /free w_orig_polar, w_orig_cart, w_rot_cart, w_rot_polar
1179 w_orig_polar[0][] = radius
1180 w_orig_polar[1][] = analyser[q]
1181 w_orig_polar[2][] = 0
1182 polar2cart_wave(w_orig_polar, w_orig_cart)
1183 // if the angle-dispersive axis was horizontal, we'd need to rotate the detector
1184 //rotate_z_wave(w_orig_cart, 90)
1185
1186 variable ii
1187 for (ii = 0; ii < nn; ii += 1)
1188 // step 2: rotate the detection vectors according to the manipulator angles
1189 // the order of rotations is important because we rotate about fixed axes
1190 // y-axis = tilt rotation axis
1191 // x-axis = polar rotation axis
1192 // z-axis = normal emission = azimuthal rotation axis
1193 w_rot_cart = w_orig_cart
1194 rotate_y_wave(w_rot_cart, -tilt[ii])
1195 rotate_x_wave(w_rot_cart, -theta[ii])
1196 rotate_z_wave(w_rot_cart, -phi[ii] - 90)
1197 // map the vectors back to the sample coordinate system
1198 cart2polar_wave(w_rot_cart, w_rot_polar)
1199 // copy to output
1200 polar[][ii] = w_rot_polar[1][p]
1201 azi[][ii] = w_rot_polar[2][p]
1202 endfor
1203end
1204
1205static function line_average(source, dest)
1206 // is this function used?
1207 wave source
1208 wave dest
1209
1210 variable ii
1211 variable nn = dimsize(source, 1)
1212 make /n=(dimsize(source, 0))/d/free line
1213 for (ii = 0; ii < nn; ii += 1)
1214 line = source[p][ii]
1215 wavestats /q line
1216 dest[][ii] = line[p] / v_max
1217 endfor
1218end
1219
1223static function calc_nth(Theta_st, Theta_in, th, Phi_ran, Phi_ref, Holomode)
1224 Variable Theta_st, Theta_in, th, Phi_ran, Phi_ref
1225 String Holomode
1226 Variable The_step
1227 Variable deg2rad=0.01745329
1228
1229 if ( cmpstr(Holomode, "Stereographic") == 0)
1230 The_step =trunc( Phi_ran*sin(th*deg2rad)*Phi_ref/Theta_st )
1231 if(th==90)
1232 The_step =trunc( Phi_ran*sin(th*pi/180)*Phi_ref/Theta_st )
1233 endif
1234 else
1235 if (cmpstr(Holomode, "Parallel") == 0)
1236 The_step=trunc( Phi_ran*tan(th*deg2rad)*Phi_ref/Theta_st )
1237 else
1238 if ( cmpstr(Holomode, "h") == 0)
1239 The_step=trunc( th/Theta_in*Phi_ran/Theta_st )
1240 else
1241 //altro
1242 endif
1243 endif
1244 endif
1245
1246 return(The_step)
1247end
1248
1252static function calc_phi_step(Theta_in, th, Theta_st, Phi_ran, Phi_ref, Holomode)
1253 Variable Theta_in, th, Theta_st, Phi_ran, Phi_ref
1254 String Holomode
1255
1256 Variable Phi_st
1257 Variable deg2rad=0.01745329
1258
1259 if ( cmpstr(Holomode, "Stereographic") == 0 )
1260 if ((th < 0.5) || (trunc(Phi_ran*sin(th*deg2rad)*Phi_ref/Theta_st) == 0))
1261 Phi_st=0.0
1262 else
1263 Phi_st=Phi_ran/(trunc(Phi_ran*sin(th*deg2rad)*Phi_ref/Theta_st))
1264 endif
1265 if(th==90)
1266 Phi_st=2.0
1267 endif
1268 endif
1269
1270 if ( cmpstr(Holomode, "Parallel") == 0 )
1271 if((th < 0.5) || (trunc(Phi_ran*tan(th*deg2rad)*Phi_ref/Theta_st) == 0))
1272 Phi_st=0.0
1273 else
1274 Phi_st=Phi_ran/(trunc(Phi_ran*tan(th*deg2rad)*Phi_ref/Theta_st))
1275 endif
1276 endif
1277
1278 if ( cmpstr(Holomode, "h") == 0 )
1279 if((th < 0.5) || (trunc(Phi_ran*sin(th*deg2rad)*Phi_ref/Theta_st) == 0))
1280 Phi_st=0.0
1281 else
1282 Phi_st=Phi_ran/trunc(th/Theta_in*Phi_ran/Theta_st)
1283 endif
1284 endif
1285
1286 if (Phi_st==0)
1287 Phi_st=360
1288 endif
1289
1290 return(Phi_st)
1291end
1292
1296static function Calc_The_step(th, Theta_st, Holomode)
1297 String Holomode
1298 Variable th, Theta_st
1299
1300 Variable deg2rad=0.01745329, dt_loc,The_step
1301
1302 if ( (cmpstr(Holomode, "Stereographic")) ==0 )
1303 The_step=Theta_st
1304 endif
1305
1306 if ( (cmpstr(Holomode, "h")) ==0 )
1307 The_step=Theta_st
1308 endif
1309
1310 if ( cmpstr(Holomode, "Parallel") == 0 )
1311 if(th < 89.5)
1312 dt_loc = Theta_st/cos(th*deg2rad)
1313 if(dt_loc > 10)
1314 dt_loc=10
1315 endif
1316 The_step=dt_loc
1317 else
1318 The_step=10
1319 endif
1320 endif
1321 return(The_step)
1322end
1323
1327static function CalcN_Theta(HoloMode,Theta_in,Theta_ran,Theta_st)
1328 String HoloMode
1329 Variable Theta_in,Theta_ran,Theta_st
1330 Variable n_theta, aux, aux1,ii
1331
1332 aux = Theta_in
1333 aux1= Theta_in - Theta_ran
1334 ii = 0
1335 do
1336 aux = aux - Calc_The_step(aux, Theta_st, HoloMode)
1337 if(aux<=Theta_in-Theta_ran)
1338 aux=Theta_in-Theta_ran
1339 endif
1340 ii = ii+1
1341 while((aux>aux1)%&(Theta_in-aux<=Theta_ran)) //
1342 n_theta=ii+1
1343 Return(n_theta)
1344end
1345
1365function make_hemi_grid(npol, nickname, [xpdplot])
1366 variable npol
1367 string nickname
1368 variable xpdplot
1369
1370 if (ParamIsDefault(xpdplot))
1371 xpdplot = 0
1372 endif
1373
1374 string HoloMode = "h"
1375 variable Theta_in = 90
1376 variable Theta_ran = 90
1377 variable Theta_st = 90 / (npol - 1)
1378 variable Phi_ran = 360
1379 variable Phi_ref = 1
1380 variable Phi_in = 0
1381
1382 variable n_theta = CalcN_Theta(HoloMode, Theta_in, Theta_ran, Theta_st)
1383
1384 // wave names
1385 if (strlen(nickname))
1386 string s_prefix = nickname + "_"
1387 string s_int = s_prefix + "i" // Intensity wave (counts/sec)
1388 else
1389 s_prefix = ""
1390 s_int = "values" // "i" is not a valid wave name
1391 endif
1392 string s_polar = s_prefix + "pol" // thetas for each int-point of the holo
1393 string s_azim = s_prefix + "az" // phis for each int-point of the holo
1394
1395 string s_index = s_prefix + "index" // starting index for each theta
1396 string s_theta = s_prefix + "th" // theta values
1397 string s_dphi = s_prefix + "dphi" // delta phis at each theta
1398 string s_nphis = s_prefix + "nphis" // number of phis at each theta
1399
1400 string s_HoloData = s_prefix + "data" // All holo exp.- parameter information
1401 string s_HoloInfo = s_prefix + "info"
1402
1403 // the following two waves are used by the pearl-anglescan procedures but not by XPDplot
1404 string s_tot = s_prefix + "tot" // accumulated counts at each point
1405 string s_weight = s_prefix + "wt" // total accumulation time at each point (arb. units)
1406
1407 make /O/D/n=(n_theta) $s_index /wave=index
1408 make /O/D/n=(n_theta) $s_theta /wave=theta
1409 make /O/D/n=(n_theta) $s_dphi /wave=dphi
1410 make /O/D/n=(n_theta) $s_nphis /wave=nphis
1411
1412 //---------- calculate phi-step-size for this theta:
1413 variable aux = Calc_The_step(Theta_in, Theta_st, HoloMode)
1414 dphi[0] = calc_phi_step(Theta_in, Theta_in, aux, Phi_ran, Phi_ref, HoloMode)
1415 Theta[0] = Theta_in
1416 nphis[0] = calc_nth(aux, Theta_in, Theta_in, Phi_ran, Phi_ref, HoloMode)
1417 Index[0] = nphis[0]
1418
1419 //---------- calculate number of phis, phi-step, and starting-index for each theta:
1420 variable ii = 1
1421 do
1422 Theta[ii] = Theta[ii-1] - aux
1423 if(Theta[ii] <= Theta_in-Theta_ran)
1424 Theta[ii] = Theta_in-Theta_ran
1425 endif
1426 aux = Calc_The_step(Theta[ii], Theta_st, HoloMode)
1427 dphi[ii] = calc_phi_step(Theta_in, Theta[ii], aux, Phi_ran, Phi_ref, HoloMode)
1428 nphis[ii] = calc_nth(aux, Theta_in, Theta[ii], Phi_ran, Phi_ref, HoloMode)
1429 Index[ii] = Index[ii-1] + nphis[ii]
1430 ii=ii+1
1431 while(ii < n_theta)
1432
1433 if (Index[n_theta-1]==Index[n_theta-2])
1434 Index[n_theta-1]=Index[n_theta-2]+1
1435 nphis[n_theta-1]=1
1436 endif
1437
1438 variable NumPoints = sum(nphis, 0, numpnts(nphis))
1439
1440 //---------- calculate theta and phi for each data point:
1441 make /O/D/N=(NumPoints) $s_polar /wave=polar, $s_azim /wave=azim
1442 note azim, "version=1.6"
1443
1444 ii = 0
1445 variable StartIndex = 0
1446 variable EndIndex
1447 do
1448 EndIndex=Index[ii]
1449 Polar[StartIndex, EndIndex-1]=Theta[ii]
1450 Azim[StartIndex, EndIndex-1]= mod(Phi_ran+(x-StartIndex)*dphi[ii]+Phi_in,Phi_ran)
1451 ii = ii + 1
1452 StartIndex = EndIndex
1453 while(ii < n_theta)
1454
1455 duplicate /o azim, $s_int /wave=values
1456 duplicate /o azim, $s_tot /wave=totals
1457 duplicate /o azim, $s_weight /wave=weights
1458 values = nan
1459 totals = 0
1460 weights = 0
1461
1462 // XPDplot metadata
1463 if (xpdplot)
1464 string s_FileName = ""
1465 string s_Comment = "created by pearl-anglescan-process.ipf"
1466 string s_HoloMode = "Stereographic"
1467 variable /g gb_SpectraFile = 0
1468
1469 Make/O/D/n=22 $s_HoloData /wave=HoloData
1470 HoloData[0] = NaN // v_StartKE
1471 HoloData[1] = NaN // v_StoppKE
1472 HoloData[6] = NumPoints
1473 HoloData[7] = Theta_in
1474 HoloData[8] = Theta_ran
1475 HoloData[9] = Theta_st
1476 HoloData[11] = Phi_in
1477 HoloData[12] = Phi_ran
1478 HoloData[13] = Theta_st
1479 HoloData[15] = Phi_ref
1480 HoloData[16] = Phi_ran
1481 HoloData[17] = 0 // v_HoloBit (stereographic)
1482
1483 Make/O/T/n=22 $s_HoloInfo /wave=HoloInfo
1484 HoloInfo[0] = s_FileName
1485 HoloInfo[1] = s_Comment
1486 HoloInfo[10] = s_HoloMode
1487 HoloInfo[11] = "" // s_MeasuringMode
1488
1489 // notebook for XPDplot
1490 if (WinType(NickName) == 5)
1491 Notebook $NickName selection={startOfFile, endOfFile}
1492 Notebook $NickName text=""
1493 else
1494 NewNotebook /F=0 /K=1 /N=$NickName /W=(5,40,341,260)
1495 Notebook $NickName defaultTab=140
1496 Notebook $NickName statusWidth=300
1497 Notebook $NickName backRGB=(56797,56797,56797)
1498 Notebook $NickName pageMargins={80,80,80,80}
1499 Notebook $NickName fSize=10
1500 Notebook $NickName fStyle=0,textRGB=(65535,0,26214)
1501 Notebook $NickName textRGB=(65535,0,26214)
1502 endif
1503 Notebook $NickName text = "File:\t" + s_FileName + "\r"
1504 Notebook $NickName text = "*** " + s_Comment + " ***\r\r"
1505 Notebook $NickName text = "Angle-Mode:\t" + s_HoloMode + "\r"
1506 Notebook $NickName text = "XPDplot Nickname:\t" + NickName + "\r"
1507 endif
1508end
1509
1516function /s get_hemi_nickname(w)
1517 wave w
1518
1519 string prefix = get_hemi_prefix(w)
1520 string wname = nameofwave(w)
1521 string nickname
1522
1523 if (strlen(prefix))
1524 nickname = prefix
1525 else
1526 string s_wave_df = GetWavesDataFolder(w, 1)
1527 dfref parent_df = $(s_wave_df + "::")
1528 nickname = GetDataFolder(0, parent_df)
1529 endif
1530
1531 return nickname
1532end
1533
1541function /s get_hemi_prefix(w)
1542 wave w
1543
1544 string wname = nameofwave(w)
1545 string prefix
1546 if (ItemsInList(wname, "_") >= 2)
1547 prefix = StringFromList(0, wname, "_")
1548 else
1549 prefix = ""
1550 endif
1551
1552 return prefix
1553end
1554
1572function /df find_hemi_data(nickname, prefix, intwave)
1573 string nickname
1574 string &prefix
1575 string &intwave
1576
1577 dfref datadf
1578 prefix = ""
1579 intwave = "values"
1580 if (strlen(nickname))
1581 if (DataFolderExists(nickname))
1582 datadf = $nickname
1583 else
1584 datadf = getdatafolderdfr()
1585 prefix = nickname + "_"
1586 intwave = prefix + "i"
1587 if (exists(intwave) != 1)
1588 datadf = root:
1589 endif
1590 endif
1591 else
1592 datadf = getdatafolderdfr()
1593 prefix = ""
1594 intwave = "values"
1595 endif
1596 return datadf
1597end
1598
1606function clear_hemi_grid(nickname)
1607 string nickname
1608
1609 dfref datadf
1610 string s_prefix
1611 string s_int
1612 datadf = find_hemi_data(nickname, s_prefix, s_int)
1613
1614 string s_totals = s_prefix + "tot"
1615 string s_weights = s_prefix + "wt"
1616
1617 wave /sdfr=datadf /z w_values = $s_int
1618 wave /sdfr=datadf /z w_totals = $s_totals
1619 wave /sdfr=datadf /z w_weights = $s_weights
1620
1621 if (waveexists(w_totals))
1622 w_totals = 0
1623 endif
1624 if (waveexists(w_weights))
1625 w_weights = 0
1626 endif
1627 if (waveexists(w_values))
1628 w_values = nan
1629 endif
1630end
1631
1653function duplicate_hemi_scan(source_nickname, dest_folder, dest_nickname, [xpdplot])
1654 string source_nickname
1655 dfref dest_folder
1656 string dest_nickname
1657 variable xpdplot
1658
1659 if (ParamIsDefault(xpdplot))
1660 xpdplot = 0
1661 endif
1662
1663 dfref savedf = getdatafolderdfr()
1664
1665 // source data
1666 string s_prefix = ""
1667 string s_int = "values"
1668 dfref source_df = find_hemi_data(source_nickname, s_prefix, s_int)
1669 string s_polar = s_prefix + "pol"
1670 string s_azim = s_prefix + "az"
1671 string s_theta = s_prefix + "th"
1672 string s_tot = s_prefix + "tot"
1673 string s_weight = s_prefix + "wt"
1674 string s_matrix = s_prefix + "matrix"
1675
1676 wave /sdfr=source_df theta1 = $s_theta
1677 wave /sdfr=source_df polar1 = $s_polar
1678 wave /sdfr=source_df azim1 = $s_azim
1679 wave /sdfr=source_df tot1 = $s_tot
1680 wave /sdfr=source_df weight1 = $s_weight
1681 wave /sdfr=source_df values1 = $s_int
1682 wave /sdfr=source_df /z matrix1 = $s_matrix
1683
1684 variable npol = numpnts(theta1)
1685
1686 setdatafolder dest_folder
1687 make_hemi_grid(npol, dest_nickname, xpdplot=xpdplot)
1688
1689 // dest data
1690 dfref dest_df = find_hemi_data(dest_nickname, s_prefix, s_int)
1691 s_polar = s_prefix + "pol"
1692 s_azim = s_prefix + "az"
1693 s_theta = s_prefix + "th"
1694 s_tot = s_prefix + "tot"
1695 s_weight = s_prefix + "wt"
1696 s_matrix = s_prefix + "matrix"
1697
1698 wave /sdfr=dest_df theta2 = $s_theta
1699 wave /sdfr=dest_df polar2 = $s_polar
1700 wave /sdfr=dest_df azim2 = $s_azim
1701 wave /sdfr=dest_df tot2 = $s_tot
1702 wave /sdfr=dest_df weight2 = $s_weight
1703 wave /sdfr=dest_df values2 = $s_int
1704
1705 tot2 = tot1
1706 weight2 = weight1
1707 values2 = values1
1708 if (waveexists(matrix1))
1709 setdatafolder dest_df
1710 duplicate /o matrix1, $s_matrix
1711 endif
1712
1713 if (!(NumberByKey("version", note(azim1), "=", "\r") >= 1.6))
1714 azim2 += 180 // changed 151030 (v1.6)
1715 azim2 = azim2 >= 360 ? azim2 - 360 : azim2
1716 endif
1717
1718 setdatafolder saveDF
1719end
1720
1728function rotate_hemi_scan(nickname, angle)
1729 string nickname
1730 variable angle
1731
1732 dfref savedf = getdatafolderdfr()
1733
1734 string s_prefix = ""
1735 string s_int = "values"
1736 dfref df = find_hemi_data(nickname, s_prefix, s_int)
1737
1738 string s_polar = s_prefix + "pol"
1739 string s_azim = s_prefix + "az"
1740 string s_tot = s_prefix + "tot"
1741 string s_weight = s_prefix + "wt"
1742
1743 wave /sdfr=df polar = $s_polar
1744 wave /sdfr=df azim = $s_azim
1745 wave /sdfr=df tot = $s_tot
1746 wave /sdfr=df weight = $s_weight
1747 wave /sdfr=df values = $s_int
1748
1749 azim += angle
1750 azim = azim < 0 ? azim + 360 : azim
1751 azim = azim >= 360 ? azim - 360 : azim
1752
1753 duplicate /free polar, neg_polar
1754 neg_polar = -polar
1755 sort {neg_polar, azim}, polar, azim, tot, weight, values
1756
1757 setdatafolder saveDF
1758end
1759
1776function /s prepare_hemi_scan_display(nickname, [projection])
1777 string nickname
1778 variable projection
1779
1780 dfref savedf = getdatafolderdfr()
1781
1782 if (ParamIsDefault(projection))
1783 projection = 1
1784 endif
1785
1786 // hemi grid waves
1787 string s_prefix = ""
1788 string s_int = "values"
1789 dfref df = find_hemi_data(nickname, s_prefix, s_int)
1790
1791 string s_polar = s_prefix + "pol"
1792 string s_azim = s_prefix + "az"
1793
1794 wave /sdfr=df /z values = $s_int
1795 wave /sdfr=df /z azim = $s_azim
1796 wave /sdfr=df /z polar = $s_polar
1797
1798 setdatafolder df
1799 string s_ster_rad = s_prefix + "ster_rad"
1800 duplicate /o polar, $s_ster_rad /wave=ster_rad
1801 ster_rad = calc_graph_radius(polar, projection=projection)
1802
1803 string s_ster_x = s_prefix + "ster_x"
1804 string s_ster_y = s_prefix + "ster_y"
1805 duplicate /o azim, $s_ster_x /wave=ster_x, $s_ster_y /wave=ster_y
1806 ster_x = ster_rad * cos(azim * pi / 180)
1807 ster_y = ster_rad * sin(azim * pi / 180)
1808
1809 setdatafolder savedf
1810end
1811
1858function /s display_hemi_scan(nickname, [projection, graphtype, do_ticks, do_grids, graphname])
1859 string nickname
1860 variable projection
1861 variable graphtype
1862 variable do_ticks
1863 variable do_grids
1864 string graphname
1865
1866 dfref savedf = getdatafolderdfr()
1867
1868 if (ParamIsDefault(projection))
1869 projection = 1
1870 endif
1871 if (ParamIsDefault(graphtype))
1872 graphtype = 1
1873 endif
1874 if (ParamIsDefault(do_ticks))
1875 do_ticks = 3
1876 endif
1877 if (ParamIsDefault(do_grids))
1878 do_grids = 3
1879 endif
1880 if (ParamIsDefault(graphname))
1881 if (strlen(nickname) > 0)
1882 graphname = nickname
1883 else
1884 graphname = GetDataFolder(0)
1885 endif
1886 endif
1887
1888 prepare_hemi_scan_display(nickname, projection=projection)
1889
1890 // hemi grid waves
1891 string s_prefix = ""
1892 string s_int = "values"
1893 dfref df = find_hemi_data(nickname, s_prefix, s_int)
1894
1895 string s_polar = s_prefix + "pol"
1896 string s_azim = s_prefix + "az"
1897 string s_matrix = s_prefix + "matrix"
1898 string s_ster_rad = s_prefix + "ster_rad"
1899
1900 wave /sdfr=df /z values = $s_int
1901 wave /sdfr=df /z azim = $s_azim
1902 wave /sdfr=df /z polar = $s_polar
1903 wave /sdfr=df /z ster_rad = $s_ster_rad
1904 wave /sdfr=df /z matrix = $s_matrix
1905
1906 setdatafolder df
1907 variable azim_offset = 0
1908 if (!(NumberByKey("version", note(azim), "=", "\r") >= 1.6))
1909 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!"
1910 azim_offset = 180 // changed 151030 (v1.6)
1911 endif
1912
1913 string s_trace
1914 DoWindow $graphname
1915 if (v_flag)
1916 if (str2num(GetUserData(graphname, "", "graphtype")) == graphtype)
1917 // graph exists and will update automatically - do not recreate
1918 graphtype = 0
1919 else
1920 // graph exists - but needs recreating
1921 killwindow $graphname
1922 endif
1923 endif
1924
1925 switch(graphtype)
1926 case 1:
1927 graphname = display_polar_graph(graphname, angle_offset=azim_offset, do_ticks=do_ticks)
1928
1929 s_trace = WMPolarAppendTrace(graphname, ster_rad, azim, 360)
1930 ModifyGraph /W=$graphname mode($s_trace)=2, lsize($s_trace)=2
1931 ModifyGraph /W=$graphname zColor($s_trace)={values,*,*,BlueGreenOrange,0}
1932
1933 ColorScale /W=$graphname /C /N=text0 /E=2 /F=0 /B=1 /A=RB /X=0.00 /Y=0.00 trace=polarY0
1934 ColorScale /W=$graphname /C /N=text0 side=2, width=5, heightPct=40, frame=0.50, lblMargin=0
1935 ColorScale /W=$graphname /C /N=text0 nticks=2, minor=1, tickLen=4.00, tickThick=0.50
1936
1937 SetWindow $graphname, userdata(projection)=num2str(projection)
1938 SetWindow $graphname, userdata(graphtype)=num2str(graphtype)
1939 draw_hemi_axes(graphname, do_grids=do_grids)
1940 break
1941 case 3:
1942 graphname = display_polar_graph(graphname, angle_offset=azim_offset, do_ticks=do_ticks)
1943
1944 s_trace = WMPolarAppendTrace(graphname, ster_rad, azim, 360)
1945 ModifyGraph /W=$graphname mode($s_trace)=0, lsize($s_trace)=0
1946 AppendImage /L=VertCrossing /B=HorizCrossing matrix
1947
1948 ColorScale /W=$graphname /C /N=text0 /E=2 /F=0 /B=1 /A=RB /X=0.00 /Y=0.00 image=$s_matrix
1949 ColorScale /W=$graphname /C /N=text0 side=2, width=5, heightPct=40, frame=0.50, lblMargin=0
1950 ColorScale /W=$graphname /C /N=text0 nticks=2, minor=1, tickLen=4.00, tickThick=0.50
1951
1952 SetWindow $graphname, userdata(projection)=num2str(projection)
1953 SetWindow $graphname, userdata(graphtype)=num2str(graphtype)
1954 draw_hemi_axes(graphname, do_grids=do_grids)
1955 break
1956 endswitch
1957
1958 setdatafolder savedf
1959 return graphname
1960end
1961
2003static function /s display_polar_graph(graphname, [angle_offset, do_ticks])
2004
2005 string graphname
2006 variable angle_offset
2007 variable do_ticks
2008
2009 dfref savedf = GetDataFolderDFR()
2010
2011 if (ParamIsDefault(angle_offset))
2012 angle_offset = 0
2013 endif
2014 if (ParamIsDefault(do_ticks))
2015 do_ticks = 3
2016 endif
2017
2018 if ((strlen(graphname) == 0) || (wintype(graphname) == 0))
2019 Display /k=1 /W=(10,45,360,345)
2020 DoWindow /C $graphname
2021 graphname = WMNewPolarGraph("", graphname)
2022 WMPolarGraphSetVar(graphname, "zeroAngleWhere", angle_offset)
2023
2024 WMPolarGraphSetVar(graphname, "angleAxisThick", 0.5)
2025 WMPolarGraphSetStr(graphname, "doMajorAngleTicks", "manual")
2026 WMPolarGraphSetVar(graphname, "majorAngleInc", 30) // major ticks in 30 deg steps
2027 WMPolarGraphSetVar(graphname, "minorAngleTicks", 2) // minor ticks in 10 deg steps
2028 WMPolarGraphSetStr(graphname, "angleTicksLocation", "Outside")
2029 WMPolarGraphSetVar(graphname, "doAngleTickLabelSubRange", 1)
2030 WMPolarGraphSetVar(graphname, "angleTickLabelRangeStart", 0)
2031 WMPolarGraphSetVar(graphname, "angleTickLabelRangeExtent", 90)
2032 WMPolarGraphSetStr(graphname, "angleTickLabelNotation", "%g°")
2033
2034 WMPolarGraphSetVar(graphname, "doPolarGrids", 0)
2035 WMPolarGraphSetVar(graphname, "doRadiusTickLabels", 0)
2036 WMPolarGraphSetStr(graphname, "radiusAxesWhere", " Off") // note the leading spaces, cf. WMPolarAnglesForRadiusAxes
2037 WMPolarGraphSetStr(graphname, "radiusTicksLocation", "Off")
2038
2039 WMPolarGraphSetVar(graphname, "majorTickLength", 2)
2040 WMPolarGraphSetVar(graphname, "majorTickThick", 0.5)
2041 WMPolarGraphSetVar(graphname, "minorTickLength", 1)
2042 WMPolarGraphSetVar(graphname, "minorTickThick", 0.5)
2043 WMPolarGraphSetVar(graphname, "tickLabelOpaque", 0)
2044 WMPolarGraphSetVar(graphname, "tickLabelFontSize", 7)
2045
2046 // changes
2047 if (do_ticks & 1)
2048 WMPolarGraphSetStr(graphname, "angleTicksLocation", "Outside")
2049 else
2050 WMPolarGraphSetStr(graphname, "angleTicksLocation", "Off")
2051 endif
2052 if (do_ticks & 2)
2053 WMPolarGraphSetVar(graphname, "doMinorAngleTicks", 1)
2054 else
2055 WMPolarGraphSetVar(graphname, "doMinorAngleTicks", 0)
2056 endif
2057
2058 DoWindow /T $graphname, graphname
2059
2060 // cursor info in angles
2061 string graphdf = "root:packages:WMPolarGraphs:" + graphname
2062 setdatafolder graphdf
2063 // current theta, phi coordinates are stored in global variables in the package folder of the graph
2064 variable /g csrA_theta
2065 variable /g csrA_phi
2066 variable /g csrB_theta
2067 variable /g csrB_phi
2068 // the text box is hidden initially. it shows up and hides with the cursor info box.
2069 string tb
2070 tb = "\\{"
2071 tb = tb + "\"A = (%.1f, %.1f)\","
2072 tb = tb + graphdf + ":csrA_theta,"
2073 tb = tb + graphdf + ":csrA_phi"
2074 tb = tb + "}"
2075 TextBox /W=$graphname /A=LT /B=1 /E=2 /F=0 /N=tb_angles /X=1 /Y=1 /V=0 tb
2076 tb = "\\{"
2077 tb = tb + "\"B = (%.1f, %.1f)\","
2078 tb = tb + graphdf + ":csrB_theta,"
2079 tb = tb + graphdf + ":csrB_phi"
2080 tb = tb + "}"
2081 AppendText /W=$graphname /N=tb_angles tb
2082 // updates are triggered by a window hook
2083 SetWindow $graphname, hook(polar_graph_hook)=PearlAnglescanProcess#polar_graph_hook
2084 else
2085 // graph window exists
2086 DoWindow /F $graphname
2087 endif
2088
2089 setdatafolder savedf
2090 return graphname
2091end
2092
2118static function /s draw_hemi_axes(graphname, [do_grids])
2119 string graphname
2120 variable do_grids
2121
2122 if (ParamIsDefault(do_grids))
2123 do_grids = 3
2124 endif
2125
2126 dfref savedf = GetDataFolderDFR()
2127
2128 string sproj = GetUserData(graphname, "", "projection")
2129 variable projection = str2num("0" + sproj)
2130
2131 SetDrawLayer /W=$graphname ProgFront
2132
2133 // polar axis
2134 SetDrawEnv /W=$graphname xcoord=HorizCrossing, ycoord=VertCrossing
2135 SetDrawEnv /W=$graphname linethick= 0.5
2136 SetDrawEnv /W=$graphname dash=2
2137 SetDrawEnv /W=$graphname fillpat=0
2138 SetDrawEnv /W=$graphname fname="default", fsize=7
2139 SetDrawEnv /W=$graphname textxjust=1, textyjust=1
2140 //SetDrawEnv /W=$graphname linefgc=(65535,65535,65535)
2141 SetDrawEnv /W=$graphname save
2142
2143 if (do_grids & 1)
2144 DrawLine /W=$graphname 0, -2, 0, 2
2145 DrawLine /W=$graphname -2, 0, 2, 0
2146 endif
2147
2148 variable radi
2149 if (do_grids & 2)
2150 radi = calc_graph_radius(0.5, projection=projection)
2151 DrawOval /W=$graphname -radi, radi, radi, -radi
2152 radi = calc_graph_radius(30, projection=projection)
2153 DrawOval /W=$graphname -radi, radi, radi, -radi
2154 radi = calc_graph_radius(60, projection=projection)
2155 DrawOval /W=$graphname -radi, radi, radi, -radi
2156
2157 SetDrawEnv /W=$graphname textxjust= 1,textyjust= 2
2158 SetDrawEnv /W=$graphname save
2159 radi = calc_graph_radius(30, projection=projection)
2160 DrawText /W=$graphname radi, -0.1, "30°"
2161 radi = calc_graph_radius(60, projection=projection)
2162 DrawText /W=$graphname radi, -0.1, "60°"
2163 endif
2164
2165 setdatafolder savedf
2166end
2167
2190function draw_diffraction_cone(graphname, groupname, theta_axis, theta_inner, phi)
2191 string graphname
2192 string groupname
2193
2194 variable theta_axis
2195 variable theta_inner
2196 variable phi
2197
2198 variable r_axis = calc_graph_radius(theta_axis)
2199 variable r_inner = calc_graph_radius(theta_inner)
2200 variable r_outer = calc_graph_radius(2 * theta_axis - theta_inner)
2201
2202 SetDrawEnv push
2203 SetDrawLayer UserFront
2204 DrawAction getgroup=$groupname, delete
2205 SetDrawEnv gstart, gname=$groupname
2206 variable xc, yc, xr, yr
2207
2208 // cone periphery
2209 variable r_center = (r_outer + r_inner) / 2
2210 variable r_radius = (r_outer - r_inner) / 2
2211 xc = r_center * cos(phi * pi / 180)
2212 yc = r_center * sin(phi * pi / 180)
2213 xr = r_radius
2214 yr = r_radius
2215 SetDrawEnv xcoord=HorizCrossing, ycoord=VertCrossing
2216 SetDrawEnv dash=11, fillpat=0
2217 DrawOval xc - xr, yc - yr, xc + xr, yc + yr
2218
2219 // cone axis
2220 xc = r_axis * cos(phi * pi / 180)
2221 yc = r_axis * sin(phi * pi / 180)
2222 r_radius = calc_graph_radius(2)
2223 xr = r_radius
2224 yr = r_radius
2225 SetDrawEnv xcoord=HorizCrossing, ycoord=VertCrossing
2226 SetDrawEnv fillfgc=(0,0,0)
2227 DrawOval xc - xr, yc - yr, xc + xr, yc + yr
2228
2229 SetDrawEnv gstop
2230 SetDrawEnv pop
2231end
2232
2254function /s display_scanlines(nickname, alpha_lo, alpha_hi, m_theta, m_tilt, m_phi, [folding, projection])
2255 string nickname
2256 variable alpha_lo
2257 variable alpha_hi
2258 wave m_theta
2259 wave m_tilt
2260 wave m_phi
2261 variable folding
2262 variable projection
2263
2264 if (ParamIsDefault(folding))
2265 folding = 1
2266 endif
2267 if (ParamIsDefault(projection))
2268 projection = 1
2269 endif
2270
2271 // sort out data folder structure
2272 dfref saveDF = GetDataFolderDFR()
2273 newdatafolder /s/o $nickname
2274 string graphname = "graph_" + nickname
2275
2276 duplicate /free m_tilt, loc_m_tilt
2277 loc_m_tilt = -m_tilt
2278
2279 make /n=1 /d /free d_polar, d_azi
2280 variable n_alpha = round(alpha_hi - alpha_lo) + 1
2281 make /n=(n_alpha) /d /free analyser
2282 setscale /i x alpha_lo, alpha_hi, "°", analyser
2283 analyser = x
2284
2285 convert_angles_ttpa2polar(m_theta, loc_m_tilt, m_phi, analyser, d_polar, d_azi)
2286 duplicate /free d_polar, d_radius
2287 d_radius = calc_graph_radius(d_polar, projection=projection)
2288 d_azi += 180 // changed 151030 (v1.6)
2289
2290 graphname = display_polar_graph(graphname)
2291 SetWindow $graphname, userdata(projection)=num2str(projection)
2292
2293 variable ifold
2294 variable iang
2295 variable nang = numpnts(m_theta)
2296 string s_rad
2297 string s_azi
2298 string s_trace
2299 for (ifold = 0; ifold < folding; ifold += 1)
2300 d_azi = d_azi >= 360 ? d_azi - 360 : d_azi
2301 for (iang = 0; iang < nang; iang += 1)
2302 sprintf s_rad, "rad_%d_%d", ifold, iang
2303 duplicate /o analyser, $s_rad
2304 wave w_rad = $s_rad
2305 w_rad = d_radius[p][iang]
2306
2307 sprintf s_azi, "azi_%d_%d", ifold, iang
2308 duplicate /o analyser, $s_azi
2309 wave w_azi = $s_azi
2310 w_azi = d_azi[p][iang]
2311
2312 if (numtype(sum(w_rad)) == 0)
2313 s_trace = WMPolarAppendTrace(graphname, w_rad, w_azi, 360)
2314 ModifyGraph /w=$graphname mode($s_trace)=0, lsize($s_trace)=0.5
2315 endif
2316 endfor
2317 d_azi += 360 / folding
2318 endfor
2319
2320 draw_hemi_axes(graphname)
2321
2322 setdatafolder saveDF
2323 return graphname
2324end
2325
2342constant kProjDist = 0
2343constant kProjStereo = 1
2344constant kProjArea = 2
2345constant kProjGnom = 3
2346constant kProjOrtho = 4
2347
2348static constant kProjScaleDist = 2
2349static constant kProjScaleStereo = 2
2350static constant kProjScaleArea = 2
2351// scaled so that radius(gnom) = radius(stereo) for polar = 88
2352static constant kProjScaleGnom = 0.06744519021
2353static constant kProjScaleOrtho = 2
2354
2369threadsafe function calc_graph_radius(polar, [projection])
2370 variable polar
2371 variable projection
2372
2373 if (ParamIsDefault(projection))
2374 projection = 1
2375 endif
2376
2377 variable radius
2378 switch(projection)
2379 case kProjStereo: // stereographic
2380 radius = kProjScaleStereo * tan(polar / 2 * pi / 180)
2381 break
2382 case kProjArea: // equal area
2383 radius = kProjScaleArea * sin(polar / 2 * pi / 180)
2384 break
2385 case kProjGnom: // gnomonic
2386 radius = polar < 90 ? kProjScaleGnom * tan(polar * pi / 180) : inf
2387 break
2388 case kProjOrtho: // orthographic
2389 radius = kProjScaleOrtho * sin(polar * pi / 180)
2390 break
2391 default: // equidistant
2392 radius = kProjScaleDist * polar / 90
2393 endswitch
2394
2395 return radius
2396end
2397
2414threadsafe function calc_graph_polar(x, y, [projection])
2415 variable x
2416 variable y
2417 variable projection
2418
2419 if (ParamIsDefault(projection))
2420 projection = 1
2421 endif
2422
2423 variable radius
2424 variable polar
2425
2426 radius = sqrt(x^2 + y^2)
2427 switch(projection)
2428 case kProjStereo: // stereographic
2429 polar = 2 * atan(radius / kProjScaleStereo) * 180 / pi
2430 break
2431 case kProjArea: // equal area
2432 polar = 2 * asin(radius / kProjScaleArea) * 180 / pi
2433 break
2434 case kProjGnom: // gnomonic
2435 polar = atan(radius / kProjScaleGnom) * 180 / pi
2436 break
2437 case kProjOrtho: // orthographic
2438 polar = asin(radius / kProjScaleOrtho) * 180 / pi
2439 break
2440 default: // equidistant
2441 polar = 90 * radius / kProjScaleDist
2442 endswitch
2443
2444 return polar
2445end
2446
2467threadsafe function calc_graph_azi(x, y, [projection,zeroAngle])
2468 variable x
2469 variable y
2470 variable projection
2471 variable zeroAngle
2472
2473 if (ParamIsDefault(projection))
2474 projection = 1
2475 endif
2476 if (ParamIsDefault(zeroAngle))
2477 zeroAngle = 0
2478 endif
2479
2480 variable azi
2481 if (x > 0)
2482 azi = atan(y / x) * 180 / pi
2483 else
2484 azi = atan(y / x) * 180 / pi + 180
2485 endif
2486
2487 azi += zeroAngle
2488 if (azi < 0)
2489 azi += 360
2490 endif
2491 if (azi >= 360)
2492 azi -= 360
2493 endif
2494 if (numtype(azi) != 0)
2495 azi = 0
2496 endif
2497
2498 return azi
2499end
2500
2512static function update_polar_info(graphname)
2513 string graphname
2514
2515 dfref savedf = GetDataFolderDFR()
2516
2517 string graphdf = "root:packages:WMPolarGraphs:" + graphname
2518 setdatafolder graphdf
2519
2520 nvar csrA_theta
2521 nvar csrA_phi
2522 nvar csrB_theta
2523 nvar csrB_phi
2524
2525 string sproj = GetUserData(graphname, "", "projection")
2526 variable projection = str2num("0" + sproj)
2527 nvar zeroAngleWhere
2528
2529 variable x = hcsr(A, graphname)
2530 variable y = vcsr(A, graphname)
2531 csrA_theta = calc_graph_polar(x, y, projection=projection)
2532 csrA_phi = calc_graph_azi(x, y, projection=projection, zeroAngle=zeroAngleWhere)
2533
2534 x = hcsr(B, graphname)
2535 y = vcsr(B, graphname)
2536 csrB_theta = calc_graph_polar(x, y, projection=projection)
2537 csrB_phi = calc_graph_azi(x, y, projection=projection, zeroAngle=zeroAngleWhere)
2538
2539 setdatafolder savedf
2540end
2541
2547static function polar_graph_hook(s)
2548 STRUCT WMWinHookStruct &s
2549
2550 Variable hookResult = 0
2551
2552 switch(s.eventCode)
2553 case 7: // cursor moved
2554 update_polar_info(s.winname)
2555 break
2556 case 20: // show info
2557 TextBox /W=$s.winname /N=tb_angles /C /V=1
2558 break
2559 case 21: // hide info
2560 TextBox /W=$s.winname /N=tb_angles /C /V=0
2561 break
2562 endswitch
2563
2564 return hookResult // 0 if nothing done, else 1
2565end
2566
2567function set_polar_graph_cursor(nickname, cursorname, polar_angle, azim_angle, [graphname])
2568 string nickname
2569 string cursorname
2570 variable polar_angle
2571 variable azim_angle
2572 string graphname
2573
2574 if (ParamIsDefault(graphname))
2575 if (strlen(nickname) > 0)
2576 graphname = nickname
2577 else
2578 graphname = GetDataFolder(0)
2579 endif
2580 endif
2581
2582 string s_prefix = ""
2583 string s_int = "values"
2584 dfref df = find_hemi_data(nickname, s_prefix, s_int)
2585
2586 string s_polar = s_prefix + "pol"
2587 string s_azim = s_prefix + "az"
2588 wave /sdfr=df /z azim = $s_azim
2589 wave /sdfr=df /z polar = $s_polar
2590
2591 FindLevel /P /Q polar, polar_angle
2592 if (v_flag == 0)
2593 variable polar_level = floor(v_levelx)
2594 FindLevel /P /Q /R=[polar_level] azim, azim_angle
2595 if (v_flag == 0)
2596 variable azim_level = round(v_levelx)
2597 string tracename = "polarY0"
2598 Cursor /W=$graphname /P $cursorname $traceName azim_level
2599 endif
2600 endif
2601end
2602
2603
2637function hemi_add_anglescan(nickname, values, polar, azi, [weights])
2638 string nickname
2639 wave values
2640 wave polar
2641 wave azi
2642 wave weights
2643
2644 dfref savedf = GetDataFolderDFR()
2645
2646 if (ParamIsDefault(weights))
2647 duplicate /free values, weights
2648 weights = 1
2649 endif
2650
2651 string s_prefix = ""
2652 string s_int = "values"
2653 dfref df = find_hemi_data(nickname, s_prefix, s_int)
2654
2655 string s_totals = s_prefix + "tot"
2656 string s_weights = s_prefix + "wt"
2657 string s_polar = s_prefix + "pol"
2658 string s_azim = s_prefix + "az"
2659 string s_index = s_prefix + "index"
2660 string s_theta = s_prefix + "th"
2661 string s_dphi = s_prefix + "dphi"
2662 string s_nphis = s_prefix + "nphis"
2663
2664 wave /sdfr=df w_polar = $s_polar
2665 wave /sdfr=df w_azim = $s_azim
2666 wave /sdfr=df w_values = $s_int
2667 wave /sdfr=df w_totals = $s_totals
2668 wave /sdfr=df w_weights = $s_weights
2669 wave /sdfr=df w_index = $s_index
2670 wave /sdfr=df w_theta = $s_theta
2671 wave /sdfr=df w_dphi = $s_dphi
2672 wave /sdfr=df w_nphis = $s_nphis
2673
2674 // make internal copies of input, one-dimensional, ordered in theta
2675 duplicate /free values, values_copy
2676 duplicate /free polar, polar_copy
2677 duplicate /free azi, azi_copy
2678 duplicate /free weights, weights_copy
2679 variable nn = dimsize(values, 0) * max(dimsize(values, 1), 1)
2680 redimension /n=(nn) values_copy, polar_copy, azi_copy, weights_copy
2681 sort /r polar_copy, polar_copy, azi_copy, values_copy, weights_copy
2682
2683 make /n=(numpnts(w_theta)) /free /df dfw
2684 // for debugging: remove the MultiThread keyword and the ThreadSafe keywords of sub-functions
2685 MultiThread dfw = add_anglescan_worker(p, values_copy, weights_copy, polar_copy, azi_copy, w_polar, w_azim, w_theta, w_index, w_dphi, w_nphis)
2686
2687 variable pp
2688 for (pp = 0; pp < numpnts(dfw); pp += 1)
2689 dfref tdf= dfw[pp]
2690 wave df_totals = tdf:w_totals
2691 wave df_weights = tdf:w_weights
2692 w_totals += df_totals
2693 w_weights += df_weights
2694 endfor
2695 w_values = w_weights > 0 ? w_totals / w_weights : nan
2696
2697 SetDataFolder savedf
2698end
2699
2711threadsafe static function /df add_anglescan_worker(ith, values, weights, polar, azi, w_polar, w_azim, w_theta, w_index, w_dphi, w_nphis)
2712 variable ith // index into w_theta
2713 wave values // input data: intensity/counts
2714 wave weights // input data: weights/dwell time
2715 wave polar // input data: polar angles
2716 wave azi // input data: azimuthal angles
2717 wave w_polar // hemi grid
2718 wave w_azim // hemi grid
2719 wave w_theta // hemi grid
2720 wave w_index // hemi grid
2721 wave w_dphi // hemi grid
2722 wave w_nphis // hemi grid
2723
2724 dfref savedf= GetDataFolderDFR()
2725 dfref freedf= NewFreeDataFolder()
2726 SetDataFolder freedf
2727 make /n=(numpnts(w_polar)) /d w_totals, w_weights
2728
2729 variable pol = w_theta[ith]
2730 variable pol_st = abs(w_theta[1] - w_theta[0])
2731 variable pol1 = pol - pol_st / 2
2732 variable pol2 = pol + pol_st / 2
2733
2734 extract /free /indx polar, sel, (pol1 < polar) && (polar <= pol2) && (numtype(values) == 0) && (weights > 0)
2735 if (numpnts(sel) > 0)
2736 duplicate /free /r=[0, numpnts(sel)-1] azi, azi_slice
2737 duplicate /free /r=[0, numpnts(sel)-1] values, values_slice
2738 duplicate /free /r=[0, numpnts(sel)-1] weights, weights_slice
2739 azi_slice = azi[sel]
2740 values_slice = values[sel]
2741 weights_slice = weights[sel]
2742 add_aziscan_core(values_slice, weights_slice, pol, azi_slice, w_theta, w_azim, w_index, w_dphi, w_totals, w_weights)
2743 endif
2744
2745 SetDataFolder savedf
2746 return freedf
2747end
2748
2761threadsafe static function add_aziscan_core(values, weights, polar, azi, w_theta, w_azim, w_index, w_dphi, w_totals, w_weights)
2762 wave values // input data: intensity/counts
2763 wave weights // input data: weights/dwell time
2764 variable polar // input data: polar angle
2765 wave azi // input data: angle positions of the azimuthal scan
2766 // acceptable range: >= -360 and < +360
2767 // no specific order required, the function sorts the array in place (!)
2768 wave w_theta // hemi grid
2769 wave w_azim // hemi grid
2770 wave w_index // hemi grid
2771 wave w_dphi // hemi grid
2772 wave w_totals // output data: total counts in hemi grid order
2773 wave w_weights // output data: total weights in hemi grid order
2774
2775 // destination slice coordinates
2776 variable ipol = BinarySearch(w_theta, polar)
2777 if (ipol < 0)
2778 return -1
2779 endif
2780
2781 variable d1, d2
2782 if (ipol >= 1)
2783 d1 = w_index[ipol - 1]
2784 else
2785 d1 = 0
2786 endif
2787 d2 = w_index[ipol] - 1
2788 variable nd = d2 - d1 + 1
2789 variable dphi = w_dphi[ipol]
2790 make /n=(nd+1) /free bin_index
2791 setscale /i x w_azim[d1] - dphi/2, w_azim[d2] + dphi/2, "deg", bin_index
2792
2793 // source slice coordinates
2794 // order the slice from -dphi/2 to 360-dphi/2
2795 azi = azi < 0 ? azi + 360 : azi
2796 azi = azi >= 360 - dphi/2 ? azi - 360 : azi
2797 sort azi, values, weights, azi
2798 setscale /p x 0, 1, "", values, weights, azi
2799
2800 bin_index = BinarySearch(azi, x) + 1
2801 bin_index = bin_index == -2 ? 0 : bin_index[p]
2802 bin_index = bin_index == -1 ? numpnts(azi) : bin_index[p]
2803 bin_index[nd] = numpnts(azi)
2804
2805 // loop over destination
2806 variable id
2807 variable v1, v2, w1, w2
2808 for (id = 0; id < nd; id += 1)
2809 if (bin_index[id+1] > bin_index[id])
2810 v1 = w_totals[d1 + id]
2811 w1 = w_weights[d1 + id]
2812 if ((numtype(v1) == 2) || (w1 <= 0))
2813 v1 = 0
2814 w1 = 0
2815 endif
2816 v2 = sum(values, bin_index[id], bin_index[id+1] - 1)
2817 w2 = sum(weights, bin_index[id], bin_index[id+1] - 1)
2818 w_totals[d1 + id] = v1 + v2
2819 w_weights[d1 + id] = w1 + w2
2820 endif
2821 endfor
2822end
2823
2844function hemi_add_aziscan(nickname, values, polar, azi, [weights])
2845 string nickname
2846 wave values
2847 variable polar
2848 wave azi
2849 wave weights
2850
2851 dfref savedf = GetDataFolderDFR()
2852
2853 duplicate /free values, values_copy
2854 duplicate /free azi, azi_copy
2855 if (ParamIsDefault(weights))
2856 duplicate /free values, weights_copy
2857 weights_copy = 1
2858 else
2859 duplicate /free weights, weights_copy
2860 endif
2861
2862 // hemi grid waves
2863 string s_prefix = ""
2864 string s_int = "values"
2865 dfref df = find_hemi_data(nickname, s_prefix, s_int)
2866
2867 string s_totals = s_prefix + "tot"
2868 string s_weights = s_prefix + "wt"
2869 string s_polar = s_prefix + "pol"
2870 string s_azim = s_prefix + "az"
2871 string s_index = s_prefix + "index"
2872 string s_theta = s_prefix + "th"
2873 string s_dphi = s_prefix + "dphi"
2874 string s_nphis = s_prefix + "nphis"
2875
2876 wave /sdfr=df w_polar = $s_polar
2877 wave /sdfr=df w_azim = $s_azim
2878 wave /sdfr=df w_values = $s_int
2879 wave /sdfr=df w_totals = $s_totals
2880 wave /sdfr=df w_weights = $s_weights
2881 wave /sdfr=df w_index = $s_index
2882 wave /sdfr=df w_theta = $s_theta
2883 wave /sdfr=df w_dphi = $s_dphi
2884 wave /sdfr=df w_nphis = $s_nphis
2885
2886 add_aziscan_core(values_copy, weights_copy, polar, azi_copy, w_theta, w_azim, w_index, w_dphi, w_totals, w_weights)
2887
2888 w_values = w_weights > 0 ? w_totals / w_weights : nan
2889
2890 SetDataFolder savedf
2891end
2892
2920function interpolate_hemi_scan(nickname, [projection])
2921 string nickname
2922 variable projection
2923
2924 dfref savedf = GetDataFolderDFR()
2925
2926 if (ParamIsDefault(projection))
2927 projection = 1
2928 endif
2929
2930 string s_prefix = ""
2931 string s_int = "values"
2932 dfref df = find_hemi_data(nickname, s_prefix, s_int)
2933 prepare_hemi_scan_display(nickname, projection=projection)
2934
2935 string s_polar = s_prefix + "pol"
2936 string s_azim = s_prefix + "az"
2937 string s_matrix = s_prefix + "matrix"
2938 string s_ster_rad = s_prefix + "ster_rad"
2939 string s_ster_x = s_prefix + "ster_x"
2940 string s_ster_y = s_prefix + "ster_y"
2941
2942 wave /sdfr=df /z values = $s_int
2943 wave /sdfr=df /z azim = $s_azim
2944 wave /sdfr=df /z polar = $s_polar
2945 wave /sdfr=df /z ster_rad = $s_ster_rad
2946 wave /sdfr=df /z ster_x = $s_ster_x
2947 wave /sdfr=df /z ster_y = $s_ster_y
2948
2949 variable min_ster_x = wavemin(ster_x)
2950 variable max_ster_x = wavemax(ster_x)
2951 variable x0 = min_ster_x
2952 variable xn = 181
2953 variable dx = (max_ster_x - min_ster_x) / (xn - 1)
2954 make /n=(numpnts(ster_x), 3) /free triplet
2955 triplet[][0] = ster_x[p]
2956 triplet[][1] = ster_y[p]
2957 triplet[][2] = values[p]
2958
2959 variable size = 181
2960 setdatafolder df
2961 make /n=(size, size) /d /o $(s_prefix + "matrix") /wave=matrix
2962 make /n=(size, size) /free mnorm
2963 ImageFromXYZ /as {ster_x, ster_y, values}, matrix, mnorm
2964 matrix /= mnorm
2965 matrixfilter NanZapMedian, matrix
2966 matrixfilter gauss, matrix
2967
2968 duplicate /free values, ster_finite
2969 ster_finite = (numtype(values) == 0) * (ster_x^2 + ster_y^2)
2970 variable ster_max = wavemax(ster_finite)
2971 matrix = (x^2 + y^2) <= ster_max ? matrix : nan
2972
2973 setdatafolder savedf
2974end
2975
2986function quick_pizza_image(data, nickname, theta_offset, tilt_offset, phi_offset, [npolar, nograph, folding])
2987 wave data // 2D intensity wave, see requirements above
2988 string nickname // nick name for output data
2989 // in default mode, this will be the name of a child folder containing the output
2990 // in XPDplot mode, this will be a prefix of the generated data in the root folder
2991 variable theta_offset // manipulator theta angle corresponding to normal emission
2992 variable tilt_offset // manipulator tilt angle corresponding to normal emission
2993 variable phi_offset // manipulator phi angle corresponding to phi_result = 0
2994 variable npolar // number of polar angles, determines polar and azimuthal step size
2995 // default = 91 (1 degree steps)
2996 variable nograph // 0 (default) = display a new polar graph
2997 // 1 = don't display a new graph (if a graph is existing from a previous call, it will update)
2998 variable folding // rotational averaging, default = 1
2999
3000 if (ParamIsDefault(npolar))
3001 npolar = 91
3002 endif
3003 if (ParamIsDefault(nograph))
3004 nograph = 0
3005 endif
3006 if (ParamIsDefault(folding))
3007 folding = 1
3008 endif
3009 string graphname = "graph_" + nickname
3010 string s_prefix = ""
3011
3012 // sort out data folder structure
3013 dfref saveDF = GetDataFolderDFR()
3014 dfref dataDF = GetWavesDataFolderDFR(data)
3015 setdatafolder dataDF
3016 if (DataFolderExists(":attr"))
3017 setdatafolder :attr
3018 endif
3019 dfref attrDF = GetDataFolderDFR()
3020 setdatafolder dataDF
3021 newdatafolder /s/o $nickname
3022 dfref destDF = GetDataFolderDFR()
3023
3024 // performance monitoring
3025 variable timerRefNum
3026 variable /g xyz_perf_secs
3027 timerRefNum = startMSTimer
3028
3029 wave /sdfr=attrDF ManipulatorTheta
3030 wave /sdfr=attrDF ManipulatorTilt
3031 wave /sdfr=attrDF ManipulatorPhi
3032 duplicate /free ManipulatorTheta, m_theta
3033 duplicate /free ManipulatorTilt, m_tilt
3034 duplicate /free ManipulatorPhi, m_phi
3035 m_theta -= theta_offset
3036 m_tilt -= tilt_offset
3037 m_tilt *= -1 // checked 140702
3038 m_phi -= phi_offset
3039 //m_phi *= -1 // checked 140702
3040
3041 make /n=1/d/free d_polar, d_azi
3042 convert_angles_ttpd2polar(m_theta, m_tilt, m_phi, data, d_polar, d_azi)
3043 d_azi += 180 // changed 151030 (v1.6)
3044 d_azi = d_azi >= 360 ? d_azi - 360 : d_azi
3045
3046 duplicate /free data, values
3047 variable nn = dimsize(values, 0) * max(dimsize(values, 1), 1)
3048 redimension /n=(nn) values, d_polar, d_azi
3049 duplicate /o d_polar, ster_rad, ster_x, ster_y
3050
3051 variable projection = 1
3052 switch(projection)
3053 case 1: // stereographic
3054 ster_rad = 2 * tan(d_polar / 2 * pi / 180)
3055 break
3056 case 2: // azimuthal
3057 ster_rad = 2 * cos((180 - d_polar) / 2 * pi / 180)
3058 break
3059 endswitch
3060 string s_ster_x = s_prefix + "ster_x"
3061 string s_ster_y = s_prefix + "ster_y"
3062
3063 nn = 401
3064 make /n=(nn, nn) /d /o matrix
3065 make /n=(nn, nn) /free mnorm
3066 setscale /i x -2, +2, matrix, mnorm
3067 setscale /i y -2, +2, matrix, mnorm
3068 matrix = 0
3069 mnorm = 0
3070
3071 variable ifold
3072 for (ifold = 0; ifold < folding; ifold += 1)
3073 ster_x = ster_rad * cos(d_azi * pi / 180)
3074 ster_y = ster_rad * sin(d_azi * pi / 180)
3075 ImageFromXYZ {ster_x, ster_y, values}, matrix, mnorm
3076 d_azi = d_azi >= 180 ? d_azi + 360 / folding - 180 : d_azi + 360 / folding
3077 endfor
3078
3079 matrix /= mnorm
3080 matrixfilter /n=5 NanZapMedian matrix
3081 matrixfilter /n=3 gauss matrix
3082
3083 if (!nograph)
3084 display /k=1
3085 appendimage matrix
3086 modifygraph width={Plan,1,bottom,left}
3087 endif
3088
3089 if (timerRefNum >= 0)
3090 xyz_perf_secs = stopMSTimer(timerRefNum) / 1e6
3091 endif
3092
3093 setdatafolder saveDF
3094end
3095
3097function save_hemi_scan(nickname, pathname, filename)
3098 string nickname
3099 string pathname
3100 string filename
3101
3102 dfref savedf = getdatafolderdfr()
3103
3104 // source data
3105 string s_prefix = ""
3106 string s_int = "values"
3107 dfref df = find_hemi_data(nickname, s_prefix, s_int)
3108
3109 string s_polar = s_prefix + "pol"
3110 string s_azim = s_prefix + "az"
3111 string s_theta = s_prefix + "th"
3112 string s_tot = s_prefix + "tot"
3113 string s_weight = s_prefix + "wt"
3114
3115 wave /sdfr=df theta1 = $s_theta
3116 wave /sdfr=df polar1 = $s_polar
3117 wave /sdfr=df azim1 = $s_azim
3118 wave /sdfr=df tot1 = $s_tot
3119 wave /sdfr=df weight1 = $s_weight
3120 wave /sdfr=df values1 = $s_int
3121
3122 save /m="\r\n" /o /p=$pathname /t theta1, polar1, azim1, tot1, weight1, values1 as filename
3123
3124 setdatafolder saveDF
3125end
3126
3130function load_hemi_scan(nickname, pathname, filename)
3131 string nickname
3132 string pathname
3133 string filename
3134
3135 dfref savedf = getdatafolderdfr()
3136
3137 //loadwave /p=$pathname /t theta1, polar1, azim1, tot1, weight1, values1 as filename
3138 //LoadWave /t/p=pearl_explorer_filepath/q filename
3139 //svar waves = s_wavenames
3140 //if (v_flag > 0)
3141 // string /g pearl_explorer_import = "load_itx_file"
3142 //endif
3143
3144 setdatafolder saveDF
3145end
3146
3179function import_tpi_scan(nickname, theta, phi, intensity, [folding, npolar, nograph, xpdplot])
3180 string nickname
3181 wave theta
3182 wave phi
3183 wave intensity
3184
3185 variable folding
3186 variable npolar
3187 variable nograph
3188 variable xpdplot
3189
3190 if (ParamIsDefault(npolar))
3191 npolar = 91
3192 endif
3193 if (ParamIsDefault(nograph))
3194 nograph = 0
3195 endif
3196 if (ParamIsDefault(folding))
3197 folding = 1
3198 endif
3199 if (ParamIsDefault(xpdplot))
3200 xpdplot = 0
3201 endif
3202
3203 make_hemi_grid(npolar, nickname, xpdplot=xpdplot)
3204
3205 variable ifold
3206 duplicate /free phi, fold_phi
3207 for (ifold = 0; ifold < folding; ifold += 1)
3208 fold_phi = fold_phi >= 360 ? fold_phi - 360 : fold_phi
3209 hemi_add_anglescan(nickname, intensity, theta, fold_phi)
3210 fold_phi += 360 / folding
3211 endfor
3212
3213 if (nograph==0)
3214 display_hemi_scan(nickname)
3215 endif
3216end
3217
3229function trim_hemi_scan(nickname, theta_max)
3230 string nickname
3231 variable theta_max
3232
3233 string s_prefix = ""
3234 string s_int = "values"
3235 dfref df = find_hemi_data(nickname, s_prefix, s_int)
3236
3237 string s_totals = s_prefix + "tot"
3238 string s_weights = s_prefix + "wt"
3239 string s_polar = s_prefix + "pol"
3240
3241 wave /sdfr=df w_polar = $s_polar
3242 wave /sdfr=df w_values = $s_int
3243 wave /sdfr=df w_totals = $s_totals
3244 wave /sdfr=df w_weights = $s_weights
3245
3246 w_values = w_polar <= theta_max ? w_totals / w_weights : nan
3247end
3248
3268function /wave hemi_polar_cut(nickname, azim)
3269 string nickname
3270 variable azim
3271
3272 dfref savedf = getdatafolderdfr()
3273 string s_prefix = ""
3274 string s_int = "values"
3275 dfref df = find_hemi_data(nickname, s_prefix, s_int)
3276
3277 string s_totals = s_prefix + "tot"
3278 string s_weights = s_prefix + "wt"
3279 string s_polar = s_prefix + "pol"
3280 string s_azim = s_prefix + "az"
3281 string s_index = s_prefix + "index"
3282 string s_theta = s_prefix + "th"
3283 string s_dphi = s_prefix + "dphi"
3284 string s_nphis = s_prefix + "nphis"
3285 string s_cut
3286 sprintf s_cut, "%s_azi%03u", s_int, round(azim)
3287
3288 wave /sdfr=df w_polar = $s_polar
3289 wave /sdfr=df w_azim = $s_azim
3290 wave /sdfr=df w_values = $s_int
3291 wave /sdfr=df w_totals = $s_totals
3292 wave /sdfr=df w_weights = $s_weights
3293 wave /sdfr=df w_index = $s_index
3294 wave /sdfr=df w_theta = $s_theta
3295 wave /sdfr=df w_dphi = $s_dphi
3296 wave /sdfr=df w_nphis = $s_nphis
3297
3298 variable npol = numpnts(w_theta)
3299 variable ipol
3300 variable pol_st = abs(w_theta[1] - w_theta[0])
3301 variable pol
3302 variable pol1, pol2
3303 variable nsel
3304
3305 setdatafolder df
3306 make /n=(npol) /o $s_cut
3307 wave w_cut = $s_cut
3308 setscale /i x w_theta[0], w_theta[numpnts(w_theta)-1], "deg", w_cut
3309 make /n=1 /free azi_slice
3310 make /n=1 /free values_slice
3311
3312 for (ipol = 0; ipol < npol; ipol += 1)
3313 pol = w_theta[ipol]
3314 pol1 = pol - pol_st / 2
3315 pol2 = pol + pol_st / 2
3316 extract /free /indx w_polar, sel, (pol1 < w_polar) && (w_polar <= pol2)
3317 nsel = numpnts(sel)
3318 if (nsel > 0)
3319 redimension /n=(nsel+2) azi_slice, values_slice
3320 azi_slice[1, nsel] = w_azim[sel[p-1]]
3321 azi_slice[0] = azi_slice[nsel] - 360
3322 azi_slice[nsel+1] = azi_slice[1] + 360
3323 values_slice[1, nsel] = w_values[sel[p-1]]
3324 values_slice[0] = values_slice[nsel]
3325 values_slice[nsel+1] = values_slice[1]
3326 w_cut[ipol] = interp(azim, azi_slice, values_slice)
3327 else
3328 w_cut[ipol] = nan
3329 endif
3330 endfor
3331
3332 setdatafolder savedf
3333 return w_cut
3334end
3335
3354function /wave hemi_azi_cut(nickname, pol)
3355 string nickname
3356 variable pol
3357
3358 dfref savedf = getdatafolderdfr()
3359 string s_prefix = ""
3360 string s_int = "values"
3361 dfref df = find_hemi_data(nickname, s_prefix, s_int)
3362
3363 string s_totals = s_prefix + "tot"
3364 string s_weights = s_prefix + "wt"
3365 string s_polar = s_prefix + "pol"
3366 string s_azim = s_prefix + "az"
3367 string s_index = s_prefix + "index"
3368 string s_theta = s_prefix + "th"
3369 string s_dphi = s_prefix + "dphi"
3370 string s_nphis = s_prefix + "nphis"
3371 string s_cut
3372 sprintf s_cut, "%s_pol%03u", s_int, round(pol)
3373
3374 wave /sdfr=df w_polar = $s_polar
3375 wave /sdfr=df w_azim = $s_azim
3376 wave /sdfr=df w_values = $s_int
3377 wave /sdfr=df w_totals = $s_totals
3378 wave /sdfr=df w_weights = $s_weights
3379 wave /sdfr=df w_index = $s_index
3380 wave /sdfr=df w_theta = $s_theta
3381 wave /sdfr=df w_dphi = $s_dphi
3382 wave /sdfr=df w_nphis = $s_nphis
3383
3384 variable pol_st = abs(w_theta[1] - w_theta[0])
3385 variable pol1, pol2
3386 variable nsel
3387
3388 pol1 = pol - pol_st / 2
3389 pol2 = pol + pol_st / 2
3390 extract /free /indx w_polar, sel, (pol1 < w_polar) && (w_polar <= pol2)
3391 nsel = numpnts(sel)
3392 if (nsel > 0)
3393 setdatafolder df
3394 make /n=(nsel) /o $s_cut
3395 wave w_cut = $s_cut
3396 w_cut = w_values[sel]
3397 setscale /i x w_azim[sel[0]], w_azim[sel[nsel-1]], "°", w_cut
3398 setdatafolder savedf
3399 return w_cut
3400 else
3401 setdatafolder savedf
3402 return $""
3403 endif
3404 setdatafolder savedf
3405end
3406
3407static function check_contrast(values, pcmin, pcmax, vmin, vmax, sym)
3408 wave values
3409 variable pcmin
3410 variable pcmax
3411 variable &vmin
3412 variable &vmax
3413 variable sym
3414
3415 dfref save_df = GetDataFolderDFR()
3416 dfref dfr = NewFreeDataFolder()
3417 setdatafolder dfr
3418 StatsQuantiles /inan /iw /q /z values
3419 wave /z index = w_quantilesindex
3420 setdatafolder save_df
3421
3422 if (waveexists(index))
3423 variable imin = round(numpnts(index) * pcmin / 100)
3424 variable imax = round(numpnts(index) * (100 - pcmax) / 100)
3425 vmin = values[index[imin]]
3426 vmax = values[index[imax]]
3427 if (sym)
3428 variable d = vmax - vmin
3429 if ((vmax >= d/4) && (-vmin >= d/4))
3430 vmax = min(abs(vmin), abs(vmax))
3431 vmin = -vmax
3432 endif
3433 endif
3434 else
3435 vmin = wavemin(values)
3436 vmax = wavemax(values)
3437 endif
3438end
3439
3463function set_contrast(pcmin, pcmax, [graphname, colortable, reversecolors, symmetric])
3464 variable pcmin
3465 variable pcmax
3466 string graphname
3467 string colortable
3468 variable reversecolors
3469 variable symmetric
3470
3471 if (ParamIsDefault(graphname))
3472 graphname = ""
3473 endif
3474 if (ParamIsDefault(colortable))
3475 colortable = ""
3476 endif
3477 if (ParamIsDefault(reversecolors))
3478 reversecolors = 0
3479 endif
3480 if (ParamIsDefault(symmetric))
3481 symmetric = 0
3482 endif
3483
3484 dfref save_df = GetDataFolderDFR()
3485
3486 string objname
3487 string info
3488 string wname
3489 string ctab
3490 variable rev
3491 variable n
3492 variable i
3493 variable vmin
3494 variable vmax
3495
3496 string traces = TraceNameList(graphname, ";", 1+4)
3497 n = ItemsInList(traces, ";")
3498 for (i = 0; i < n; i += 1)
3499 objname = StringFromList(i, traces, ";")
3500 info = TraceInfo(graphname, objname, 0)
3501 if (strlen(info) > 0)
3502 info = StringByKey("RECREATION", info, ":", ";")
3503 info = StringByKey("zColor(x)", info, "=", ";")
3504 if (strlen(info) > 2)
3505 info = info[1,strlen(info)-2]
3506 wname = StringFromList(0, info, ",")
3507 wave w = $wname
3508 ctab = StringFromList(3, info, ",")
3509 rev = str2num("0" + StringFromList(4, info, ","))
3510 if (strlen(colortable) > 0)
3511 ctab = colortable
3512 rev = reversecolors
3513 endif
3514 check_contrast(w, pcmin, pcmax, vmin, vmax, symmetric)
3515 if (vmax > vmin)
3516 ModifyGraph /w=$graphname zColor($objname)={w, vmin, vmax, $ctab, rev}
3517 endif
3518 endif
3519 endif
3520 endfor
3521
3522 string images = ImageNameList(graphname, ";")
3523 n = ItemsInList(images, ";")
3524 for (i = 0; i < n; i += 1)
3525 objname = StringFromList(i, images, ";")
3526 wave w = ImageNameToWaveRef(graphname, objname)
3527 info = ImageInfo(graphname, objname, 0)
3528 if (strlen(info) > 0)
3529 info = StringByKey("RECREATION", info, ":", ";")
3530 info = StringByKey("ctab", info, "=", ";")
3531 if (strlen(info) > 2)
3532 info = info[1,strlen(info)-2]
3533 ctab = StringFromList(2, info, ",")
3534 rev = str2num("0" + StringFromList(3, info, ","))
3535 if (strlen(colortable) > 0)
3536 ctab = colortable
3537 rev = reversecolors
3538 endif
3539 check_contrast(w, pcmin, pcmax, vmin, vmax, symmetric)
3540 if (vmax > vmin)
3541 ModifyImage /w=$graphname $objname ctab={vmin, vmax, $ctab, rev}
3542 endif
3543 endif
3544 endif
3545 endfor
3546
3547 setdatafolder save_df
3548end
3549
3562Function AngleToK(inwave)
3563 Wave inwave
3564 String newname = NameofWave(inwave)+"_k"
3565 Duplicate/O inwave, $newname
3566 Wave outwave = $newname
3567 Variable rows,columns,xdelta,xoffset,ydelta,yoffset,kmin,kmax,Emax
3568 // inwave parameters
3569 rows = DimSize(inwave,0)
3570 columns = DimSize(inwave,1)
3571 xdelta = DimDelta(inwave,0)
3572 xoffset = DimOffset(inwave,0)
3573 ydelta = DimDelta(inwave,1)
3574 yoffset = DimOffset(inwave,1)
3575 Emax= xoffset + xdelta*(rows-1)
3576 kmin = 0.5123*sqrt(Emax)*sin(pi/180*(yoffset)) // calculate the k boundaries
3577 kmax = 0.5123*sqrt(Emax)*sin(pi/180*(yoffset+(columns-1)*ydelta))
3578 SetScale/I y kmin,kmax,"Ang^-1", outwave
3579 // scale the y axis
3580 outwave = interp2D(inwave, x, 180/pi*asin(y/ (0.5123*sqrt(x)))) // recalculate to k
3581 outwave = (NumType(outwave)==2) ? 0 : outwave // replace NaNs (optional)
3582End
processing and holographic mapping of angle scanned XPD data.
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
static const variable kProjScaleDist
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
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.
string get_hemi_prefix(wave w)
finds the prefix given any hemi wave
static variable update_polar_info(string graphname)
update the angles info based on cursors A and B of a given polar graph window
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.
static variable Calc_The_step(variable th, variable Theta_st, string Holomode)
calculate delta-theta for a given theta
const variable kProjArea
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
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.
const variable kProjOrtho
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.
variable clear_hemi_grid(string nickname)
clear a hemispherical scan grid
variable hemi_add_aziscan(string nickname, wave values, variable polar, wave azi, wave weights=defaultValue)
add azimuthal data to a hemispherical scan grid.
static string display_polar_graph(string graphname, variable angle_offset=defaultValue, variable do_ticks=defaultValue)
displays an empty polar graph
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.
variable save_hemi_scan(string nickname, string pathname, string filename)
save a hemispherical scan to an Igor text file
variable hemi_add_anglescan(string nickname, wave values, wave polar, wave azi, wave weights=defaultValue)
add arbitrary angle scan data to a hemispherical scan grid.
const variable kProjGnom
threadsafe variable calc_graph_azi(variable x, variable y, variable projection=defaultValue, variable zeroAngle=defaultValue)
calculate azimuthal angle from Cartesian coordinate
variable rotate_hemi_scan(string nickname, variable angle)
azimuthally rotate a hemispherical scan dataset.
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
variable trim_hemi_scan(string nickname, variable theta_max)
trim a hemispherical scan at grazing angle
static variable check_contrast(wave values, variable pcmin, variable pcmax, variable *vmin, variable *vmax, variable sym)
variable set_polar_graph_cursor(string nickname, string cursorname, variable polar_angle, variable azim_angle, string graphname=defaultValue)
threadsafe variable calc_graph_radius(variable polar, variable projection=defaultValue)
calculate the projected polar angle
variable load_hemi_scan(string nickname, string pathname, string filename)
load a hemispherical scan from an Igor text file
static threadsafe dfr add_anglescan_worker(variable ith, wave values, wave weights, wave polar, wave azi, wave w_polar, wave w_azim, wave w_theta, wave w_index, wave w_dphi, wave w_nphis)
thread worker for hemi_add_anglescan
static threadsafe variable add_aziscan_core(wave values, wave weights, variable polar, wave azi, wave w_theta, wave w_azim, wave w_index, wave w_dphi, wave w_totals, wave w_weights)
thread worker for hemi_add_anglescan and hemi_add_aziscan
variable make_hemi_grid(variable npol, string nickname, variable xpdplot=defaultValue)
create a hemispherical, constant solid angle grid
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
string get_hemi_nickname(wave w)
finds the nick name given any hemi wave
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.
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
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.
dfr find_hemi_data(string nickname, string *prefix, string *intwave)
finds the folder, prefix and name of holo waves given their nick name
wave hemi_polar_cut(string nickname, variable azim)
extract a polar cut from a hemispherical scan.
static const variable kProjScaleOrtho
static variable line_average(wave source, wave dest)
variable duplicate_hemi_scan(string source_nickname, dfref dest_folder, string dest_nickname, variable xpdplot=defaultValue)
duplicate a hemispherical scan dataset.
variable crop_strip_theta(wave strip, variable theta_lo, variable theta_hi, wave theta, wave tilt, wave phi)
crop a strip in theta.
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).
const variable kProjDist
variable crop_strip(wave strip, variable xlo, variable xhi)
crop a strip at the sides.
static const variable kProjScaleGnom
wave hemi_azi_cut(string nickname, variable pol)
extract an azimuthal cut from a hemispherical scan
string strip_append(wave strip1, wave strip2)
append an angle scan strip to another one
static variable CalcN_Theta(string HoloMode, variable Theta_in, variable Theta_ran, variable Theta_st)
calculate the number of thetas for a pattern
const variable kProjStereo
string prepare_hemi_scan_display(string nickname, variable projection=defaultValue)
create waves for plotting a hemispherical angle scan.
static variable polar_graph_hook(WMWinHookStruct *s)
polar graph window hook
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.
variable interpolate_hemi_scan(string nickname, variable projection=defaultValue)
interpolate a hemispherical scan onto a rectangular grid
variable AngleToK(wave inwave)
k-space mapping of 2D angle-energy distribution (scienta image)
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.
threadsafe variable calc_graph_polar(variable x, variable y, variable projection=defaultValue)
calculate polar angle from Cartesian coordinate
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.
static const variable kProjScaleStereo
static string draw_hemi_axes(string graphname, variable do_grids=defaultValue)
draw polar and azimuthal grids in an existing polar graph.
variable set_contrast(variable pcmin, variable pcmax, string graphname=defaultValue, string colortable=defaultValue, variable reversecolors=defaultValue, variable symmetric=defaultValue)
set the pseudocolor contrast by percentile.
static const variable kProjScaleArea
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
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.
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.
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.
variable polar2cart_wave(wave in, wave out)
variable cart2polar_wave(wave in, wave out)
variable rotate_z_wave(wave inout, variable angle)
rotates a wave of 3-vectors about the z axis
variable rotate_x_wave(wave inout, variable angle)
rotate a wave of 3-vectors about the x axis.
variable rotate_y_wave(wave inout, variable angle)
rotates a wave of 3-vectors about the y axis