quscope.quantum_ctem

This is QuScope’s main module — a complete framework for simulating Conventional TEM, STEM, and diffraction image formation on quantum computers. Everything below is re-exported from quscope.quantum_ctem directly (from quscope.quantum_ctem import ...).

Backends

Quantum Backend Abstraction Layer.

This module provides a unified interface for running quantum circuits on different backends: IBM Quantum hardware, local simulators, and fake devices.

Usage:

from quscope.quantum_ctem.backends import get_backend, SimulatorBackend, IBMBackend

# For development/testing - use simulator backend = get_backend(“simulator”)

# For production - use IBM hardware backend = get_backend(“ibm”, device_name=”ibm_kyoto”)

# Run a circuit result = backend.run(circuit, shots=1024)

class quscope.quantum_ctem.backends.Backend(name: str = 'base')[source]

Bases: ABC

Abstract base class for quantum backends.

All backends (simulator, IBM hardware, etc.) must implement this interface to ensure consistent behavior across the quantum CTEM package.

property is_connected: bool

Check if backend is ready for execution.

abstract connect() bool[source]

Establish connection to the backend.

Returns:

True if connection successful, False otherwise

abstract run(circuit: qiskit.QuantumCircuit, config: BackendConfig | None = None) ExecutionResult[source]

Execute a quantum circuit on this backend.

Parameters:
  • circuit – Qiskit QuantumCircuit to execute

  • config – Execution configuration options

Returns:

ExecutionResult with counts, statevector (if available), and metadata

abstract run_batch(circuits: List[qiskit.QuantumCircuit], config: BackendConfig | None = None) List[ExecutionResult][source]

Execute multiple circuits in a batch.

Parameters:
  • circuits – List of QuantumCircuit objects

  • config – Execution configuration options

Returns:

List of ExecutionResult objects

transpile(circuit: qiskit.QuantumCircuit, optimization_level: int = 3) qiskit.QuantumCircuit[source]

Transpile circuit for this backend.

Parameters:
  • circuit – Circuit to transpile

  • optimization_level – Qiskit optimization level (0-3)

Returns:

Transpiled circuit

get_circuit_metrics(circuit: qiskit.QuantumCircuit) Dict[str, Any][source]

Get metrics for a circuit on this backend.

Parameters:

circuit – Circuit to analyze

Returns:

Dictionary with depth, gate counts, etc.

class quscope.quantum_ctem.backends.BackendConfig(shots: int = 1024, optimization_level: int = 3, seed_simulator: int | None = None, memory: bool = False, init_qubits: bool = True, dynamic_decoupling: bool = False, resilience_level: int = 0)[source]

Bases: object

Configuration for quantum backend execution.

shots: int = 1024
optimization_level: int = 3
seed_simulator: int | None = None
memory: bool = False
init_qubits: bool = True
dynamic_decoupling: bool = False
resilience_level: int = 0
to_dict() Dict[str, Any][source]

Convert config to dictionary for backend options.

class quscope.quantum_ctem.backends.ExecutionResult(counts: ~typing.Dict[str, int] = <factory>, statevector: ~numpy.ndarray | None = None, probabilities: ~numpy.ndarray | None = None, shots: int = 0, success: bool = True, backend_name: str = '', execution_time: float = 0.0, job_id: str | None = None, num_qubits: int = 0, depth: int = 0, gate_counts: ~typing.Dict[str, int] = <factory>, error_message: str | None = None)[source]

Bases: object

Standardized result from quantum circuit execution.

counts: Dict[str, int]
statevector: ndarray | None = None
probabilities: ndarray | None = None
shots: int = 0
success: bool = True
backend_name: str = ''
execution_time: float = 0.0
job_id: str | None = None
num_qubits: int = 0
depth: int = 0
gate_counts: Dict[str, int]
error_message: str | None = None
get_statevector_2d(nx: int, ny: int) ndarray[source]

Reshape statevector to 2D grid for CTEM wavefunction.

Parameters:
  • nx – Number of pixels in x direction

  • ny – Number of pixels in y direction

Returns:

Complex 2D array of shape (ny, nx) representing the wavefunction

get_intensity(nx: int, ny: int) ndarray[source]

Get intensity (|ψ|²) as 2D array.

Parameters:
  • nx – Number of pixels in x direction

  • ny – Number of pixels in y direction

Returns:

Real 2D array of intensity values

class quscope.quantum_ctem.backends.SimulatorBackend(simulation_method: str = 'statevector', device: str | None = None, seed: int | None = None)[source]

Bases: Backend

Local quantum simulator backend using Qiskit Aer.

Supports both statevector (exact) and sampling (shot-based) simulation. Ideal for development, testing, and validating quantum CTEM circuits.

simulation_method

“statevector” for exact simulation, “automatic” for sampling

device

Optional device to mimic (e.g., “ibm_kyoto” for noise model)

Examples

>>> backend = SimulatorBackend()
>>> result = backend.run(circuit)
>>> psi = result.get_statevector_2d(nx=32, ny=32)
>>> # With noise model mimicking IBM hardware
>>> backend = SimulatorBackend(device="ibm_kyoto")
connect() bool[source]

Initialize the simulator backends.

run(circuit: qiskit.QuantumCircuit, config: BackendConfig | None = None) ExecutionResult[source]

Execute circuit on simulator.

Parameters:
  • circuit – QuantumCircuit to execute

  • config – Execution configuration

Returns:

ExecutionResult with statevector and/or counts

run_batch(circuits: List[qiskit.QuantumCircuit], config: BackendConfig | None = None) List[ExecutionResult][source]

Execute multiple circuits.

get_statevector(circuit: qiskit.QuantumCircuit) ndarray[source]

Convenience method to get statevector directly.

Parameters:

circuit – Circuit to simulate

Returns:

Complex numpy array of state amplitudes

simulate_ctem_wavefunction(circuit: qiskit.QuantumCircuit, nx: int, ny: int) ndarray[source]

Simulate circuit and return CTEM wavefunction as 2D array.

Parameters:
  • circuit – Quantum circuit encoding the electron wavefunction

  • nx – Number of pixels in x

  • ny – Number of pixels in y

Returns:

Complex 2D array (ny, nx) representing ψ(x, y)

class quscope.quantum_ctem.backends.IBMBackend(device_name: str = 'ibm_kyoto', channel: str = 'ibm_quantum', instance: str | None = None, token: str | None = None)[source]

Bases: Backend

IBM Quantum hardware backend.

Connects to IBM Quantum services and executes circuits on real quantum processors or IBM’s cloud simulators.

device_name

Name of the IBM device (e.g., “ibm_kyoto”, “ibm_osaka”)

channel

“ibm_quantum” for open access, “ibm_cloud” for premium

Examples

>>> backend = IBMBackend(device_name="ibm_kyoto")
>>> backend.connect()
>>> result = backend.run(circuit, BackendConfig(shots=4096))
>>> # List available devices
>>> devices = backend.list_devices()
DEVICE_PROFILES = {'ibm_brisbane': {'qubits': 127, 'topology': 'heavy_hex'}, 'ibm_kyoto': {'qubits': 127, 'topology': 'heavy_hex'}, 'ibm_nazca': {'qubits': 127, 'topology': 'heavy_hex'}, 'ibm_osaka': {'qubits': 127, 'topology': 'heavy_hex'}, 'ibm_sherbrooke': {'qubits': 127, 'topology': 'heavy_hex'}}
connect() bool[source]

Connect to IBM Quantum service.

Returns:

True if connection successful

Raises:

RuntimeError – If connection fails or credentials invalid

run(circuit: qiskit.QuantumCircuit, config: BackendConfig | None = None) ExecutionResult[source]

Execute circuit on IBM hardware.

Parameters:
  • circuit – QuantumCircuit to execute

  • config – Execution configuration

Returns:

ExecutionResult with counts and metadata

run_batch(circuits: List[qiskit.QuantumCircuit], config: BackendConfig | None = None) List[ExecutionResult][source]

Execute multiple circuits as a batch job.

More efficient than individual runs for parameter sweeps.

list_devices() List[Dict[str, Any]][source]

List available IBM Quantum devices.

Returns:

List of device info dictionaries

get_device_info() Dict[str, Any][source]

Get detailed info about the current device.

static save_credentials(token: str, channel: str = 'ibm_quantum') None[source]

Save IBM Quantum credentials for future use.

Parameters:
  • token – IBM Quantum API token

  • channel – Service channel

quscope.quantum_ctem.backends.get_backend(backend_type: str, **kwargs) Backend[source]

Factory function to get a quantum backend.

Parameters:
  • backend_type – One of “simulator”, “statevector”, “ibm”, “ibm_quantum”

  • **kwargs – Backend-specific configuration options

Returns:

Configured Backend instance

Examples

>>> backend = get_backend("simulator")
>>> backend = get_backend("ibm", device_name="ibm_kyoto")
quscope.quantum_ctem.backends.list_available_backends() dict[source]

List all available backend types and their descriptions.

Materials

Material Definitions for Quantum CTEM Simulation.

This module provides material-specific parameters and structure builders for quantum CTEM simulations. Currently supports: - MoS₂ (Molybdenum disulfide) - 2D transition metal dichalcogenide - Graphene - 2D carbon allotrope

Usage:

from quscope.quantum_ctem.materials import get_material, MoS2, Graphene

# Get material by name material = get_material(“mos2”) atoms = material.build_structure(nx=3, ny=2) potential = material.get_projected_potential(atoms, grid_size=256)

# Or use directly graphene = Graphene() atoms = graphene.build_supercell(nx=5, ny=5)

class quscope.quantum_ctem.materials.Material[source]

Bases: ABC

Abstract base class for materials in quantum CTEM simulations.

Subclasses must implement: - build_structure(): Generate atomic structure - get_scattering_params(): Return Kirkland parameters for all elements

abstract property parameters: MaterialParameters

Get material parameters.

property name: str
property formula: str
abstract build_structure(**kwargs)[source]

Build atomic structure for this material.

Returns:

ASE Atoms object representing the structure

abstract get_scattering_params() Dict[str, AtomicScatteringParams][source]

Get Kirkland scattering parameters for all elements.

Returns:

Dictionary mapping element symbol to AtomicScatteringParams

get_projected_potential(atoms, grid_size: int = 256, pixel_size: float = 0.1, padding: float = 2.0) ndarray[source]

Calculate 2D projected potential for the structure.

Parameters:
  • atoms – ASE Atoms object

  • grid_size – Number of pixels (grid_size × grid_size)

  • pixel_size – Pixel size in Ångströms

  • padding – Padding around structure in Å

Returns:

2D numpy array of projected potential in V·Å

get_interaction_constant(voltage: float) float[source]

Calculate relativistic interaction constant σ.

Parameters:

voltage – Accelerating voltage in Volts

Returns:

Interaction constant in rad/(V·Å)

validate_structure(atoms) bool[source]

Validate that the structure is suitable for CTEM simulation.

Parameters:

atoms – ASE Atoms object

Returns:

True if valid, raises ValueError otherwise

class quscope.quantum_ctem.materials.MaterialParameters(name: str, formula: str, lattice_constants: ~typing.Tuple[float, float, float], lattice_angles: ~typing.Tuple[float, float, float] = (90.0, 90.0, 90.0), space_group: str = 'P1', elements: ~typing.List[str] = <factory>, typical_thickness: float = 10.0)[source]

Bases: object

Physical parameters for a material.

name

Material name

Type:

str

formula

Chemical formula

Type:

str

lattice_constants

(a, b, c) in Ångströms

Type:

Tuple[float, float, float]

lattice_angles

(α, β, γ) in degrees

Type:

Tuple[float, float, float]

space_group

Crystallographic space group

Type:

str

elements

List of element symbols

Type:

List[str]

typical_thickness

Typical specimen thickness in Å

Type:

float

name: str
formula: str
lattice_constants: Tuple[float, float, float]
lattice_angles: Tuple[float, float, float] = (90.0, 90.0, 90.0)
space_group: str = 'P1'
elements: List[str]
typical_thickness: float = 10.0
property a: float
property b: float
property c: float
class quscope.quantum_ctem.materials.AtomicScatteringParams(symbol: str, atomic_number: int, a_coefficients: ~typing.List[float] = <factory>, b_coefficients: ~typing.List[float] = <factory>)[source]

Bases: object

Kirkland parameterization for atomic scattering factors.

Based on: Kirkland, “Advanced Computing in Electron Microscopy”, Appendix C. The projected potential is computed as a sum of Gaussians:

V(r) = Σ a_i * exp(-π * r² / b_i)

symbol

Element symbol (e.g., “C”, “Mo”, “S”)

Type:

str

atomic_number

Z

Type:

int

a_coefficients

Gaussian amplitudes [Ų·V]

Type:

List[float]

b_coefficients

Gaussian widths [Ų]

Type:

List[float]

symbol: str
atomic_number: int
a_coefficients: List[float]
b_coefficients: List[float]
projected_potential(r: ndarray) ndarray[source]

Calculate projected potential at distance r from atom center.

Parameters:

r – Distance array in Ångströms

Returns:

Projected potential in V·Å

class quscope.quantum_ctem.materials.MoS2(layer_type: str = '2H')[source]

Bases: Material

Molybdenum Disulfide (MoS₂) material for CTEM simulation.

