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:
ABCAbstract base class for quantum backends.
All backends (simulator, IBM hardware, etc.) must implement this interface to ensure consistent behavior across the quantum CTEM package.
- 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
- 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:
objectConfiguration for quantum backend execution.
- 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:
objectStandardized result from quantum circuit execution.
- class quscope.quantum_ctem.backends.SimulatorBackend(simulation_method: str = 'statevector', device: str | None = None, seed: int | None = None)[source]
Bases:
BackendLocal 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")
- 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:
BackendIBM 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.
- 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")
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:
ABCAbstract 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.
- 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·Å
- 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:
objectPhysical parameters for a material.
- 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:
objectKirkland 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)
- class quscope.quantum_ctem.materials.MoS2(layer_type: str = '2H')[source]
Bases:
MaterialMolybdenum 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.
- class quscope.quantum_ctem.materials.Graphene(edge_type: str = 'zigzag')[source]
Bases:
MaterialGraphene 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
- 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")
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:
ABCAbstract 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
- 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:
objectCTEM microscope configuration parameters.
Based on typical parameters for modern 200-300 kV instruments.
- 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:
objectComplete result from a quantum CTEM simulation.
Contains the wavefunction, image intensity, and all metadata needed for analysis and visualization.
- microscope_config: MicroscopeConfig | None = None
- backend_result: ExecutionResult | None = None
- 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:
CTEMWorkflowQuantum 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:
CTEMWorkflowQuantum 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:
- Physical Framework:
Incident plane wave: Uniform superposition via Hadamard gates
Phase grating: exp(iσV) via DiagonalGate (WPOA transmission)
QFT: Transform to momentum space (2D separable QFT)
Lens CTF: exp(iχ(k)) via DiagonalGate (aberration function)
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:
objectParameters for fully quantum CTEM simulation.
- 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:
objectQuantum 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.
- class quscope.quantum_ctem.quantum_ctem_circuit.LensCTFCircuit(n_qubits: int, n_qubits_x: int, n_qubits_y: int)[source]
Bases:
objectQuantum 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)
- class quscope.quantum_ctem.quantum_ctem_circuit.QuantumCTEMCircuit(params: QuantumCTEMParameters)[source]
Bases:
objectComplete quantum CTEM simulation circuit.
Implements the full TEM imaging pipeline as a quantum circuit:
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
- class quscope.quantum_ctem.quantum_ctem_circuit.QuantumClassicalValidator(params: QuantumCTEMParameters)[source]
Bases:
objectValidate 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
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:
QuantumCTEMParametersParameters for fully quantum Multislice simulation.
- Attributes inherit from QuantumCTEMParameters, with additional:
slice_thickness: Thickness of each discrete slice (Angstroms)
- class quscope.quantum_ctem.quantum_multislice_circuit.FresnelPropagatorCircuit(n_qubits: int, n_qubits_x: int, n_qubits_y: int)[source]
Bases:
objectQuantum 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)
- class quscope.quantum_ctem.quantum_multislice_circuit.QuantumMultisliceCircuit(params: QuantumMultisliceParameters)[source]
Bases:
objectComplete quantum Multislice simulation circuit.
Implements the multislice imaging pipeline as a quantum circuit:
- 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:
objectValidates quantum multislice simulation against classical multislice implementation.
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:
objectPure 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⟩.
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
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:
objectConvert 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.
- 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.
- Parameters:
circuit (QuantumCircuit) – Circuit with wave function in momentum space
- Returns:
Circuit with wave function in real space
- Return type:
QuantumCircuit
- class quscope.quantum_ctem.momentum_space.ParsevalValidator(tolerance: float = 1e-10)[source]
Bases:
objectValidate 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:
- validate_round_trip(circuit_original: qiskit.QuantumCircuit, circuit_round_trip: qiskit.QuantumCircuit) Dict[str, bool | float][source]
Validate QFT → IQFT round trip preserves state.
- Parameters:
circuit_original (QuantumCircuit) – Original circuit
circuit_round_trip (QuantumCircuit) – Circuit after QFT → IQFT
- Returns:
Validation results with fidelity
- Return type:
- class quscope.quantum_ctem.momentum_space.MomentumSpaceFilter(n_qubits_x: int, n_qubits_y: int)[source]
Bases:
objectApply 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.
- 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:
- 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:
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:
objectParameters for CTF calculation.
- class quscope.quantum_ctem.ctf_calculator.CTFCalculator(params: CTFParameters, max_k: float = 10.0, n_points: int = 1000)[source]
Bases:
objectCalculate 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:
objectGenerate 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:
Free propagation
Sample interaction (Weak Phase Object Approximation)
Lens aberrations (up to 5th order)
Evolution operator decomposition
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:
objectParameters for the quantum Hamiltonian.
- class quscope.quantum_ctem.hamiltonian.FreeParticleHamiltonian(params: HamiltonianParameters)[source]
Bases:
objectFree 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)
- class quscope.quantum_ctem.hamiltonian.SampleHamiltonian(params: HamiltonianParameters)[source]
Bases:
objectSample 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)
- class quscope.quantum_ctem.hamiltonian.LensHamiltonian(params: HamiltonianParameters, aberrations: Dict[str, float])[source]
Bases:
objectLens 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)
- class quscope.quantum_ctem.hamiltonian.TEMHamiltonian(params: HamiltonianParameters, aberrations: Dict[str, float])[source]
Bases:
objectComplete 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)
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:
Coherent focused probe formed in k-space with CTF.
Phase grating applied via quantum DiagonalGate circuit.
Free-space propagation in k-space via diagonal phase (Fresnel).
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:
objectAngular detector definitions for STEM.
All angles in mrad. Pass to run_stem().
- 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:
objectOptimize 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:
- 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:
- class quscope.quantum_ctem.circuit_optimization.HardwareTranspiler(backend_name: str | None = None, optimization_level: int = 3, seed_transpiler: int = 42)[source]
Bases:
objectTranspile 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
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:
objectBridge 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:
objectInterface 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:
objectInterface 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:
objectIBM Quantum device specifications.
- 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:
objectValidates 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
- 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:
objectContainer for benchmark results.
- class quscope.quantum_ctem.performance_benchmarking.PerformanceBenchmark(random_seed: int | None = 42)[source]
Bases:
objectComprehensive 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:
objectCreate 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.
- 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