Skip to content

Commit

Permalink
Merge pull request #1 from ando-lab/dev-spm
Browse files Browse the repository at this point in the history
Dev spm
  • Loading branch information
spmeisburger authored Aug 25, 2022
2 parents 9e92dcd + 77f1d8f commit 191f367
Show file tree
Hide file tree
Showing 74 changed files with 32,442 additions and 62 deletions.
126 changes: 126 additions & 0 deletions +geom/@Profile/Profile.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
classdef Profile
%PROFILE a collection of methods for spot profile calculations
% <Detailed explanation goes here>

methods(Static)

function [idx,hkl_refl] = hkl2idx(h,k,l)
% assign each pixel an index to its nearest reflection
h = round(h);
k = round(k);
l = round(l);
[hkl_refl,~,ic] = unique([h(:),k(:),l(:)],'rows');
idx = reshape(ic,size(h));
end

function [e1,e2,e3] = s2e(s_refl,Source)
% calculate local coordinate system for each reflection
s0 = Source.wavevector;

e1 = zeros(size(s_refl));
e2 = zeros(size(s_refl));
e3 = zeros(size(s_refl));

for j=1:size(s_refl,1)
k1 = s0 + s_refl(j,:);
e1(j,:) = quickcross(k1,s0);
e1(j,:) = e1(j,:)/sqrt(quickdot(e1(j,:),e1(j,:)));

e2(j,:) = quickcross(k1,e1(j,:));
e2(j,:) = e2(j,:)/sqrt(quickdot(e2(j,:),e2(j,:)));

e3(j,:) = (k1 + s0);
e3(j,:) = e3(j,:)/sqrt(quickdot(e3(j,:),e3(j,:)));
end
end

function [phixy1,phixy2] = s2phi(s_refl,Source,Spindle,Detector)
% I changed how this works on 3/25/2019. It used to return:
% [phi, x, y] for whichever solution had the lowest value of
% |phi|.

s0 = Source.wavevector;
m2 = Spindle.rotationAxis;
f = Detector.f;
ed = Detector.ed;
[phixy1, phixy2] = calc_reflection_center(s0, m2, f, ed, s_refl);

% [c1,c2] = calc_reflection_center(s0, m2, f, ed, s_refl);
% all_phi = [c1(:,1),c2(:,1)];
% [~,ix] = min(abs(all_phi),[],2);
%
% c = c1;
% for j=1:size(all_phi,1)
% if ix(j)==2
% c(j,:) = c2(j,:);
% end
% end
%
% x = c(:,2);
% y = c(:,3);
% phi = c(:,1);
end

function [eps1,eps2] = s2eps(sx,sy,sz,idx,s,e1,e2,Source,Detector)

nrefl = size(s,1);

s0 = Source.wavevector;
ed = Detector.ed;

d1 = ed(:,1)';
d2 = ed(:,2)';
d3 = ed(:,3)';

krefl = s + repmat(s0,nrefl,1);
krefl_mag = sqrt(sum(krefl.*krefl,2));

d1_dot_e1 = sum(repmat(d1,nrefl,1).*e1,2);
d1_dot_e2 = sum(repmat(d1,nrefl,1).*e2,2);

d2_dot_e1 = sum(repmat(d2,nrefl,1).*e1,2);
d2_dot_e2 = sum(repmat(d2,nrefl,1).*e2,2);

d3_dot_e1 = sum(repmat(d3,nrefl,1).*e1,2);
d3_dot_e2 = sum(repmat(d3,nrefl,1).*e2,2);

sx_refl = s(:,1);
sy_refl = s(:,2);
sz_refl = s(:,3);

eps1 = (180/pi)*((sx - sx_refl(idx)).*d1_dot_e1(idx) + ...
(sy - sy_refl(idx)).*d2_dot_e1(idx) + ...
(sz - sz_refl(idx)).*d3_dot_e1(idx))./krefl_mag(idx);

eps2 =(180/pi)* ((sx - sx_refl(idx)).*d1_dot_e2(idx) + ...
(sy - sy_refl(idx)).*d2_dot_e2(idx) + ...
(sz - sz_refl(idx)).*d3_dot_e2(idx))./krefl_mag(idx);