MoS₂ has a layered structure with: - Hexagonal in-plane symmetry (a ≈ 3.16 Å) - S-Mo-S sandwich structure - Clear Z-contrast between Mo (Z=42) and S (Z=16) columns

layer_type

“1H” (trigonal prismatic) or “1T” (octahedral)

Examples

>>> mos2 = MoS2()
>>> atoms = mos2.build_structure(nx=3, ny=2)
>>> V = mos2.get_projected_potential(atoms, grid_size=256)
SCATTERING_PARAMS = {'Mo': AtomicScatteringParams(symbol='Mo', atomic_number=42, a_coefficients=[2.546, 2.6963, 1.8027, 0.596], b_coefficients=[0.0667, 0.5717, 3.1346, 12.313]), 'S': AtomicScatteringParams(symbol='S', atomic_number=16, a_coefficients=[1.2052, 1.1717, 0.4403, 0.2037], b_coefficients=[0.0331, 0.2636, 1.0096, 4.121])}
property parameters: MaterialParameters

Get material parameters.

build_structure(nx: int = 3, ny: int = 2, vacuum: float = 10.0, **kwargs)[source]

Build MoS₂ supercell using ASE.

Parameters:
  • nx – Number of unit cells in x direction

  • ny – Number of unit cells in y direction

  • vacuum – Vacuum padding in z direction (Å)

Returns:

ASE Atoms object

build_supercell(nx: int = 3, ny: int = 2, vacuum: float = 10.0)[source]

Alias for build_structure for API consistency.

get_scattering_params() Dict[str, AtomicScatteringParams][source]

Get Kirkland scattering parameters for Mo and S.

get_column_positions(atoms) Dict[str, ndarray][source]

Get projected column positions for Mo and S.

Useful for analyzing image contrast at column locations.

Parameters:

atoms – ASE Atoms object

Returns:

Dictionary with “Mo” and “S” keys containing (N, 2) position arrays

expected_contrast(voltage: float = 200000.0) str[source]

Describe expected CTEM contrast for MoS₂.

Parameters:

voltage – Accelerating voltage in V

Returns:

Description of expected contrast

class quscope.quantum_ctem.materials.Graphene(edge_type: str = 'zigzag')[source]

Bases: Material

Graphene material for CTEM simulation.

Graphene has: - Honeycomb lattice with a ≈ 2.46 Å - Single atomic layer of carbon (Z=6) - Excellent WPOA validity due to weak scattering - Six-fold symmetry in diffraction pattern

edge_type

“zigzag” or “armchair” for nanoribbons

Examples

>>> graphene = Graphene()
>>> atoms = graphene.build_structure(nx=5, ny=5)
>>> V = graphene.get_projected_potential(atoms, grid_size=256)
>>> # Build nanoribbon
>>> ribbon = graphene.build_nanoribbon(width=10, length=50)
SCATTERING_PARAMS = {'C': AtomicScatteringParams(symbol='C', atomic_number=6, a_coefficients=[0.7307, 0.6166, 0.2098, 0.1058], b_coefficients=[0.0207, 0.1813, 0.7028, 2.8454])}
LATTICE_CONSTANT = 2.46
BOND_LENGTH = 1.42
LAYER_SPACING = 3.35
property parameters: MaterialParameters

Get material parameters.

build_structure(nx: int = 5, ny: int = 5, vacuum: float = 10.0, **kwargs)[source]

Build graphene supercell using ASE.

Parameters:
  • nx – Number of unit cells in x direction

  • ny – Number of unit cells in y direction

  • vacuum – Vacuum padding in z direction (Å)

Returns:

ASE Atoms object

build_supercell(nx: int = 5, ny: int = 5, vacuum: float = 10.0)[source]

Alias for build_structure for API consistency.

build_nanoribbon(width: int = 10, length: int = 20, edge_type: str | None = None, vacuum: float = 10.0, saturated: bool = False)[source]

Build graphene nanoribbon.

Parameters:
  • width – Width in unit cells (perpendicular to ribbon axis)

  • length – Length in unit cells (along ribbon axis)

  • edge_type – “zigzag” or “armchair” (defaults to instance setting)

  • vacuum – Vacuum padding (Å)

  • saturated – If True, saturate edges with hydrogen

Returns:

ASE Atoms object

build_with_vacancy(nx: int = 5, ny: int = 5, vacancy_fraction: float = 0.01, vacuum: float = 10.0, seed: int | None = None)[source]

Build graphene with random vacancies.

Parameters:
  • nx – Supercell size

  • ny – Supercell size

  • vacancy_fraction – Fraction of atoms to remove (0-1)

  • vacuum – Vacuum padding (Å)

  • seed – Random seed for reproducibility

Returns:

ASE Atoms object with vacancies

get_scattering_params() Dict[str, AtomicScatteringParams][source]

Get Kirkland scattering parameters for Carbon.

get_sublattice_positions(atoms) Dict[str, ndarray][source]

Get positions of A and B sublattice atoms.

In graphene, the honeycomb lattice has two sublattices. This is useful for analyzing sublattice-resolved contrast.

Parameters:

atoms – ASE Atoms object

Returns:

Dictionary with “A” and “B” sublattice positions

wpoa_validity(voltage: float = 200000.0) Dict[str, float][source]

Assess WPOA validity for graphene at given voltage.

The WPOA is valid when σ·V_proj << 1.

Parameters:

voltage – Accelerating voltage in V

Returns:

Dictionary with validity metrics

expected_contrast(voltage: float = 200000.0) str[source]

Describe expected CTEM contrast for graphene.

Parameters:

voltage – Accelerating voltage in V

Returns:

Description of expected contrast

get_diffraction_spots() Dict[str, ndarray][source]

Get expected diffraction spot positions for graphene.

Returns:

Dictionary with reciprocal lattice vectors and spot positions

quscope.quantum_ctem.materials.get_material(name: str, **kwargs) Material[source]

Factory function to get a material instance.

Parameters:
  • name – Material name (e.g., “mos2”, “graphene”)

  • **kwargs – Material-specific parameters

Returns:

Configured Material instance

Examples

>>> material = get_material("mos2")
>>> material = get_material("graphene", edge_type="zigzag")
quscope.quantum_ctem.materials.list_materials() dict[source]

List all available materials with descriptions.

Workflows

Quantum CTEM Workflows.

This module provides end-to-end workflows for quantum CTEM simulation of different materials. Each workflow handles: - Structure generation - Microscope parameter setup - Quantum circuit construction - Simulation execution (simulator or IBM hardware) - Result visualization and validation

Available Workflows:
  • MoS2Workflow: For MoS₂ 2D materials

  • GrapheneWorkflow: For graphene and carbon nanostructures

Usage:

from quscope.quantum_ctem.workflows import MoS2Workflow, GrapheneWorkflow from quscope.quantum_ctem.backends import get_backend

# Setup backend backend = get_backend(“simulator”)

# Run MoS2 workflow workflow = MoS2Workflow(backend=backend, voltage=200e3) results = workflow.run(nx=3, ny=2, grid_size=64)

# Run Graphene workflow workflow = GrapheneWorkflow(backend=backend, voltage=200e3) results = workflow.run(nx=5, ny=5, grid_size=64)

class quscope.quantum_ctem.workflows.CTEMWorkflow(material: Material, backend: Backend, microscope: MicroscopeConfig | None = None, **kwargs)[source]

Bases: ABC

Abstract base class for quantum CTEM simulation workflows.

Provides the template method pattern for running CTEM simulations. Subclasses implement material-specific structure building and visualization.

material

Material instance for the simulation

backend

Quantum backend (simulator or IBM hardware)

microscope

Microscope configuration

abstract build_structure(**kwargs)[source]

Build atomic structure for simulation.

setup_quantum_state(atoms, grid_size: int = 64, pixel_size: float = 0.1) Tuple[ndarray, ndarray][source]

Setup quantum state from atomic structure.

Parameters:
  • atoms – ASE Atoms object

  • grid_size – Number of grid points per dimension

  • pixel_size – Pixel size in Å

Returns:

Tuple of (projected_potential, transmission_function)

build_quantum_circuit(transmission_function: ndarray, apply_ctf: bool = True)[source]

Build quantum circuit for CTEM simulation.

The quantum circuit encodes the exit wave function, which is the product of the incident plane wave and the transmission function. For WPOA with unit incident wave: exit_wave ≈ transmission_function

If CTF is applied, it modifies the wave in momentum space.

Parameters:
  • transmission_function – Complex 2D transmission function

  • apply_ctf – Whether to apply contrast transfer function

Returns:

Qiskit QuantumCircuit

run(grid_size: int = 64, pixel_size: float = 0.1, shots: int = 0, apply_ctf: bool = True, compare_classical: bool = False, **structure_kwargs) SimulationResult[source]

Run complete quantum CTEM simulation.

Parameters:
  • grid_size – Number of grid points per dimension (must be power of 2)

  • pixel_size – Pixel size in Ångströms

  • shots – Number of measurement shots (0 for statevector only)

  • apply_ctf – Whether to apply contrast transfer function

  • compare_classical – Whether to run classical comparison

  • **structure_kwargs – Arguments passed to build_structure()

Returns:

SimulationResult with all simulation data

run_defocus_series(defocus_values: List[float], grid_size: int = 64, pixel_size: float = 0.1, **structure_kwargs) List[SimulationResult][source]

Run simulation at multiple defocus values.

Parameters:
  • defocus_values – List of defocus values in Å

  • grid_size – Grid size

  • pixel_size – Pixel size in Å

  • **structure_kwargs – Structure parameters

Returns:

List of SimulationResult for each defocus

abstract visualize(result: SimulationResult, **kwargs)[source]

Create visualization of simulation results.

class quscope.quantum_ctem.workflows.MicroscopeConfig(voltage: float = 200000.0, defocus: float = -500.0, cs: float = 1.3, c5: float = 0.0, aperture: float = 10.0, convergence: float = 0.5, energy_spread: float = 0.7)[source]

Bases: object

CTEM microscope configuration parameters.

Based on typical parameters for modern 200-300 kV instruments.

voltage

Accelerating voltage in Volts

Type:

float

defocus

Defocus value in Ångströms (positive = underfocus)

Type:

float

cs

Spherical aberration coefficient in mm

Type:

float

aperture

Objective aperture semi-angle in mrad

Type:

float

convergence

Beam convergence semi-angle in mrad

Type:

float

energy_spread

Energy spread in eV (for partial coherence)

Type:

float

voltage: float = 200000.0
defocus: float = -500.0
cs: float = 1.3
c5: float = 0.0
aperture: float = 10.0
convergence: float = 0.5
energy_spread: float = 0.7
property wavelength: float

Calculate relativistic electron wavelength in Ångströms.

property scherzer_defocus: float

Calculate Scherzer defocus for optimal phase contrast.

to_dict() Dict[str, float][source]

Convert to dictionary.

class quscope.quantum_ctem.workflows.SimulationResult(material_name: str = '', n_atoms: int = 0, supercell_size: Tuple[int, int] = (0, 0), grid_size: int = 0, pixel_size: float = 0.0, field_of_view: Tuple[float, float] = (0.0, 0.0), wavefunction: ndarray | None = None, intensity: ndarray | None = None, phase: ndarray | None = None, projected_potential: ndarray | None = None, transmission_function: ndarray | None = None, microscope_config: MicroscopeConfig | None = None, backend_result: ExecutionResult | None = None, execution_time: float = 0.0, circuit_depth: int = 0, n_qubits: int = 0, classical_intensity: ndarray | None = None, correlation_coefficient: float | None = None)[source]

Bases: object

Complete result from a quantum CTEM simulation.

Contains the wavefunction, image intensity, and all metadata needed for analysis and visualization.

material_name: str = ''
n_atoms: int = 0
supercell_size: Tuple[int, int] = (0, 0)
grid_size: int = 0
pixel_size: float = 0.0
field_of_view: Tuple[float, float] = (0.0, 0.0)
wavefunction: ndarray | None = None
intensity: ndarray | None = None
phase: ndarray | None = None
projected_potential: ndarray | None = None
transmission_function: ndarray | None = None
microscope_config: MicroscopeConfig | None = None
backend_result: ExecutionResult | None = None
execution_time: float = 0.0
circuit_depth: int = 0
n_qubits: int = 0
classical_intensity: ndarray | None = None
correlation_coefficient: float | None = None
get_contrast() ndarray | None[source]

Calculate image contrast: (I - mean) / mean.

summary() str[source]

Generate text summary of results.

class quscope.quantum_ctem.workflows.MoS2Workflow(backend: Backend, voltage: float = 200000.0, defocus: float | None = None, cs: float = 1.3, layer_type: str = '1H', **kwargs)[source]

Bases: CTEMWorkflow

Quantum CTEM workflow for MoS₂ (Molybdenum Disulfide).

Provides end-to-end simulation capabilities including: - MoS₂ supercell generation - Quantum circuit construction for WPOA - Execution on simulators or IBM hardware - Comparison with classical multislice - Publication-quality visualization

Examples

>>> from quscope.quantum_ctem.backends import get_backend
>>> from quscope.quantum_ctem.workflows import MoS2Workflow
>>> # Quick simulation with simulator
>>> backend = get_backend("simulator")
>>> workflow = MoS2Workflow(backend=backend)
>>> result = workflow.run(nx=3, ny=2, grid_size=64)
>>> print(result.summary())
>>> # Production run on IBM hardware
>>> backend = get_backend("ibm", device_name="ibm_kyoto")
>>> workflow = MoS2Workflow(backend=backend, voltage=200e3)
>>> result = workflow.run(nx=3, ny=2, grid_size=64, shots=4096)
build_structure(nx: int = 3, ny: int = 2, vacuum: float = 10.0, **kwargs)[source]

