xptycho blueprints › User API
The scripts a user writes, one per use, and every public name in one place. The three objects are those of the software architecture blueprint; the helper functions and the Scan methods are listed here. The scripts follow the three demos in demo/.
import xptycho as xpt TRUTH_URL = 'https://www.datadepot.rcac.purdue.edu/bouman/data/demo_xptycho_synthetic.h5' truth = xpt.Sample.load(xpt.download(TRUTH_URL, './demo/input')) # a Sample: truth.object, truth.probe, truth.pixel_pitch pixel_pitch = truth.pixel_pitch probe_positions = xpt.scan_positions(grid=(12, 12), step=68 * pixel_pitch, max_offset=5 * pixel_pitch, seed=0) det_distance = pixel_pitch * 256 * 75e-6 / xpt.energy_to_wavelength(8.8) model = xpt.PtychoModel(energy=8.8, det_distance=det_distance, det_pixel_pitch=75e-6, frame_size=256, probe_positions=probe_positions) model.set_params(object_shape=truth.object.shape) # the object grid of the truth scan = model.simulate(truth, peak_photons=1e4, dark_rate=0.5, seed=0) print(scan.summary()) model.set_params(object_data_fit=0.7, probe_weight_exponent=1.5, relaxation=0.5) model.print_params() recon = model.recon(scan, probe=truth.probe, iterations=100) print(recon.summary()) figures = xpt.view_sample(recon, compare_to=truth) xpt.save_figures(figures, './output/demo_1') recon.save('./output/demo_1/recon.h5')
The detector distance is chosen so the model's object pixel equals the truth's pixel pitch. simulate compares the sample's pixel_pitch with the model's and refuses a mismatch, naming both values.
TRUTH_URL = 'https://www.datadepot.rcac.purdue.edu/bouman/data/demo_xptycho_blind.h5'
truth = xpt.Sample.load(xpt.download(TRUTH_URL, './demo/input'))
pixel_pitch = truth.pixel_pitch
probe_positions = xpt.scan_positions(grid=(20, 20), step=36 * pixel_pitch, max_offset=5 * pixel_pitch, seed=0)
model = xpt.PtychoModel(wavelength=1.4e-9, det_distance=pixel_pitch * 256 * 75e-6 / 1.4e-9,
det_pixel_pitch=75e-6, frame_size=256, probe_positions=probe_positions,
num_probe_modes=2)
model.set_params(object_shape=truth.object.shape)
scan = model.simulate(truth, peak_photons=1e4, seed=0)
model.set_params(object_data_fit=0.5, probe_data_fit=0.6, probe_weight_exponent=1.25, relaxation=0.5,
mode_schedule=[20], mode_energy_fraction=0.1, probe_fresnel_radius_pixels=22.05)
recon = model.recon(scan, iterations=200) # probe not given: estimated
figures = xpt.view_sample(recon, compare_to=truth)
import xptycho.preprocess as xpp RAW_URL = 'https://cxidb.org/data/65/AuBalls_700ms_30nmStep_3_full.cxi' # entry 65 of the CXI database, cxidb.org raw = xpp.cxi.load_raw(xpt.download(RAW_URL, './demo/input')) # counts, dark frames, translations, instrument facts frames = xpp.subtract_dark(raw['frames'], raw['dark_frames']) outlier = xpp.find_outlier_frames(frames, 2.0) frames, translations = frames[~outlier], raw['translations'][~outlier] center = xpp.diffraction_center(frames) frames = xpp.crop_frames(frames, center, 512) frames = frames * xpp.tukey_window(512, 0.5) ** 2 scan = xpt.Scan(frames, translations[:, [1, 0]], wavelength=raw['wavelength'], det_distance=raw['det_distance'], det_pixel_pitch=raw['det_pixel_pitch']) print(scan.summary()); xpt.view_scan(scan) scan.save('goldballs.h5') # optional: a later script can start from Scan.load model = xpt.PtychoModel.from_scan(scan, num_probe_modes=2) model.set_params(object_data_fit=0.5, probe_data_fit=0.6, probe_weight_exponent=1.25, relaxation=0.5, mode_schedule=[10], mode_energy_fraction=0.05, orthogonalize_modes=True, probe_fresnel_radius_pixels=2.5) recon = model.recon(scan, iterations=100) # probe not given: estimated xpt.view_sample(recon, region=(77, 477, 99, 499)); recon.save('./output/goldballs/recon.h5')
model.configure_devices(num_devices=4) # default: every GPU present recon = model.recon(scan, iterations=100) # the same call; the positions are divided among the GPUs
scan = xpt.Scan.load('goldballs.h5')
model = xpt.PtychoModel.from_scan(scan, num_probe_modes=2)
model.set_params(object_data_fit=0.5, probe_data_fit=0.6, probe_fresnel_radius_pixels=2.5)
recon = xpt.Sample.load('./output/goldballs/recon.h5')
model.set_params(object_shape=recon.object.shape, object_origin=recon.origin) # keep the object grid of the first run
new_pos, misfit = model.refine_probe_positions(scan, recon.object, recon.probe, max_shift=1)
model.set_params(probe_positions=new_pos)
recon = model.recon(scan, init=recon, iterations=100)
The object grid is set from the first result. Otherwise it is derived from the positions, new positions can change its shape, and recon refuses init=recon.
amplitudes = model.forward(recon.object, recon.probe) # (J, Np, Np), no noise
print(model.data_error(scan, recon.object, recon.probe))
| name | what it is |
|---|---|
| Scan(frames, probe_positions, *, wavelength or energy, det_distance, det_pixel_pitch, name) | the measurement: frames (intensities), recorded positions, instrument facts. Scan.load(path), scan.save(path), scan.summary(), scan.amplitudes(), scan.frames, scan.probe_positions, scan.wavelength, scan.det_distance, scan.det_pixel_pitch, scan.name, scan.num_frames, scan.frame_size |
| PtychoModel | the parameters and the forward model; the software architecture blueprint, section 2, lists every method |
| Sample | an object and the probe it was seen with; a ground truth or what recon returns: object, probe, pixel_pitch, origin, name, mode_energies, phase, magnitude, and run for a reconstruction (run.parameters, run.data_error, run.iterations, run.probe_positions, run.coverage); scanned_region(), the rectangle spanned by the probe centers, for a reconstruction; summary(), save(path), Sample.load(path) |
| RunRecord | the class of run, the record of a reconstruction |
| view_scan(scan), view_sample(sample, region, compare_to, compare_label) | viewing, separate from the objects: each makes figures, puts them on the screen, and returns them. region is the part of the object to show, chosen in the script; with none given, the rectangle spanned by the probe centers. The windows zoom and pan with the mouse. |
| save_figures(figures, directory) | write the figures a view returned to PNG files |
| download(url, directory) | download a file into a directory unless it is already there; returns the local path |
| scan_positions(grid, step, max_offset, seed) | positions of a rectangular scan with random offsets, in meters |
| preprocess | the module of preprocessing steps, each a function of arrays in memory: cxi.load_raw(path), subtract_dark, find_outlier_frames, diffraction_center, crop_frames, tukey_window; see the pre and post processing blueprint |
| nrmse(image, truth, region=None) | error after removing one complex scale; with a region (for example recon.scanned_region()) only the pixels inside it count |
| match_scale(image, truth, region=None) | image times the one complex number that brings it closest to truth |
| energy_to_wavelength(energy) | photon energy in keV to wavelength in meters |
| operators | the building blocks of the forward model: the centered Fourier transform, cutting patches out of an image, adding patches into an image, the stable division |
| name | kind | meaning |
|---|---|---|
| energy / wavelength | forward model | keV, or meters |
| det_distance | forward model | meters, object to detector |
| det_pixel_pitch | forward model | meters, after any binning |
| frame_size | forward model | \(N_p\), detector pixels per side |
| probe_positions | forward model | (J, 2), row then column, meters; settable, for refinement |
| num_probe_modes | forward model | \(K\); default 1 |
| object_data_fit, probe_data_fit | reconstruction | \(\alpha_1\), \(\alpha_2\); defaults 0.6, 0.6 |
| probe_weight_exponent | reconstruction | \(\kappa\); default 1.25 |
| relaxation | reconstruction | \(\rho\); default 0.5 |
| mode_schedule | reconstruction | iterations at which a mode is added; default none |
| mode_energy_fraction | reconstruction | \(f\); default 0.05 |
| orthogonalize_modes | reconstruction | make the modes orthogonal each time a mode is added; default off |
| probe_fresnel_radius_pixels | reconstruction | The radius, in pixels, over which Fresnel propagation spreads each point of the initial probe and of a new mode; default 0 (no propagation) |
| object_shape | reconstruction | rows and columns of the object grid; default: the smallest grid that holds every patch |
| object_origin | reconstruction | meters, the position of the center of the first pixel of the object grid; default: from the positions |
| num_devices, devices | device | arguments of configure_devices: how many GPUs, or which; see Hardware Mapping, section 4 |
| batch_size | device | positions processed together on a device; set with set_params; default: from the free memory |
Arguments of recon, not parameters: probe, init_probe, init, iterations (default 100), verbose (default 1, one line per iteration; 0 prints nothing).