I have two issues, one data specific and one in regards to general understanding:
The specific one is that, when i run the reconstruct.py example with device='gpu', i get a data type error:
Traceback (most recent call last):
File "C:\Users\root\Desktop\scripts in progress\PythonInDM\jupyter_nb.py", line 59, in
reconstructions_full = epie(band_limited_measurment, probe_guess, maxiter=3, return_iterations=True, fix_com=True, device='gpu')
File "C:\ProgramData\Anaconda3\lib\site-packages\abtem\reconstruct.py", line 187, in epie
result = _run_epie(diffraction_patterns.shape[-2:],
File "C:\ProgramData\Anaconda3\lib\site-packages\abtem\reconstruct.py", line 87, in _run_epie
com = center_of_mass(xp.fft.fftshift(xp.abs(probe) ** 2))
File "C:\ProgramData\Anaconda3\lib\site-packages\scipy\ndimage\measurements.py", line 1406, in center_of_mass
results = [sum(input * grids[dir].astype(float), labels, index) / normalizer
File "C:\ProgramData\Anaconda3\lib\site-packages\scipy\ndimage\measurements.py", line 1406, in
results = [sum(input * grids[dir].astype(float), labels, index) / normalizer
File "cupy_core\core.pyx", line 1115, in cupy._core.core.ndarray.mul
File "cupy_core\core.pyx", line 1491, in cupy._core.core.ndarray.array_ufunc
File "cupy_core_kernel.pyx", line 1119, in cupy._core._kernel.ufunc.call
File "cupy_core_kernel.pyx", line 110, in cupy._core._kernel._preprocess_args
TypeError: Unsupported type <class 'numpy.ndarray'>
This seems to be an issue with cupy, since device='cpu' works without issue. I could list my package environment, but i think a general reply whether there are known issues with version conflicts would be useful. I am using cupy-9.4.0 and abtem-1.0.0b24.
The other question is regarding interfacing with experimental data from Gatan GMS3.x in order to run the ePie reconstruction and compare with simulations. I am a complete amateur, but as an example this works partially (using dm3-lib to import GMS data and meta tags):
import dm3_lib as dm3
import os
import numpy as np
import cupy as cp
from abtem import *
import math
listfiles = []
this_path= os.getcwd()
for filename in os.listdir(this_path):
if '.dm3' in filename:
lastname = os.path.join(this_path, filename)
listfiles.append(lastname)
dm3f = dm3.DM3(listfiles[0])
grid_x=int(float(dm3f.tags['root.ImageList.1.ImageTags.nx'])) #the information on the size of the scan area is stored in custom tags
grid_y=int(float(dm3f.tags['root.ImageList.1.ImageTags.ny']))
diff_x=np.shape(dm3f.imagedata)[0]
diff_y=np.shape(dm3f.imagedata)[1]
sampling_x = float(dm3f.tags['root.ImageList.1.ImageData.Calibrations.Dimension.0.Scale'])
offset_x=((np.shape(dm3f.imagedata)[0])/2)*(-sampling_x)
units_x= str(dm3f.tags['root.ImageList.1.ImageData.Calibrations.Dimension.0.Units'])
name_x= 'dx_cal'
dfx_cal= measure.Calibration(offset_x,sampling_x,units_x,name_x)
sampling_y = float(dm3f.tags['root.ImageList.1.ImageData.Calibrations.Dimension.1.Scale'])
offset_y=((np.shape(dm3f.imagedata)[1])/2)*(-sampling_y)
units_y= str(dm3f.tags['root.ImageList.1.ImageData.Calibrations.Dimension.1.Units'])
name_y= 'dy_cal'
dfy_cal= measure.Calibration(offset_y,sampling_y,units_y,name_y)
sampling_x = 10*float(dm3f.tags['root.ImageList.1.ImageTags.dx']) #the calibration values are stored in nm
offset_x=0
units_x= 'A'
name_x= 'x_cal'
x_cal= measure.Calibration(offset_x,sampling_x,units_x,name_x)
sampling_y = 10*float(dm3f.tags['root.ImageList.1.ImageTags.dy'])
offset_y=0
units_y= 'A'
name_y= 'y_cal'
y_cal= measure.Calibration(offset_y,sampling_y,units_y,name_y)
array = np.zeros_like(np.empty((grid_x,grid_y,diff_x,diff_y)), dtype=np.float32)
calibration = (x_cal,y_cal,dfx_cal,dfy_cal)
measurement = Measurement(array, calibration)
for i in range(len(listfiles)):
dm3f = dm3.DM3(listfiles[i])
x = i%grid_x
y = math.trunc(i/grid_x)
measurement.array[x, y] += cp.asnumpy(dm3f.imagedata)
When i run this code snippet and attempt to run the reconstruction, it kind of sortof works, but the grid that the scan area is cast on is wrong/of the size of the diffraction pattern. There seems to be some basic property of the measurement object that i am missing or do not understand.
Would it be possible to get a layout of the required entries in the measurement class, in some "beginners' guide" kind of way?
edit: After some more testing, it seems that the probe_guess shape is actually what determines the output grid, but if i fix a larger grid the reconstruction bins the probe down again, which seems both counterintuitive and unncessary. It should be possible to pad the probe for large scan grids so that the illumination wave is never undefined?