Build MoS₂ supercell.

Parameters:
  • nx – Unit cells in x direction

  • ny – Unit cells in y direction

  • vacuum – Vacuum padding in Å

Returns:

ASE Atoms object

run(nx: int = 3, ny: int = 2, grid_size: int = 64, pixel_size: float = 0.1, shots: int = 0, apply_ctf: bool = True, compare_classical: bool = False, vacuum: float = 10.0) SimulationResult[source]

Run MoS₂ quantum CTEM simulation.

Parameters:
  • nx – Unit cells in x

  • ny – Unit cells in y

  • grid_size – Grid size (must be power of 2)

  • pixel_size – Pixel size in Å

  • shots – Measurement shots (0 for statevector)

  • apply_ctf – Apply contrast transfer function

  • compare_classical – Run classical comparison

  • vacuum – Vacuum padding in Å

Returns:

SimulationResult with complete simulation data

run_voltage_series(voltages: List[float] = [80000.0, 120000.0, 200000.0, 300000.0], nx: int = 3, ny: int = 2, grid_size: int = 64, pixel_size: float = 0.1) Dict[float, SimulationResult][source]

Run simulations at multiple accelerating voltages.

Useful for studying voltage-dependent contrast and WPOA validity.

Parameters:
  • voltages – List of voltages in V

  • nx – Supercell dimensions

  • ny – Supercell dimensions

  • grid_size – Grid size

  • pixel_size – Pixel size in Å

Returns:

Dictionary mapping voltage to SimulationResult

run_cs_series(cs_values: List[float] = [0.0, 0.5, 1.0, 1.3, 2.0], nx: int = 3, ny: int = 2, grid_size: int = 64, pixel_size: float = 0.1) Dict[float, SimulationResult][source]

Run simulations at multiple spherical aberration values.

Useful for comparing aberration-corrected vs uncorrected imaging.

Parameters:
  • cs_values – List of Cs values in mm

  • nx – Supercell dimensions

  • ny – Supercell dimensions

  • grid_size – Grid size

  • pixel_size – Pixel size in Å

Returns:

Dictionary mapping Cs to SimulationResult

visualize(result: SimulationResult, show_potential: bool = True, show_intensity: bool = True, show_phase: bool = True, show_ctf: bool = False, figsize: Tuple[int, int] = (12, 4), save_path: str | None = None)[source]

Visualize MoS₂ simulation results.

Parameters:
  • result – SimulationResult to visualize

  • show_potential – Show projected potential

  • show_intensity – Show image intensity

  • show_phase – Show phase map

  • show_ctf – Show CTF curve

  • figsize – Figure size

  • save_path – Path to save figure (optional)

Returns:

matplotlib Figure

compare_with_classical(result: SimulationResult, figsize: Tuple[int, int] = (15, 5), save_path: str | None = None)[source]

Create comparison plot between quantum and classical results.

Parameters:
  • result – SimulationResult (must have classical_intensity)

  • figsize – Figure size

  • save_path – Path to save figure

class quscope.quantum_ctem.workflows.GrapheneWorkflow(backend: Backend, voltage: float = 80000.0, defocus: float | None = None, cs: float = 0.001, edge_type: str = 'zigzag', **kwargs)[source]

Bases: CTEMWorkflow

Quantum CTEM workflow for Graphene.

Graphene is ideal for quantum CTEM simulation validation because: - Light atoms (C, Z=6) give excellent WPOA validity - Honeycomb lattice provides clear symmetry tests - Well-characterized diffraction pattern for validation - Single-atom thickness eliminates multislice complexity

Examples

>>> from quscope.quantum_ctem.backends import get_backend
>>> from quscope.quantum_ctem.workflows import GrapheneWorkflow
>>> # Quick simulation with simulator
>>> backend = get_backend("simulator")
>>> workflow = GrapheneWorkflow(backend=backend)
>>> result = workflow.run(nx=5, ny=5, grid_size=64)
>>> print(result.summary())
>>> # With IBM hardware
>>> backend = get_backend("ibm", device_name="ibm_kyoto")
>>> workflow = GrapheneWorkflow(backend=backend, voltage=80e3)
>>> result = workflow.run(nx=5, ny=5, grid_size=64, shots=4096)
>>> # Nanoribbon simulation
>>> result = workflow.run_nanoribbon(width=10, length=20, edge_type="zigzag")
build_structure(nx: int = 5, ny: int = 5, vacuum: float = 10.0, **kwargs)[source]

Build graphene supercell.

Parameters:
  • nx – Unit cells in x direction

  • ny – Unit cells in y direction

  • vacuum – Vacuum padding in Å

Returns:

ASE Atoms object

run(nx: int = 5, ny: int = 5, grid_size: int = 64, pixel_size: float = 0.05, shots: int = 0, apply_ctf: bool = True, compare_classical: bool = False, vacuum: float = 10.0) SimulationResult[source]

Run graphene quantum CTEM simulation.

Parameters:
  • nx – Unit cells in x

  • ny – Unit cells in y

  • grid_size – Grid size (must be power of 2)

  • pixel_size – Pixel size in Å (default finer for graphene)

  • shots – Measurement shots (0 for statevector)

  • apply_ctf – Apply contrast transfer function

  • compare_classical – Run classical comparison

  • vacuum – Vacuum padding in Å

Returns:

SimulationResult with complete simulation data

run_nanoribbon(width: int = 10, length: int = 20, edge_type: str | None = None, grid_size: int = 64, pixel_size: float = 0.05, shots: int = 0, apply_ctf: bool = True, saturated: bool = False) SimulationResult[source]

Run quantum CTEM simulation of graphene nanoribbon.

Parameters:
  • width – Ribbon width in unit cells

  • length – Ribbon length in unit cells

  • edge_type – “zigzag” or “armchair” (default: instance setting)

  • grid_size – Grid size

  • pixel_size – Pixel size in Å

  • shots – Measurement shots

  • apply_ctf – Apply CTF

  • saturated – Saturate edges with hydrogen

Returns:

SimulationResult for nanoribbon

run_with_vacancies(nx: int = 10, ny: int = 10, vacancy_fraction: float = 0.02, grid_size: int = 64, pixel_size: float = 0.05, shots: int = 0, seed: int | None = None) SimulationResult[source]

Run simulation of graphene with vacancy defects.

Parameters:
  • nx – Supercell size

  • ny – Supercell size

  • vacancy_fraction – Fraction of atoms to remove (0-1)

  • grid_size – Grid size

  • pixel_size – Pixel size in Å

  • shots – Measurement shots

  • seed – Random seed for vacancy positions

Returns:

SimulationResult showing vacancy contrast

validate_wpoa() Dict[str, any][source]

Validate WPOA approximation for current settings.

Returns:

Dictionary with validity metrics

visualize(result: SimulationResult, show_potential: bool = True, show_intensity: bool = True, show_phase: bool = True, show_fft: bool = True, figsize: Tuple[int, int] = (14, 4), save_path: str | None = None)[source]

Visualize graphene simulation results.

Parameters:
  • result – SimulationResult to visualize

  • show_potential – Show projected potential

  • show_intensity – Show image intensity

  • show_phase – Show phase map

  • show_fft – Show FFT (diffraction pattern)

  • figsize – Figure size

  • save_path – Path to save figure

Returns:

matplotlib Figure

visualize_honeycomb(result: SimulationResult, zoom_factor: float = 2.0, figsize: Tuple[int, int] = (10, 5), save_path: str | None = None)[source]

Specialized visualization highlighting honeycomb lattice.

Parameters:
  • result – SimulationResult

  • zoom_factor – Zoom into center region

  • figsize – Figure size

  • save_path – Path to save figure

Quantum CTEM Circuit

Fully Quantum CTEM Simulation Circuit

This module implements a complete quantum TEM simulation pipeline using Qiskit quantum circuits. Unlike classical FFT-based approaches, this implementation uses quantum gates for all operations:

|ψ₀⟩ → [Phase Grating] → [QFT] → [CTF] → [IQFT] → |ψ_image⟩

Physical Framework:
  1. Incident plane wave: Uniform superposition via Hadamard gates

  2. Phase grating: exp(iσV) via DiagonalGate (WPOA transmission)

  3. QFT: Transform to momentum space (2D separable QFT)

  4. Lens CTF: exp(iχ(k)) via DiagonalGate (aberration function)

  5. IQFT: Transform back to real space

This is a quantum implementation suitable for publication-quality demonstrations of quantum advantage in electron microscopy simulation.

References

  • Kirkland, E. J. (2020). Advanced Computing in Electron Microscopy.

  • Nielsen & Chuang (2010). Quantum Computation and Quantum Information.

class quscope.quantum_ctem.quantum_ctem_circuit.QuantumCTEMParameters(acceleration_voltage: float, grid_size: int, pixel_size: float, defocus: float = 0.0, cs: float = 0.0, c5: float = 0.0)[source]

Bases: object

Parameters for fully quantum CTEM simulation.

acceleration_voltage

Electron acceleration voltage (V)

Type:

float

grid_size

Image size N for N×N grid (must be power of 2)

Type:

int

pixel_size

Real-space pixel size (Angstroms)

Type:

float

defocus

Defocus value C₁ (Angstroms, negative = underfocus)

Type:

float

cs

Spherical aberration C₃ (mm)

Type:

float

c5

5th order spherical aberration (mm)

Type:

float

acceleration_voltage: float
grid_size: int
pixel_size: float
defocus: float = 0.0
cs: float = 0.0
c5: float = 0.0
__post_init__()[source]

Validate parameters.

quscope.quantum_ctem.quantum_ctem_circuit.relativistic_wavelength(voltage: float) float[source]

Calculate relativistic electron wavelength.

λ = h / √(2·m₀·e·V·(1 + e·V/(2·m₀·c²))) - equivalent to Kirkland (2020) - Eq. 2.5

Parameters:

voltage – Acceleration voltage (V)

Returns:

Wavelength in Angstroms

quscope.quantum_ctem.quantum_ctem_circuit.interaction_constant(voltage: float, wavelength: float) float[source]

Calculate interaction constant σ for WPOA.

σ = 2π·γ / (λ·V) — Kirkland (2020) Eq. 5.6

where γ is the relativistic correction factor.

Parameters:
  • voltage – Acceleration voltage (V)

  • wavelength – Electron wavelength (Angstroms)

Returns:

Interaction constant σ in rad/(V·Å)

class quscope.quantum_ctem.quantum_ctem_circuit.PhaseGratingCircuit(n_qubits: int)[source]

Bases: object

Quantum circuit for phase grating exp(iσV).

Implements the Weak Phase Object Approximation (WPOA) transmission function as a quantum diagonal unitary gate.

The transmission function t(x,y) = exp(iσV(x,y)) applies a position- dependent phase shift based on the projected atomic potential.

build_circuit(V: ndarray, sigma: float) qiskit.QuantumCircuit[source]

Build phase grating circuit from potential array.

Parameters:
  • V – Projected potential V(x,y) in V·Å, shape (N, N)

  • sigma – Interaction constant in rad/(V·Å)

Returns:

QuantumCircuit implementing exp(iσV)

get_transmission_function(V: ndarray, sigma: float) ndarray[source]

Get classical transmission function for validation.

Parameters:
  • V – Projected potential

  • sigma – Interaction constant

Returns:

Transmission function t(x,y) = exp(iσV)

class quscope.quantum_ctem.quantum_ctem_circuit.LensCTFCircuit(n_qubits: int, n_qubits_x: int, n_qubits_y: int)[source]

Bases: object

Quantum circuit for lens aberration exp(iχ(k)).

Implements the Contrast Transfer Function (CTF) as a quantum diagonal unitary in momentum space. The aberration function χ(k) includes:

χ(k) = π·λ·Δf·k² + 0.5·π·λ³·Cs·k⁴ + …

This must be applied after the QFT transforms to momentum space.

calculate_chi(wavelength: float, pixel_size: float, defocus: float, cs: float = 0.0, c5: float = 0.0) ndarray[source]

Calculate aberration function χ(k).

χ(k) = π·λ·Δf·k² + 0.5·π·λ³·Cs·k⁴ + (π/3)·λ⁵·C₅·k⁶

Parameters:
  • wavelength – Electron wavelength (Å)

  • pixel_size – Real-space pixel size (Å)

  • defocus – Defocus C₁ (Å)

  • cs – Spherical aberration C₃ (mm)

  • c5 – 5th order aberration (mm)

Returns:

χ(k) array of shape (N, N)

build_circuit(chi_k: ndarray) qiskit.QuantumCircuit[source]

Build CTF circuit from aberration function.

Parameters:

chi_k – Aberration function χ(k), shape (N, N)

Returns:

QuantumCircuit implementing exp(iχ(k))

class quscope.quantum_ctem.quantum_ctem_circuit.QuantumCTEMCircuit(params: QuantumCTEMParameters)[source]

Bases: object

Complete quantum CTEM simulation circuit.

Implements the full TEM imaging pipeline as a quantum circuit:

|ψ₀⟩ → [Hadamards] → [Phase Grating] → [QFT] → [CTF] → [IQFT] → |ψ_image⟩

This is a true quantum implementation where all operations are performed using quantum gates, not classical FFT.

Example

>>> params = QuantumCTEMParameters(
...     acceleration_voltage=200e3,
...     grid_size=8,
...     pixel_size=0.5,
...     defocus=-500.0,
...     cs=1.3
... )
>>> sim = QuantumCTEMCircuit(params)
>>> V = np.random.rand(8, 8) * 100  # Test potential
>>> result = sim.simulate(V)
>>> print(result['intensity'].shape)
(8, 8)
build_full_circuit(V: ndarray, include_barriers: bool = True) qiskit.QuantumCircuit[source]

Build complete quantum CTEM circuit.

Parameters:
  • V – Projected potential V(x,y) in V·Å, shape (N, N)

  • include_barriers – Add barriers between stages for visualization

Returns:

Complete quantum circuit for TEM simulation

simulate(V: ndarray) Dict[source]

Run complete quantum simulation and extract results.

Uses statevector simulation to extract the final wave function and intensity image.

Parameters:

V – Projected potential V(x,y) in V·Å, shape (N, N)

Returns:

  • ‘circuit’: The quantum circuit

  • ’psi_image’: Complex wave function ψ(x,y)

  • ’intensity’: Image intensity |ψ|²

  • ’metrics’: Circuit complexity metrics

  • ’parameters’: Physics parameters used

Return type:

Dictionary containing

get_ctf() ndarray[source]

Get the Contrast Transfer Function sin(χ(k)).

Returns:

CTF array of shape (N, N)

get_info() str[source]

Get simulation information string.

class quscope.quantum_ctem.quantum_ctem_circuit.QuantumClassicalValidator(params: QuantumCTEMParameters)[source]

Bases: object

Validate quantum CTEM against classical FFT simulation.

Computes fidelity and error metrics between quantum circuit simulation and classical numpy FFT-based simulation.

classical_simulation(V: ndarray) Dict[source]

Run classical FFT-based CTEM simulation.

Parameters:

V – Projected potential V(x,y) in V·Å

Returns:

Dictionary with classical results

compare(V: ndarray) Dict[source]

Compare quantum and classical simulations.

Parameters:

V – Projected potential

Returns:

  • ‘fidelity’: State fidelity |⟨ψ_c|ψ_q⟩|²

  • ’intensity_mse’: Mean squared error of intensities

  • ’quantum’: Quantum simulation results

  • ’classical’: Classical simulation results

Return type:

Dictionary with comparison metrics

quscope.quantum_ctem.quantum_ctem_circuit.demo_quantum_ctem()[source]

Demonstrate fully quantum CTEM simulation.

Quantum Multislice Circuit

Fully Quantum Multislice Simulation Circuit

This module extends the quantum CTEM implementation to support multislice simulations. In the multislice method, the sample is divided into multiple slices along the beam direction. The electron wave propagation is modeled as an alternating sequence of WPOA transmissions through the slices (in real space) and Fresnel propagations between slices (in momentum space).

The quantum circuit architecture for N slices:

|ψ₀⟩ → [Hadamards] → [Phase Grating 1] → [QFT] → [Fresnel Propagator 1] → [IQFT] → [Phase Grating 2] → [QFT] → [Fresnel Propagator 2] → [IQFT] … → [Phase Grating N] → [QFT] → [Lens CTF] → [IQFT] → |ψ_image⟩

class quscope.quantum_ctem.quantum_multislice_circuit.QuantumMultisliceParameters(acceleration_voltage: float, grid_size: int, pixel_size: float, defocus: float = 0.0, cs: float = 0.0, c5: float = 0.0, slice_thickness: float = 1.0)[source]

Bases: QuantumCTEMParameters

Parameters for fully quantum Multislice simulation.

Attributes inherit from QuantumCTEMParameters, with additional:

slice_thickness: Thickness of each discrete slice (Angstroms)

slice_thickness: float = 1.0
class quscope.quantum_ctem.quantum_multislice_circuit.FresnelPropagatorCircuit(n_qubits: int, n_qubits_x: int, n_qubits_y: int)[source]

Bases: object

Quantum circuit for Fresnel free-space propagator in momentum space.

The Fresnel propagator over distance Δz in the paraxial approximation is:

P(k) = exp(-i·π·λ·Δz·k²)

where k = √(k_x² + k_y²) is the spatial frequency magnitude. This introduces a phase shift in momentum space.

calculate_propagator_phase(wavelength: float, pixel_size: float, slice_thickness: float) ndarray[source]

Calculate Fresnel propagator phase function: -π·λ·Δz·k² - Kirkland (2020) Eq. 6.65

Parameters:
  • wavelength – Electron wavelength (Å)

  • pixel_size – Real-space pixel size (Å)

  • slice_thickness – Propagation distance Δz (Å)

Returns:

Propagator phase array of shape (N, N)

build_circuit(phase_k: ndarray) qiskit.QuantumCircuit[source]

Build Fresnel propagator circuit.

Parameters:

phase_k – Phase array in momentum space

Returns:

QuantumCircuit implementing exp(i·phase(k))

class quscope.quantum_ctem.quantum_multislice_circuit.QuantumMultisliceCircuit(params: QuantumMultisliceParameters)[source]

Bases: object

Complete quantum Multislice simulation circuit.

Implements the multislice imaging pipeline as a quantum circuit:

|ψ₀⟩ → [Hadamards]
→ loop over slices:

[Phase Grating] → [QFT] → [Fresnel Propagator] → [IQFT]

→ [QFT] → [Lens CTF] → [IQFT] → |ψ_image⟩

build_full_circuit(potentials: List[ndarray], include_barriers: bool = True) qiskit.QuantumCircuit[source]

Build complete quantum Multislice circuit.

Parameters:
  • potentials – List of projected potentials V(x,y) for each slice. Each array should have shape (N, N).

  • include_barriers – Add barriers between stages for visualization

Returns:

Complete quantum circuit

simulate(potentials: List[ndarray]) Dict[str, ndarray][source]

Run the quantum multislice simulation using Qiskit statevector simulator.

Parameters:

potentials – List of sample potentials for each slice

Returns:

‘statevector’: Full complex wave function ‘amplitude’: Real-space wave amplitude ‘phase’: Real-space wave phase ‘intensity’: Simulated image intensity

Return type:

Dictionary containing

class quscope.quantum_ctem.quantum_multislice_circuit.QuantumClassicalMultisliceValidator(params: QuantumMultisliceParameters)[source]

Bases: object

Validates quantum multislice simulation against classical multislice implementation.

classical_multislice(potentials: List[ndarray]) ndarray[source]

Perform classical baseline multislice.

compare(potentials: List[ndarray]) Dict[str, float][source]

Compare quantum and classical outputs.

Quantum Wave Function Encoding

Quantum Wave Function Representation for Pure Quantum CTEM

This module implements quantum encoding of electron wave functions for pure quantum Bloch wave simulation. The wave function ψ(x,y) is represented as a quantum state |ψ⟩ using amplitude encoding.

Physical Principle:

Classical wave function: ψ(x,y) = A(x,y) exp(iφ(x,y)) Quantum encoding: |ψ⟩ = Σ_{x,y} ψ(x,y)|x⟩|y⟩

This is the foundation for Phase 1 of the pure quantum CTEM development.

References

  • Le, P. Q., et al. (2011). “Quantum image processing.” Quantum Information Processing, 10(1), 63-89.

  • Schuld, M., & Petruccione, F. (2021). “Machine Learning with Quantum Computers.” Chapter 3: Quantum Feature Maps and Kernels.

Author: QuScope Development Team Date: October 3, 2025 Phase: 1.1 - Quantum State Encoding

class quscope.quantum_ctem.quantum_wave_function.QuantumWaveFunction(n_qubits_x: int, n_qubits_y: int)[source]

Bases: object

Pure quantum representation of electron wave function.

This class provides methods to encode classical wave functions ψ(x,y) as quantum states and decode quantum states back to classical arrays.

The encoding uses amplitude encoding where the complex values of ψ(x,y) directly become the amplitudes of quantum basis states |xy⟩.

n_qubits_x

Number of qubits for x dimension

Type:

int

n_qubits_y

Number of qubits for y dimension

Type:

int

pixels_x

Number of pixels in x (2^n_qubits_x)

Type:

int

pixels_y

Number of pixels in y (2^n_qubits_y)

Type:

int

total_qubits

Total qubits needed (n_qubits_x + n_qubits_y)

Type:

int

Example

>>> # Create quantum wave function for 8×8 image
>>> qwf = QuantumWaveFunction(n_qubits_x=3, n_qubits_y=3)
>>>
>>> # Prepare incident plane wave
>>> circuit = qwf.prepare_incident_wave()
>>>
>>> # Extract wave function
>>> psi = qwf.extract_wave(circuit)
>>> print(psi.shape)  # (8, 8)
prepare_incident_wave() qiskit.QuantumCircuit[source]

Prepare incident plane wave state.

For normal incidence CTEM, the incident wave is a plane wave: ψ₀(x,y) = 1 (constant everywhere)

In quantum representation: |ψ₀⟩ = 1/√N Σ_{x,y} |xy⟩

This is a uniform superposition over all spatial positions, created by applying Hadamard gates to all qubits.

Returns:

QuantumCircuit with incident plane wave prepared

Example

>>> qwf = QuantumWaveFunction(3, 3)
>>> circuit = qwf.prepare_incident_wave()
>>> psi = qwf.extract_wave(circuit)
>>> # psi should be uniform with value 1/√64
prepare_arbitrary_wave(psi_classical: ndarray, validate_shape: bool = True) qiskit.QuantumCircuit[source]

Prepare arbitrary complex wave function.

Encodes a classical wave function ψ(x,y) into quantum state: |ψ⟩ = Σ_{x,y} ψ(x,y)|xy⟩

The wave function is automatically normalized for quantum encoding, and the normalization factor is stored for later reconstruction.

Parameters:
  • psi_classical – Complex 2D array of shape (pixels_x, pixels_y)

  • validate_shape – Check if input shape matches expected dimensions

Returns:

QuantumCircuit with wave function prepared

Raises:

ValueError – If shape doesn’t match (pixels_x, pixels_y)

Example

>>> # Gaussian wave packet
>>> x = np.linspace(-4, 4, 8)
>>> X, Y = np.meshgrid(x, x)
>>> psi = np.exp(-(X**2 + Y**2)/2) * np.exp(1j * np.pi/4)
>>>
>>> qwf = QuantumWaveFunction(3, 3)
>>> circuit = qwf.prepare_arbitrary_wave(psi)
>>> psi_decoded = qwf.extract_wave(circuit)
>>> # psi_decoded should match psi (up to global phase)
extract_wave(circuit: qiskit.QuantumCircuit) ndarray[source]

Extract classical wave function from quantum circuit.

Decodes the quantum state back into a classical complex array. This uses statevector simulation to get the amplitudes, then reshapes and denormalizes to recover the original wave function.

Note: This operation requires a quantum statevector simulator and is exponentially expensive. In real quantum hardware, this would be replaced by tomography or other measurement protocols.

Parameters:

circuit – QuantumCircuit containing the quantum state

Returns:

Complex 2D array of shape (pixels_x, pixels_y)

Example

>>> qwf = QuantumWaveFunction(3, 3)
>>> circuit = qwf.prepare_incident_wave()
>>> psi = qwf.extract_wave(circuit)
>>> assert psi.shape == (8, 8)
>>> # For plane wave, all values should be equal
>>> assert np.allclose(np.abs(psi), np.abs(psi[0, 0]))
get_normalization_factor() float[source]

Get the stored normalization factor.

Returns:

Normalization factor from last encoding operation

create_2d_qft_circuit() qiskit.QuantumCircuit[source]

Create 2D Quantum Fourier Transform circuit.

Applies QFT separately to x and y dimensions: QFT₂D = QFT_x ⊗ QFT_y

This transforms real-space wave function to momentum space: |ψ(x,y)⟩ → |ψ(kₓ,k_y)⟩

Returns:

QuantumCircuit implementing 2D QFT

Example

>>> qwf = QuantumWaveFunction(3, 3)
>>> qft_circuit = qwf.create_2d_qft_circuit()
>>>
>>> # Apply to plane wave
>>> psi_circuit = qwf.prepare_incident_wave()
>>> psi_circuit.compose(qft_circuit, inplace=True)
>>>
>>> # Extract momentum space wave function
>>> psi_k = qwf.extract_wave(psi_circuit)
create_2d_iqft_circuit() qiskit.QuantumCircuit[source]

Create 2D Inverse Quantum Fourier Transform circuit.

Inverse of QFT₂D, transforms momentum space back to real space: |ψ(kₓ,k_y)⟩ → |ψ(x,y)⟩

Returns:

QuantumCircuit implementing 2D IQFT

get_info() Dict[str, any][source]

Get information about the quantum wave function configuration.

Returns:

Dictionary with configuration parameters

__repr__() str[source]

String representation of the quantum wave function.

Momentum Space (QFT-based)

Momentum space utilities for quantum CTEM.

This module provides enhanced momentum space operations for quantum electron microscopy simulations, including: - Direct k-space wave function encoding - Bidirectional real ↔ reciprocal space transformations - Energy conservation validation (Parseval’s theorem) - Momentum-space filtering operations