end

function Rj = partiality(phi,e1,sigmaM,Spindle,frame)
% added frame argument on March 25, 2019
m2 = Spindle.rotationAxis;
dPhi = Spindle.oscillationRange;
phiMid = Spindle.frame2phi(frame);
phi1 = phiMid - dPhi/2;
phi2 = phiMid + dPhi/2; % before, assumed phimid = 0
%disp([phi1,phi2])
Rj = calc_partiality(phi,e1,phi1,phi2,sigmaM,m2);

end

end
end

function c = quickdot(a,b)
c = a(1)*b(1) + a(2)*b(2) + a(3)*b(3);
end

function c = quickcross(a,b)
c = zeros(1,3);
c(1) = a(2)*b(3) - a(3)*b(2);
c(2) = a(3)*b(1) - a(1)*b(3);
c(3) = a(1)*b(2) - a(2)*b(1);
end

14 changes: 14 additions & 0 deletions +geom/@Profile/private/calc_partiality.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
function R = calc_partiality(phi,e1,phi1,phi2,sigmaM,m2)
% Feb 16, 2017: modified to use m2 as input rather than xds_parm

%m2 = xds_parm.rotation_axis;
nrefl = size(phi,1);

% xi = m2 dot e1
xi = sum(repmat(m2,nrefl,1).*e1,2);

a = abs(xi)/(sqrt(2)*sigmaM);

R = 0.5 * (erf(a.*(phi2-phi)) - erf(a.*(phi1-phi)));

end
119 changes: 119 additions & 0 deletions +geom/@Profile/private/calc_reflection_center.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
function [c1,c2] = calc_reflection_center(s0, m2, f, ed, p0star)
%
% columns of c1, c2: phi,x,y,p1,p2,p3
%
% where p1,p2,p3 are the reciprocal space coordinates once rotated into the
% diffraction condition
%
% xparm = structure containing xds parameters
%
% p0star = some arbitrary point of interest in reciprocal space of the
% unrotated crystal (inverse angstrom)
%
% c1 = [phi,x,y]; <- first set of solutions
% c2 = [phi,x,y]; <- second set of solutions
%
% partly vectorized on May 18, 2015
% (several operations could be more succinctly written as matrix
% multiplications)
%
% removed x0, and y0 (x and y are now relative to detector origin)
%
% moved to scatterbrain project: Feb 17, 2017
%
% removed xparm. now s0, m2, f, ed are passed as arguments

%s0 = xparm.incident_wavevector;
%m2 = xparm.rotation_axis;
m1 = cross(m2,s0); m1 = m1/sqrt(dot(m1,m1));
m3 = cross(m1,m2);

%f = xparm.detector.f;
%d1 = xparm.detector.ed(:,1)';
%d2 = xparm.detector.ed(:,2)';
%d3 = xparm.detector.ed(:,3)';

d1 = ed(:,1)';
d2 = ed(:,2)';
d3 = ed(:,3)';

p0star_dot_p0star = ...
p0star(:,1).*p0star(:,1) + ...
p0star(:,2).*p0star(:,2) + ...
p0star(:,3).*p0star(:,3);

p0star_dot_m2 = ...
p0star(:,1)*m2(1) + ...
p0star(:,2)*m2(2) + ...
p0star(:,3)*m2(3);

p0star_dot_m1 = ...
p0star(:,1)*m1(1) + ...
p0star(:,2)*m1(2) + ...
p0star(:,3)*m1(3);

p0star_dot_m3 = ...
p0star(:,1)*m3(1) + ...
p0star(:,2)*m3(2) + ...
p0star(:,3)*m3(3);

rho_squared = p0star_dot_p0star - p0star_dot_m2.*p0star_dot_m2;
%rho = sqrt(rho_squared); % distance to rot. axis

pstar_dot_m3 = (-0.5*p0star_dot_p0star - p0star_dot_m2*dot(s0,m2))/dot(s0,m3);
pstar_dot_m2 = p0star_dot_m2;

