de_twin.twin.DigitalTwin#

class de_twin.twin.DigitalTwin(specimen='Dense Au on holey C', camera='DE16', *, column=None, corrector=None, holder=None, seed=0, calibration=None, optics_config=None, render_config=None, clock=None, flood_for_gain=True, detector_overrides=None, start_on_specimen=True)[source]#

Bases: object

A complete simulated instrument.

Parameters:
  • specimen (str | object) – A preset/pattern name (see de_twin.specimen.PRESETS/PATTERNS), a SpecimenConfig or a ready Specimen.

  • camera (str | object) – A camera model name (de_twin.detector.CAMERAS) or CameraModel.

  • column – A Column (default: a new simulated column on this twin’s clock) or a MirrorColumn following real software.

  • corrector (str | None) – None (uncorrected), "probe", "image" or "both": give the twin’s own column a CEOS-like aberration corrector (see de_twin.column.corrector).

  • holder (str | object | None) – A holder object (duck type of autopilot’s heater) or a spec string ("none", "sim-heating", "impulse").

  • clock (Clock | None) – Shared clock; default real time. Use ManualClock for deterministic offline runs or Clock(time_scale=...) to fast-forward.

  • flood_for_gain (bool) – Gain/vacuum exposure modes render a uniform flood (as if the operator moved to an empty area), which is what gain references expect.

  • seed (int)

  • detector_overrides (dict | None)

  • start_on_specimen (bool)

__init__(specimen='Dense Au on holey C', camera='DE16', *, column=None, corrector=None, holder=None, seed=0, calibration=None, optics_config=None, render_config=None, clock=None, flood_for_gain=True, detector_overrides=None, start_on_specimen=True)[source]#
Parameters:

Methods

__init__([specimen, camera, column, ...])

acquire(request, *[, pace])

Sum of all frames of request (uint32/float64 like a DE-Server integrated image).

beam_on_detector(request, state)

calibration_truth([request])

What SerialEM's calibrations should find at the column's current state: the true pixel size against the nominal one, the image rotation on the camera, the image-shift matrix, the magnification's image offset, the stage's backlash error and how far the specimen is off eucentric height.

close()

datacube(request)

Noiseless 4D-STEM data for the request's scan: float32 (scan ny, nx, Hd, Wd) at the detector's binned output shape, electrons per binned pixel per second (multiply by the dwell time for electrons per pattern).

flux(request[, frame_index, scan_point, ...])

Noiseless electrons/pixel/second on the ROI, or None if no beam.

frames(request, *[, pace, stop])

Raw detector frames for request.

ground_truth([request, as_arrays])

Phase + effective orientation (grain x stage tilt) per STEM scan point, or per raster pixel of a TEM view, for scoring orientation maps (e.g. pyxem against CrystalLibrary.template_library).

ground_truth_ptychography(request)

Ground truth of the coherent 4D-STEM simulation of request (to score ptychography / tcBF):

holder_state([t])

microscope_state()

optics(request[, state])

raw_frame([frame_time_s])

One raw detector frame (offset, noise, defects and all).

request(**fields)

An AcquisitionRequest for this twin's camera.

reset_serial()

Restart the running frame count that seeds the detector noise, so the next acquisition's noise is the same as a fresh twin's (see AcquisitionRequest.seed to pin one acquisition without touching the count).

safe_dose_e_per_px_s([fps])

A dose rate the detector takes without saturating a frame at fps.

scan_point(request, frame_index)

set_specimen(specimen[, start])

Swap the specimen (e.g. a new preset) keeping column/holder/detector.

snap([exposure_s, fps, units])

An integrated, dark/gain-corrected image, the way DE-Server delivers one.

start_on_specimen()

Point the column at the specimen, as an operator would on loading it.

stem_model(request)

"coherent" or "kinematic": the STEM model the renderer uses for this request.

virtual_image(request, inner_mrad, outer_mrad)

STEM virtual detector image for the request's scan (noiseless).

Attributes

camera_model

processor

Reference store + correction (DE-Server-like processing).

property camera_model#
microscope_state()[source]#
Return type:

MicroscopeState

holder_state(t=None)[source]#
Parameters:

t (float | None)

Return type:

HolderState

start_on_specimen()[source]#

Point the column at the specimen, as an operator would on loading it.

The stage goes to Specimen.home_um (the origin is often a grid bar, a chip frame or bare film), the beam to the preset’s start_dose_e_per_px_s (by solving the Intensity — the default spread beam gives ~2 e- per live frame, which reads as pure noise), and the defocus to its start_defocus_um. Everything stays the operator’s to change afterwards.

Return type:

None

safe_dose_e_per_px_s(fps=40.0)[source]#

A dose rate the detector takes without saturating a frame at fps.

A DE integrating pixel holds only a few electrons per frame (~206 ADU per e- at 300 kV against ~2100 ADU of range), so its frames are meant to be sparse and an image is their sum over the exposure: ~35 % of that per frame here. A counting camera wants ~0.1 e- per pixel per sensor cycle, or coincidence loss sets in.

Parameters:

fps (float)

Return type:

float

