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
wave hemi_polar_cut(string nickname, variable azim)
extract a polar cut from a hemispherical scan.
variable trim_hemi_scan(string nickname, variable theta_max)
trim a hemispherical scan at grazing angle
string prepare_hemi_scan_display(string nickname, variable projection=defaultValue)
create waves for plotting a hemispherical angle scan.
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 AngleToK(wave inwave)
k-space mapping of 2D angle-energy distribution (scienta image)
static const variable kProjScaleOrtho
variable polar2cart_wave(wave in, wave out)
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.
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 crop_strip(wave strip, variable xlo, variable xhi)
crop a strip at the sides.
const variable kProjGnom
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 make_hemi_grid(variable npol, string nickname, variable xpdplot=defaultValue)
create a hemispherical, constant solid angle grid
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.
string get_hemi_nickname(wave w)
finds the nick name given any hemi wave
string get_hemi_prefix(wave w)
finds the prefix given any hemi wave
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 variable CalcN_Theta(string HoloMode, variable Theta_in, variable Theta_ran, variable Theta_st)
calculate the number of thetas for a pattern
dfr find_hemi_data(string nickname, string *prefix, string *intwave)
finds the folder, prefix and name of holo waves given their nick name
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.
variable clear_hemi_grid(string nickname)
clear a hemispherical scan grid
static const variable kProjScaleDist
threadsafe variable calc_graph_polar(variable x, variable y, variable projection=defaultValue)
calculate polar angle from Cartesian coordinate
static variable check_contrast(wave values, variable pcmin, variable pcmax, variable *vmin, variable *vmax)
static variable Calc_The_step(variable th, variable Theta_st, string Holomode)
calculate delta-theta for a given theta
const variable kProjArea
static variable line_average(wave source, wave dest)
threadsafe variable calc_graph_radius(variable polar, variable projection=defaultValue)
calculate the projected polar angle
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 rotate_x_wave(wave inout, variable angle)
rotate a wave of 3-vectors about the x axis.
variable cart2polar_wave(wave in, wave out)
variable crop_strip_theta(wave strip, variable theta_lo, variable theta_hi, wave theta, wave tilt, wave phi)
crop a strip in theta.
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.
wave hemi_azi_cut(string nickname, variable pol)
extract an azimuthal cut from a hemispherical scan
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.
variable interpolate_hemi_scan(string nickname, variable projection=defaultValue)
interpolate a hemispherical scan onto a rectangular grid
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.
variable hemi_add_aziscan(string nickname, wave values, variable polar, wave azi, wave weights=defaultValue)
add an azimuthal scan to a hemispherical scan grid.
static const variable kProjScaleGnom
variable rotate_y_wave(wave inout, variable angle)
rotates a wave of 3-vectors about the y axis
variable rotate_hemi_scan(string nickname, variable angle)
azimuthally rotate a hemispherical scan dataset.
static const variable kProjScaleStereo
processing and holographic mapping of angle scanned XPD data.
static string display_polar_graph(string graphname, variable angle_offset=defaultValue, variable do_ticks=defaultValue)
displays an empty polar graph
const variable kProjOrtho
variable save_hemi_scan(string nickname, string pathname, string filename)
save a hemispherical scan to an Igor text file
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).
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.
const variable kProjStereo
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
static variable polar_graph_hook(WMWinHookStruct *s)
polar graph window hook
const variable kProjDist
threadsafe variable calc_graph_azi(variable x, variable y, variable projection=defaultValue, variable zeroAngle=defaultValue)
calculate azimuthal angle from Cartesian coordinate
variable set_contrast(variable pcmin, variable pcmax, string graphname=defaultValue, string colortable=defaultValue)
set the pseudocolor contrast by percentile.
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.
variable rotate_z_wave(wave inout, variable angle)
rotates a wave of 3-vectors about the z axis
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
static const variable kProjScaleArea
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 ...
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.
static string draw_hemi_axes(string graphname, variable do_grids=defaultValue)
draw polar and azimuthal grids in an existing polar graph.
variable duplicate_hemi_scan(string source_nickname, dfref dest_folder, string dest_nickname, variable xpdplot=defaultValue)
duplicate a hemispherical scan dataset.
variable set_polar_graph_cursor(string nickname, string cursorname, variable polar_angle, variable azim_angle, string graphname=defaultValue)
static variable update_polar_info(string graphname)
update the angles info based on cursors A and B of a given polar graph window
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 load_hemi_scan(string nickname, string pathname, string filename)
load a hemispherical scan from an Igor text file
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.
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_x(wave strip, variable smooth_method=defaultValue, variable smooth_factor=defaultValue, variable check=defaultValue)
divide the strip by the average X distribution.