% check not in blind region

isoutside = rho_squared < (pstar_dot_m3.*pstar_dot_m3) | ...
p0star_dot_p0star > 4*dot(s0,s0);
pstar_dot_m1 = sqrt(rho_squared - pstar_dot_m3.*pstar_dot_m3);
pstar_dot_m1(isoutside) = NaN;
cos_phi = (pstar_dot_m1.*p0star_dot_m1 + ...
pstar_dot_m3.*p0star_dot_m3)./rho_squared;
sin_phi = (pstar_dot_m1.*p0star_dot_m3 - ...
pstar_dot_m3.*p0star_dot_m1)./rho_squared;
phi = atan2(sin_phi,cos_phi)*180/pi;
pstar = [m1(1)*pstar_dot_m1 + m2(1)*pstar_dot_m2 + m3(1)*pstar_dot_m3,...
m1(2)*pstar_dot_m1 + m2(2)*pstar_dot_m2 + m3(2)*pstar_dot_m3,...
m1(3)*pstar_dot_m1 + m2(3)*pstar_dot_m2 + m3(3)*pstar_dot_m3];
S_dot_d1 = (pstar(:,1) + s0(1))*d1(1) + ...
(pstar(:,2) + s0(2))*d1(2) + ...
(pstar(:,3) + s0(3))*d1(3);
S_dot_d2 = (pstar(:,1) + s0(1))*d2(1) + ...
(pstar(:,2) + s0(2))*d2(2) + ...
(pstar(:,3) + s0(3))*d2(3);
S_dot_d3 = (pstar(:,1) + s0(1))*d3(1) + ...
(pstar(:,2) + s0(2))*d3(2) + ...
(pstar(:,3) + s0(3))*d3(3);

x = f*S_dot_d1./S_dot_d3;
y = f*S_dot_d2./S_dot_d3;
c1 = [phi,x,y,pstar];

pstar_dot_m1 = -1*sqrt(rho_squared - pstar_dot_m3.*pstar_dot_m3);
pstar_dot_m1(isoutside) = NaN;
cos_phi = (pstar_dot_m1.*p0star_dot_m1 + ...
pstar_dot_m3.*p0star_dot_m3)./rho_squared;
sin_phi = (pstar_dot_m1.*p0star_dot_m3 - ...
pstar_dot_m3.*p0star_dot_m1)./rho_squared;
phi = atan2(sin_phi,cos_phi)*180/pi;
pstar = [m1(1)*pstar_dot_m1 + m2(1)*pstar_dot_m2 + m3(1)*pstar_dot_m3,...
m1(2)*pstar_dot_m1 + m2(2)*pstar_dot_m2 + m3(2)*pstar_dot_m3,...
m1(3)*pstar_dot_m1 + m2(3)*pstar_dot_m2 + m3(3)*pstar_dot_m3];

S_dot_d1 = (pstar(:,1) + s0(1))*d1(1) + ...
(pstar(:,2) + s0(2))*d1(2) + ...
(pstar(:,3) + s0(3))*d1(3);
S_dot_d2 = (pstar(:,1) + s0(1))*d2(1) + ...
(pstar(:,2) + s0(2))*d2(2) + ...
(pstar(:,3) + s0(3))*d2(3);
S_dot_d3 = (pstar(:,1) + s0(1))*d3(1) + ...
(pstar(:,2) + s0(2))*d3(2) + ...
(pstar(:,3) + s0(3))*d3(3);

x = f*S_dot_d1./S_dot_d3;
y = f*S_dot_d2./S_dot_d3;
c2 = [phi,x,y,pstar];

end
2 changes: 1 addition & 1 deletion +geom/@Scattering/ewald2hkl.m
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@

% apply symmetry limits
indh = indh(sum((indh*Binv).^2,2) <= smax^2,:);

% unique list of miller indices with edges that intersect the ewald sphere
hkl = unique([indh;indk;indl],'rows');

Expand Down
Loading

0 comments on commit 191f367

Please sign in to comment.