set_specimen(specimen, start=True)[source]#

Swap the specimen (e.g. a new preset) keeping column/holder/detector. With start, the column is pointed at the new specimen (start_on_specimen).

Parameters:

start (bool)

Return type:

None

optics(request, state=None)[source]#
Parameters:
beam_on_detector(request, state)[source]#
Parameters:
Return type:

bool

scan_point(request, frame_index)[source]#
Parameters:
Return type:

tuple[int, int] | None

flux(request, frame_index=0, scan_point=None, *, state=None, optics=None, time_s=None)[source]#

Noiseless electrons/pixel/second on the ROI, or None if no beam.

Parameters:
Return type:

ndarray | None

frames(request, *, pace=False, stop=None)[source]#

Raw detector frames for request.

TEM imaging re-reads the column at every buffer boundary (live view follows stage moves); diffraction and STEM freeze the optics for the whole acquisition, like DE-Server’s VirtualSpecimen. total_frames == 0 means “until stop is set”.

Parameters:
Return type:

Iterator[tuple[ndarray, FrameMeta]]

reset_serial()[source]#

Restart the running frame count that seeds the detector noise, so the next acquisition’s noise is the same as a fresh twin’s (see AcquisitionRequest.seed to pin one acquisition without touching the count).

Return type:

None

acquire(request, *, pace=False)[source]#

Sum of all frames of request (uint32/float64 like a DE-Server integrated image).

Parameters:
Return type:

ndarray

raw_frame(frame_time_s=0.025, **request_kw)[source]#

One raw detector frame (offset, noise, defects and all).

Parameters:

frame_time_s (float)

Return type:

ndarray

snap(exposure_s=1.0, *, fps=40.0, units='electrons', **request_kw)[source]#

An integrated, dark/gain-corrected image, the way DE-Server delivers one.

exposure_s is split into frames at fps, each corrected with references the twin measures on first use (see processor). units: “electrons” | “adu” | “raw”. seed= (a request field) pins the image’s noise: the same seed gives the same image whatever came before.

Parameters:
Return type:

ndarray

property processor#

Reference store + correction (DE-Server-like processing).

virtual_image(request, inner_mrad, outer_mrad)[source]#

STEM virtual detector image for the request’s scan (noiseless).

Parameters:
Return type:

ndarray

datacube(request)[source]#

Noiseless 4D-STEM data for the request’s scan: float32 (scan ny, nx, Hd, Wd) at the detector’s binned output shape, electrons per binned pixel per second (multiply by the dwell time for electrons per pattern). The same patterns frames() exposes.

Parameters:

request (AcquisitionRequest)

Return type:

ndarray

stem_model(request)[source]#

“coherent” or “kinematic”: the STEM model the renderer uses for this request.

Parameters:

request (AcquisitionRequest)

Return type:

str

ground_truth_ptychography(request)[source]#

Ground truth of the coherent 4D-STEM simulation of request (to score ptychography / tcBF):

  • object: complex transmission t(r) over the scanned field at the simulation pixel dx_nm (lab frame: x = detector columns); view: its world placement;

  • positions_px / positions_nm: (N, 2) probe centres (row, col) in that array, in scan order (row-major), exactly as simulated;

  • probe (principal mode), probe_modes / mode_weights (partial coherence): complex (n, n) at dx_nm, centred at (n/2, n/2), sum |P|^2 = 1;

  • wavelength_nm, convergence_mrad (alpha), aberrations (the full probe set, Aberrations, incl. C1 = defocus and A1 = condenser stig) and C1_nm, A1_nm, B2_nm, C3_nm, C5_nm; focal_spread_nm, source_size_nm, scan_step_nm, scan_rotation_rad;

  • detector_shape, detector_recip_px_inv_nm, detector_center_px (binned) and sampling (Sampling).

the test helper tests/reconstruction.object_on_grid resamples the object to a reconstruction’s pixel.

Parameters:

request (AcquisitionRequest)

Return type:

dict

calibration_truth(request=None)[source]#

What SerialEM’s calibrations should find at the column’s current state: the true pixel size against the nominal one, the image rotation on the camera, the image-shift matrix, the magnification’s image offset, the stage’s backlash error and how far the specimen is off eucentric height. For closed-loop tests: calibrate the twin, then compare. An ideal column (no OpticsConfig.realism) reports the identities.

image_rotation_deg is the view’s world -> camera rotation: image features turn by minus it in (x right, y down) pixel coordinates.

Parameters:

request (AcquisitionRequest | None)

Return type:

dict

ground_truth(request=None, *, as_arrays=False)[source]#

Phase + effective orientation (grain x stage tilt) per STEM scan point, or per raster pixel of a TEM view, for scoring orientation maps (e.g. pyxem against CrystalLibrary.template_library). An orix CrystalMap (phase id = material id, -1 = not indexed: vacuum/amorphous; props grain_id, thickness_nm; x/y in nm), or the raw arrays with as_arrays=True.

Parameters:
request(**fields)[source]#

An AcquisitionRequest for this twin’s camera.

Return type:

AcquisitionRequest

close()[source]#
Return type:

None