Skip to content

Proposal: Separate Reconstruction Data from Options #68

Description

@mdw771

Proposal: Separate Reconstruction Data from Options

We propose changing how Pty-Chi users provide large reconstruction arrays such as diffraction data, object/probe initial guesses, probe positions, OPR mode weights, and valid pixel masks.

Today, these arrays are stored directly inside the Options dataclass. This makes the options object hard to save, reload, compare, or share as a clean configuration file. The proposed change is to keep Options for reconstruction settings only, and pass large data arrays explicitly to PtychographyTask.

Why This Change Is Needed

Many users want to save a reconstruction setup so it can be reused later, shared with collaborators, or recorded alongside reconstruction results. However, the current Options object contains both:

  • small settings, such as number of epochs, batch size, optimizer choices, pixel size, and constraints
  • large data arrays, such as measured diffraction data, object guesses, probe guesses, scan positions, and masks

Why this is bad:

  • These large arrays are not always easy or appropriate to serialize inside a dataclass. They may be PyTorch tensors, NumPy arrays, GPU tensors, memory-mapped arrays, or very large datasets. Keeping them inside Options makes it difficult to save the options as a simple JSON/YAML-like configuration.
  • This design is also making the internal data structure of Pty-Chi messier: currently, ReconstructParameter obejcts like Object, Probe own both an options object and a data tensor. The data tensor references the buffer in the options object. The duplicated references are error-prone.

The goal is to make the separation clearer:

  • Options describes how to run the reconstruction.
  • PtychographyTask receives the actual data needed to run it.

This should make reconstruction jobs easier to save, reproduce, document, and share.

Why not pickle?

Pickle files are not a good long-term format for saving reconstruction settings:

  • They have poor cross-version compatibility. A pickle created with one Pty-Chi version may fail to load after option fields are renamed, added, removed, or reorganized.
  • They are tied to Python class definitions. If the API changes, the saved object may no longer match the code that tries to load it.
  • They are difficult to inspect or edit by hand.
  • They can contain very large embedded arrays, making them inefficient for sharing settings.
  • They have security risks. Loading a pickle file can execute arbitrary code, so users should not load pickle files from untrusted sources.

What Will Change

The following large data fields would be removed from the option classes:

  • options.data_options.data
  • options.data_options.valid_pixel_mask
  • options.object_options.initial_guess
  • options.probe_options.initial_guess
  • options.probe_position_options.position_x_px
  • options.probe_position_options.position_y_px
  • options.opr_mode_weight_options.initial_weights

Instead, these values would be passed directly when creating a PtychographyTask.

The options classes would still contain reconstruction settings, for example:

  • object pixel size
  • whether the object/probe/positions/OPR weights are optimizable
  • optimizer type and step size
  • number of epochs
  • batch size
  • noise model
  • position correction settings
  • regularization and constraint settings
  • detector and wavelength settings

Current Interface

Today, a user may write:

options = api.LSQMLOptions()

options.data_options.data = diffraction_data
options.data_options.valid_pixel_mask = valid_pixel_mask

options.object_options.initial_guess = object_guess
options.object_options.pixel_size_m = pixel_size_m
options.object_options.optimizable = True

options.probe_options.initial_guess = probe_guess
options.probe_options.optimizable = True

options.probe_position_options.position_x_px = positions_px[:, 1]
options.probe_position_options.position_y_px = positions_px[:, 0]

options.opr_mode_weight_options.initial_weights = opr_weights

options.reconstructor_options.num_epochs = 8
options.reconstructor_options.batch_size = 44

task = PtychographyTask(options)
task.run()

Proposed Interface

After the change, users would keep large arrays outside the options object:

options = api.LSQMLOptions()

options.object_options.pixel_size_m = pixel_size_m
options.object_options.optimizable = True

options.probe_options.optimizable = True

options.probe_position_options.optimizable = False

options.opr_mode_weight_options.optimizable = True
options.opr_mode_weight_options.update_relaxation = 0.1

options.reconstructor_options.num_epochs = 8
options.reconstructor_options.batch_size = 44
options.reconstructor_options.noise_model = api.NoiseModels.GAUSSIAN

task = PtychographyTask(
    options,
    data=diffraction_data,
    object_initial_guess=object_guess,
    probe_initial_guess=probe_guess,
    probe_positions_px=positions_px,
    opr_mode_weights_initial_guess=opr_weights,
    valid_pixel_mask=valid_pixel_mask,
)

task.run()

The exact argument names are open for discussion, but the main idea is that the arrays are passed to PtychographyTask, not stored inside Options.

Benefits for Users

This change would make it easier to:

  • save reconstruction settings without saving huge arrays inside the same object
  • reuse the same options with different datasets or initial guesses
  • compare reconstruction settings between runs
  • share a reconstruction configuration with collaborators
  • keep large experimental data in dedicated files such as HDF5, TIFF, NumPy, or PyTorch files
  • avoid accidentally copying or serializing large GPU tensors
  • avoid relying on pickle files for long-term storage of reconstruction settings

For most users, the reconstruction workflow stays conceptually the same: you still create options, provide data, create a task, and run it. The main difference is where the large arrays are passed.

How data and settings should be saved after this change

  • Settings can be saved to a YAML or JSON file by dumping the fields and values from the Options objects.
  • Pty-Chi does not mandate a format for data storage as it directly expects arrays or tensors. However, we recommend using the Ptychodus format.

Expected Impact

This is an interface change, so existing scripts would need a small update. Settings that are currently assigned into options would remain there, but data arrays would move into the PtychographyTask(...) call.

We would aim to provide a transition period where the old style still works with a warning, so users have time to update scripts.

Questions for Users

We would like feedback on the following:

  1. Is the proposed separation between "settings" and "data arrays" clear?
  2. Are the proposed PtychographyTask(...) arguments easy to understand?
  3. Would you prefer passing probe positions as one array, probe_positions_px, or as separate position_x_px and position_y_px arrays?
  4. Would this change make it easier for you to save and reuse reconstruction configurations?
  5. Are there other large inputs currently stored in options that should also be moved to the task?

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions