Working with Data from NanoMAX#
Learning how to reconstruct data from the NanoMAX beamline
The data#
Data file |
Type |
Download |
Courtesy of |
Reference |
|---|---|---|---|---|
000077.h5 |
Raw |
Maik Kahnt |
||
scan_000077_eiger4m.h5 |
Raw |
Maik Kahnt |
The following notebook has been adapted from the original PtyPy run script as provided by the data deposition referenced above.
Reconstruction#
After 1000 iterations of DM + 1000 iterations of ML, the result looks like this

import ptypy, os
import ptypy.utils as u
ptypy.load_ptyscan_module("nanomax")
ptypy.load_gpu_engines(arch="cupy")
# Root directory of tutorial data
tutorial_data_home = "../../data/"
tutorial_data_home = "/dls/science/groups/imaging/ptypy_tutorials/"
# Dataset for this tutorial
dataset = "nanomax_10_keV"
# Absolute path to HDF5 file with raw data
beamtime_basedir = os.path.join(tutorial_data_home, dataset)
# Detector / Sample name
detector = 'eiger4m'
sample = '0001_setup'
# Parameters
scannr = 77
distance_m = 7.180 # distance between the sample and the detector in meters
defocus_um = 1500 # distance between the focus and the sample plane in micro meters -> used for inital probe
cropping = 512 # Cropped to 512 for the purpose of this tutorial, original value is 1536
binning = 1
probe_modes = 2
# General parameters
p = u.Param()
p.verbose_level = "interactive"
p.run = 'scan%d' % scannr
p.frames_per_block = 1000 # reduce this number if you run out of memory on the GPU.
# Set io settings (no files saved)
p.io = u.Param()
p.io.rfile = None
p.io.autosave = u.Param(active=False)
p.io.interaction = u.Param(active=False)
# Live-plotting during the reconstruction
p.io.autoplot = u.Param()
p.io.autoplot.active=True
p.io.autoplot.threaded = False
p.io.autoplot.layout = "jupyter"
p.io.autoplot.interval = 10
# Scan parameters
p.scans = u.Param()
p.scans.scan00 = u.Param()
p.scans.scan00.name = 'BlockFull'
p.scans.scan00.coherence = u.Param()
p.scans.scan00.coherence.num_probe_modes = probe_modes # number of probe modes
p.scans.scan00.coherence.num_object_modes = 1 # number of object modes
p.scans.scan00.data = u.Param()
p.scans.scan00.data.name = 'NanomaxContrast'
p.scans.scan00.data.path = beamtime_basedir+'/raw/'+sample+'/'
p.scans.scan00.data.detector = detector
p.scans.scan00.data.maskfile = {'merlin': '/data/visitors/nanomax/common/masks/merlin/latest.h5',
'pilatus': None,
'eiger': '/data/visitors/nanomax/common/masks/eiger/eiger_4M_blinking_pixels.h5', # legacy
'eiger1m': None,
'eiger4m': None}[detector]
p.scans.scan00.data.scanNumber = scannr
p.scans.scan00.data.xMotor = 'pseudo/x'
p.scans.scan00.data.yMotor = 'pseudo/y'
p.scans.scan00.data.zDetectorAngle = 0.0 # rotation of the detector around the beam axis in [deg]
p.scans.scan00.data.xyAxisSkewOffset = 0.0
p.scans.scan00.data.shape = cropping # size of the window of the diffraction patterns to be used in pixel
# p.scans.scan00.data.save = 'append'
# p.scans.scan00.data.dfile = path_data # once all data is collected, save it as .ptyd file
p.scans.scan00.data.center = (1340,685) # center of the diffraction pattern (y,x) in pixel or None -> auto
p.scans.scan00.data.cropOnLoad = True # only load used part of detector frames -> save memory
# requires center to be set explicitly
p.scans.scan00.data.xMotorFlipped = True
p.scans.scan00.data.yMotorFlipped = False
p.scans.scan00.data.orientation = {'merlin': (False, False, True), # (do_transpose, do_flipud, do_fliplr)
'pilatus': (False, True, False),
'eiger': (False, True, False), # legacy
'eiger1m': (False, True, False),
'eiger4m': (False, True, False)}[detector] # when mounted 180 degrees rotated
#'eiger4m': (False, True, False)}[detector] # old version when mounted the right way around
p.scans.scan00.data.distance = distance_m # distance between sample and detector in [m]
p.scans.scan00.data.psize = {'pilatus': 172e-6,
'merlin': 55e-6,
'eiger': 75e-6, # legacy
'eiger1m': 75e-6,
'eiger4m': 75e-6}[detector]
p.scans.scan00.data.rebin = binning
p.scans.scan00.data.I0 = None # can be like 'alba2/1'
p.scans.scan00.data.min_frames = 10
p.scans.scan00.data.load_parallel = 'all'
# Init probe from KB parameters
p.scans.scan00.illumination = u.Param()
p.scans.scan00.illumination.model = None
p.scans.scan00.illumination.aperture = u.Param()
p.scans.scan00.illumination.aperture.form = 'rect'
p.scans.scan00.illumination.aperture.size = 525e-6 # EH1-M1 aperture diameter
p.scans.scan00.illumination.propagation = u.Param()
p.scans.scan00.illumination.propagation.focussed = 0.200 # EH1-M1 focal length
p.scans.scan00.illumination.propagation.parallel = 1.*defocus_um*1e-6 # propagate the inital guess -> gives phase curvature
p.scans.scan00.illumination.propagation.antialiasing = 1
### details on how to init multiple probe modes differently
p.scans.scan00.illumination.diversity = u.Param()
p.scans.scan00.illumination.diversity.power = 0.1 # Power of modes relative to main mode (zero-layer)
p.scans.scan00.illumination.diversity.noise = (0.5, 1.0) # (rms, mfs, rms_mod, mfs_mod)
p.engines = u.Param()
# 1st use the difference map algorithm
p.engines.engine00 = u.Param()
p.engines.engine00.name = 'DM_cupy'
p.engines.engine00.numiter = 1000 # number of iterations
p.engines.engine00.numiter_contiguous = 10 # Number of iterations without interruption
p.engines.engine00.probe_support = 3 # non-zero probe area as fraction of the probe frame
#p.engines.engine00.probe_update_start = 50 # number of iterations before probe update starts
p.engines.engine00.obj_smooth_std = 10. # gaussian smoothing (pixel) of the current object prior to update
p.engines.engine00.clip_object = (0,1) # clip object amplitude into this interval
# 2nd use the maximum likelyhood algorithm
p.engines.engine01 = u.Param()
p.engines.engine01.name = 'ML_cupy'
p.engines.engine01.numiter = 1000 # number of iterations
p.engines.engine01.numiter_contiguous = 10 # Number of iterations without interruption
p.engines.engine01.probe_support = 3 # non-zero probe area as fraction of the probe frame
#p.engines.engine01.probe_update_start = 50 # number of iterations before probe update starts
# start the reconstruction
P = ptypy.core.Ptycho(p,level=5)