Physical Background: - Real space: |ψ(x,y)⟩ - Electron wave function in position basis - Momentum space: |ψ̃(kₓ,k_y)⟩ - Same state in momentum basis - Connection: QFT transforms between representations - Energy: E = ℏ²k²/2m - Related to momentum

Target: IBM quantum hardware with pure quantum operations.

Author: QuScope Team Date: October 2025

class quscope.quantum_ctem.momentum_space.MomentumSpaceConverter(n_qubits_x: int, n_qubits_y: int)[source]

Bases: object

Convert between real and momentum space representations.

This class provides utilities for working with electron wave functions in both position and momentum representations, crucial for: - Fresnel propagation (easier in k-space) - Aperture functions (applied in k-space) - Energy analysis - Wave packet dynamics

Physical Principle: ψ̃(k) = ∫ ψ(x) exp(-ikx) dx → Implemented via QFT ψ(x) = ∫ ψ̃(k) exp(ikx) dk → Implemented via IQFT

create_qft_circuit() qiskit.QuantumCircuit[source]

Create 2D QFT circuit for real → momentum space.

The 2D QFT is separable: QFT₂D = QFT_x ⊗ QFT_y

Returns:

2D QFT circuit

Return type:

QuantumCircuit

create_iqft_circuit() qiskit.QuantumCircuit[source]

Create 2D inverse QFT circuit for momentum → real space.

Returns:

2D inverse QFT circuit

Return type:

QuantumCircuit

transform_to_momentum(circuit: qiskit.QuantumCircuit) qiskit.QuantumCircuit[source]

Transform wave function from real to momentum space.

|ψ(x,y)⟩ → |ψ̃(kₓ,k_y)⟩

Parameters:

circuit (QuantumCircuit) – Circuit with wave function in real space

Returns:

Circuit with wave function in momentum space

Return type:

QuantumCircuit

transform_to_real(circuit: qiskit.QuantumCircuit) qiskit.QuantumCircuit[source]

Transform wave function from momentum to real space.

|ψ̃(kₓ,k_y)⟩ → |ψ(x,y)⟩

Parameters:

circuit (QuantumCircuit) – Circuit with wave function in momentum space

Returns:

Circuit with wave function in real space

Return type:

QuantumCircuit

get_momentum_grid(real_size: float, shift: bool = True) Tuple[ndarray, ndarray][source]

Get momentum space grid corresponding to real space grid.

For real space grid: x ∈ [-L/2, L/2] with N points Momentum space grid: k ∈ [-π/Δx, π/Δx] with N points where Δx = L/N

Parameters:
  • real_size (float) – Physical size of real space grid (Ångströms)

  • shift (bool, optional) – If True, shift grid to center zero frequency (default: True) If False, keep in FFT order matching QFT output

Returns:

kx_grid, ky_grid – 2D momentum grids (units: 1/Å)

Return type:

np.ndarray

class quscope.quantum_ctem.momentum_space.ParsevalValidator(tolerance: float = 1e-10)[source]

Bases: object

Validate energy conservation via Parseval’s theorem.

Parseval’s theorem states that the total energy (norm) is preserved under Fourier transform:

∫|ψ(x)|² dx = ∫|ψ̃(k)|² dk

Or in quantum notation: ⟨ψ|ψ⟩_real = ⟨ψ̃|ψ̃⟩_momentum

This is a critical validation for quantum CTEM algorithms.

validate_transform(circuit_real: qiskit.QuantumCircuit, circuit_momentum: qiskit.QuantumCircuit) Dict[str, bool | float][source]

Validate that QFT preserves energy (Parseval’s theorem).

Parameters:
  • circuit_real (QuantumCircuit) – Circuit with wave function in real space

  • circuit_momentum (QuantumCircuit) – Circuit with wave function in momentum space

Returns:

Validation results with keys: - ‘valid’: bool - Whether energy is conserved - ‘energy_real’: float - Energy in real space - ‘energy_momentum’: float - Energy in momentum space - ‘relative_error’: float - Relative error in conservation

Return type:

dict

validate_round_trip(circuit_original: qiskit.QuantumCircuit, circuit_round_trip: qiskit.QuantumCircuit) Dict[str, bool | float][source]

Validate QFT → IQFT round trip preserves state.

Tests: QFT(IQFT(|ψ⟩)) = |ψ⟩

Parameters:
  • circuit_original (QuantumCircuit) – Original circuit

  • circuit_round_trip (QuantumCircuit) – Circuit after QFT → IQFT

Returns:

Validation results with fidelity

Return type:

dict

class quscope.quantum_ctem.momentum_space.MomentumSpaceFilter(n_qubits_x: int, n_qubits_y: int)[source]

Bases: object

Apply filtering operations in momentum space.

Common filters in CTEM: - Low-pass: Remove high-k components (smoothing) - High-pass: Remove low-k components (edge enhancement) - Band-pass: Keep specific k-range - Objective aperture: Hard cutoff at k_max

Implementation: Apply phase or amplitude modulation in k-space

create_aperture_filter(k_max: float, kx_grid: ndarray, ky_grid: ndarray) ndarray[source]

Create objective aperture filter.

Filters out high-k components beyond aperture radius.

Parameters:
  • k_max (float) – Maximum k-vector magnitude (aperture radius)

  • kx_grid (np.ndarray) – Momentum space grids

  • ky_grid (np.ndarray) – Momentum space grids

Returns:

Filter mask (1 inside aperture, 0 outside)

Return type:

np.ndarray

create_lowpass_filter(k_cutoff: float, kx_grid: ndarray, ky_grid: ndarray, smoothness: float = 0.1) ndarray[source]

Create smooth low-pass filter.

Smoothly attenuates high-k components.

Parameters:
  • k_cutoff (float) – Cutoff frequency

  • kx_grid (np.ndarray) – Momentum space grids

  • ky_grid (np.ndarray) – Momentum space grids

  • smoothness (float) – Filter smoothness parameter (larger = smoother)

Returns:

Filter function

Return type:

np.ndarray

apply_filter_classical(psi_k: ndarray, filter_mask: ndarray) ndarray[source]

Apply filter in momentum space (classical simulation).

This is for validation and comparison. The full quantum implementation requires controlled amplitude modulation.

Parameters:
  • psi_k (np.ndarray) – Wave function in momentum space

  • filter_mask (np.ndarray) – Filter function (real-valued)

Returns:

Filtered wave function in momentum space

Return type:

np.ndarray

quscope.quantum_ctem.momentum_space.analyze_momentum_distribution(circuit: qiskit.QuantumCircuit, n_qubits_x: int, n_qubits_y: int, real_size: float = 10.0) Dict[str, ndarray][source]

Analyze momentum distribution of quantum wave function.

Parameters:
  • circuit (QuantumCircuit) – Circuit with wave function (in real or momentum space)

  • n_qubits_x (int) – Qubit dimensions

  • n_qubits_y (int) – Qubit dimensions

  • real_size (float) – Physical size of real space region (Å)

Returns:

Analysis results: - ‘momentum_amplitudes’: Complex amplitudes in k-space - ‘momentum_probabilities’: |ψ̃(k)|² - ‘kx_grid’: Momentum grid x-component - ‘ky_grid’: Momentum grid y-component - ‘mean_k’: Mean momentum vector - ‘k_spread’: Momentum spread (std deviation)

Return type:

dict

quscope.quantum_ctem.momentum_space.demonstrate_uncertainty_principle(n_qubits: int = 3, width_real: float = 2.0) Dict[str, float][source]

Demonstrate Heisenberg uncertainty principle: Δx·Δk ≥ 1/2

Creates Gaussian wave packet and measures position/momentum spreads.

Parameters:
  • n_qubits (int) – Number of qubits per dimension

  • width_real (float) – Width parameter for Gaussian in real space

Returns:

Results showing uncertainty relation

Return type:

dict

Contrast Transfer Function

Contrast Transfer Function (CTF) Calculator and Visualization

This module provides comprehensive CTF analysis for Conventional TEM including: - 1D radial CTF plots - 2D CTF visualization in momentum space - Multi-voltage comparison - Individual aberration contributions - Scherzer defocus calculation - Resolution limits

Designed for publication-quality figures suitable for both quantum computing and electron microscopy audiences.

References

  • Kirkland, E. J. (2010). Advanced Computing in Electron Microscopy.

  • Krivanek, O. L., et al. (2008). Ultramicroscopy 108(3), 179-195.

  • Spence, J. C. H. (2013). High-Resolution Electron Microscopy (4th ed.).

Author: QuScope Development Team Date: January 2025

class quscope.quantum_ctem.ctf_calculator.CTFParameters(voltage: float, defocus: float, cs: float = 0.0, c5: float = 0.0, aperture: float = 10.0, aberrations: Dict[str, float] | None = None)[source]

Bases: object

Parameters for CTF calculation.

voltage

Acceleration voltage (V)

Type:

float

defocus

Defocus C₁ (Angstrom)

Type:

float

cs

Spherical aberration C₃ (mm)

Type:

float

c5

5th order spherical aberration (mm)

Type:

float

aperture

Objective aperture semi-angle (mrad)

Type:

float

aberrations

Complete aberration dictionary

Type:

Dict[str, float]

voltage: float
defocus: float
cs: float = 0.0
c5: float = 0.0
aperture: float = 10.0
aberrations: Dict[str, float] = None
__post_init__()[source]

Initialize aberrations dictionary if not provided.

class quscope.quantum_ctem.ctf_calculator.CTFCalculator(params: CTFParameters, max_k: float = 10.0, n_points: int = 1000)[source]

Bases: object

Calculate Contrast Transfer Function for TEM.

The CTF describes how spatial frequencies are transferred from the sample to the image, including effects of defocus and aberrations.

For phase contrast imaging (weak phase object):

CTF(k) = A(k) · sin(χ(k)) - B(k) · cos(χ(k))

where χ(k) is the wave aberration function and A(k), B(k) are envelope functions describing partial coherence and damping effects.

For simplicity, we often use:

CTF(k) = sin(χ(k))

chi(k: ndarray, theta: ndarray | None = None) ndarray[source]

Calculate wave aberration function χ(k).

For axially symmetric aberrations (no astigmatism/coma):

χ(k) = π·λ·k²·C₁ + π/2·(λk)⁴·C₃ + π/3·(λk)⁶·C₅

Parameters:
  • k – Spatial frequency (1/Angstrom), scalar or array

  • theta – Azimuthal angle (radians), for non-axial aberrations

Returns:

χ(k) in radians

ctf(k: ndarray, theta: ndarray | None = None) ndarray[source]

Calculate CTF = sin(χ(k)).

Parameters:
  • k – Spatial frequency

  • theta – Azimuthal angle (optional)

Returns:

CTF value

calculate_scherzer_defocus() float[source]

Calculate Scherzer defocus for optimal phase contrast.

Scherzer defocus balances defocus and spherical aberration to maximize contrast transfer at medium spatial frequencies.

For C₃-dominated systems:

Δf_Scherzer = -1.2 · √(C₃·λ)

Returns:

Scherzer defocus (Angstrom), negative = overfocus

calculate_point_resolution() float[source]

Calculate point resolution (Scherzer limit).

d_Scherzer = 0.66 · (C₃·λ³)^(1/4)

This is the finest detail that can be resolved with optimal defocus in a Cs-uncorrected microscope.

Returns:

Point resolution (Angstrom)

find_first_zero() float[source]

Find first zero of CTF (point resolution crossover).

Returns:

k value of first CTF zero (1/Angstrom)

calculate_information_limit() float[source]

Calculate information limit (highest usable spatial frequency).

This is limited by damping envelopes due to: - Chromatic aberration - Partial spatial coherence - Partial temporal coherence - Instabilities

Simplified estimate based on aberrations:

k_max ≈ 1 / (acceptable phase error)

Returns:

Information limit (1/Angstrom)

class quscope.quantum_ctem.ctf_calculator.CTFVisualizer(figsize: Tuple[int, int] = (12, 10))[source]

Bases: object

Generate publication-quality CTF visualizations.

plot_1d_ctf(calculators: Dict[str, CTFCalculator], ax: matplotlib.pyplot.Axes | None = None, show_zeros: bool = True, show_envelope: bool = False) matplotlib.pyplot.Figure[source]

Plot 1D radial CTF for multiple conditions.

Parameters:
  • calculators – Dictionary of {label: CTFCalculator}

  • ax – Matplotlib axes (creates new if None)

  • show_zeros – Mark CTF zeros

  • show_envelope – Show envelope function

Returns:

Figure object

plot_2d_ctf(calc: CTFCalculator, n_points: int = 512, cmap: str = 'RdBu_r') matplotlib.pyplot.Figure[source]

Plot 2D CTF in momentum space.

Parameters:
  • calc – CTF calculator

  • n_points – Number of points in each dimension

  • cmap – Colormap name

Returns:

Figure object with 2D CTF visualization

plot_multi_voltage_comparison(voltages: List[float], cs: float = 1.3, defocus: float | None = None) matplotlib.pyplot.Figure[source]

Compare CTF for different acceleration voltages.

Parameters:
  • voltages – List of voltages (V), e.g., [80e3, 120e3, 200e3, 300e3]

  • cs – Spherical aberration (mm)

  • defocus – Defocus (Angstrom), uses Scherzer if None

Returns:

Figure with multi-voltage comparison

Hamiltonian

