From a97e4cdf39590049643de1845aadd0437ad09b22 Mon Sep 17 00:00:00 2001 From: Abe Levitan Date: Wed, 14 Jan 2026 17:01:11 +0100 Subject: [PATCH] Add licensed near-field ptycho data to enable testing --- examples/example_data/LICENSE.txt | 11 ++++++ examples/near_field_ptycho.py | 56 +++++++++++++++++++++++++++++++ tests/conftest.py | 5 +++ tests/models/test_fancy_ptycho.py | 37 ++++++++++++++++++++ 4 files changed, 109 insertions(+) create mode 100644 examples/near_field_ptycho.py diff --git a/examples/example_data/LICENSE.txt b/examples/example_data/LICENSE.txt index a3877bb..88678ad 100644 --- a/examples/example_data/LICENSE.txt +++ b/examples/example_data/LICENSE.txt @@ -11,3 +11,14 @@ The dataset contained in the file: - AuBalls_700ms_30nmStep_3_6SS_filter.cxi is sourced from https://cxidb.org/id-65.html, and was made available by the original authors under the CC0 Public Domain Dedication Waiver. This data was deposited into the CXIDB by Stefano Marchesini. + +The dataset contained in the file: + +- PETRAIII_P25_Near_Field_Ptycho.cxi + +is sourced from from [this](http://dx.doi.org/10.5281/zenodo.17899482) Zenodo upload, and was collected at the P25 beamline of the PETRA III light source at DESY. The following list of experiment participants were involved: + + +Nazanin Samadi, Aknur Karabay, Pengju Sheng, Canrong Qiu, Kathryn Spiers, Wenhui Xu, Abraham Levitan, and Manuel Guizar-Sicairos. + +The dataset is made available under a CC BY 4.0 License, defined at https://creativecommons.org/licenses/by/4.0/. diff --git a/examples/near_field_ptycho.py b/examples/near_field_ptycho.py new file mode 100644 index 0000000..c91076f --- /dev/null +++ b/examples/near_field_ptycho.py @@ -0,0 +1,56 @@ +import cdtools +from matplotlib import pyplot as plt + +filename = 'example_data/PETRAIII_P25_Near_Field_Ptycho.cxi' +dataset = cdtools.datasets.Ptycho2DDataset.from_cxi(filename) + +dataset.inspect() +plt.show() + +# Setting near_field equal to True uses an angular spectrum propagator in +# lieu of the default Fourier-transform propagator for far-field ptychography. +# +# If propagation_distance is not set, it assumes that the geometry is +# a standard near-field geometry with flat illumination wavefronts, and +# pulls the sample to detector distance from dataset.distance +# +# If propagation_distance is set, it assumes a Fresnel scaling theorem +# geometry with: +# +# - distance (from the dataset): The sample-to-detector distance +# - propagation_distance: The focus-to-sample distance +# +model = cdtools.models.FancyPtycho.from_dataset( + dataset, + n_modes=1, + near_field=True, + propagation_distance=3.65e-3, # 3.65 downstream from focus + units='um', # Set the units for the live plots + obj_view_crop=-35, +) + +device = 'cuda' +model.to(device=device) +dataset.get_as(device=device) + +model.inspect(dataset) + +recon = cdtools.reconstructors.AdamReconstructor(model, dataset) + +for loss in recon.optimize(100, lr=0.04, batch_size=10): + print(model.report()) + # Plotting is expensive, so we only do it every tenth epoch + if model.epoch % 10 == 0: + model.inspect(dataset) + +for loss in recon.optimize(50, lr=0.005, batch_size=50): + print(model.report()) + if model.epoch % 10 == 0: + model.inspect(dataset) + +# This orthogonalizes the recovered probe modes +model.tidy_probes() + +model.inspect(dataset) +model.compare(dataset) +plt.show() diff --git a/tests/conftest.py b/tests/conftest.py index f0faea5..3e8826d 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -379,6 +379,11 @@ def lab_ptycho_cxi(pytestconfig): return str(pytestconfig.rootpath) + \ '/examples/example_data/lab_ptycho_data.cxi' +@pytest.fixture(scope='module') +def near_field_ptycho_cxi(pytestconfig): + return str(pytestconfig.rootpath) + \ + '/examples/example_data/PETRAIII_P25_Near_Field_Ptycho.cxi' + @pytest.fixture(scope='module') def optical_data_ss_cxi(pytestconfig): diff --git a/tests/models/test_fancy_ptycho.py b/tests/models/test_fancy_ptycho.py index 02893f9..db05a75 100644 --- a/tests/models/test_fancy_ptycho.py +++ b/tests/models/test_fancy_ptycho.py @@ -98,3 +98,40 @@ def test_lab_ptycho(lab_ptycho_cxi, reconstruction_device, show_plot): # If this fails, the reconstruction has gotten worse assert model.loss_history[-1] < 0.0013 + +@pytest.mark.slow +def test_near_field_ptycho(near_field_ptycho_cxi, reconstruction_device, show_plot): + + print('\nTesting performance on the standard transmission ptycho dataset') + dataset = cdtools.datasets.Ptycho2DDataset.from_cxi(near_field_ptycho_cxi) + + model = cdtools.models.FancyPtycho.from_dataset( + dataset, + n_modes=1, + near_field=True, + propagation_distance=3.65e-3, # 3.65 downstream from focus + ) + + print('Running reconstruction on provided reconstruction_device,', + reconstruction_device) + model.to(device=reconstruction_device) + dataset.get_as(device=reconstruction_device) + + for loss in model.Adam_optimize(100, dataset, lr=0.04, batch_size=10): + print(model.report()) + if show_plot and model.epoch % 10 == 0: + model.inspect(dataset) + + for loss in model.Adam_optimize(50, dataset, lr=0.005, batch_size=50): + print(model.report()) + if show_plot and model.epoch % 10 == 0: + model.inspect(dataset) + + model.tidy_probes() + + if show_plot: + model.inspect(dataset) + model.compare(dataset) + + # If this fails, the reconstruction has gotten worse + assert model.loss_history[-1] < 0.005