Add tool to convert from real space to pixel space translations

This commit is contained in:
Abe Levitan
2019-04-01 16:51:36 -04:00
parent b8bdcfeb44
commit 3248a3b46e
2 changed files with 74 additions and 0 deletions
+44
View File
@@ -9,6 +9,50 @@ import torch as t
# area.
#
def translations_to_pixel(basis, translations, surface_normal=t.Tensor([0,0,1])):
"""Takes real space translations and outputs them in pixel space
This works for any 2D ptychography geometry. It takes in
A set of translations in (x,y) space and outputs the same translations
in internal pixel units perpendicular to the detector.
It uses information on the wavefield basis and, if defined, the
sample normal, to perform the conversion.
The assumed geometry is incoming radiation with a wavevector parallel
to the +z axis, [0,0,1]. The default sample orientation has a surface
normal parallel to this direction
Args:
basis (torch.Tensor) : The real space basis the wavefields are defined in
translations (torch.Tensor) : A Jx3 stack of real-space translations
surface_normal (torch.Tensor) : Optional, the sample's surface normal
"""
projection_1 = t.Tensor([[1,0,0],
[0,1,0],
[0,0,0]])
projection_2 = t.inverse(t.Tensor([[1,0,0],
[0,1,0],
-surface_normal/
surface_normal[2]]))
basis_vectors_inv = t.pinverse(basis)
projection = t.mm(basis_vectors_inv,
t.mm(projection_2,projection_1))
projection = projection.t()
single_translation = False
if len(translations.shape) == 1:
translations = translations[None,:]
single_translation = True
pixel_translations = t.mm(translations, projection)
if single_translation:
return pixel_translations[0]
else:
return pixel_translations
def ptycho_2D_round(probe, obj, translations):
"""Returns a stack of exit waves without accounting for subpixel shifts
+30
View File
@@ -28,6 +28,36 @@ def single_pixel_probe(scope='module'):
return probe
def test_translations_to_pixel():
# First, try the case where everything is ones and simple
basis = t.Tensor([[0,-1,0],[-1,0,0]]).t()
translations = t.rand((10,3))
output = interactions.translations_to_pixel(basis, translations)
assert t.allclose(output, -translations[:,:2].flip(1))
# Next, try a case with a single translation
translation = t.rand((3))
output = interactions.translations_to_pixel(basis, translation)
assert t.allclose(output, -translation[:2].flip(0))
# Then, try a case with no surface normal but with a real conversion
basis = t.Tensor([[0,-2,0],[-1,0,0.1]]).t()
translations = t.rand((10,3))
output = interactions.translations_to_pixel(basis, translations)
basis_vectors_inv = t.pinverse(basis)
translations[:,2] = 0 # manually project off z component
assert t.allclose(output, t.mm(translations,basis_vectors_inv.t()))
# Finally, try a case with a known surface normal (reflection)
basis = t.Tensor([[0,-1,0],[0,0,1]]).t()
surface_normal = t.Tensor([np.sqrt(2),0,-np.sqrt(2)])
translations = t.rand((10,3))
output = interactions.translations_to_pixel(basis, translations,
surface_normal=surface_normal)
exp_translations = t.stack((-translations[:,1],translations[:,0]),dim=1)
assert t.allclose(output, exp_translations)
def test_ptycho_2D_round(random_probe, random_obj):
# Test a stack of images
translations = np.random.rand(10,2) * 500