Quantum Hamiltonian for Conventional TEM

This module implements the complete quantum mechanical Hamiltonian for electron wave propagation in Conventional Transmission Electron Microscopy, including:

  1. Free propagation

  2. Sample interaction (Weak Phase Object Approximation)

  3. Lens aberrations (up to 5th order)

  4. Evolution operator decomposition

  5. Mapping to quantum circuits

Theoretical Framework:

The electron wave function evolution in TEM can be described by the time-independent Schrödinger equation with a position-dependent potential.

Total Hamiltonian:

H_total = H_0 + H_sample + H_lens

where:

H_0: Free particle kinetic energy H_sample: Sample-electron interaction H_lens: Lens aberrations in momentum space

The evolution operator is:

U = exp(-iH_lens·t/ℏ) · exp(-iH_sample·t/ℏ) · exp(-iH_0·t/ℏ)

This operator can be efficiently implemented as a quantum circuit.

References

  • Messiah, A. (1961). Quantum Mechanics. North-Holland.

  • Kirkland, E. J. (2010). Advanced Computing in Electron Microscopy.

  • Nielsen & Chuang (2010). Quantum Computation and Quantum Information.

Author: QuScope Development Team Date: January 2025

class quscope.quantum_ctem.hamiltonian.HamiltonianParameters(acceleration_voltage: float, wavelength: float, grid_size_x: int, grid_size_y: int, pixel_size: float, interaction_constant: float | None = None)[source]

Bases: object

Parameters for the quantum Hamiltonian.

acceleration_voltage

Electron acceleration voltage (V)

Type:

float

wavelength

Relativistic electron wavelength (Angstrom)

Type:

float

grid_size_x

Number of grid points in x

Type:

int

grid_size_y

Number of grid points in y

Type:

int

pixel_size

Real-space pixel size (Angstrom)

Type:

float

interaction_constant

σ = (2π·m_e·e·λ)/(h²) for WPOA

Type:

float

acceleration_voltage: float
wavelength: float
grid_size_x: int
grid_size_y: int
pixel_size: float
interaction_constant: float = None
__post_init__()[source]

Calculate interaction constant if not provided.

class quscope.quantum_ctem.hamiltonian.FreeParticleHamiltonian(params: HamiltonianParameters)[source]

Bases: object

Free particle Hamiltonian H₀ = p²/(2m) = ℏ²k²/(2m).

In the paraxial approximation (small scattering angles), this describes the kinetic energy of the electron beam.

For high-energy electrons (80-300 kV), relativistic corrections are small but can be included in the wavelength calculation.

energy() ndarray[source]

Calculate kinetic energy E = ℏ²k²/(2m).

In practice, we work with dimensionless units where ℏ=m=1, so E = k²/2.

Returns:

Energy at each k-point (2D array)

propagator(distance: float) ndarray[source]

Free space propagation operator exp(-iH₀·z/ℏ).

For small angles (paraxial approximation):

exp(-iH₀·z/ℏ) ≈ exp(-iπλz·k²)

Parameters:

distance – Propagation distance (Angstrom)

Returns:

Propagator in momentum space (2D complex array)

apply(psi: ndarray, distance: float) ndarray[source]

Apply free space propagation to wave function.

Parameters:
  • psi – Wave function in real space (2D complex array)

  • distance – Propagation distance (Angstrom)

Returns:

Propagated wave function in real space

class quscope.quantum_ctem.hamiltonian.SampleHamiltonian(params: HamiltonianParameters)[source]

Bases: object

Sample interaction Hamiltonian under Weak Phase Object Approximation (WPOA).

H_sample = V(x,y) where V is the projected atomic potential.

The transmission function is:

t(x,y) = exp(iσV(x,y))

where σ = (2π·m_e·e·λ)/(h²) is the interaction constant.

WPOA is valid when:

σV << 1 (weak phase modulation) Sample thickness << mean free path

set_potential(V: ndarray)[source]

Set the projected potential V(x,y).

Parameters:

V – Projected potential in V·Angstrom (2D array)

transmission_function() ndarray[source]

Calculate transmission function t(x,y) = exp(iσV(x,y)).

Returns:

Transmission function (2D complex array)

apply(psi: ndarray) ndarray[source]

Apply sample interaction to wave function.

This is a simple multiplication in real space:

ψ_exit(x,y) = ψ_incident(x,y) · t(x,y)

Parameters:

psi – Incident wave function (2D complex array)

Returns:

Exit wave function (2D complex array)

class quscope.quantum_ctem.hamiltonian.LensHamiltonian(params: HamiltonianParameters, aberrations: Dict[str, float])[source]

Bases: object

Lens aberration Hamiltonian in momentum space.

The lens applies a k-dependent phase shift:

H_lens → exp(iχ(k))

where χ(k) is the wave aberration function including all aberration coefficients up to 5th order.

This operator is diagonal in momentum space, making it efficient to apply.

calculate_aberration_function() ndarray[source]

Calculate complete wave aberration function χ(k).

Standard TEM convention (Kirkland, Spence & Zuo):

χ(k) = π λ Δf k² + 0.5 π λ³ Cs k⁴ + …

where:

λ = wavelength (Angstrom) Δf = defocus (Angstrom, positive = underfocus) k = spatial frequency (1/Angstrom) Cs = spherical aberration (Angstrom)

Returns:

χ(kx, ky) in radians (2D array)

transfer_function() ndarray[source]

Calculate lens transfer function exp(iχ(k)).

Returns:

Transfer function in momentum space (2D complex array)

ctf() ndarray[source]

Calculate Contrast Transfer Function sin(χ(k)).

For phase contrast imaging with weak phase objects.

Returns:

CTF (2D array)

apply(psi: ndarray) ndarray[source]

Apply lens aberrations to wave function.

This operates in momentum space:

ψ_image(k) = exp(iχ(k)) · ψ_exit(k)

Parameters:

psi – Exit wave function in real space (2D complex array)

Returns:

Image wave function in real space (2D complex array)

class quscope.quantum_ctem.hamiltonian.TEMHamiltonian(params: HamiltonianParameters, aberrations: Dict[str, float])[source]

Bases: object

Complete TEM Hamiltonian combining all contributions.

Total evolution:

U = U_lens · U_sample · U_propagation

This represents the complete electron wave propagation through: 1. Free space to sample 2. Sample interaction 3. Free space to image plane 4. Lens aberrations

set_sample_potential(V: ndarray)[source]

Set sample potential.

Parameters:

V – Projected potential (V·Angstrom)

propagate(psi_incident: ndarray, propagation_distance: float = 0.0) ndarray[source]

Complete TEM wave propagation.

Parameters:
  • psi_incident – Incident wave function

  • propagation_distance – Free space propagation before sample

Returns:

Final image wave function

get_ctf() ndarray[source]

Get Contrast Transfer Function.

get_aberration_function() ndarray[source]

Get wave aberration function χ(k).

calculate_intensity(psi: ndarray) ndarray[source]

Calculate image intensity I = |ψ|².

Parameters:

psi – Image wave function

Returns:

Intensity image

quscope.quantum_ctem.hamiltonian.relativistic_wavelength(voltage: float) float[source]

Calculate relativistic electron wavelength.

λ = h / √(2·m₀·e·V·(1 + e·V/(2·m₀·c²)))

Parameters:

voltage – Acceleration voltage (V)

Returns:

Wavelength in Angstroms

Quantum STEM

Quantum STEM (Scanning Transmission Electron Microscopy)

Simulates STEM images using TRUE quantum electron probe propagation.

Each probe position runs a quantum circuit (DiagonalGate + QFT). Detectors integrate scattered intensity over defined angular ranges:

HAADF — High-Angle Annular Dark Field (Z-contrast) ADF — Annular Dark Field ABF — Annular Bright Field BF — Bright Field iDPC — integrated Differential Phase Contrast

Physical steps per probe position:
  1. Coherent focused probe formed in k-space with CTF.

  2. Phase grating applied via quantum DiagonalGate circuit.

  3. Free-space propagation in k-space via diagonal phase (Fresnel).

  4. Detector masks applied → signal readout.

For large grids (n_qubits > MAX_SV_QUBITS) or large scan arrays, a classical numpy fallback is used automatically.

References

  • Kirkland (2010). Advanced Computing in Electron Microscopy.

  • Nellist & Pennycook (1999). Incoherent imaging. Adv. Imaging Elec. Phys. 113.

  • Ophus (2023). 4D-STEM. arXiv:2301.00345.

class quscope.quantum_ctem.quantum_stem.STEMDetectors(haadf_inner: float = 60.0, haadf_outer: float = 200.0, adf_inner: float = 25.0, adf_outer: float = 60.0, abf_inner: float = 10.0, abf_outer: float = 25.0, bf_outer: float = 10.0)[source]

Bases: object

Angular detector definitions for STEM.

All angles in mrad. Pass to run_stem().

haadf_inner: float = 60.0
haadf_outer: float = 200.0
adf_inner: float = 25.0
adf_outer: float = 60.0
abf_inner: float = 10.0
abf_outer: float = 25.0
bf_outer: float = 10.0
masks(N: int, pixel_size: float, wavelength: float) Dict[str, ndarray][source]

Return boolean k-space masks for each detector.

quscope.quantum_ctem.quantum_stem.run_stem(V: ndarray, pixel_size: float, voltage: float, convergence_mrad: float = 25.0, defocus_ang: float = 0.0, cs_mm: float = 0.0, detectors: STEMDetectors | None = None, scan_step_px: int = 1, store_4d: bool = False) Dict[source]

Run a quantum STEM simulation over the full field of view.

Parameters:
  • V (np.ndarray (N, N)) – Projected electrostatic potential [V·Å].

  • pixel_size (float) – Real-space pixel size [Å/pixel].

  • voltage (float) – Accelerating voltage [V].

  • convergence_mrad (float) – Semi-angle of convergence [mrad].

  • defocus_ang (float) – Probe defocus [Å]. Positive → over-focus.

  • cs_mm (float) – Spherical aberration coefficient [mm].

  • detectors (STEMDetectors or None) – Detector configuration. Uses defaults if None.

  • scan_step_px (int) – Scan step in pixels (1 = Nyquist, 2 = half-Nyquist, etc.).

  • store_4d (bool) – If True, store all diffraction patterns → 4D-STEM dataset.

Returns:

‘HAADF’, ‘ADF’, ‘ABF’, ‘BF’ — STEM images (N_scan, N_scan) ‘idpc’ — iDPC image ‘images’ — dict of all images ‘KX’, ‘KY’ — k-space axes ‘metadata’ — parameters dict ‘data4d’ — 4D array if store_4d=True

Return type:

dict with keys

Quantum Multislice STEM

Extends quantum_stem.py’s single-slice WPOA STEM to full multislice: at each probe position, the focused probe is propagated through N slices via the same alternating phase-grating / Fresnel-propagation sequence used in quantum_multislice_circuit.py. Then the exit wave is scattered into the same HAADF/ADF/BF/iDPC detectors as run_stem().

quscope.quantum_ctem.quantum_stem_multislice.fresnel_propagator_phase(N: int, pixel_size: float, wavelength: float, slice_thickness: float) ndarray[source]

P(k) = exp(-i*pi*lambda*dz*k^2), flattened, unshifted (matches fft2 ordering).

quscope.quantum_ctem.quantum_stem_multislice.build_probe_circuit(n_q: int, grating_list: List[ndarray], propagator: ndarray) qiskit.QuantumCircuit[source]

Assemble the quantum multislice circuit (DiagonalGate + QFTGate throughout) for one probe position. This is the “show your work” circuit object. Use it for depth/gate-count reporting or single-shot demonstrations. Do not call this inside the scan-position loop -> use the array-based run_stem_multislice for that.

quscope.quantum_ctem.quantum_stem_multislice.run_stem_multislice(V_total: ndarray, pixel_size: float, voltage: float, n_slices: int = 4, slice_thickness: float = 6.5, convergence_mrad: float = 15.0, defocus_ang: float = 0.0, cs_mm: float = 0.0, detectors: STEMDetectors | None = None, scan_step_px: int = 1, max_qubits: int = 16) Dict[source]

Fully quantum multislice STEM image.

Splits V_total evenly into n_slices slices (pass a list directly via V_total already pre-split if you want a physically layered structure instead of a uniform split – just pass a 3D array of shape (n_slices, N, N) and it will be used as-is).

Parameters mirror quantum_stem.run_stem() plus the slice geometry. Note: choose pixel_size/grid such that Nyquist k_max = 1/(2*pixel_size) comfortably exceeds your detector angles in 1/Angstrom (k = mrad*1e-3/wavelength).

Circuit Optimization

Circuit optimization for quantum CTEM implementation.

This module provides tools to optimize quantum circuits for: 1. Reduced circuit depth (critical for NISQ devices) 2. Hardware-specific gate sets (IBM quantum devices) 3. Qubit connectivity constraints 4. Error mitigation strategies

Target Hardware: IBM Quantum devices (127+ qubits) - ibm_kyoto: 127 qubits - ibm_osaka: 127 qubits - ibm_brisbane: 127 qubits

Author: QuScope Team Date: October 2025

class quscope.quantum_ctem.circuit_optimization.StatePreparationOptimizer(method: str = 'direct', optimization_level: int = 3)[source]

Bases: object

Optimize quantum state preparation circuits for hardware deployment.

