qiskit 1.4.1__cp39-abi3-macosx_11_0_arm64.whl → 2.0.0rc1__cp39-abi3-macosx_11_0_arm64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- qiskit/VERSION.txt +1 -1
- qiskit/__init__.py +2 -5
- qiskit/_accelerate.abi3.so +0 -0
- qiskit/circuit/__init__.py +24 -5
- qiskit/circuit/{add_control.py → _add_control.py} +32 -12
- qiskit/circuit/_classical_resource_map.py +5 -3
- qiskit/circuit/barrier.py +3 -7
- qiskit/circuit/classical/expr/__init__.py +31 -3
- qiskit/circuit/classical/expr/constructors.py +248 -28
- qiskit/circuit/classical/expr/expr.py +104 -3
- qiskit/circuit/classical/expr/visitors.py +75 -0
- qiskit/circuit/classical/types/__init__.py +12 -8
- qiskit/circuit/classical/types/ordering.py +14 -7
- qiskit/circuit/classical/types/types.py +36 -0
- qiskit/circuit/commutation_checker.py +34 -7
- qiskit/circuit/controlflow/__init__.py +32 -1
- qiskit/circuit/controlflow/_builder_utils.py +9 -5
- qiskit/circuit/controlflow/box.py +163 -0
- qiskit/circuit/controlflow/break_loop.py +1 -1
- qiskit/circuit/controlflow/builder.py +139 -39
- qiskit/circuit/controlflow/continue_loop.py +1 -3
- qiskit/circuit/controlflow/control_flow.py +10 -0
- qiskit/circuit/controlflow/for_loop.py +2 -1
- qiskit/circuit/controlflow/if_else.py +3 -16
- qiskit/circuit/controlflow/switch_case.py +2 -8
- qiskit/circuit/controlflow/while_loop.py +2 -7
- qiskit/circuit/controlledgate.py +2 -4
- qiskit/circuit/delay.py +40 -11
- qiskit/circuit/duration.py +0 -15
- qiskit/circuit/gate.py +2 -4
- qiskit/circuit/instruction.py +2 -141
- qiskit/circuit/instructionset.py +7 -54
- qiskit/circuit/library/__init__.py +34 -5
- qiskit/circuit/library/arithmetic/__init__.py +16 -10
- qiskit/circuit/library/arithmetic/adders/cdkm_ripple_carry_adder.py +1 -1
- qiskit/circuit/library/arithmetic/adders/draper_qft_adder.py +2 -2
- qiskit/circuit/library/arithmetic/adders/vbe_ripple_carry_adder.py +1 -1
- qiskit/circuit/library/arithmetic/exact_reciprocal.py +64 -21
- qiskit/circuit/library/arithmetic/integer_comparator.py +37 -80
- qiskit/circuit/library/arithmetic/linear_amplitude_function.py +169 -2
- qiskit/circuit/library/arithmetic/linear_pauli_rotations.py +59 -5
- qiskit/circuit/library/arithmetic/piecewise_chebyshev.py +154 -6
- qiskit/circuit/library/arithmetic/piecewise_linear_pauli_rotations.py +114 -4
- qiskit/circuit/library/arithmetic/piecewise_polynomial_pauli_rotations.py +191 -15
- qiskit/circuit/library/arithmetic/polynomial_pauli_rotations.py +93 -39
- qiskit/circuit/library/arithmetic/quadratic_form.py +168 -2
- qiskit/circuit/library/arithmetic/weighted_adder.py +73 -1
- qiskit/circuit/library/bit_flip_oracle.py +130 -0
- qiskit/circuit/library/blueprintcircuit.py +52 -16
- qiskit/circuit/library/data_preparation/initializer.py +1 -1
- qiskit/circuit/library/data_preparation/pauli_feature_map.py +4 -4
- qiskit/circuit/library/data_preparation/state_preparation.py +1 -1
- qiskit/circuit/library/generalized_gates/gms.py +1 -1
- qiskit/circuit/library/generalized_gates/isometry.py +1 -1
- qiskit/circuit/library/generalized_gates/pauli.py +1 -2
- qiskit/circuit/library/generalized_gates/uc.py +97 -7
- qiskit/circuit/library/generalized_gates/uc_pauli_rot.py +1 -1
- qiskit/circuit/library/generalized_gates/unitary.py +4 -2
- qiskit/circuit/library/hamiltonian_gate.py +1 -1
- qiskit/circuit/library/n_local/evolved_operator_ansatz.py +1 -1
- qiskit/circuit/library/n_local/n_local.py +1 -1
- qiskit/circuit/library/n_local/qaoa_ansatz.py +1 -1
- qiskit/circuit/library/overlap.py +2 -2
- qiskit/circuit/library/pauli_evolution.py +39 -24
- qiskit/circuit/library/phase_oracle.py +130 -51
- qiskit/circuit/library/standard_gates/__init__.py +0 -1
- qiskit/circuit/library/standard_gates/dcx.py +3 -4
- qiskit/circuit/library/standard_gates/ecr.py +3 -4
- qiskit/circuit/library/standard_gates/global_phase.py +5 -6
- qiskit/circuit/library/standard_gates/h.py +4 -9
- qiskit/circuit/library/standard_gates/i.py +2 -2
- qiskit/circuit/library/standard_gates/iswap.py +3 -4
- qiskit/circuit/library/standard_gates/p.py +15 -34
- qiskit/circuit/library/standard_gates/r.py +2 -6
- qiskit/circuit/library/standard_gates/rx.py +5 -15
- qiskit/circuit/library/standard_gates/rxx.py +3 -6
- qiskit/circuit/library/standard_gates/ry.py +5 -17
- qiskit/circuit/library/standard_gates/ryy.py +3 -6
- qiskit/circuit/library/standard_gates/rz.py +5 -17
- qiskit/circuit/library/standard_gates/rzx.py +3 -6
- qiskit/circuit/library/standard_gates/rzz.py +3 -6
- qiskit/circuit/library/standard_gates/s.py +6 -15
- qiskit/circuit/library/standard_gates/swap.py +4 -11
- qiskit/circuit/library/standard_gates/sx.py +7 -12
- qiskit/circuit/library/standard_gates/t.py +6 -7
- qiskit/circuit/library/standard_gates/u.py +2 -10
- qiskit/circuit/library/standard_gates/u1.py +5 -16
- qiskit/circuit/library/standard_gates/u2.py +2 -6
- qiskit/circuit/library/standard_gates/u3.py +3 -11
- qiskit/circuit/library/standard_gates/x.py +13 -60
- qiskit/circuit/library/standard_gates/xx_minus_yy.py +2 -5
- qiskit/circuit/library/standard_gates/xx_plus_yy.py +2 -5
- qiskit/circuit/library/standard_gates/y.py +4 -9
- qiskit/circuit/library/standard_gates/z.py +5 -15
- qiskit/circuit/measure.py +11 -2
- qiskit/circuit/parameterexpression.py +4 -0
- qiskit/circuit/quantumcircuit.py +881 -555
- qiskit/circuit/random/utils.py +12 -6
- qiskit/circuit/reset.py +5 -2
- qiskit/circuit/singleton.py +5 -11
- qiskit/circuit/store.py +0 -8
- qiskit/compiler/__init__.py +1 -7
- qiskit/compiler/transpiler.py +38 -196
- qiskit/converters/circuit_to_dag.py +4 -2
- qiskit/converters/circuit_to_dagdependency.py +0 -2
- qiskit/converters/circuit_to_dagdependency_v2.py +0 -1
- qiskit/converters/circuit_to_gate.py +1 -1
- qiskit/converters/circuit_to_instruction.py +16 -29
- qiskit/converters/dag_to_circuit.py +5 -5
- qiskit/converters/dag_to_dagdependency.py +0 -1
- qiskit/converters/dag_to_dagdependency_v2.py +0 -1
- qiskit/converters/dagdependency_to_circuit.py +0 -6
- qiskit/converters/dagdependency_to_dag.py +0 -6
- qiskit/dagcircuit/collect_blocks.py +32 -20
- qiskit/dagcircuit/dagdependency.py +3 -37
- qiskit/dagcircuit/dagdependency_v2.py +2 -80
- qiskit/dagcircuit/dagnode.py +14 -2
- qiskit/passmanager/__init__.py +24 -6
- qiskit/passmanager/passmanager.py +26 -24
- qiskit/primitives/__init__.py +44 -35
- qiskit/primitives/backend_estimator_v2.py +102 -23
- qiskit/primitives/backend_sampler_v2.py +5 -20
- qiskit/primitives/base/__init__.py +4 -4
- qiskit/primitives/base/base_estimator.py +77 -82
- qiskit/primitives/base/base_primitive_job.py +2 -2
- qiskit/primitives/base/{base_primitive.py → base_primitive_v1.py} +1 -1
- qiskit/primitives/base/{base_result.py → base_result_v1.py} +1 -1
- qiskit/primitives/base/base_sampler.py +52 -60
- qiskit/primitives/base/{estimator_result.py → estimator_result_v1.py} +2 -2
- qiskit/primitives/base/{sampler_result.py → sampler_result_v1.py} +2 -2
- qiskit/primitives/base/{validation.py → validation_v1.py} +34 -15
- qiskit/primitives/containers/bindings_array.py +3 -1
- qiskit/primitives/containers/bit_array.py +23 -0
- qiskit/primitives/containers/data_bin.py +3 -1
- qiskit/primitives/containers/observables_array.py +19 -2
- qiskit/primitives/statevector_sampler.py +6 -8
- qiskit/primitives/utils.py +14 -189
- qiskit/providers/__init__.py +4 -130
- qiskit/providers/backend.py +11 -314
- qiskit/providers/basic_provider/__init__.py +3 -1
- qiskit/providers/basic_provider/basic_provider.py +29 -9
- qiskit/providers/basic_provider/basic_simulator.py +158 -298
- qiskit/providers/exceptions.py +0 -33
- qiskit/providers/fake_provider/__init__.py +0 -37
- qiskit/providers/fake_provider/generic_backend_v2.py +32 -693
- qiskit/qasm2/__init__.py +21 -6
- qiskit/qasm2/export.py +2 -10
- qiskit/qasm2/parse.py +11 -25
- qiskit/qasm3/__init__.py +5 -1
- qiskit/qasm3/ast.py +44 -0
- qiskit/qasm3/exporter.py +65 -27
- qiskit/qasm3/printer.py +35 -4
- qiskit/qpy/__init__.py +141 -19
- qiskit/qpy/binary_io/__init__.py +0 -1
- qiskit/qpy/binary_io/circuits.py +91 -116
- qiskit/qpy/binary_io/schedules.py +61 -388
- qiskit/qpy/binary_io/value.py +154 -28
- qiskit/qpy/common.py +10 -7
- qiskit/qpy/formats.py +41 -0
- qiskit/qpy/interface.py +29 -62
- qiskit/qpy/type_keys.py +58 -221
- qiskit/quantum_info/analysis/distance.py +3 -1
- qiskit/quantum_info/operators/dihedral/dihedral.py +3 -1
- qiskit/quantum_info/operators/operator.py +6 -2
- qiskit/quantum_info/operators/symplectic/clifford.py +3 -1
- qiskit/quantum_info/operators/symplectic/pauli.py +4 -2
- qiskit/quantum_info/operators/symplectic/pauli_list.py +17 -5
- qiskit/quantum_info/operators/symplectic/sparse_pauli_op.py +40 -6
- qiskit/quantum_info/states/densitymatrix.py +16 -6
- qiskit/quantum_info/states/stabilizerstate.py +35 -4
- qiskit/quantum_info/states/statevector.py +16 -6
- qiskit/result/__init__.py +5 -17
- qiskit/result/models.py +18 -10
- qiskit/result/result.py +28 -126
- qiskit/result/sampled_expval.py +1 -2
- qiskit/result/utils.py +3 -4
- qiskit/synthesis/__init__.py +21 -1
- qiskit/synthesis/arithmetic/__init__.py +3 -1
- qiskit/synthesis/arithmetic/adders/cdkm_ripple_carry_adder.py +1 -1
- qiskit/synthesis/arithmetic/adders/draper_qft_adder.py +1 -1
- qiskit/synthesis/arithmetic/adders/vbe_ripple_carry_adder.py +2 -2
- qiskit/{providers/fake_provider/backends_v1/fake_20q → synthesis/arithmetic/comparators}/__init__.py +4 -6
- qiskit/synthesis/arithmetic/comparators/compare_2s.py +112 -0
- qiskit/synthesis/arithmetic/comparators/compare_greedy.py +66 -0
- qiskit/synthesis/arithmetic/multipliers/hrs_cumulative_multiplier.py +1 -1
- qiskit/synthesis/arithmetic/multipliers/rg_qft_multiplier.py +1 -1
- qiskit/synthesis/arithmetic/weighted_sum.py +155 -0
- qiskit/{result/mitigation → synthesis/boolean}/__init__.py +2 -2
- qiskit/synthesis/boolean/boolean_expression.py +231 -0
- qiskit/synthesis/boolean/boolean_expression_synth.py +124 -0
- qiskit/synthesis/boolean/boolean_expression_visitor.py +96 -0
- qiskit/synthesis/discrete_basis/generate_basis_approximations.py +2 -0
- qiskit/synthesis/evolution/lie_trotter.py +10 -7
- qiskit/synthesis/evolution/product_formula.py +44 -35
- qiskit/synthesis/evolution/qdrift.py +17 -24
- qiskit/synthesis/evolution/suzuki_trotter.py +20 -27
- qiskit/synthesis/linear/linear_depth_lnn.py +6 -221
- qiskit/synthesis/linear_phase/cx_cz_depth_lnn.py +4 -205
- qiskit/synthesis/multi_controlled/__init__.py +1 -0
- qiskit/synthesis/multi_controlled/mcx_synthesis.py +5 -2
- qiskit/synthesis/multi_controlled/multi_control_rotation_gates.py +206 -0
- qiskit/synthesis/one_qubit/one_qubit_decompose.py +1 -1
- qiskit/synthesis/two_qubit/__init__.py +1 -0
- qiskit/synthesis/two_qubit/two_qubit_decompose.py +28 -145
- qiskit/transpiler/__init__.py +32 -232
- qiskit/transpiler/basepasses.py +20 -51
- qiskit/transpiler/layout.py +1 -1
- qiskit/transpiler/passes/__init__.py +2 -40
- qiskit/transpiler/passes/basis/basis_translator.py +4 -3
- qiskit/transpiler/passes/basis/decompose.py +1 -15
- qiskit/transpiler/passes/basis/unroll_3q_or_more.py +1 -5
- qiskit/transpiler/passes/basis/unroll_custom_definitions.py +3 -2
- qiskit/transpiler/passes/layout/apply_layout.py +4 -0
- qiskit/transpiler/passes/layout/dense_layout.py +2 -39
- qiskit/transpiler/passes/layout/full_ancilla_allocation.py +4 -4
- qiskit/transpiler/passes/layout/sabre_layout.py +7 -3
- qiskit/transpiler/passes/layout/vf2_layout.py +2 -20
- qiskit/transpiler/passes/layout/vf2_post_layout.py +60 -125
- qiskit/transpiler/passes/layout/vf2_utils.py +2 -26
- qiskit/transpiler/passes/optimization/__init__.py +1 -3
- qiskit/transpiler/passes/optimization/collect_and_collapse.py +2 -0
- qiskit/transpiler/passes/optimization/collect_cliffords.py +5 -0
- qiskit/transpiler/passes/optimization/collect_linear_functions.py +5 -0
- qiskit/transpiler/passes/optimization/collect_multiqubit_blocks.py +16 -1
- qiskit/transpiler/passes/optimization/commutation_analysis.py +3 -3
- qiskit/transpiler/passes/optimization/consolidate_blocks.py +41 -19
- qiskit/transpiler/passes/optimization/contract_idle_wires_in_control_flow.py +104 -0
- qiskit/transpiler/passes/optimization/light_cone.py +135 -0
- qiskit/transpiler/passes/optimization/optimize_1q_commutation.py +0 -1
- qiskit/transpiler/passes/optimization/optimize_1q_decomposition.py +18 -22
- qiskit/transpiler/passes/optimization/optimize_annotated.py +3 -2
- qiskit/transpiler/passes/optimization/remove_identity_equiv.py +6 -4
- qiskit/transpiler/passes/optimization/reset_after_measure_simplification.py +5 -2
- qiskit/transpiler/passes/optimization/split_2q_unitaries.py +26 -3
- qiskit/transpiler/passes/optimization/template_matching/template_substitution.py +1 -0
- qiskit/transpiler/passes/routing/__init__.py +0 -1
- qiskit/transpiler/passes/routing/commuting_2q_gate_routing/commuting_2q_gate_router.py +3 -1
- qiskit/transpiler/passes/routing/sabre_swap.py +14 -6
- qiskit/transpiler/passes/routing/star_prerouting.py +1 -1
- qiskit/transpiler/passes/scheduling/__init__.py +1 -7
- qiskit/transpiler/passes/scheduling/alignments/__init__.py +2 -4
- qiskit/transpiler/passes/scheduling/alignments/check_durations.py +1 -9
- qiskit/transpiler/passes/scheduling/alignments/reschedule.py +17 -16
- qiskit/transpiler/passes/scheduling/padding/base_padding.py +30 -2
- qiskit/transpiler/passes/scheduling/padding/dynamical_decoupling.py +20 -58
- qiskit/transpiler/passes/scheduling/padding/pad_delay.py +11 -3
- qiskit/transpiler/passes/scheduling/scheduling/alap.py +5 -39
- qiskit/transpiler/passes/scheduling/scheduling/asap.py +4 -35
- qiskit/transpiler/passes/scheduling/scheduling/base_scheduler.py +10 -16
- qiskit/transpiler/passes/scheduling/time_unit_conversion.py +127 -59
- qiskit/transpiler/passes/synthesis/default_unitary_synth_plugin.py +653 -0
- qiskit/transpiler/passes/synthesis/high_level_synthesis.py +176 -601
- qiskit/transpiler/passes/synthesis/hls_plugins.py +294 -1
- qiskit/transpiler/passes/synthesis/plugin.py +4 -0
- qiskit/transpiler/passes/synthesis/solovay_kitaev_synthesis.py +16 -10
- qiskit/transpiler/passes/synthesis/unitary_synthesis.py +34 -697
- qiskit/transpiler/passes/utils/__init__.py +0 -1
- qiskit/transpiler/passes/utils/check_gate_direction.py +13 -5
- qiskit/transpiler/passes/utils/control_flow.py +2 -6
- qiskit/transpiler/passes/utils/gate_direction.py +7 -0
- qiskit/transpiler/passes/utils/remove_final_measurements.py +40 -33
- qiskit/transpiler/passmanager.py +13 -0
- qiskit/transpiler/passmanager_config.py +5 -81
- qiskit/transpiler/preset_passmanagers/builtin_plugins.py +225 -344
- qiskit/transpiler/preset_passmanagers/common.py +140 -167
- qiskit/transpiler/preset_passmanagers/generate_preset_pass_manager.py +101 -322
- qiskit/transpiler/preset_passmanagers/level0.py +2 -11
- qiskit/transpiler/preset_passmanagers/level1.py +2 -14
- qiskit/transpiler/preset_passmanagers/level2.py +2 -12
- qiskit/transpiler/preset_passmanagers/level3.py +2 -11
- qiskit/transpiler/preset_passmanagers/plugin.py +5 -3
- qiskit/transpiler/target.py +67 -524
- qiskit/user_config.py +8 -4
- qiskit/utils/__init__.py +13 -12
- qiskit/utils/deprecation.py +4 -112
- qiskit/utils/optionals.py +11 -4
- qiskit/utils/parallel.py +214 -87
- qiskit/utils/units.py +4 -1
- qiskit/visualization/__init__.py +3 -7
- qiskit/visualization/array.py +4 -1
- qiskit/visualization/bloch.py +1 -1
- qiskit/visualization/circuit/_utils.py +19 -19
- qiskit/visualization/circuit/circuit_visualization.py +11 -4
- qiskit/visualization/circuit/matplotlib.py +13 -23
- qiskit/visualization/circuit/text.py +7 -3
- qiskit/visualization/dag_visualization.py +2 -1
- qiskit/visualization/gate_map.py +39 -154
- qiskit/visualization/pass_manager_visualization.py +6 -2
- qiskit/visualization/state_visualization.py +6 -0
- qiskit/visualization/timeline/core.py +18 -12
- qiskit/visualization/timeline/interface.py +19 -18
- {qiskit-1.4.1.dist-info → qiskit-2.0.0rc1.dist-info}/METADATA +2 -2
- {qiskit-1.4.1.dist-info → qiskit-2.0.0rc1.dist-info}/RECORD +297 -444
- {qiskit-1.4.1.dist-info → qiskit-2.0.0rc1.dist-info}/WHEEL +2 -1
- {qiskit-1.4.1.dist-info → qiskit-2.0.0rc1.dist-info}/entry_points.txt +8 -2
- qiskit/assembler/__init__.py +0 -42
- qiskit/assembler/assemble_circuits.py +0 -451
- qiskit/assembler/assemble_schedules.py +0 -367
- qiskit/assembler/disassemble.py +0 -310
- qiskit/assembler/run_config.py +0 -77
- qiskit/circuit/bit.py +0 -106
- qiskit/circuit/classicalfunction/__init__.py +0 -152
- qiskit/circuit/classicalfunction/boolean_expression.py +0 -138
- qiskit/circuit/classicalfunction/classical_element.py +0 -54
- qiskit/circuit/classicalfunction/classical_function_visitor.py +0 -155
- qiskit/circuit/classicalfunction/classicalfunction.py +0 -182
- qiskit/circuit/classicalfunction/exceptions.py +0 -41
- qiskit/circuit/classicalfunction/types.py +0 -18
- qiskit/circuit/classicalfunction/utils.py +0 -91
- qiskit/circuit/classicalregister.py +0 -57
- qiskit/circuit/library/standard_gates/multi_control_rotation_gates.py +0 -405
- qiskit/circuit/quantumregister.py +0 -75
- qiskit/circuit/register.py +0 -246
- qiskit/compiler/assembler.py +0 -689
- qiskit/compiler/scheduler.py +0 -109
- qiskit/compiler/sequencer.py +0 -71
- qiskit/primitives/backend_estimator.py +0 -486
- qiskit/primitives/backend_sampler.py +0 -222
- qiskit/primitives/estimator.py +0 -172
- qiskit/primitives/sampler.py +0 -162
- qiskit/providers/backend_compat.py +0 -507
- qiskit/providers/fake_provider/backends_v1/__init__.py +0 -22
- qiskit/providers/fake_provider/backends_v1/fake_127q_pulse/__init__.py +0 -18
- qiskit/providers/fake_provider/backends_v1/fake_127q_pulse/conf_washington.json +0 -1
- qiskit/providers/fake_provider/backends_v1/fake_127q_pulse/defs_washington.json +0 -1
- qiskit/providers/fake_provider/backends_v1/fake_127q_pulse/fake_127q_pulse_v1.py +0 -37
- qiskit/providers/fake_provider/backends_v1/fake_127q_pulse/props_washington.json +0 -1
- qiskit/providers/fake_provider/backends_v1/fake_20q/conf_singapore.json +0 -1
- qiskit/providers/fake_provider/backends_v1/fake_20q/fake_20q.py +0 -43
- qiskit/providers/fake_provider/backends_v1/fake_20q/props_singapore.json +0 -1
- qiskit/providers/fake_provider/backends_v1/fake_27q_pulse/__init__.py +0 -18
- qiskit/providers/fake_provider/backends_v1/fake_27q_pulse/conf_hanoi.json +0 -1
- qiskit/providers/fake_provider/backends_v1/fake_27q_pulse/defs_hanoi.json +0 -1
- qiskit/providers/fake_provider/backends_v1/fake_27q_pulse/fake_27q_pulse_v1.py +0 -50
- qiskit/providers/fake_provider/backends_v1/fake_27q_pulse/props_hanoi.json +0 -1
- qiskit/providers/fake_provider/backends_v1/fake_5q/__init__.py +0 -18
- qiskit/providers/fake_provider/backends_v1/fake_5q/conf_yorktown.json +0 -1
- qiskit/providers/fake_provider/backends_v1/fake_5q/fake_5q_v1.py +0 -41
- qiskit/providers/fake_provider/backends_v1/fake_5q/props_yorktown.json +0 -1
- qiskit/providers/fake_provider/backends_v1/fake_7q_pulse/__init__.py +0 -18
- qiskit/providers/fake_provider/backends_v1/fake_7q_pulse/conf_nairobi.json +0 -1
- qiskit/providers/fake_provider/backends_v1/fake_7q_pulse/defs_nairobi.json +0 -1
- qiskit/providers/fake_provider/backends_v1/fake_7q_pulse/fake_7q_pulse_v1.py +0 -44
- qiskit/providers/fake_provider/backends_v1/fake_7q_pulse/props_nairobi.json +0 -1
- qiskit/providers/fake_provider/fake_1q.py +0 -91
- qiskit/providers/fake_provider/fake_backend.py +0 -165
- qiskit/providers/fake_provider/fake_openpulse_2q.py +0 -391
- qiskit/providers/fake_provider/fake_openpulse_3q.py +0 -340
- qiskit/providers/fake_provider/fake_pulse_backend.py +0 -49
- qiskit/providers/fake_provider/fake_qasm_backend.py +0 -77
- qiskit/providers/fake_provider/utils/backend_converter.py +0 -150
- qiskit/providers/fake_provider/utils/json_decoder.py +0 -109
- qiskit/providers/models/__init__.py +0 -89
- qiskit/providers/models/backendconfiguration.py +0 -1040
- qiskit/providers/models/backendproperties.py +0 -535
- qiskit/providers/models/backendstatus.py +0 -104
- qiskit/providers/models/jobstatus.py +0 -77
- qiskit/providers/models/pulsedefaults.py +0 -305
- qiskit/providers/provider.py +0 -95
- qiskit/pulse/__init__.py +0 -158
- qiskit/pulse/builder.py +0 -2262
- qiskit/pulse/calibration_entries.py +0 -381
- qiskit/pulse/channels.py +0 -227
- qiskit/pulse/configuration.py +0 -245
- qiskit/pulse/exceptions.py +0 -45
- qiskit/pulse/filters.py +0 -309
- qiskit/pulse/instruction_schedule_map.py +0 -424
- qiskit/pulse/instructions/__init__.py +0 -67
- qiskit/pulse/instructions/acquire.py +0 -150
- qiskit/pulse/instructions/delay.py +0 -71
- qiskit/pulse/instructions/directives.py +0 -154
- qiskit/pulse/instructions/frequency.py +0 -135
- qiskit/pulse/instructions/instruction.py +0 -270
- qiskit/pulse/instructions/phase.py +0 -152
- qiskit/pulse/instructions/play.py +0 -99
- qiskit/pulse/instructions/reference.py +0 -100
- qiskit/pulse/instructions/snapshot.py +0 -82
- qiskit/pulse/library/__init__.py +0 -97
- qiskit/pulse/library/continuous.py +0 -430
- qiskit/pulse/library/pulse.py +0 -148
- qiskit/pulse/library/samplers/__init__.py +0 -15
- qiskit/pulse/library/samplers/decorators.py +0 -295
- qiskit/pulse/library/samplers/strategies.py +0 -71
- qiskit/pulse/library/symbolic_pulses.py +0 -1989
- qiskit/pulse/library/waveform.py +0 -136
- qiskit/pulse/macros.py +0 -262
- qiskit/pulse/parameter_manager.py +0 -445
- qiskit/pulse/parser.py +0 -314
- qiskit/pulse/reference_manager.py +0 -58
- qiskit/pulse/schedule.py +0 -1854
- qiskit/pulse/transforms/__init__.py +0 -106
- qiskit/pulse/transforms/alignments.py +0 -406
- qiskit/pulse/transforms/base_transforms.py +0 -71
- qiskit/pulse/transforms/canonicalization.py +0 -498
- qiskit/pulse/transforms/dag.py +0 -122
- qiskit/pulse/utils.py +0 -149
- qiskit/qobj/__init__.py +0 -75
- qiskit/qobj/common.py +0 -81
- qiskit/qobj/converters/__init__.py +0 -18
- qiskit/qobj/converters/lo_config.py +0 -177
- qiskit/qobj/converters/pulse_instruction.py +0 -897
- qiskit/qobj/pulse_qobj.py +0 -709
- qiskit/qobj/qasm_qobj.py +0 -708
- qiskit/qobj/utils.py +0 -46
- qiskit/result/mitigation/base_readout_mitigator.py +0 -79
- qiskit/result/mitigation/correlated_readout_mitigator.py +0 -277
- qiskit/result/mitigation/local_readout_mitigator.py +0 -328
- qiskit/result/mitigation/utils.py +0 -217
- qiskit/scheduler/__init__.py +0 -40
- qiskit/scheduler/config.py +0 -37
- qiskit/scheduler/lowering.py +0 -187
- qiskit/scheduler/methods/__init__.py +0 -15
- qiskit/scheduler/methods/basic.py +0 -140
- qiskit/scheduler/schedule_circuit.py +0 -69
- qiskit/scheduler/sequence.py +0 -104
- qiskit/transpiler/passes/calibration/__init__.py +0 -17
- qiskit/transpiler/passes/calibration/base_builder.py +0 -79
- qiskit/transpiler/passes/calibration/builders.py +0 -20
- qiskit/transpiler/passes/calibration/exceptions.py +0 -22
- qiskit/transpiler/passes/calibration/pulse_gate.py +0 -100
- qiskit/transpiler/passes/calibration/rx_builder.py +0 -164
- qiskit/transpiler/passes/calibration/rzx_builder.py +0 -411
- qiskit/transpiler/passes/calibration/rzx_templates.py +0 -58
- qiskit/transpiler/passes/optimization/cx_cancellation.py +0 -65
- qiskit/transpiler/passes/optimization/echo_rzx_weyl_decomposition.py +0 -162
- qiskit/transpiler/passes/optimization/normalize_rx_angle.py +0 -157
- qiskit/transpiler/passes/routing/stochastic_swap.py +0 -532
- qiskit/transpiler/passes/scheduling/alap.py +0 -153
- qiskit/transpiler/passes/scheduling/alignments/align_measures.py +0 -255
- qiskit/transpiler/passes/scheduling/alignments/pulse_gate_validation.py +0 -107
- qiskit/transpiler/passes/scheduling/asap.py +0 -175
- qiskit/transpiler/passes/scheduling/base_scheduler.py +0 -310
- qiskit/transpiler/passes/scheduling/dynamical_decoupling.py +0 -313
- qiskit/transpiler/passes/utils/convert_conditions_to_if_ops.py +0 -93
- qiskit/utils/deprecate_pulse.py +0 -119
- qiskit/utils/multiprocessing.py +0 -56
- qiskit/visualization/pulse_v2/__init__.py +0 -21
- qiskit/visualization/pulse_v2/core.py +0 -901
- qiskit/visualization/pulse_v2/device_info.py +0 -173
- qiskit/visualization/pulse_v2/drawings.py +0 -253
- qiskit/visualization/pulse_v2/events.py +0 -254
- qiskit/visualization/pulse_v2/generators/__init__.py +0 -40
- qiskit/visualization/pulse_v2/generators/barrier.py +0 -76
- qiskit/visualization/pulse_v2/generators/chart.py +0 -208
- qiskit/visualization/pulse_v2/generators/frame.py +0 -436
- qiskit/visualization/pulse_v2/generators/snapshot.py +0 -133
- qiskit/visualization/pulse_v2/generators/waveform.py +0 -645
- qiskit/visualization/pulse_v2/interface.py +0 -459
- qiskit/visualization/pulse_v2/layouts.py +0 -387
- qiskit/visualization/pulse_v2/plotters/__init__.py +0 -17
- qiskit/visualization/pulse_v2/plotters/base_plotter.py +0 -53
- qiskit/visualization/pulse_v2/plotters/matplotlib.py +0 -201
- qiskit/visualization/pulse_v2/stylesheet.py +0 -312
- qiskit/visualization/pulse_v2/types.py +0 -242
- {qiskit-1.4.1.dist-info → qiskit-2.0.0rc1.dist-info}/LICENSE.txt +0 -0
- {qiskit-1.4.1.dist-info → qiskit-2.0.0rc1.dist-info}/top_level.txt +0 -0
@@ -1,901 +0,0 @@
|
|
1
|
-
# This code is part of Qiskit.
|
2
|
-
#
|
3
|
-
# (C) Copyright IBM 2020.
|
4
|
-
#
|
5
|
-
# This code is licensed under the Apache License, Version 2.0. You may
|
6
|
-
# obtain a copy of this license in the LICENSE.txt file in the root directory
|
7
|
-
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
|
8
|
-
#
|
9
|
-
# Any modifications or derivative works of this code must retain this
|
10
|
-
# copyright notice, and modified files need to carry a notice indicating
|
11
|
-
# that they have been altered from the originals.
|
12
|
-
|
13
|
-
"""
|
14
|
-
Core module of the pulse drawer.
|
15
|
-
|
16
|
-
This module provides the `DrawerCanvas` which is a collection of `Chart` object.
|
17
|
-
The `Chart` object is a collection of drawings. A user can assign multiple channels
|
18
|
-
to a single chart instance. For example, we can define a chart for specific qubit
|
19
|
-
and assign all related channels to the chart. This chart-channel mapping is defined by
|
20
|
-
the function specified by ``layout.chart_channel_map`` of the stylesheet.
|
21
|
-
|
22
|
-
Because this chart instance is decoupled from the coordinate system of the plotter,
|
23
|
-
we can arbitrarily place charts on the plotter canvas, i.e. if we want to create 3D plot,
|
24
|
-
each chart may be placed on the X-Z plane and charts are arranged along the Y-axis.
|
25
|
-
Thus this data model maximizes the flexibility to generate an output image.
|
26
|
-
|
27
|
-
The chart instance is not just a container of drawings, as it also performs
|
28
|
-
data processing like binding abstract coordinates and truncating long pulses for an axis break.
|
29
|
-
Each chart object has `.parent` which points to the `DrawerCanvas` instance so that
|
30
|
-
each child chart can refer to the global figure settings such as time range and axis break.
|
31
|
-
|
32
|
-
|
33
|
-
Initialization
|
34
|
-
~~~~~~~~~~~~~~
|
35
|
-
The `DataCanvas` and `Chart` are not exposed to users as they are implicitly
|
36
|
-
initialized in the interface function. It is noteworthy that the data canvas is agnostic
|
37
|
-
to plotters. This means once the canvas instance is initialized we can reuse this data
|
38
|
-
among multiple plotters. The canvas is initialized with a stylesheet and quantum backend
|
39
|
-
information :py:class:`~qiskit.visualization.pulse_v2.device_info.DrawerBackendInfo`.
|
40
|
-
Chart instances are automatically generated when pulse program is loaded.
|
41
|
-
|
42
|
-
```python
|
43
|
-
canvas = DrawerCanvas(stylesheet=stylesheet, device=device)
|
44
|
-
canvas.load_program(sched)
|
45
|
-
canvas.update()
|
46
|
-
```
|
47
|
-
|
48
|
-
Once all properties are set, `.update` method is called to apply changes to drawings.
|
49
|
-
If the `DrawDataContainer` is initialized without backend information, the output shows
|
50
|
-
the time in units of the system cycle time `dt` and the frequencies are initialized to zero.
|
51
|
-
|
52
|
-
Update
|
53
|
-
~~~~~~
|
54
|
-
To update the image, a user can set new values to canvas and then call the `.update` method.
|
55
|
-
|
56
|
-
```python
|
57
|
-
canvas.set_time_range(2000, 3000, seconds=False)
|
58
|
-
canvas.update()
|
59
|
-
```
|
60
|
-
|
61
|
-
All stored drawings are updated accordingly. The plotter API can access to
|
62
|
-
drawings with `.collections` property of chart instance. This returns
|
63
|
-
an iterator of drawing with the unique data key.
|
64
|
-
If a plotter provides object handler for plotted shapes, the plotter API can manage
|
65
|
-
the lookup table of the handler and the drawing by using this data key.
|
66
|
-
"""
|
67
|
-
|
68
|
-
from __future__ import annotations
|
69
|
-
|
70
|
-
from collections.abc import Iterator, Sequence
|
71
|
-
from copy import deepcopy
|
72
|
-
from enum import Enum
|
73
|
-
from functools import partial
|
74
|
-
from itertools import chain
|
75
|
-
|
76
|
-
import numpy as np
|
77
|
-
from qiskit import pulse
|
78
|
-
from qiskit.pulse.transforms import target_qobj_transform
|
79
|
-
from qiskit.visualization.exceptions import VisualizationError
|
80
|
-
from qiskit.visualization.pulse_v2 import events, types, drawings, device_info
|
81
|
-
from qiskit.visualization.pulse_v2.stylesheet import QiskitPulseStyle
|
82
|
-
|
83
|
-
|
84
|
-
class DrawerCanvas:
|
85
|
-
"""Collection of `Chart` and configuration data.
|
86
|
-
|
87
|
-
Pulse channels are associated with some `Chart` instance and
|
88
|
-
drawing data object are stored in the `Chart` instance.
|
89
|
-
|
90
|
-
Device, stylesheet, and some user generators are stored in the `DrawingCanvas`
|
91
|
-
and `Chart` instances are also attached to the `DrawerCanvas` as children.
|
92
|
-
Global configurations are accessed by those children to modify
|
93
|
-
the appearance of the `Chart` output.
|
94
|
-
"""
|
95
|
-
|
96
|
-
def __init__(self, stylesheet: QiskitPulseStyle, device: device_info.DrawerBackendInfo):
|
97
|
-
"""Create new data container with backend system information.
|
98
|
-
|
99
|
-
Args:
|
100
|
-
stylesheet: Stylesheet to decide appearance of output image.
|
101
|
-
device: Backend information to run the program.
|
102
|
-
"""
|
103
|
-
# stylesheet
|
104
|
-
self.formatter = stylesheet.formatter
|
105
|
-
self.generator = stylesheet.generator
|
106
|
-
self.layout = stylesheet.layout
|
107
|
-
|
108
|
-
# device info
|
109
|
-
self.device = device
|
110
|
-
|
111
|
-
# chart
|
112
|
-
self.global_charts = Chart(parent=self, name="global")
|
113
|
-
self.charts: list[Chart] = []
|
114
|
-
|
115
|
-
# visible controls
|
116
|
-
self.disable_chans: set[pulse.channels.Channel] = set()
|
117
|
-
self.disable_types: set[str] = set()
|
118
|
-
|
119
|
-
# data scaling
|
120
|
-
self.chan_scales: dict[
|
121
|
-
pulse.channels.DriveChannel
|
122
|
-
| pulse.channels.MeasureChannel
|
123
|
-
| pulse.channels.ControlChannel
|
124
|
-
| pulse.channels.AcquireChannel,
|
125
|
-
float,
|
126
|
-
] = {}
|
127
|
-
|
128
|
-
# global time
|
129
|
-
self._time_range = (0, 0)
|
130
|
-
self._time_breaks: list[tuple[int, int]] = []
|
131
|
-
|
132
|
-
# title
|
133
|
-
self.fig_title = ""
|
134
|
-
|
135
|
-
@property
|
136
|
-
def time_range(self) -> tuple[int, int]:
|
137
|
-
"""Return current time range to draw.
|
138
|
-
|
139
|
-
Calculate net duration and add side margin to edge location.
|
140
|
-
|
141
|
-
Returns:
|
142
|
-
Time window considering side margin.
|
143
|
-
"""
|
144
|
-
t0, t1 = self._time_range
|
145
|
-
|
146
|
-
total_time_elimination = 0
|
147
|
-
for t0b, t1b in self.time_breaks:
|
148
|
-
if t1b > t0 and t0b < t1:
|
149
|
-
total_time_elimination += t1b - t0b
|
150
|
-
net_duration = t1 - t0 - total_time_elimination
|
151
|
-
|
152
|
-
new_t0 = t0 - net_duration * self.formatter["margin.left_percent"]
|
153
|
-
new_t1 = t1 + net_duration * self.formatter["margin.right_percent"]
|
154
|
-
|
155
|
-
return new_t0, new_t1
|
156
|
-
|
157
|
-
@time_range.setter
|
158
|
-
def time_range(self, new_range: tuple[int, int]):
|
159
|
-
"""Update time range to draw."""
|
160
|
-
self._time_range = new_range
|
161
|
-
|
162
|
-
@property
|
163
|
-
def time_breaks(self) -> list[tuple[int, int]]:
|
164
|
-
"""Return time breaks with time range.
|
165
|
-
|
166
|
-
If an edge of time range is in the axis break period,
|
167
|
-
the axis break period is recalculated.
|
168
|
-
|
169
|
-
Raises:
|
170
|
-
VisualizationError: When axis break is greater than time window.
|
171
|
-
|
172
|
-
Returns:
|
173
|
-
List of axis break periods considering the time window edges.
|
174
|
-
"""
|
175
|
-
t0, t1 = self._time_range
|
176
|
-
|
177
|
-
axis_breaks = []
|
178
|
-
for t0b, t1b in self._time_breaks:
|
179
|
-
if t0b >= t1 or t1b <= t0:
|
180
|
-
# skip because break period is outside of time window
|
181
|
-
continue
|
182
|
-
|
183
|
-
if t0b < t0 and t1b > t1:
|
184
|
-
raise VisualizationError(
|
185
|
-
"Axis break is greater than time window. Nothing will be drawn."
|
186
|
-
)
|
187
|
-
if t0b < t0 < t1b:
|
188
|
-
if t1b - t0 > self.formatter["axis_break.length"]:
|
189
|
-
new_t0 = t0 + 0.5 * self.formatter["axis_break.max_length"]
|
190
|
-
axis_breaks.append((new_t0, t1b))
|
191
|
-
continue
|
192
|
-
if t0b < t1 < t1b:
|
193
|
-
if t1 - t0b > self.formatter["axis_break.length"]:
|
194
|
-
new_t1 = t1 - 0.5 * self.formatter["axis_break.max_length"]
|
195
|
-
axis_breaks.append((t0b, new_t1))
|
196
|
-
continue
|
197
|
-
axis_breaks.append((t0b, t1b))
|
198
|
-
|
199
|
-
return axis_breaks
|
200
|
-
|
201
|
-
@time_breaks.setter
|
202
|
-
def time_breaks(self, new_breaks: list[tuple[int, int]]):
|
203
|
-
"""Set new time breaks."""
|
204
|
-
self._time_breaks = sorted(new_breaks, key=lambda x: x[0])
|
205
|
-
|
206
|
-
def load_program(
|
207
|
-
self,
|
208
|
-
program: pulse.Waveform | pulse.SymbolicPulse | pulse.Schedule | pulse.ScheduleBlock,
|
209
|
-
):
|
210
|
-
"""Load a program to draw.
|
211
|
-
|
212
|
-
Args:
|
213
|
-
program: Pulse program or waveform to draw.
|
214
|
-
|
215
|
-
Raises:
|
216
|
-
VisualizationError: When input program is invalid data format.
|
217
|
-
"""
|
218
|
-
if isinstance(program, (pulse.Schedule, pulse.ScheduleBlock)):
|
219
|
-
self._schedule_loader(program)
|
220
|
-
elif isinstance(program, (pulse.Waveform, pulse.SymbolicPulse)):
|
221
|
-
self._waveform_loader(program)
|
222
|
-
else:
|
223
|
-
raise VisualizationError(f"Data type {type(program)} is not supported.")
|
224
|
-
|
225
|
-
# update time range
|
226
|
-
self.set_time_range(0, program.duration, seconds=False)
|
227
|
-
|
228
|
-
# set title
|
229
|
-
self.fig_title = self.layout["figure_title"](program=program, device=self.device)
|
230
|
-
|
231
|
-
def _waveform_loader(
|
232
|
-
self,
|
233
|
-
program: pulse.Waveform | pulse.SymbolicPulse,
|
234
|
-
):
|
235
|
-
"""Load Waveform instance.
|
236
|
-
|
237
|
-
This function is sub-routine of py:method:`load_program`.
|
238
|
-
|
239
|
-
Args:
|
240
|
-
program: `Waveform` to draw.
|
241
|
-
"""
|
242
|
-
chart = Chart(parent=self)
|
243
|
-
|
244
|
-
# add waveform data
|
245
|
-
fake_inst = pulse.Play(program, types.WaveformChannel())
|
246
|
-
inst_data = types.PulseInstruction(
|
247
|
-
t0=0,
|
248
|
-
dt=self.device.dt,
|
249
|
-
frame=types.PhaseFreqTuple(phase=0, freq=0),
|
250
|
-
inst=fake_inst,
|
251
|
-
is_opaque=program.is_parameterized(),
|
252
|
-
)
|
253
|
-
for gen in self.generator["waveform"]:
|
254
|
-
obj_generator = partial(gen, formatter=self.formatter, device=self.device)
|
255
|
-
for data in obj_generator(inst_data):
|
256
|
-
chart.add_data(data)
|
257
|
-
|
258
|
-
self.charts.append(chart)
|
259
|
-
|
260
|
-
def _schedule_loader(self, program: pulse.Schedule | pulse.ScheduleBlock):
|
261
|
-
"""Load Schedule instance.
|
262
|
-
|
263
|
-
This function is sub-routine of py:method:`load_program`.
|
264
|
-
|
265
|
-
Args:
|
266
|
-
program: `Schedule` to draw.
|
267
|
-
"""
|
268
|
-
program = target_qobj_transform(program, remove_directives=False)
|
269
|
-
|
270
|
-
# initialize scale values
|
271
|
-
self.chan_scales = {}
|
272
|
-
for chan in program.channels:
|
273
|
-
if isinstance(chan, pulse.channels.DriveChannel):
|
274
|
-
self.chan_scales[chan] = self.formatter["channel_scaling.drive"]
|
275
|
-
elif isinstance(chan, pulse.channels.MeasureChannel):
|
276
|
-
self.chan_scales[chan] = self.formatter["channel_scaling.measure"]
|
277
|
-
elif isinstance(chan, pulse.channels.ControlChannel):
|
278
|
-
self.chan_scales[chan] = self.formatter["channel_scaling.control"]
|
279
|
-
elif isinstance(chan, pulse.channels.AcquireChannel):
|
280
|
-
self.chan_scales[chan] = self.formatter["channel_scaling.acquire"]
|
281
|
-
else:
|
282
|
-
self.chan_scales[chan] = 1.0
|
283
|
-
|
284
|
-
# create charts
|
285
|
-
mapper = self.layout["chart_channel_map"]
|
286
|
-
for name, chans in mapper(
|
287
|
-
channels=program.channels, formatter=self.formatter, device=self.device
|
288
|
-
):
|
289
|
-
|
290
|
-
chart = Chart(parent=self, name=name)
|
291
|
-
|
292
|
-
# add standard pulse instructions
|
293
|
-
for chan in chans:
|
294
|
-
chart.load_program(program=program, chan=chan)
|
295
|
-
|
296
|
-
# add barriers
|
297
|
-
barrier_sched = program.filter(
|
298
|
-
instruction_types=[pulse.instructions.RelativeBarrier], channels=chans
|
299
|
-
)
|
300
|
-
for t0, _ in barrier_sched.instructions:
|
301
|
-
inst_data = types.BarrierInstruction(t0, self.device.dt, chans)
|
302
|
-
for gen in self.generator["barrier"]:
|
303
|
-
obj_generator = partial(gen, formatter=self.formatter, device=self.device)
|
304
|
-
for data in obj_generator(inst_data):
|
305
|
-
chart.add_data(data)
|
306
|
-
|
307
|
-
# add chart axis
|
308
|
-
chart_axis = types.ChartAxis(name=chart.name, channels=chart.channels)
|
309
|
-
for gen in self.generator["chart"]:
|
310
|
-
obj_generator = partial(gen, formatter=self.formatter, device=self.device)
|
311
|
-
for data in obj_generator(chart_axis):
|
312
|
-
chart.add_data(data)
|
313
|
-
|
314
|
-
self.charts.append(chart)
|
315
|
-
|
316
|
-
# add snapshot data to global
|
317
|
-
snapshot_sched = program.filter(instruction_types=[pulse.instructions.Snapshot])
|
318
|
-
for t0, inst in snapshot_sched.instructions:
|
319
|
-
inst_data = types.SnapshotInstruction(t0, self.device.dt, inst.label, inst.channels)
|
320
|
-
for gen in self.generator["snapshot"]:
|
321
|
-
obj_generator = partial(gen, formatter=self.formatter, device=self.device)
|
322
|
-
for data in obj_generator(inst_data):
|
323
|
-
self.global_charts.add_data(data)
|
324
|
-
|
325
|
-
# calculate axis break
|
326
|
-
self.time_breaks = self._calculate_axis_break(program)
|
327
|
-
|
328
|
-
def _calculate_axis_break(self, program: pulse.Schedule) -> list[tuple[int, int]]:
|
329
|
-
"""A helper function to calculate axis break of long pulse sequence.
|
330
|
-
|
331
|
-
Args:
|
332
|
-
program: A schedule to calculate axis break.
|
333
|
-
|
334
|
-
Returns:
|
335
|
-
List of axis break periods.
|
336
|
-
"""
|
337
|
-
axis_breaks = []
|
338
|
-
|
339
|
-
edges = set()
|
340
|
-
for t0, t1 in chain.from_iterable(program.timeslots.values()):
|
341
|
-
if t1 - t0 > 0:
|
342
|
-
edges.add(t0)
|
343
|
-
edges.add(t1)
|
344
|
-
edges = sorted(edges)
|
345
|
-
|
346
|
-
for t0, t1 in zip(edges[:-1], edges[1:]):
|
347
|
-
if t1 - t0 > self.formatter["axis_break.length"]:
|
348
|
-
t_l = t0 + 0.5 * self.formatter["axis_break.max_length"]
|
349
|
-
t_r = t1 - 0.5 * self.formatter["axis_break.max_length"]
|
350
|
-
axis_breaks.append((t_l, t_r))
|
351
|
-
|
352
|
-
return axis_breaks
|
353
|
-
|
354
|
-
def set_time_range(self, t_start: float, t_end: float, seconds: bool = True):
|
355
|
-
"""Set time range to draw.
|
356
|
-
|
357
|
-
All child chart instances are updated when time range is updated.
|
358
|
-
|
359
|
-
Args:
|
360
|
-
t_start: Left boundary of drawing in units of cycle time or real time.
|
361
|
-
t_end: Right boundary of drawing in units of cycle time or real time.
|
362
|
-
seconds: Set `True` if times are given in SI unit rather than dt.
|
363
|
-
|
364
|
-
Raises:
|
365
|
-
VisualizationError: When times are given in float without specifying dt.
|
366
|
-
"""
|
367
|
-
# convert into nearest cycle time
|
368
|
-
if seconds:
|
369
|
-
if self.device.dt is not None:
|
370
|
-
t_start = int(np.round(t_start / self.device.dt))
|
371
|
-
t_end = int(np.round(t_end / self.device.dt))
|
372
|
-
else:
|
373
|
-
raise VisualizationError(
|
374
|
-
"Setting time range with SI units requires backend `dt` information."
|
375
|
-
)
|
376
|
-
self.time_range = (t_start, t_end)
|
377
|
-
|
378
|
-
def set_disable_channel(self, channel: pulse.channels.Channel, remove: bool = True):
|
379
|
-
"""Interface method to control visibility of pulse channels.
|
380
|
-
|
381
|
-
Specified object in the blocked list will not be shown.
|
382
|
-
|
383
|
-
Args:
|
384
|
-
channel: A pulse channel object to disable.
|
385
|
-
remove: Set `True` to disable, set `False` to enable.
|
386
|
-
"""
|
387
|
-
if remove:
|
388
|
-
self.disable_chans.add(channel)
|
389
|
-
else:
|
390
|
-
self.disable_chans.discard(channel)
|
391
|
-
|
392
|
-
def set_disable_type(self, data_type: types.DataTypes, remove: bool = True):
|
393
|
-
"""Interface method to control visibility of data types.
|
394
|
-
|
395
|
-
Specified object in the blocked list will not be shown.
|
396
|
-
|
397
|
-
Args:
|
398
|
-
data_type: A drawing data type to disable.
|
399
|
-
remove: Set `True` to disable, set `False` to enable.
|
400
|
-
"""
|
401
|
-
if isinstance(data_type, Enum):
|
402
|
-
data_type_str = str(data_type.value)
|
403
|
-
else:
|
404
|
-
data_type_str = data_type
|
405
|
-
|
406
|
-
if remove:
|
407
|
-
self.disable_types.add(data_type_str)
|
408
|
-
else:
|
409
|
-
self.disable_types.discard(data_type_str)
|
410
|
-
|
411
|
-
def update(self):
|
412
|
-
"""Update all associated charts and generate actual drawing data from template object.
|
413
|
-
|
414
|
-
This method should be called before the canvas is passed to the plotter.
|
415
|
-
"""
|
416
|
-
for chart in self.charts:
|
417
|
-
chart.update()
|
418
|
-
|
419
|
-
|
420
|
-
class Chart:
|
421
|
-
"""A collection of drawing to be shown on the same line.
|
422
|
-
|
423
|
-
Multiple pulse channels can be assigned to a single `Chart`.
|
424
|
-
The parent `DrawerCanvas` should be specified to refer to the current user preference.
|
425
|
-
|
426
|
-
The vertical value of each `Chart` should be in the range [-1, 1].
|
427
|
-
This truncation should be performed in the plotter interface.
|
428
|
-
"""
|
429
|
-
|
430
|
-
# unique index of chart
|
431
|
-
chart_index = 0
|
432
|
-
|
433
|
-
# list of waveform type names
|
434
|
-
waveform_types = [
|
435
|
-
str(types.WaveformType.REAL.value),
|
436
|
-
str(types.WaveformType.IMAG.value),
|
437
|
-
str(types.WaveformType.OPAQUE.value),
|
438
|
-
]
|
439
|
-
|
440
|
-
def __init__(self, parent: DrawerCanvas, name: str | None = None):
|
441
|
-
"""Create new chart.
|
442
|
-
|
443
|
-
Args:
|
444
|
-
parent: `DrawerCanvas` that this `Chart` instance belongs to.
|
445
|
-
name: Name of this `Chart` instance.
|
446
|
-
"""
|
447
|
-
self.parent = parent
|
448
|
-
|
449
|
-
# data stored in this channel
|
450
|
-
self._collections: dict[str, drawings.ElementaryData] = {}
|
451
|
-
self._output_dataset: dict[str, drawings.ElementaryData] = {}
|
452
|
-
|
453
|
-
# channel metadata
|
454
|
-
self.index = self._cls_index()
|
455
|
-
self.name = name or ""
|
456
|
-
self._channels: set[pulse.channels.Channel] = set()
|
457
|
-
|
458
|
-
# vertical axis information
|
459
|
-
self.vmax = 0
|
460
|
-
self.vmin = 0
|
461
|
-
self.scale = 1.0
|
462
|
-
|
463
|
-
self._increment_cls_index()
|
464
|
-
|
465
|
-
def add_data(self, data: drawings.ElementaryData):
|
466
|
-
"""Add drawing to collections.
|
467
|
-
|
468
|
-
If the given object already exists in the collections,
|
469
|
-
this interface replaces the old object instead of adding new entry.
|
470
|
-
|
471
|
-
Args:
|
472
|
-
data: New drawing to add.
|
473
|
-
"""
|
474
|
-
self._collections[data.data_key] = data
|
475
|
-
|
476
|
-
def load_program(self, program: pulse.Schedule, chan: pulse.channels.Channel):
|
477
|
-
"""Load pulse schedule.
|
478
|
-
|
479
|
-
This method internally generates `ChannelEvents` to parse the program
|
480
|
-
for the specified pulse channel. This method is called once
|
481
|
-
|
482
|
-
Args:
|
483
|
-
program: Pulse schedule to load.
|
484
|
-
chan: A pulse channels associated with this instance.
|
485
|
-
"""
|
486
|
-
chan_events = events.ChannelEvents.load_program(program, chan)
|
487
|
-
chan_events.set_config(
|
488
|
-
dt=self.parent.device.dt,
|
489
|
-
init_frequency=self.parent.device.get_channel_frequency(chan),
|
490
|
-
init_phase=0,
|
491
|
-
)
|
492
|
-
|
493
|
-
# create objects associated with waveform
|
494
|
-
for gen in self.parent.generator["waveform"]:
|
495
|
-
waveforms = chan_events.get_waveforms()
|
496
|
-
obj_generator = partial(gen, formatter=self.parent.formatter, device=self.parent.device)
|
497
|
-
drawing_items = [obj_generator(waveform) for waveform in waveforms]
|
498
|
-
for drawing_item in list(chain.from_iterable(drawing_items)):
|
499
|
-
self.add_data(drawing_item)
|
500
|
-
|
501
|
-
# create objects associated with frame change
|
502
|
-
for gen in self.parent.generator["frame"]:
|
503
|
-
frames = chan_events.get_frame_changes()
|
504
|
-
obj_generator = partial(gen, formatter=self.parent.formatter, device=self.parent.device)
|
505
|
-
drawing_items = [obj_generator(frame) for frame in frames]
|
506
|
-
for drawing_item in list(chain.from_iterable(drawing_items)):
|
507
|
-
self.add_data(drawing_item)
|
508
|
-
|
509
|
-
self._channels.add(chan)
|
510
|
-
|
511
|
-
def update(self):
|
512
|
-
"""Update vertical data range and scaling factor of this chart.
|
513
|
-
|
514
|
-
Those parameters are updated based on current time range in the parent canvas.
|
515
|
-
"""
|
516
|
-
self._output_dataset.clear()
|
517
|
-
self.vmax = 0
|
518
|
-
self.vmin = 0
|
519
|
-
|
520
|
-
# waveform
|
521
|
-
for key, data in self._collections.items():
|
522
|
-
if data.data_type not in Chart.waveform_types:
|
523
|
-
continue
|
524
|
-
|
525
|
-
# truncate, assume no abstract coordinate in waveform sample
|
526
|
-
trunc_x, trunc_y = self._truncate_data(data)
|
527
|
-
|
528
|
-
# no available data points
|
529
|
-
if trunc_x.size == 0 or trunc_y.size == 0:
|
530
|
-
continue
|
531
|
-
|
532
|
-
# update y range
|
533
|
-
scale = min(self.parent.chan_scales.get(chan, 1.0) for chan in data.channels)
|
534
|
-
self.vmax = max(scale * np.max(trunc_y), self.vmax)
|
535
|
-
self.vmin = min(scale * np.min(trunc_y), self.vmin)
|
536
|
-
|
537
|
-
# generate new data
|
538
|
-
new_data = deepcopy(data)
|
539
|
-
new_data.xvals = trunc_x
|
540
|
-
new_data.yvals = trunc_y
|
541
|
-
|
542
|
-
self._output_dataset[key] = new_data
|
543
|
-
|
544
|
-
# calculate chart level scaling factor
|
545
|
-
if self.parent.formatter["control.auto_chart_scaling"]:
|
546
|
-
max_val = max(
|
547
|
-
abs(self.vmax), abs(self.vmin), self.parent.formatter["general.vertical_resolution"]
|
548
|
-
)
|
549
|
-
self.scale = min(1.0 / max_val, self.parent.formatter["general.max_scale"])
|
550
|
-
else:
|
551
|
-
self.scale = 1.0
|
552
|
-
|
553
|
-
# update vertical range with scaling and limitation
|
554
|
-
self.vmax = max(
|
555
|
-
self.scale * self.vmax, self.parent.formatter["channel_scaling.pos_spacing"]
|
556
|
-
)
|
557
|
-
|
558
|
-
self.vmin = min(
|
559
|
-
self.scale * self.vmin, self.parent.formatter["channel_scaling.neg_spacing"]
|
560
|
-
)
|
561
|
-
|
562
|
-
# other data
|
563
|
-
for key, data in self._collections.items():
|
564
|
-
if data.data_type in Chart.waveform_types:
|
565
|
-
continue
|
566
|
-
|
567
|
-
# truncate
|
568
|
-
trunc_x, trunc_y = self._truncate_data(data)
|
569
|
-
|
570
|
-
# no available data points
|
571
|
-
if trunc_x.size == 0 or trunc_y.size == 0:
|
572
|
-
continue
|
573
|
-
|
574
|
-
# generate new data
|
575
|
-
new_data = deepcopy(data)
|
576
|
-
new_data.xvals = trunc_x
|
577
|
-
new_data.yvals = trunc_y
|
578
|
-
|
579
|
-
self._output_dataset[key] = new_data
|
580
|
-
|
581
|
-
@property
|
582
|
-
def is_active(self) -> bool:
|
583
|
-
"""Check if there is any active waveform data in this entry.
|
584
|
-
|
585
|
-
Returns:
|
586
|
-
Return `True` if there is any visible waveform in this chart.
|
587
|
-
"""
|
588
|
-
for data in self._output_dataset.values():
|
589
|
-
if data.data_type in Chart.waveform_types and self._check_visible(data):
|
590
|
-
return True
|
591
|
-
return False
|
592
|
-
|
593
|
-
@property
|
594
|
-
def collections(self) -> Iterator[tuple[str, drawings.ElementaryData]]:
|
595
|
-
"""Return currently active entries from drawing data collection.
|
596
|
-
|
597
|
-
The object is returned with unique name as a key of an object handler.
|
598
|
-
When the horizontal coordinate contains `AbstractCoordinate`,
|
599
|
-
the value is substituted by current time range preference.
|
600
|
-
"""
|
601
|
-
for name, data in self._output_dataset.items():
|
602
|
-
# prepare unique name
|
603
|
-
unique_id = f"chart{self.index:d}_{name}"
|
604
|
-
if self._check_visible(data):
|
605
|
-
yield unique_id, data
|
606
|
-
|
607
|
-
@property
|
608
|
-
def channels(self) -> list[pulse.channels.Channel]:
|
609
|
-
"""Return a list of channels associated with this chart.
|
610
|
-
|
611
|
-
Returns:
|
612
|
-
List of channels associated with this chart.
|
613
|
-
"""
|
614
|
-
return list(self._channels)
|
615
|
-
|
616
|
-
def _truncate_data(self, data: drawings.ElementaryData) -> tuple[np.ndarray, np.ndarray]:
|
617
|
-
"""A helper function to truncate drawings according to time breaks.
|
618
|
-
|
619
|
-
# TODO: move this function to common module to support axis break for timeline.
|
620
|
-
|
621
|
-
Args:
|
622
|
-
data: Drawing object to truncate.
|
623
|
-
|
624
|
-
Returns:
|
625
|
-
Set of truncated numpy arrays for x and y coordinate.
|
626
|
-
"""
|
627
|
-
xvals = self._bind_coordinate(data.xvals)
|
628
|
-
yvals = self._bind_coordinate(data.yvals)
|
629
|
-
|
630
|
-
if isinstance(data, drawings.BoxData):
|
631
|
-
# truncate box data. these object don't require interpolation at axis break.
|
632
|
-
return self._truncate_boxes(xvals, yvals)
|
633
|
-
elif data.data_type in [types.LabelType.PULSE_NAME, types.LabelType.OPAQUE_BOXTEXT]:
|
634
|
-
# truncate pulse labels. these objects are not removed by truncation.
|
635
|
-
return self._truncate_pulse_labels(xvals, yvals)
|
636
|
-
else:
|
637
|
-
# other objects
|
638
|
-
return self._truncate_vectors(xvals, yvals)
|
639
|
-
|
640
|
-
def _truncate_pulse_labels(
|
641
|
-
self, xvals: np.ndarray, yvals: np.ndarray
|
642
|
-
) -> tuple[np.ndarray, np.ndarray]:
|
643
|
-
"""A helper function to remove text according to time breaks.
|
644
|
-
|
645
|
-
Args:
|
646
|
-
xvals: Time points.
|
647
|
-
yvals: Data points.
|
648
|
-
|
649
|
-
Returns:
|
650
|
-
Set of truncated numpy arrays for x and y coordinate.
|
651
|
-
"""
|
652
|
-
xpos = xvals[0]
|
653
|
-
t0, t1 = self.parent.time_range
|
654
|
-
|
655
|
-
if xpos < t0 or xpos > t1:
|
656
|
-
return np.array([]), np.array([])
|
657
|
-
offset_accumulation = 0
|
658
|
-
for tl, tr in self.parent.time_breaks:
|
659
|
-
if xpos < tl:
|
660
|
-
return np.array([xpos - offset_accumulation]), yvals
|
661
|
-
if tl < xpos < tr:
|
662
|
-
return np.array([tl - offset_accumulation]), yvals
|
663
|
-
else:
|
664
|
-
offset_accumulation += tr - tl
|
665
|
-
return np.array([xpos - offset_accumulation]), yvals
|
666
|
-
|
667
|
-
def _truncate_boxes(
|
668
|
-
self, xvals: np.ndarray, yvals: np.ndarray
|
669
|
-
) -> tuple[np.ndarray, np.ndarray]:
|
670
|
-
"""A helper function to clip box object according to time breaks.
|
671
|
-
|
672
|
-
Args:
|
673
|
-
xvals: Time points.
|
674
|
-
yvals: Data points.
|
675
|
-
|
676
|
-
Returns:
|
677
|
-
Set of truncated numpy arrays for x and y coordinate.
|
678
|
-
"""
|
679
|
-
x0, x1 = xvals
|
680
|
-
t0, t1 = self.parent.time_range
|
681
|
-
|
682
|
-
if x1 < t0 or x0 > t1:
|
683
|
-
# out of drawing range
|
684
|
-
return np.array([]), np.array([])
|
685
|
-
|
686
|
-
# clip outside
|
687
|
-
x0 = max(t0, x0)
|
688
|
-
x1 = min(t1, x1)
|
689
|
-
|
690
|
-
offset_accumulate = 0
|
691
|
-
for tl, tr in self.parent.time_breaks:
|
692
|
-
tl -= offset_accumulate
|
693
|
-
tr -= offset_accumulate
|
694
|
-
|
695
|
-
#
|
696
|
-
# truncate, there are 5 patterns wrt the relative position of truncation and xvals
|
697
|
-
#
|
698
|
-
if x1 < tl:
|
699
|
-
break
|
700
|
-
|
701
|
-
if tl < x0 and tr > x1:
|
702
|
-
# case 1: all data points are truncated
|
703
|
-
# : +-----+ :
|
704
|
-
# : |/////| :
|
705
|
-
# -----:---+-----+---:-----
|
706
|
-
# l 0 1 r
|
707
|
-
return np.array([]), np.array([])
|
708
|
-
elif tl < x1 < tr:
|
709
|
-
# case 2: t < tl, right side is truncated
|
710
|
-
# +---:-----+ :
|
711
|
-
# | ://///| :
|
712
|
-
# -----+---:-----+---:-----
|
713
|
-
# 0 l 1 r
|
714
|
-
x1 = tl
|
715
|
-
elif tl < x0 < tr:
|
716
|
-
# case 3: tr > t, left side is truncated
|
717
|
-
# : +-----:---+
|
718
|
-
# : |/////: |
|
719
|
-
# -----:---+-----:---+-----
|
720
|
-
# l 0 r 1
|
721
|
-
x0 = tl
|
722
|
-
x1 = tl + t1 - tr
|
723
|
-
elif tl > x0 and tr < x1:
|
724
|
-
# case 4: tr > t > tl, middle part is truncated
|
725
|
-
# +---:-----:---+
|
726
|
-
# | ://///: |
|
727
|
-
# -----+---:-----:---+-----
|
728
|
-
# 0 l r 1
|
729
|
-
x1 -= tr - tl
|
730
|
-
elif tr < x0:
|
731
|
-
# case 5: tr > t > tl, nothing truncated but need time shift
|
732
|
-
# : : +---+
|
733
|
-
# : : | |
|
734
|
-
# -----:---:-----+---+-----
|
735
|
-
# l r 0 1
|
736
|
-
x0 -= tr - tl
|
737
|
-
x1 -= tr - tl
|
738
|
-
|
739
|
-
offset_accumulate += tr - tl
|
740
|
-
|
741
|
-
return np.asarray([x0, x1], dtype=float), yvals
|
742
|
-
|
743
|
-
def _truncate_vectors(
|
744
|
-
self, xvals: np.ndarray, yvals: np.ndarray
|
745
|
-
) -> tuple[np.ndarray, np.ndarray]:
|
746
|
-
"""A helper function to remove sequential data points according to time breaks.
|
747
|
-
|
748
|
-
Args:
|
749
|
-
xvals: Time points.
|
750
|
-
yvals: Data points.
|
751
|
-
|
752
|
-
Returns:
|
753
|
-
Set of truncated numpy arrays for x and y coordinate.
|
754
|
-
"""
|
755
|
-
xvals = np.asarray(xvals, dtype=float)
|
756
|
-
yvals = np.asarray(yvals, dtype=float)
|
757
|
-
t0, t1 = self.parent.time_range
|
758
|
-
|
759
|
-
if max(xvals) < t0 or min(xvals) > t1:
|
760
|
-
# out of drawing range
|
761
|
-
return np.array([]), np.array([])
|
762
|
-
|
763
|
-
if min(xvals) < t0:
|
764
|
-
# truncate x less than left limit
|
765
|
-
inds = xvals > t0
|
766
|
-
yvals = np.append(np.interp(t0, xvals, yvals), yvals[inds])
|
767
|
-
xvals = np.append(t0, xvals[inds])
|
768
|
-
|
769
|
-
if max(xvals) > t1:
|
770
|
-
# truncate x larger than right limit
|
771
|
-
inds = xvals < t1
|
772
|
-
yvals = np.append(yvals[inds], np.interp(t1, xvals, yvals))
|
773
|
-
xvals = np.append(xvals[inds], t1)
|
774
|
-
|
775
|
-
# time breaks
|
776
|
-
trunc_xvals = [xvals]
|
777
|
-
trunc_yvals = [yvals]
|
778
|
-
offset_accumulate = 0
|
779
|
-
for tl, tr in self.parent.time_breaks:
|
780
|
-
sub_xs = trunc_xvals.pop()
|
781
|
-
sub_ys = trunc_yvals.pop()
|
782
|
-
tl -= offset_accumulate
|
783
|
-
tr -= offset_accumulate
|
784
|
-
|
785
|
-
#
|
786
|
-
# truncate, there are 5 patterns wrt the relative position of truncation and xvals
|
787
|
-
#
|
788
|
-
min_xs = min(sub_xs)
|
789
|
-
max_xs = max(sub_xs)
|
790
|
-
if max_xs < tl:
|
791
|
-
trunc_xvals.append(sub_xs)
|
792
|
-
trunc_yvals.append(sub_ys)
|
793
|
-
break
|
794
|
-
|
795
|
-
if tl < min_xs and tr > max_xs:
|
796
|
-
# case 1: all data points are truncated
|
797
|
-
# : +-----+ :
|
798
|
-
# : |/////| :
|
799
|
-
# -----:---+-----+---:-----
|
800
|
-
# l min max r
|
801
|
-
return np.array([]), np.array([])
|
802
|
-
elif tl < max_xs < tr:
|
803
|
-
# case 2: t < tl, right side is truncated
|
804
|
-
# +---:-----+ :
|
805
|
-
# | ://///| :
|
806
|
-
# -----+---:-----+---:-----
|
807
|
-
# min l max r
|
808
|
-
inds = sub_xs > tl
|
809
|
-
trunc_xvals.append(np.append(tl, sub_xs[inds]) - (tl - min_xs))
|
810
|
-
trunc_yvals.append(np.append(np.interp(tl, sub_xs, sub_ys), sub_ys[inds]))
|
811
|
-
elif tl < min_xs < tr:
|
812
|
-
# case 3: tr > t, left side is truncated
|
813
|
-
# : +-----:---+
|
814
|
-
# : |/////: |
|
815
|
-
# -----:---+-----:---+-----
|
816
|
-
# l min r max
|
817
|
-
inds = sub_xs < tr
|
818
|
-
trunc_xvals.append(np.append(sub_xs[inds], tr))
|
819
|
-
trunc_yvals.append(np.append(sub_ys[inds], np.interp(tr, sub_xs, sub_ys)))
|
820
|
-
elif tl > min_xs and tr < max_xs:
|
821
|
-
# case 4: tr > t > tl, middle part is truncated
|
822
|
-
# +---:-----:---+
|
823
|
-
# | ://///: |
|
824
|
-
# -----+---:-----:---+-----
|
825
|
-
# min l r max
|
826
|
-
inds0 = sub_xs < tl
|
827
|
-
trunc_xvals.append(np.append(sub_xs[inds0], tl))
|
828
|
-
trunc_yvals.append(np.append(sub_ys[inds0], np.interp(tl, sub_xs, sub_ys)))
|
829
|
-
inds1 = sub_xs > tr
|
830
|
-
trunc_xvals.append(np.append(tr, sub_xs[inds1]) - (tr - tl))
|
831
|
-
trunc_yvals.append(np.append(np.interp(tr, sub_xs, sub_ys), sub_ys[inds1]))
|
832
|
-
elif tr < min_xs:
|
833
|
-
# case 5: tr > t > tl, nothing truncated but need time shift
|
834
|
-
# : : +---+
|
835
|
-
# : : | |
|
836
|
-
# -----:---:-----+---+-----
|
837
|
-
# l r 0 1
|
838
|
-
trunc_xvals.append(sub_xs - (tr - tl))
|
839
|
-
trunc_yvals.append(sub_ys)
|
840
|
-
else:
|
841
|
-
# no need to truncate
|
842
|
-
trunc_xvals.append(sub_xs)
|
843
|
-
trunc_yvals.append(sub_ys)
|
844
|
-
offset_accumulate += tr - tl
|
845
|
-
|
846
|
-
new_x = np.concatenate(trunc_xvals)
|
847
|
-
new_y = np.concatenate(trunc_yvals)
|
848
|
-
|
849
|
-
return np.asarray(new_x, dtype=float), np.asarray(new_y, dtype=float)
|
850
|
-
|
851
|
-
def _bind_coordinate(self, vals: Sequence[types.Coordinate] | np.ndarray) -> np.ndarray:
|
852
|
-
"""A helper function to bind actual coordinates to an `AbstractCoordinate`.
|
853
|
-
|
854
|
-
Args:
|
855
|
-
vals: Sequence of coordinate objects associated with a drawing.
|
856
|
-
|
857
|
-
Returns:
|
858
|
-
Numpy data array with substituted values.
|
859
|
-
"""
|
860
|
-
|
861
|
-
def substitute(val: types.Coordinate):
|
862
|
-
if val == types.AbstractCoordinate.LEFT:
|
863
|
-
return self.parent.time_range[0]
|
864
|
-
if val == types.AbstractCoordinate.RIGHT:
|
865
|
-
return self.parent.time_range[1]
|
866
|
-
if val == types.AbstractCoordinate.TOP:
|
867
|
-
return self.vmax
|
868
|
-
if val == types.AbstractCoordinate.BOTTOM:
|
869
|
-
return self.vmin
|
870
|
-
raise VisualizationError(f"Coordinate {val} is not supported.")
|
871
|
-
|
872
|
-
try:
|
873
|
-
return np.asarray(vals, dtype=float)
|
874
|
-
except (TypeError, ValueError):
|
875
|
-
return np.asarray(list(map(substitute, vals)), dtype=float)
|
876
|
-
|
877
|
-
def _check_visible(self, data: drawings.ElementaryData) -> bool:
|
878
|
-
"""A helper function to check if the data is visible.
|
879
|
-
|
880
|
-
Args:
|
881
|
-
data: Drawing object to test.
|
882
|
-
|
883
|
-
Returns:
|
884
|
-
Return `True` if the data is visible.
|
885
|
-
"""
|
886
|
-
is_active_type = data.data_type not in self.parent.disable_types
|
887
|
-
is_active_chan = any(chan not in self.parent.disable_chans for chan in data.channels)
|
888
|
-
if not (is_active_type and is_active_chan):
|
889
|
-
return False
|
890
|
-
|
891
|
-
return True
|
892
|
-
|
893
|
-
@classmethod
|
894
|
-
def _increment_cls_index(cls):
|
895
|
-
"""Increment counter of the chart."""
|
896
|
-
cls.chart_index += 1
|
897
|
-
|
898
|
-
@classmethod
|
899
|
-
def _cls_index(cls) -> int:
|
900
|
-
"""Return counter index of the chart."""
|
901
|
-
return cls.chart_index
|