The state initialization circuit |0⟩^n → |ψ⟩ is often the deepest part of quantum algorithms. This class provides multiple strategies to reduce circuit depth while maintaining fidelity.

Strategies: 1. Direct: Qiskit’s built-in initialize() with optimization 2. Schmidt decomposition: Exploit entanglement structure 3. Variational: Parameterized circuits (requires training) 4. QGAN: Quantum GAN approach (requires training)

For hardware deployment, we focus on Direct + transpilation.

prepare_state(psi: ndarray, num_qubits: int, normalize: bool = True) qiskit.QuantumCircuit[source]

Prepare quantum state |ψ⟩ from classical array.

Parameters:
  • psi (np.ndarray) – Target state vector (flattened or 2D)

  • num_qubits (int) – Number of qubits for the state

  • normalize (bool) – Whether to normalize the state vector

Returns:

Optimized state preparation circuit

Return type:

QuantumCircuit

Notes

For hardware execution, this circuit will be transpiled to the native gate set of the target device. IBM devices typically use {√X, X, RZ, CNOT} or {SX, RZ, ECR} basis.

get_circuit_metrics(qc: qiskit.QuantumCircuit) Dict[str, int][source]

Get circuit complexity metrics.

Returns:

  • ‘depth’: Circuit depth (critical for NISQ devices)

  • ’gates’: Total gate count

  • ’1q_gates’: Single-qubit gate count

  • ’2q_gates’: Two-qubit gate count (most expensive)

  • ’qubits’: Number of qubits used

Return type:

dict

class quscope.quantum_ctem.circuit_optimization.HardwareTranspiler(backend_name: str | None = None, optimization_level: int = 3, seed_transpiler: int = 42)[source]

Bases: object

Transpile circuits for specific IBM quantum hardware.

This class handles: 1. Gate set conversion to native gates 2. Qubit routing and SWAP insertion 3. Pulse-level optimization (optional) 4. Error mitigation preparation

transpile_for_hardware(circuit: qiskit.QuantumCircuit, initial_layout: List[int] | None = None) qiskit.QuantumCircuit[source]

Transpile circuit for target hardware.

This converts the circuit to: 1. Native gate set (e.g., {SX, RZ, ECR} for IBM) 2. Hardware topology (insert SWAPs for non-adjacent qubits) 3. Optimized depth (minimize decoherence effects)

Parameters:
  • circuit (QuantumCircuit) – High-level quantum circuit

  • initial_layout (list, optional) – Initial qubit mapping to physical qubits

Returns:

Hardware-optimized transpiled circuit

Return type:

QuantumCircuit

estimate_fidelity(circuit: qiskit.QuantumCircuit, gate_error_1q: float = 0.0001, gate_error_2q: float = 0.01) float[source]

Estimate circuit fidelity on noisy hardware.

Uses simple error model: F ≈ (1 - ε₁)^(n₁) × (1 - ε₂)^(n₂)

where: - ε₁, ε₂: single/two-qubit gate errors - n₁, n₂: number of single/two-qubit gates

Parameters:
  • circuit (QuantumCircuit) – Transpiled circuit

  • gate_error_1q (float) – Single-qubit gate error rate (typical: 1e-4)

  • gate_error_2q (float) – Two-qubit gate error rate (typical: 1e-2)

Returns:

Estimated fidelity (0 to 1)

Return type:

float

compare_strategies(circuits: Dict[str, qiskit.QuantumCircuit]) Dict[str, Dict][source]

Compare multiple implementation strategies.

Parameters:

circuits (dict) – Dictionary of {strategy_name: circuit}

Returns:

Comparison metrics for each strategy

Return type:

dict

quscope.quantum_ctem.circuit_optimization.benchmark_state_preparation(n_qubits_list: List[int], methods: List[str] = ['direct', 'schmidt']) Dict[source]

Benchmark state preparation methods across different system sizes.

Parameters:
  • n_qubits_list (list) – List of qubit counts to test [2, 4, 6, 8, …]

  • methods (list) – Preparation methods to compare

Returns:

Benchmark results with circuit metrics

Return type:

dict

Classical Integration and Validation

Classical-Quantum Integration Module

This module provides interfaces between pure quantum CTEM implementations and classical simulators (WPOA and Multislice). Enables: 1. Quantum wave function ↔ Classical wave function conversion 2. Consistency validation between quantum and classical methods 3. Performance benchmarking 4. Hybrid simulation workflows

Week 3 Task 1.6: Connect to Classical Simulators

Author: QuScope Development Team Date: October 4, 2025

class quscope.quantum_ctem.classical_integration.QuantumClassicalBridge(n_qubits_x: int, n_qubits_y: int)[source]

Bases: object

Bridge between quantum and classical wave function representations.

Provides bidirectional conversion and validation between: - Quantum circuits (Qiskit QuantumCircuit) - Classical wave functions (NumPy complex arrays)

This enables: - Using quantum encodings with classical simulators - Validating quantum results against classical benchmarks - Hybrid quantum-classical workflows

Example

>>> bridge = QuantumClassicalBridge(n_qubits_x=3, n_qubits_y=3)
>>>
>>> # Classical → Quantum
>>> psi_classical = np.random.rand(8, 8) + 1j*np.random.rand(8, 8)
>>> circuit = bridge.classical_to_quantum(psi_classical)
>>>
>>> # Quantum → Classical
>>> psi_decoded = bridge.quantum_to_classical(circuit)
>>>
>>> # Validate consistency
>>> error = np.max(np.abs(psi_classical - psi_decoded))
>>> print(f"Round-trip error: {error:.2e}")
n_qubits_x

Number of qubits for x dimension

n_qubits_y

Number of qubits for y dimension

qwf

QuantumWaveFunction instance for encoding/decoding

classical_to_quantum(psi_classical: ndarray, normalize: bool = True) qiskit.QuantumCircuit[source]

Convert classical wave function to quantum circuit.

Takes a classical 2D complex wave function and encodes it into a quantum circuit using amplitude encoding.

Parameters:
  • psi_classical – Complex wave function, shape (pixels_y, pixels_x)

  • normalize – If True, normalize the wave function before encoding

Returns:

QuantumCircuit representing the wave function

Raises:

ValueError – If shape doesn’t match expected dimensions

Example

>>> # Create Gaussian wave packet
>>> x = np.linspace(-4, 4, 8)
>>> X, Y = np.meshgrid(x, x)
>>> psi = np.exp(-(X**2 + Y**2)/4)
>>>
>>> bridge = QuantumClassicalBridge(3, 3)
>>> circuit = bridge.classical_to_quantum(psi)
>>> print(f"Qubits: {circuit.num_qubits}")
quantum_to_classical(circuit: qiskit.QuantumCircuit) ndarray[source]

Convert quantum circuit to classical wave function.

Extracts the wave function from a quantum circuit by measuring the quantum state amplitudes.

Parameters:

circuit – Quantum circuit encoding the wave function

Returns:

Complex wave function array, shape (pixels_y, pixels_x)

Example

>>> circuit = bridge.classical_to_quantum(psi)
>>> psi_recovered = bridge.quantum_to_classical(circuit)
>>> error = np.linalg.norm(psi - psi_recovered)
>>> print(f"Reconstruction error: {error:.2e}")
validate_consistency(psi_classical: ndarray, circuit: qiskit.QuantumCircuit, tolerance: float = 1e-06) Dict[str, bool | float][source]

Validate consistency between classical and quantum representations.

Compares a classical wave function with its quantum circuit representation to ensure they encode the same information.

Parameters:
  • psi_classical – Classical wave function

  • circuit – Quantum circuit encoding

  • tolerance – Maximum acceptable error

Returns:

  • valid: True if error < tolerance

  • max_error: Maximum absolute error

  • mean_error: Mean absolute error

  • norm_difference: Difference in normalization

  • fidelity: State fidelity (0-1)

Return type:

Dictionary with validation results

Example

>>> circuit = bridge.classical_to_quantum(psi)
>>> results = bridge.validate_consistency(psi, circuit)
>>> if results['valid']:
...     print(f"✅ Consistent (error: {results['max_error']:.2e})")
... else:
...     print(f"❌ Inconsistent (error: {results['max_error']:.2e})")
class quscope.quantum_ctem.classical_integration.WPOAQuantumInterface(wpoa_simulator, n_qubits_x: int, n_qubits_y: int)[source]

Bases: object

Interface between WPOA classical simulator and quantum implementations.

Enables using quantum wave function encodings with the classical WPOA simulator, facilitating: - Hybrid quantum-classical simulations - Quantum algorithm validation against classical benchmarks - Performance comparisons

Example

>>> from quscope.ctem import WPOASimulator
>>>
>>> # Initialize simulators
>>> wpoa = WPOASimulator(image_size=50, pixels=256, beam_energy=200e3)
>>> interface = WPOAQuantumInterface(wpoa, n_qubits_x=4, n_qubits_y=4)
>>>
>>> # Simulate with quantum encoding
>>> atoms = [(0, 0, 6), (5, 0, 14)]
>>> results = interface.simulate_with_quantum_encoding(
...     atoms, defocus=700, Cs=1.3e7
... )
>>>
>>> # Compare quantum vs classical
>>> comparison = interface.compare_quantum_classical(atoms)
wpoa

WPOASimulator instance

bridge

QuantumClassicalBridge for conversions

n_qubits_x

Number of qubits for x dimension

n_qubits_y

Number of qubits for y dimension

simulate_with_quantum_encoding(atom_positions: List[Tuple[float, float, int]], defocus: float = 700.0, Cs: float = 13000000.0, alpha_max: float | None = None, downsample: bool = True) Dict[str, ndarray | qiskit.QuantumCircuit][source]

Run WPOA simulation using quantum wave function encoding.

Pipeline: 1. Classical WPOA simulates transmission function 2. Downsample to quantum grid size if needed 3. Encode transmission into quantum circuit 4. Classical propagation (lens CTF + inverse FFT) 5. Encode final wave function quantum

Parameters:
  • atom_positions – List of (x, y, Z) atom coordinates

  • defocus – Defocus in Angstroms

  • Cs – Spherical aberration in Angstroms

  • alpha_max – Aperture semi-angle in milliradians

  • downsample – If True, downsample to quantum grid size

Returns:

  • transmission_classical: Classical transmission function

  • transmission_quantum: Quantum circuit encoding transmission

  • wavefunction_classical: Final classical wave function

  • wavefunction_quantum: Final quantum circuit

  • intensity: Image intensity

  • potential: Atomic potential

  • consistency: Validation metrics

Return type:

Dictionary containing

compare_quantum_classical(atom_positions: List[Tuple[float, float, int]], defocus: float = 700.0, Cs: float = 13000000.0) Dict[str, float | ndarray][source]

Compare quantum encoding vs pure classical simulation.

Runs both quantum-encoded and pure classical simulations to validate that quantum encoding preserves accuracy.

Parameters:
  • atom_positions – List of (x, y, Z) atom coordinates

  • defocus – Defocus in Angstroms

  • Cs – Spherical aberration in Angstroms

Returns:

  • transmission_error: Max error in transmission function

  • wavefunction_error: Max error in final wave function

  • intensity_error: Max error in intensity image

  • transmission_fidelity: State fidelity

  • wavefunction_fidelity: State fidelity

  • quantum_overhead: Circuit depth/gates info

Return type:

Dictionary with comparison metrics

class quscope.quantum_ctem.classical_integration.MultisliceQuantumInterface(multislice_simulator, n_qubits_x: int, n_qubits_y: int)[source]

Bases: object

Interface between Multislice classical simulator and quantum implementations.

Enables using quantum wave function encodings with the classical multislice simulator for thick specimen simulations.

Example

>>> from quscope.ctem import MultisliceSimulator
>>>
>>> # Initialize simulators
>>> multislice = MultisliceSimulator(
...     image_size=40, pixels=256, beam_energy=200e3, slice_thickness=2.0
... )
>>> interface = MultisliceQuantumInterface(multislice, n_qubits_x=4, n_qubits_y=4)
>>>
>>> # Simulate with quantum encoding at each slice
>>> atoms = generate_crystal_atoms()
>>> results = interface.simulate_with_quantum_slices(
...     atoms, num_slices=100, defocus=0
... )
multislice

MultisliceSimulator instance

bridge

QuantumClassicalBridge for conversions

n_qubits_x

Number of qubits for x dimension

n_qubits_y

Number of qubits for y dimension

simulate_with_quantum_slices(atom_positions: List[Tuple[float, float, float, int]], num_slices: int, defocus: float = 0, Cs: float = 0, record_slices: List[int] | None = None) Dict[str, List | ndarray][source]

Run multislice simulation with quantum encoding at specified slices.

Performs multislice propagation and encodes the wave function into quantum circuits at specified slice indices for analysis.

Parameters:
  • atom_positions – List of (x, y, z, Z) atom coordinates

  • num_slices – Total number of slices

  • defocus – Defocus in Angstroms

  • Cs – Spherical aberration in Angstroms

  • record_slices – Slice indices to encode quantum (default: [0, middle, end])

Returns:

  • intensity_final: Final intensity image

  • quantum_snapshots: List of quantum circuits at recorded slices

  • classical_snapshots: List of classical wave functions

  • consistency: Validation metrics at each recorded slice

  • slice_indices: Which slices were recorded

Return type:

Dictionary containing

quscope.quantum_ctem.classical_integration.benchmark_quantum_classical_integration(n_qubits_range: List[int] = [2, 3, 4], num_trials: int = 5) Dict[str, List][source]

Benchmark quantum-classical integration performance.

Measures: - Encoding time: classical → quantum - Decoding time: quantum → classical - Round-trip accuracy - Memory overhead

Parameters:
  • n_qubits_range – List of qubit counts to test

  • num_trials – Number of trials per configuration

Returns:

  • n_qubits: List of qubit counts tested

  • encoding_times: Mean encoding time per config

  • decoding_times: Mean decoding time per config

  • errors: Mean round-trip errors

  • memory_overhead: Quantum vs classical memory ratio

Return type:

Dictionary with benchmark results

Example

>>> results = benchmark_quantum_classical_integration([2, 3, 4])
>>> import matplotlib.pyplot as plt
>>> plt.plot(results['n_qubits'], results['encoding_times'])
>>> plt.xlabel('Number of Qubits')
>>> plt.ylabel('Encoding Time (s)')

IBM Hardware Integration

IBM Quantum Hardware Deployment Testing

Validates quantum CTEM implementation for deployment on IBM Quantum systems. Tests real hardware constraints, connectivity, basis gates, and error mitigation.

Week 4 Task 1.8: IBM Hardware Validation

Author: QuScope Development Team Date: January 2025

class quscope.quantum_ctem.ibm_hardware_validation.IBMDeviceProfile(name: str, num_qubits: int, basis_gates: List[str], coupling_map: List[List[int]] | None, single_qubit_error: float, two_qubit_error: float, readout_error: float, t1_us: float, t2_us: float)[source]

Bases: object

IBM Quantum device specifications.

name

Device name (e.g., ‘ibm_kyoto’)

Type:

str

num_qubits

Total number of qubits

Type:

int

basis_gates

List of native gates

Type:

List[str]

coupling_map

Qubit connectivity as list of edges

Type:

List[List[int]] | None

single_qubit_error

Average single-qubit gate error rate

Type:

float

two_qubit_error

Average two-qubit gate error rate

Type:

float

readout_error

Average measurement error rate

Type:

float

t1_us

T1 coherence time in microseconds

Type:

float

t2_us

T2 coherence time in microseconds

Type:

float

name: str
num_qubits: int
basis_gates: List[str]
coupling_map: List[List[int]] | None
single_qubit_error: float
two_qubit_error: float
readout_error: float
t1_us: float
t2_us: float
static ibm_kyoto() IBMDeviceProfile[source]

IBM Kyoto device profile (127 qubits, heavy-hex topology). One of the most advanced IBM Quantum systems available.

static ibm_brisbane() IBMDeviceProfile[source]

IBM Brisbane device profile (127 qubits, heavy-hex topology). Slightly better single-qubit performance than Kyoto.

static ibm_nazca() IBMDeviceProfile[source]

IBM Nazca device profile (127 qubits, heavy-hex topology). Good balance of qubit count and error rates.

static ibm_sherbrooke() IBMDeviceProfile[source]

IBM Sherbrooke device profile (127 qubits, heavy-hex topology). Best overall coherence times.

create_backend() qiskit.providers.fake_provider.GenericBackendV2[source]

Create a GenericBackendV2 instance with this device’s specifications.

Returns:

GenericBackendV2 configured with device parameters

quscope.quantum_ctem.ibm_hardware_validation.estimate_fidelity(circuit: qiskit.QuantumCircuit, device: IBMDeviceProfile) float[source]

Estimate circuit fidelity on a given IBM device based on gate counts and error rates.

Parameters:
  • circuit – Quantum circuit to estimate fidelity for

  • device – IBM device profile with error rates

Returns:

Estimated fidelity (0 to 1)

class quscope.quantum_ctem.ibm_hardware_validation.IBMHardwareValidator[source]

Bases: object

Validates quantum circuits for deployment on IBM Quantum hardware.

Features: - Circuit transpilation to IBM basis gates - Connectivity validation for heavy-hex topology - Fidelity estimation based on gate counts - Device comparison and recommendations - Qubit mapping optimization

Example

validator = IBMHardwareValidator() results = validator.validate_for_device(‘ibm_kyoto’, n_qubits=4) guide = validator.generate_deployment_guide(results)

validate_circuit_for_ibm(circuit: qiskit.QuantumCircuit, device_name: str) Dict[source]

Validate a quantum circuit for a specific IBM device.

Parameters:
  • circuit – Quantum circuit to validate

  • device_name – Name of IBM device (‘ibm_kyoto’, etc.)

Returns:

  • transpiled_circuit: Circuit transpiled to device basis

  • original_depth: Original circuit depth

  • transpiled_depth: Depth after transpilation

  • original_gates: Original gate count

  • transpiled_gates: Gate count after transpilation

  • estimated_fidelity: Expected fidelity on device

  • execution_time_us: Estimated execution time

  • warnings: List of any issues

Return type:

Dictionary with validation results including

validate_for_device(device_name: str, n_qubits: int = 4) Dict[source]

Complete validation workflow for a specific device.

Creates test circuit, validates for device, returns comprehensive results.

Parameters:
  • device_name – Name of IBM device

  • n_qubits – Number of qubits for test circuit (total, will be split for 2D)

Returns:

Validation results dictionary

compare_devices(n_qubits: int = 4) Dict[str, Dict][source]

Compare all IBM devices for the same test circuit.

Parameters:

n_qubits – Number of qubits for test circuit

Returns:

Dictionary mapping device names to validation results

test_qubit_mapping(device_name: str, n_qubits: int = 4) Dict[source]

Test different transpilation optimization levels and qubit mappings.

Parameters:
  • device_name – Name of IBM device

  • n_qubits – Number of qubits for test circuit (total)

Returns:

Dictionary with results for different optimization levels

generate_deployment_guide(device_results: Dict[str, Dict]) str[source]

Generate microscopist-friendly deployment guide.

Parameters:

device_results – Results from compare_devices()

Returns:

Markdown-formatted deployment guide

quscope.quantum_ctem.ibm_hardware_validation.validate_ibm_deployment(device: str = 'ibm_kyoto', n_qubits: int = 4) Dict[source]

Convenience function for IBM deployment validation.

Parameters:
  • device – IBM device name (‘ibm_kyoto’, ‘ibm_brisbane’, ‘ibm_nazca’, ‘ibm_sherbrooke’)

  • n_qubits – Number of qubits for test circuit

Returns:

Validation results dictionary

Example

>>> results = validate_ibm_deployment('ibm_kyoto', n_qubits=4)
>>> print(f"Estimated fidelity: {results['estimated_fidelity']:.1%}")

Benchmarking and Visualization

Performance Benchmarking Suite for Quantum CTEM

Comprehensive performance analysis tools for quantum CTEM implementations: - Encoding/decoding timing analysis - Circuit complexity scaling (depth, gates, qubits) - Memory profiling - Hardware execution time estimates - Quantum vs classical comparison

Week 3 Task 1.7: Performance Benchmarking

Author: QuScope Development Team Date: October 5, 2025

class quscope.quantum_ctem.performance_benchmarking.BenchmarkResult(n_qubits_x: int, n_qubits_y: int, pixels: int, encoding_time: float, decoding_time: float, round_trip_time: float, circuit_depth: int, total_gates: int, single_qubit_gates: int, two_qubit_gates: int, memory_classical: float, memory_circuit: float, memory_statevector: float, round_trip_error: float, fidelity: float, estimated_runtime_ibm: float, estimated_fidelity_ibm: float)[source]

Bases: object

Container for benchmark results.

n_qubits_x: int
n_qubits_y: int
pixels: int
encoding_time: float
decoding_time: float
round_trip_time: float
circuit_depth: int
total_gates: int
single_qubit_gates: int
two_qubit_gates: int
memory_classical: float
memory_circuit: float
memory_statevector: float
round_trip_error: float
fidelity: float
estimated_runtime_ibm: float
estimated_fidelity_ibm: float
to_dict() Dict[source]

Convert to dictionary.

to_json() str[source]

Convert to JSON string.

class quscope.quantum_ctem.performance_benchmarking.PerformanceBenchmark(random_seed: int | None = 42)[source]

Bases: object

Comprehensive performance benchmarking for quantum CTEM.

Measures: - Encoding/decoding speed - Circuit complexity scaling - Memory usage - Hardware deployment estimates - Quantum vs classical overhead

Example

>>> benchmark = PerformanceBenchmark()
>>>
>>> # Run scaling analysis
>>> results = benchmark.run_scaling_analysis(
...     n_qubits_range=[2, 3, 4, 5],
...     num_trials=10
... )
>>>
>>> # Visualize results
>>> benchmark.plot_scaling_results(results)
>>>
>>> # Generate report
>>> benchmark.generate_report(results, output_file='benchmark_report.md')
benchmark_single_configuration(n_qubits_x: int, n_qubits_y: int, num_trials: int = 5) BenchmarkResult[source]

Benchmark a single grid configuration.

Parameters:
  • n_qubits_x – Number of qubits for x dimension

  • n_qubits_y – Number of qubits for y dimension

  • num_trials – Number of trials to average

Returns:

BenchmarkResult with all metrics

run_scaling_analysis(n_qubits_range: List[int] = [2, 3, 4, 5, 6], num_trials: int = 5) List[BenchmarkResult][source]

Run scaling analysis across multiple grid sizes.

Parameters:
  • n_qubits_range – List of qubit counts to test

  • num_trials – Number of trials per configuration

Returns:

List of BenchmarkResult objects

compare_optimization_methods(n_qubits: int = 4, num_trials: int = 5) Dict[str, Dict][source]

Compare different circuit optimization methods.

Parameters:
  • n_qubits – Number of qubits per dimension

  • num_trials – Number of trials per method

Returns:

Dictionary with results for each method

profile_memory_usage(n_qubits_range: List[int] = [2, 3, 4, 5]) Dict[str, List][source]

Profile memory usage across grid sizes.

Parameters:

n_qubits_range – List of qubit counts to test

Returns:

Dictionary with memory profiles

estimate_hardware_costs(n_qubits_range: List[int] = [2, 3, 4, 5], shots_per_run: int = 1024) Dict[str, List][source]

Estimate costs for running on IBM quantum hardware.

Parameters:
  • n_qubits_range – List of qubit counts to test

  • shots_per_run – Number of shots per execution

Returns:

Dictionary with cost estimates

save_results(results: List[BenchmarkResult], output_file: str = 'benchmark_results.json')[source]

Save benchmark results to JSON file.

Parameters:
  • results – List of BenchmarkResult objects

  • output_file – Output file path

generate_report(results: List[BenchmarkResult], output_file: str = 'benchmark_report.md')[source]

Generate markdown report from benchmark results.

Parameters:
  • results – List of BenchmarkResult objects

  • output_file – Output markdown file path

quscope.quantum_ctem.performance_benchmarking.quick_benchmark(n_qubits: int = 3) BenchmarkResult[source]

Run a quick benchmark for a single configuration.

Parameters:

n_qubits – Number of qubits per dimension

Returns:

BenchmarkResult

Example

>>> result = quick_benchmark(n_qubits=4)
>>> print(f"Encoding: {result.encoding_time*1000:.2f}ms")
>>> print(f"Depth: {result.circuit_depth}")

Visualization Tools for Performance Benchmarking

Creates publication-quality plots and visualizations for benchmark results.

Week 3 Task 1.7: Performance Benchmarking

Author: QuScope Development Team Date: October 5, 2025

class quscope.quantum_ctem.benchmark_visualization.BenchmarkVisualizer(style: str = 'seaborn-v0_8-darkgrid')[source]

Bases: object

Create visualizations for benchmark results.

Example

>>> from quscope.quantum_ctem import PerformanceBenchmark, BenchmarkVisualizer
>>>
>>> # Run benchmarks
>>> benchmark = PerformanceBenchmark()
>>> results = benchmark.run_scaling_analysis([2, 3, 4, 5])
>>>
>>> # Visualize
>>> visualizer = BenchmarkVisualizer()
>>> visualizer.plot_all(results, save_path='benchmarks.png')
plot_scaling_analysis(results: List[BenchmarkResult], save_path: str | None = None)[source]

Plot comprehensive scaling analysis.

Creates 4-panel figure: 1. Timing scaling 2. Circuit complexity scaling 3. Memory scaling 4. Hardware estimates

plot_accuracy_analysis(results: List[BenchmarkResult], save_path: str | None = None)[source]

Plot accuracy metrics across grid sizes.

plot_optimization_comparison(comparison_results: Dict[str, Dict], save_path: str | None = None)[source]

Plot comparison of optimization methods.

plot_memory_profile(memory_data: Dict[str, List], save_path: str | None = None)[source]

Plot memory usage profile.

plot_hardware_costs(cost_data: Dict[str, List], save_path: str | None = None)[source]

Plot hardware deployment cost estimates.

plot_all(results: List[BenchmarkResult], save_dir: str | None = None)[source]

Create all visualization plots.

Parameters:
  • results – List of benchmark results

  • save_dir – Directory to save plots (if None, only display)

quscope.quantum_ctem.benchmark_visualization.create_summary_figure(results: List[BenchmarkResult], save_path: str = 'benchmark_summary.png')[source]

Create single summary figure with key metrics.

Parameters:
  • results – List of benchmark results

  • save_path – Path to save figure